From 69fd69645891aaf2751d60571d2a9e149a06d427 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 11 Mar 2014 17:40:43 +0400 Subject: [PATCH] GL texture drawing is working --- src/dlangui/core/types.d | 8 +++ src/dlangui/graphics/drawbuf.d | 3 + src/dlangui/graphics/gldrawbuf.d | 86 +++++++++++++++++--------- src/dlangui/graphics/glsupport.d | 3 +- src/dlangui/graphics/images.d | 2 +- src/dlangui/platforms/windows/winapp.d | 26 +++++++- 6 files changed, 94 insertions(+), 34 deletions(-) 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);