From 3113577041e0473b6aff0df07c27ff17402315d7 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 12 Mar 2014 10:29:06 +0400 Subject: [PATCH] put OpenGL support under conditional compilation: version(USE_OPENGL) --- src/dlangui/core/types.d | 6 +- src/dlangui/graphics/drawbuf.d | 18 +- src/dlangui/graphics/fonts.d | 34 ++- src/dlangui/graphics/gldrawbuf.d | 6 +- src/dlangui/graphics/glsupport.d | 5 + src/dlangui/platforms/common/platform.d | 16 +- src/dlangui/platforms/windows/win32fonts.d | 4 +- src/dlangui/platforms/windows/winapp.d | 290 +++++++++++---------- 8 files changed, 213 insertions(+), 166 deletions(-) diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d index bf880369..a6422f55 100644 --- a/src/dlangui/core/types.d +++ b/src/dlangui/core/types.d @@ -59,8 +59,10 @@ struct Rect { align(1) struct Glyph { - ///< 0: unique id of glyph (for drawing in hardware accelerated scenes) - uint id; + version (USE_OPENGL) { + ///< 0: unique id of glyph (for drawing in hardware accelerated scenes) + uint id; + } ///< 4: width of glyph black box ubyte blackBoxX; ///< 5: height of glyph black box diff --git a/src/dlangui/graphics/drawbuf.d b/src/dlangui/graphics/drawbuf.d index 5232e529..64244ffe 100644 --- a/src/dlangui/graphics/drawbuf.d +++ b/src/dlangui/graphics/drawbuf.d @@ -46,20 +46,26 @@ struct NinePatch { Rect padding; } -/// non thread safe -private __gshared uint drawBufIdGenerator = 0; +version (USE_OPENGL) { + /// non thread safe + private __gshared uint drawBufIdGenerator = 0; +} /// drawing buffer - image container which allows to perform some drawing operations class DrawBuf : RefCountedObject { - protected uint _id; protected Rect _clipRect; protected NinePatch * _ninePatch; - @property uint id() { - return _id; + version (USE_OPENGL) { + protected uint _id; + /// unique ID of drawbug instance, for using with hardware accelerated rendering for caching + @property uint id() { return _id; } } + this() { - _id = drawBufIdGenerator++; + version (USE_OPENGL) { + _id = drawBufIdGenerator++; + } } protected void function(uint) _onDestroyCallback; @property void onDestroyCallback(void function(uint) callback) { _onDestroyCallback = callback; } diff --git a/src/dlangui/graphics/fonts.d b/src/dlangui/graphics/fonts.d index 53523bcd..6d1df8b9 100644 --- a/src/dlangui/graphics/fonts.d +++ b/src/dlangui/graphics/fonts.d @@ -18,14 +18,16 @@ enum FontWeight : int { Bold = 800 } -private __gshared void function(uint id) _glyphDestroyCallback; -/// get glyph destroy callback (to cleanup OpenGL caches) -@property void function(uint id) glyphDestroyCallback() { return _glyphDestroyCallback; } -/// set glyph destroy callback (to cleanup OpenGL caches) -@property void glyphDestroyCallback(void function(uint id) callback) { _glyphDestroyCallback = callback; } +version (USE_OPENGL) { + private __gshared void function(uint id) _glyphDestroyCallback; + /// get glyph destroy callback (to cleanup OpenGL caches) + @property void function(uint id) glyphDestroyCallback() { return _glyphDestroyCallback; } + /// set glyph destroy callback (to cleanup OpenGL caches) + @property void glyphDestroyCallback(void function(uint id) callback) { _glyphDestroyCallback = callback; } -private __gshared uint _nextGlyphId; -uint nextGlyphId() { return _nextGlyphId++; } + private __gshared uint _nextGlyphId; + uint nextGlyphId() { return _nextGlyphId++; } +} struct GlyphCache { @@ -66,10 +68,12 @@ struct GlyphCache void cleanup() { uint dst = 0; // notify about destroyed glyphs - if (_glyphDestroyCallback !is null) - for (uint src = 0; src < _len; src++) - if (_data[src].lastUsage == 0) - _glyphDestroyCallback(_data[src].id); + version (USE_OPENGL) { + if (_glyphDestroyCallback !is null) + for (uint src = 0; src < _len; src++) + if (_data[src].lastUsage == 0) + _glyphDestroyCallback(_data[src].id); + } for (uint src = 0; src < _len; src++) { if (_data[src].lastUsage != 0) { _data[src].lastUsage = 0; @@ -83,9 +87,11 @@ struct GlyphCache // removes all entries void clear() { - if (_glyphDestroyCallback !is null) - for (uint src = 0; src < _len; src++) - _glyphDestroyCallback(_data[src].id); + version (USE_OPENGL) { + if (_glyphDestroyCallback !is null) + for (uint src = 0; src < _len; src++) + _glyphDestroyCallback(_data[src].id); + } _data = null; _len = 0; } diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d index 3aa5d913..199f324b 100644 --- a/src/dlangui/graphics/gldrawbuf.d +++ b/src/dlangui/graphics/gldrawbuf.d @@ -1,5 +1,7 @@ module dlangui.graphics.gldrawbuf; +version (USE_OPENGL) { + import dlangui.graphics.drawbuf; import dlangui.core.logger; private import dlangui.graphics.glsupport; @@ -819,7 +821,7 @@ public: } ~this() { } -}; - +} +} \ No newline at end of file diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index fdbb38ce..0fc259e3 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -1,5 +1,7 @@ module dlangui.graphics.glsupport; +version(USE_OPENGL) { + import dlangui.core.logger; private import derelict.opengl3.gl3; //private import gl3n.linalg; @@ -657,3 +659,6 @@ void setRotation(int x, int y, int rotationAngle) { matrix2.copyDataTo(m); */ } + + +} diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 41b8dcb4..0b6ed07b 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -51,13 +51,15 @@ public class Platform { abstract public int enterMessageLoop(); } -private __gshared bool _OPENGL_ENABLED = false; -/// check if hardware acceleration is enabled -@property bool openglEnabled() { return _OPENGL_ENABLED; } -/// call on app initialization if OpenGL support is detected -void setOpenglEnabled() { - _OPENGL_ENABLED = true; - glyphDestroyCallback = &onGlyphDestroyedCallback; +version (USE_OPENGL) { + private __gshared bool _OPENGL_ENABLED = false; + /// check if hardware acceleration is enabled + @property bool openglEnabled() { return _OPENGL_ENABLED; } + /// call on app initialization if OpenGL support is detected + void setOpenglEnabled() { + _OPENGL_ENABLED = true; + glyphDestroyCallback = &onGlyphDestroyedCallback; + } } version (Windows) { diff --git a/src/dlangui/platforms/windows/win32fonts.d b/src/dlangui/platforms/windows/win32fonts.d index 60969bba..d229f45b 100644 --- a/src/dlangui/platforms/windows/win32fonts.d +++ b/src/dlangui/platforms/windows/win32fonts.d @@ -131,7 +131,9 @@ class Win32Font : Font { return null; Glyph g; - g.id = nextGlyphId(); + version (USE_OPENGL) { + g.id = nextGlyphId(); + } g.blackBoxX = cast(ubyte)metrics.gmBlackBoxX; g.blackBoxY = cast(ubyte)metrics.gmBlackBoxY; g.originX = cast(byte)metrics.gmptGlyphOrigin.x; diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index f90fa998..74c9eaec 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -18,7 +18,6 @@ import dlangui.graphics.images; import dlangui.graphics.fonts; import dlangui.graphics.glsupport; import dlangui.core.logger; -//import derelict.opengl3.wgl; pragma(lib, "gdi32.lib"); pragma(lib, "user32.lib"); @@ -31,95 +30,97 @@ immutable WIN_CLASS_NAME = "DLANGUI_APP"; __gshared HINSTANCE _hInstance; __gshared int _cmdShow; -bool setupPixelFormat(HDC hDC) -{ - PIXELFORMATDESCRIPTOR pfd = { - PIXELFORMATDESCRIPTOR.sizeof, /* size */ - 1, /* version */ - PFD_SUPPORT_OPENGL | - PFD_DRAW_TO_WINDOW | - PFD_DOUBLEBUFFER, /* support double-buffering */ - PFD_TYPE_RGBA, /* color type */ - 16, /* prefered color depth */ - 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ - 0, /* no alpha buffer */ - 0, /* alpha bits (ignored) */ - 0, /* no accumulation buffer */ - 0, 0, 0, 0, /* accum bits (ignored) */ - 16, /* depth buffer */ - 0, /* no stencil buffer */ - 0, /* no auxiliary buffers */ - 0, /* main layer PFD_MAIN_PLANE */ - 0, /* reserved */ - 0, 0, 0, /* no layer, visible, damage masks */ - }; - int pixelFormat; - - pixelFormat = ChoosePixelFormat(hDC, &pfd); - if (pixelFormat == 0) { - Log.e("ChoosePixelFormat failed."); - return false; - } - - if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) { - Log.e("SetPixelFormat failed."); - return false; - } - return true; -} - -HPALETTE setupPalette(HDC hDC) -{ - import core.stdc.stdlib; - HPALETTE hPalette = NULL; - int pixelFormat = GetPixelFormat(hDC); - PIXELFORMATDESCRIPTOR pfd; - LOGPALETTE* pPal; - int paletteSize; - - DescribePixelFormat(hDC, pixelFormat, PIXELFORMATDESCRIPTOR.sizeof, &pfd); - - if (pfd.dwFlags & PFD_NEED_PALETTE) { - paletteSize = 1 << pfd.cColorBits; - } else { - return null; - } - - pPal = cast(LOGPALETTE*) - malloc(LOGPALETTE.sizeof + paletteSize * PALETTEENTRY.sizeof); - pPal.palVersion = 0x300; - pPal.palNumEntries = cast(ushort)paletteSize; - - /* build a simple RGB color palette */ +version (USE_OPENGL) { + bool setupPixelFormat(HDC hDC) { - int redMask = (1 << pfd.cRedBits) - 1; - int greenMask = (1 << pfd.cGreenBits) - 1; - int blueMask = (1 << pfd.cBlueBits) - 1; - int i; + PIXELFORMATDESCRIPTOR pfd = { + PIXELFORMATDESCRIPTOR.sizeof, /* size */ + 1, /* version */ + PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW | + PFD_DOUBLEBUFFER, /* support double-buffering */ + PFD_TYPE_RGBA, /* color type */ + 16, /* prefered color depth */ + 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ + 0, /* no alpha buffer */ + 0, /* alpha bits (ignored) */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits (ignored) */ + 16, /* depth buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffers */ + 0, /* main layer PFD_MAIN_PLANE */ + 0, /* reserved */ + 0, 0, 0, /* no layer, visible, damage masks */ + }; + int pixelFormat; - for (i=0; i> pfd.cRedShift) & redMask) * 255) / redMask); - pPal.palPalEntry[i].peGreen = cast(ubyte)( - (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask); - pPal.palPalEntry[i].peBlue = cast(ubyte)( - (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask); - pPal.palPalEntry[i].peFlags = 0; + pixelFormat = ChoosePixelFormat(hDC, &pfd); + if (pixelFormat == 0) { + Log.e("ChoosePixelFormat failed."); + return false; } + + if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) { + Log.e("SetPixelFormat failed."); + return false; + } + return true; } - hPalette = CreatePalette(pPal); - free(pPal); + HPALETTE setupPalette(HDC hDC) + { + import core.stdc.stdlib; + HPALETTE hPalette = NULL; + int pixelFormat = GetPixelFormat(hDC); + PIXELFORMATDESCRIPTOR pfd; + LOGPALETTE* pPal; + int paletteSize; - if (hPalette) { - SelectPalette(hDC, hPalette, FALSE); - RealizePalette(hDC); + DescribePixelFormat(hDC, pixelFormat, PIXELFORMATDESCRIPTOR.sizeof, &pfd); + + if (pfd.dwFlags & PFD_NEED_PALETTE) { + paletteSize = 1 << pfd.cColorBits; + } else { + return null; + } + + pPal = cast(LOGPALETTE*) + malloc(LOGPALETTE.sizeof + paletteSize * PALETTEENTRY.sizeof); + pPal.palVersion = 0x300; + pPal.palNumEntries = cast(ushort)paletteSize; + + /* build a simple RGB color palette */ + { + int redMask = (1 << pfd.cRedBits) - 1; + int greenMask = (1 << pfd.cGreenBits) - 1; + int blueMask = (1 << pfd.cBlueBits) - 1; + int i; + + for (i=0; i> pfd.cRedShift) & redMask) * 255) / redMask); + pPal.palPalEntry[i].peGreen = cast(ubyte)( + (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask); + pPal.palPalEntry[i].peBlue = cast(ubyte)( + (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask); + pPal.palPalEntry[i].peFlags = 0; + } + } + + hPalette = CreatePalette(pPal); + free(pPal); + + if (hPalette) { + SelectPalette(hDC, hPalette, FALSE); + RealizePalette(hDC); + } + + return hPalette; } - return hPalette; -} - -private __gshared bool DERELICT_GL3_RELOADED = false; + private __gshared bool DERELICT_GL3_RELOADED = false; +} class Win32Window : Window { private HWND _hwnd; @@ -142,56 +143,62 @@ class Win32Window : Window { null, // window menu handle _hInstance, // program instance handle cast(void*)this); // creation parameters - /* initialize OpenGL rendering */ - HDC hDC = GetDC(_hwnd); - - if (!DERELICT_GL3_RELOADED || openglEnabled) { - if (setupPixelFormat(hDC)) { - _hPalette = setupPalette(hDC); - _hGLRC = wglCreateContext(hDC); - if (_hGLRC) { - wglMakeCurrent(hDC, _hGLRC); - if (!DERELICT_GL3_RELOADED) { - // run this code only once - DERELICT_GL3_RELOADED = true; - try { - import derelict.opengl3.gl3; - DerelictGL3.reload(); - // successful - if (initShaders()) { - setOpenglEnabled(); - useOpengl = true; - } else { - Log.e("Failed to compile shaders"); + version (USE_OPENGL) { + + /* initialize OpenGL rendering */ + HDC hDC = GetDC(_hwnd); + + if (!DERELICT_GL3_RELOADED || openglEnabled) { + if (setupPixelFormat(hDC)) { + _hPalette = setupPalette(hDC); + _hGLRC = wglCreateContext(hDC); + if (_hGLRC) { + wglMakeCurrent(hDC, _hGLRC); + + if (!DERELICT_GL3_RELOADED) { + // run this code only once + DERELICT_GL3_RELOADED = true; + try { + import derelict.opengl3.gl3; + DerelictGL3.reload(); + // successful + if (initShaders()) { + setOpenglEnabled(); + useOpengl = true; + } else { + Log.e("Failed to compile shaders"); + } + } catch (Exception e) { + Log.e("Derelict exception", e); } - } catch (Exception e) { - Log.e("Derelict exception", e); + } else { + if (initShaders()) { + setOpenglEnabled(); + useOpengl = true; + } else { + Log.e("Failed to compile shaders"); + } } - } else { - if (initShaders()) { - setOpenglEnabled(); - useOpengl = true; - } else { - Log.e("Failed to compile shaders"); - } } + } else { + Log.e("Pixelformat failed"); + // disable GL + DERELICT_GL3_RELOADED = true; } - } else { - Log.e("Pixelformat failed"); - // disable GL - DERELICT_GL3_RELOADED = true; } } } ~this() { Log.d("Window destructor"); - import derelict.opengl3.wgl; - if (_hGLRC) { - uninitShaders(); - wglMakeCurrent (null, null) ; - wglDeleteContext(_hGLRC); - _hGLRC = null; + version (USE_OPENGL) { + import derelict.opengl3.wgl; + if (_hGLRC) { + uninitShaders(); + wglMakeCurrent (null, null) ; + wglDeleteContext(_hGLRC); + _hGLRC = null; + } } if (_hwnd) DestroyWindow(_hwnd); @@ -225,9 +232,20 @@ class Win32Window : Window { void onDestroy() { Log.d("Window onDestroy"); } - void onPaint() { - Log.d("onPaint()"); - if (useOpengl && _hGLRC) { + + private void paintUsingGDI() { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(_hwnd, &ps); + scope(exit) EndPaint(_hwnd, &ps); + + Win32ColorDrawBuf buf = getDrawBuf(); + buf.fill(0x808080); + onDraw(buf); + buf.drawTo(hdc, 0, 0); + } + + version (USE_OPENGL) { + private void paintUsingOpenGL() { // hack to stop infinite WM_PAINT loop PAINTSTRUCT ps; HDC hdc2 = BeginPaint(_hwnd, &ps); @@ -268,15 +286,19 @@ class Win32Window : Window { //Log.d("onPaint() end drawing opengl"); SwapBuffers(hdc); wglMakeCurrent(hdc, null); - } else { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(_hwnd, &ps); - scope(exit) EndPaint(_hwnd, &ps); + } + } - Win32ColorDrawBuf buf = getDrawBuf(); - buf.fill(0x808080); - onDraw(buf); - buf.drawTo(hdc, 0, 0); + void onPaint() { + Log.d("onPaint()"); + version (USE_OPENGL) { + if (useOpengl && _hGLRC) { + paintUsingOpenGL(); + } else { + paintUsingGDI(); + } + } else { + paintUsingGDI(); } } } @@ -391,7 +413,7 @@ int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int Win32FontManager fontMan = new Win32FontManager(); FontManager.instance = fontMan; - { + version (USE_OPENGL) { import derelict.opengl3.gl3; DerelictGL3.load();