diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d
index 411e98d4..e96a77bc 100644
--- a/src/dlangui/core/types.d
+++ b/src/dlangui/core/types.d
@@ -16,6 +16,14 @@ struct Rect {
     int top;
     int right;
     int bottom;
+    @property int middlex() { return (left + right) / 2; }
+    @property int middley() { return (top + bottom) / 2; }
+    void offset(int dx, int dy) {
+        left += dx;
+        right += dx;
+        top += dy;
+        bottom += dy;
+    }
     @property int width() { return right - left; }
     @property int height() { return bottom - top; }
     this(int x0, int y0, int x1, int y1) {
diff --git a/src/dlangui/graphics/drawbuf.d b/src/dlangui/graphics/drawbuf.d
index fdaa1f94..f6cd7197 100644
--- a/src/dlangui/graphics/drawbuf.d
+++ b/src/dlangui/graphics/drawbuf.d
@@ -5,6 +5,9 @@ import dlangui.core.logger;
 
 /// blend two RGB pixels using alpha
 uint blendARGB(uint dst, uint src, uint alpha) {
+    uint dstalpha = dst >> 24;
+    if (dstalpha > 0x80)
+        return src;
     uint srcr = (src >> 16) & 0xFF;
     uint srcg = (src >> 8) & 0xFF;
     uint srcb = (src >> 0) & 0xFF;
diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d
index b04ec93e..2ce63f4f 100644
--- a/src/dlangui/graphics/gldrawbuf.d
+++ b/src/dlangui/graphics/gldrawbuf.d
@@ -63,10 +63,20 @@ class GLDrawBuf : DrawBuf {
     /// draw source buffer rectangle contents to destination buffer
     override void drawFragment(int x, int y, DrawBuf src, Rect srcrect) {
         assert(_scene !is null);
+        GLImageCacheItem item = glImageCache.get(src.id);
+        if (item is null)
+            item = glImageCache.set(src);
+        Rect dstrect = Rect(x, y, x + srcrect.width, y + srcrect.height);
+        // TODO: clipping
+        _scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
     }
     /// draw source buffer rectangle contents to destination buffer rectangle applying rescaling
     override void drawRescaled(Rect dstrect, DrawBuf src, Rect srcrect) {
         assert(_scene !is null);
+        GLImageCacheItem item = glImageCache.get(src.id);
+        if (item is null)
+            item = glImageCache.set(src);
+        _scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
     }
     override void clear() {
     }
@@ -80,10 +90,7 @@ public:
     @property GLImageCachePage page() { return _page; }
     uint _objectId;
     // image size
-    int _dx;
-    int _dy;
-    int _x0;
-    int _y0;
+    Rect _rc;
     bool _deleted;
     this(GLImageCachePage page, uint objectId) { _page = page; _objectId = objectId; }
 };
@@ -197,10 +204,10 @@ public:
         _map.clear();
     }
     /// draw cached item
-    void drawItem(uint objectId, int x, int y, int dx, int dy, int srcx, int srcy, int srcwidth, int srcheight, uint color, int options, Rect * clip, int rotationAngle) {
+    void drawItem(uint objectId, Rect dstrc, Rect srcrc, uint color, int options, Rect * clip, int rotationAngle) {
         if (objectId in _map) {
             GLImageCacheItem item = _map[objectId];
-            item.page.drawItem(item, x, y, dx, dy, srcx, srcy, srcwidth, srcheight, color, options, clip, rotationAngle);
+            item.page.drawItem(item, dstrc, srcrc, color, options, clip, rotationAngle);
         }
     }
     /// handle cached object deletion, mark as deleted
@@ -314,13 +321,10 @@ public:
 	    }
 	}
 	void invertAlpha(GLImageCacheItem item) {
-		int x0 = item._x0;
-		int y0 = item._y0;
-		int x1 = x0 + item._dx;
-		int y1 = y0 + item._dy;
-	    for (int y = y0; y < y1; y++) {
+        Rect rc = item._rc;
+	    for (int y = rc.top; y < rc.bottom; y++) {
 	    	uint * row = _drawbuf.scanLine(y);
-	    	for (int x = x0; x < x1; x++) {
+	    	for (int x = rc.left; x < rc.right; x++) {
 	    		uint cl = row[x];
 	    		cl ^= 0xFF000000;
 	    		uint r = (cl & 0x00FF0000) >> 16;
@@ -335,30 +339,27 @@ public:
 			return null;
 
 		// next line if necessary
-		if (_x + width > _tdx) {
+		if (_x + width + 2 > _tdx) {
 			// move to next line
 			_currentLine = _nextLine;
 			_x = 0;
 		}
 		// check if no room left for glyph height
-		if (_currentLine + height > _tdy) {
+		if (_currentLine + height + 2 > _tdy) {
 			_closed = true;
 			return null;
 		}
-		cacheItem._dx = width;
-		cacheItem._dy = height;
-		cacheItem._x0 = _x;
-		cacheItem._y0 = _currentLine;
+        cacheItem._rc = Rect(_x + 1, _currentLine + 1, _x + width + 1, _currentLine + height + 1);
 		if (height && width) {
-			if (_nextLine < _currentLine + height)
-				_nextLine = _currentLine + height;
+			if (_nextLine < _currentLine + height + 2)
+				_nextLine = _currentLine + height + 2;
 			if (!_drawbuf) {
 				_drawbuf = new ColorDrawBuf(_tdx, _tdy);
 				//_drawbuf.SetBackgroundColor(0x000000);
 				//_drawbuf.SetTextColor(0xFFFFFF);
 				_drawbuf.fill(0xFF000000);
 			}
-			_x += width;
+			_x += width + 1;
 			_needUpdateTexture = true;
 		}
 		_itemCount++;
@@ -373,12 +374,12 @@ public:
 		if (cacheItem is null)
 			return null;
 		buf.onDestroyCallback = &onObjectDestroyedCallback;
-        _drawbuf.drawImage(cacheItem._x0, cacheItem._y0, buf);
+        _drawbuf.drawImage(cacheItem._rc.left, cacheItem._rc.top, buf);
 		invertAlpha(cacheItem);
 		_needUpdateTexture = true;
 		return cacheItem;
 	}
-    void drawItem(GLImageCacheItem item, int x, int y, int dx, int dy, int srcx, int srcy, int srcdx, int srcdy, uint color, uint options, Rect * clip, int rotationAngle) {
+    void drawItem(GLImageCacheItem item, Rect dstrc, Rect srcrc, uint color, uint options, Rect * clip, int rotationAngle) {
         //CRLog::trace("drawing item at %d,%d %dx%d <= %d,%d %dx%d ", x, y, dx, dy, srcx, srcy, srcdx, srcdy);
         if (_needUpdateTexture)
 			updateTexture();
@@ -388,15 +389,14 @@ public:
                 return;
             }
             //rotationAngle = 0;
-            int rx = x + dx / 2;
-            int ry = (y + dy / 2);
+            int rx = dstrc.middlex;
+            int ry = dstrc.middley;
             if (rotationAngle) {
                 //rotationAngle = 0;
                 //setRotation(rx, ry, rotationAngle);
             }
-
-            Rect srcrc = Rect(item._x0 + srcx, item._y0 + srcy, item._x0 + srcx+srcdx, item._y0 + srcy+srcdy);
-            Rect dstrc = Rect(x, y, x + dx, y+dy);
+            // convert coordinates to cached texture
+            srcrc.offset(item._rc.left, item._rc.top);
             if (clip) {
                 int srcw = srcrc.width();
                 int srch = srcrc.height();
@@ -416,7 +416,7 @@ public:
                 dstrc.bottom -= clip.bottom;
             }
             if (!dstrc.empty)
-                drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height());
+                drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); //srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()
             //drawColorAndTextureRect(vertices, texcoords, color, _textureId);
 
             if (rotationAngle) {
@@ -437,3 +437,31 @@ public:
 };
 
 
+private class TextureSceneItem : SceneItem {
+	uint objectId;
+    //CacheableObject * img;
+    Rect dstrc;
+    Rect srcrc;
+	uint color;
+	uint options;
+	Rect * clip;
+    int rotationAngle;
+public:
+	override void draw() {
+		if (glImageCache)
+            glImageCache.drawItem(objectId, dstrc, srcrc, color, options, clip, rotationAngle);
+	}
+    this(uint _objectId, Rect _dstrc, Rect _srcrc, uint _color, uint _options, Rect * _clip, int _rotationAngle)
+	{
+        objectId = _objectId;
+        dstrc = _dstrc;
+        srcrc = _srcrc;
+        color = _color;
+        options = _options;
+        clip = _clip;
+        rotationAngle = _rotationAngle;
+	}
+	~this() {
+	}
+};
+
diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d
index c799520d..e3371a4e 100644
--- a/src/dlangui/graphics/glsupport.d
+++ b/src/dlangui/graphics/glsupport.d
@@ -59,7 +59,7 @@ void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint colo
         x1,y1,Z_2D,
         x1,y0,Z_2D];
 	if (_solidFillProgram !is null) {
-		Log.d("solid fill: vertices ", vertices, " colors ", colors);
+		//Log.d("solid fill: vertices ", vertices, " colors ", colors);
 		_solidFillProgram.execute(vertices, colors);
 	} else
 		Log.e("No program");
@@ -67,6 +67,7 @@ void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint colo
 }
 
 void drawColorAndTextureRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) {
+    Log.v("drawColorAndTextureRect tx=", textureId, " src=", srcrc, " dst=", dstrc);
     drawColorAndTextureRect(textureId, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color, linear);
 }
 
diff --git a/src/dlangui/graphics/images.d b/src/dlangui/graphics/images.d
index ad88fbe8..686bc21c 100644
--- a/src/dlangui/graphics/images.d
+++ b/src/dlangui/graphics/images.d
@@ -82,7 +82,7 @@ __gshared DrawableCache _drawableCache;
 /// drawable cache singleton
 @property DrawableCache drawableCache() { return _drawableCache; }
 
-static this() {
+shared static this() {
     _imageCache = new ImageCache();
     _drawableCache = new DrawableCache();
 }
diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d
index 8008f994..3dc00f55 100644
--- a/src/dlangui/platforms/windows/winapp.d
+++ b/src/dlangui/platforms/windows/winapp.d
@@ -13,6 +13,7 @@ import dlangui.platforms.common.platform;
 import dlangui.platforms.windows.win32fonts;
 import dlangui.platforms.windows.win32drawbuf;
 import dlangui.graphics.drawbuf;
+import dlangui.graphics.images;
 import dlangui.graphics.fonts;
 import dlangui.graphics.glsupport;
 import dlangui.core.logger;
@@ -131,7 +132,7 @@ class Win32Window : Window {
         _caption = windowCaption;
         _hwnd = CreateWindow(toUTF16z(WIN_CLASS_NAME),      // window class name
                             toUTF16z(windowCaption),  // window caption
-                            WS_OVERLAPPEDWINDOW,  // window style
+                            WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,  // window style
                             CW_USEDEFAULT,        // initial x position
                             CW_USEDEFAULT,        // initial y position
                             CW_USEDEFAULT,        // initial x size
@@ -226,6 +227,12 @@ class Win32Window : Window {
     void onPaint() {
         Log.d("onPaint()");
         if (useOpengl && _hGLRC) {
+            // hack to stop infinite WM_PAINT loop
+            PAINTSTRUCT ps;
+            HDC hdc2 = BeginPaint(_hwnd, &ps);
+            EndPaint(_hwnd, &ps);
+
+
             import derelict.opengl3.gl3;
             import derelict.opengl3.wgl;
             import dlangui.graphics.gldrawbuf;
@@ -245,9 +252,22 @@ class Win32Window : Window {
             buf.fillRect(Rect(100, 100, 200, 200), 0x704020);
             buf.fillRect(Rect(40, 70, 100, 120), 0x000000);
             buf.fillRect(Rect(80, 80, 150, 150), 0x80008000); // green
+            DrawableRef img = drawableCache.get("exit");
+            if (!img.isNull) {
+                img.drawTo(buf, Rect(300, 100, 364, 164));
+                img.drawTo(buf, Rect(400, 200, 528, 328));
+            }
+            DrawableRef img2 = drawableCache.get("btn_default_pressed");
+            if (!img2.isNull) {
+                img2.drawTo(buf, Rect(300, 200, 564, 264));
+                img2.drawTo(buf, Rect(600, 200, 628, 328));
+            }
+            drawableCache.get("btn_default_normal").drawTo(buf, Rect(300, 0, 400, 50));;
+            drawableCache.get("btn_default_selected").drawTo(buf, Rect(0, 0, 100, 50));;
             buf.afterDrawing();
             //Log.d("onPaint() end drawing opengl");
             SwapBuffers(hdc);
+            wglMakeCurrent(hdc, null);
         } else {
             PAINTSTRUCT ps;
             HDC hdc = BeginPaint(_hwnd, &ps);
@@ -268,14 +288,14 @@ class Win32Platform : Platform {
         //MSG  msg;
         WNDCLASS wndclass;
 
-        wndclass.style         = CS_HREDRAW | CS_VREDRAW;
+        wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
         wndclass.lpfnWndProc   = &WndProc;
         wndclass.cbClsExtra    = 0;
         wndclass.cbWndExtra    = 0;
         wndclass.hInstance     = _hInstance;
         wndclass.hIcon         = LoadIcon(null, IDI_APPLICATION);
         wndclass.hCursor       = LoadCursor(null, IDC_ARROW);
-        wndclass.hbrBackground = cast(HBRUSH)GetStockObject(WHITE_BRUSH);
+        wndclass.hbrBackground = null; //cast(HBRUSH)GetStockObject(WHITE_BRUSH);
         wndclass.lpszMenuName  = null;
         wndclass.lpszClassName = toUTF16z(WIN_CLASS_NAME);