diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index a3290833..a28e84c3 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -66,7 +66,7 @@ 0 DebugFocus 0 - USE_OPENGL Unicode + USE_OPENGL USE_SDL Unicode 0 0 1 @@ -89,7 +89,6 @@ $(OutDir)\$(ProjectName).lib 1 - 2 @@ -184,7 +183,6 @@ $(OutDir)\$(ProjectName).lib 1 - 1 diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj index a7d67fa0..c1aca680 100644 --- a/examples/example1/example1.visualdproj +++ b/examples/example1/example1.visualdproj @@ -66,7 +66,7 @@ 0 0 - USE_OPENGL Unicode + USE_OPENGL USE_SDL Unicode 0 3 0 @@ -89,7 +89,6 @@ $(OutDir)\$(ProjectName).exe 1 - 2 -profile @@ -184,7 +183,6 @@ $(OutDir)\$(ProjectName).exe 1 - 1 diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d index 434f4232..ef414f5e 100644 --- a/src/dlangui/graphics/gldrawbuf.d +++ b/src/dlangui/graphics/gldrawbuf.d @@ -62,9 +62,9 @@ class GLDrawBuf : DrawBuf { /// reserved for hardware-accelerated drawing - ends drawing batch override void afterDrawing() { - setOrthoProjection(_dx, _dy); + glSupport.setOrthoProjection(_dx, _dy); _scene.draw(); - flushGL(); + glSupport.flushGL(); destroy(_scene); _scene = null; } @@ -244,7 +244,7 @@ private class GLImageCache { _drawbuf = null; } if (_textureId != 0) { - deleteTexture(_textureId); + glSupport.deleteTexture(_textureId); _textureId = 0; } } @@ -254,14 +254,14 @@ private class GLImageCache { return; // no draw buffer!!! if (_textureId == 0) { //CRLog::debug("updateTexture - new texture"); - _textureId = genTexture(); + _textureId = glSupport.genTexture(); if (!_textureId) return; } //CRLog::debug("updateTexture - setting image %dx%d", _drawbuf.width, _drawbuf.height); uint * pixels = _drawbuf.scanLine(0); - if (!setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) { - deleteTexture(_textureId); + if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) { + glSupport.deleteTexture(_textureId); _textureId = 0; return; } @@ -339,7 +339,7 @@ private class GLImageCache { if (_needUpdateTexture) updateTexture(); if (_textureId != 0) { - if (!isTexture(_textureId)) { + if (!glSupport.isTexture(_textureId)) { Log.e("Invalid texture ", _textureId); return; } @@ -371,12 +371,12 @@ private class GLImageCache { dstrc.bottom -= clip.bottom; } if (!dstrc.empty) - drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()); + glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()); //drawColorAndTextureRect(vertices, texcoords, color, _textureId); if (rotationAngle) { // unset rotation - setRotation(rx, ry, 0); + glSupport.setRotation(rx, ry, 0); // glMatrixMode(GL_PROJECTION); // glPopMatrix(); // checkError("pop matrix"); @@ -576,7 +576,7 @@ private class GLGlyphCache { _drawbuf = null; } if (_textureId != 0) { - deleteTexture(_textureId); + glSupport.deleteTexture(_textureId); _textureId = 0; } } @@ -589,7 +589,7 @@ private class GLGlyphCache { return; // no draw buffer!!! if (_textureId == 0) { //CRLog::debug("updateTexture - new texture"); - _textureId = genTexture(); + _textureId = glSupport.genTexture(); if (!_textureId) return; } @@ -600,8 +600,8 @@ private class GLGlyphCache { _rgbaBuffer.length = len; for (int i = 0; i < len; i++) _rgbaBuffer[i] = ((cast(uint)pixels[i]) << 24) | 0x00FFFFFF; - if (!setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)_rgbaBuffer.ptr)) { - deleteTexture(_textureId); + if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)_rgbaBuffer.ptr)) { + glSupport.deleteTexture(_textureId); _textureId = 0; return; } @@ -667,7 +667,7 @@ private class GLGlyphCache { if (_needUpdateTexture) updateTexture(); if (_textureId != 0) { - if (!isTexture(_textureId)) { + if (!glSupport.isTexture(_textureId)) { Log.e("Invalid texture ", _textureId); return; } @@ -693,7 +693,7 @@ private class GLGlyphCache { } if (!dstrc.empty) { //Log.d("drawing glyph with color ", color); - drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); + glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); } } @@ -818,7 +818,7 @@ class SolidRectSceneItem : SceneItem { _color = color; } override void draw() { - drawSolidFillRect(_rc, _color, _color, _color, _color); + glSupport.drawSolidFillRect(_rc, _color, _color, _color, _color); } } diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index fa5cb762..bfef4498 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -53,7 +53,8 @@ static this() { 0x0505: "GL_OUT_OF_MEMORY" ]; } -/* Convenient wrapper around glGetError() +/** + * Convenient wrapper around glGetError() * TODO use one of the DEBUG extensions instead */ bool checkError(string context="", string file=__FILE__, int line=__LINE__) @@ -67,295 +68,6 @@ bool checkError(string context="", string file=__FILE__, int line=__LINE__) return false; } -immutable float Z_2D = -2.0f; -void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) { - float[6 * 4] colors; - LVGLFillColor(color1, colors.ptr + 4*0, 1); - LVGLFillColor(color4, colors.ptr + 4*1, 1); - LVGLFillColor(color3, colors.ptr + 4*2, 1); - LVGLFillColor(color1, colors.ptr + 4*3, 1); - LVGLFillColor(color3, colors.ptr + 4*4, 1); - LVGLFillColor(color2, colors.ptr + 4*5, 1); - float x0 = cast(float)(rc.left); - float y0 = cast(float)(bufferDy-rc.top); - float x1 = cast(float)(rc.right); - float y1 = cast(float)(bufferDy-rc.bottom); - - // don't flip for framebuffer - if (currentFramebufferId) { - y0 = cast(float)(rc.top); - y1 = cast(float)(rc.bottom); - } - - float[3 * 6] vertices = [ - x0,y0,Z_2D, - x0,y1,Z_2D, - x1,y1,Z_2D, - x0,y0,Z_2D, - x1,y1,Z_2D, - x1,y0,Z_2D]; - if (_solidFillProgram !is null) { - //Log.d("solid fill: vertices ", vertices, " colors ", colors); - _solidFillProgram.execute(vertices, colors); - } else - Log.e("No program"); -} - -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); -} - -void drawColorAndTextureRect(uint textureId, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color, bool linear) { - float[6*4] colors; - LVGLFillColor(color, colors.ptr, 6); - float dstx0 = cast(float)xx; - float dsty0 = cast(float)(bufferDy - (yy)); - float dstx1 = cast(float)(xx + dx); - float dsty1 = cast(float)(bufferDy - (yy + dy)); - - // don't flip for framebuffer - if (currentFramebufferId) { - dsty0 = cast(float)((yy)); - dsty1 = cast(float)((yy + dy)); - } - - float srcx0 = srcx / cast(float)tdx; - float srcy0 = srcy / cast(float)tdy; - float srcx1 = (srcx + srcdx) / cast(float)tdx; - float srcy1 = (srcy + srcdy) / cast(float)tdy; - float[3 * 6] vertices = [dstx0,dsty0,Z_2D, - dstx0,dsty1,Z_2D, - dstx1,dsty1,Z_2D, - dstx0,dsty0,Z_2D, - dstx1,dsty1,Z_2D, - dstx1,dsty0,Z_2D]; - float[2 * 6] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy1, srcx0,srcy0, srcx1,srcy1, srcx1,srcy0]; - _textureProgram.execute(vertices, texcoords, colors, textureId, linear); - //drawColorAndTextureRect(vertices, texcoords, colors, textureId, linear); -} - -/// generate new texture ID -uint genTexture() { - GLuint textureId = 0; - glGenTextures(1, &textureId); - return textureId; -} - -/// delete OpenGL texture -void deleteTexture(ref uint textureId) { - if (!textureId) - return; - if (glIsTexture(textureId) != GL_TRUE) { - Log.e("Invalid texture ", textureId); - return; - } - GLuint id = textureId; - glDeleteTextures(1, &id); - checkError("glDeleteTextures"); - textureId = 0; -} - -/// call glFlush -void flushGL() { - glFlush(); - checkError("glFlush"); -} - -bool setTextureImage(uint textureId, int dx, int dy, ubyte * pixels) { - //checkError("before setTextureImage"); - glActiveTexture(GL_TEXTURE0); - checkError("updateTexture - glActiveTexture"); - glBindTexture(GL_TEXTURE_2D, 0); - checkError("updateTexture - glBindTexture(0)"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("updateTexture - glBindTexture"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - checkError("updateTexture - glPixelStorei"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - checkError("updateTexture - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - checkError("updateTexture - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - checkError("updateTexture - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - checkError("updateTexture - glTexParameteri"); - - if (!glIsTexture(textureId)) - Log.e("second test - invalid texture passed to CRGLSupportImpl::setTextureImage"); - - // ORIGINAL: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - checkError("updateTexture - glTexImage2D"); - if (glGetError() != GL_NO_ERROR) { - Log.e("Cannot set image for texture"); - return false; - } - checkError("after setTextureImage"); - return true; -} - -bool setTextureImageAlpha(uint textureId, int dx, int dy, ubyte * pixels) { - checkError("before setTextureImageAlpha"); - glActiveTexture(GL_TEXTURE0); - checkError("updateTexture - glActiveTexture"); - glBindTexture(GL_TEXTURE_2D, 0); - checkError("updateTexture - glBindTexture(0)"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("setTextureImageAlpha - glBindTexture"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - checkError("setTextureImageAlpha - glPixelStorei"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - checkError("setTextureImageAlpha - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - checkError("setTextureImageAlpha - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - checkError("setTextureImageAlpha - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - checkError("setTextureImageAlpha - glTexParameteri"); - - if (!glIsTexture(textureId)) - Log.e("second test: invalid texture passed to CRGLSupportImpl::setTextureImageAlpha"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, dx, dy, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); - checkError("setTextureImageAlpha - glTexImage2D"); - if (glGetError() != GL_NO_ERROR) { - Log.e("Cannot set image for texture"); - return false; - } - glBindTexture(GL_TEXTURE_2D, 0); - checkError("updateTexture - glBindTexture(0)"); - checkError("after setTextureImageAlpha"); - return true; -} - -private uint currentFramebufferId; - -/// returns texture ID for buffer, 0 if failed -bool createFramebuffer(ref uint textureId, ref uint framebufferId, int dx, int dy) { - checkError("before createFramebuffer"); - bool res = true; - textureId = framebufferId = 0; - textureId = genTexture(); - if (!textureId) - return false; - GLuint fid = 0; - glGenFramebuffers(1, &fid); - if (checkError("createFramebuffer glGenFramebuffersOES")) return false; - framebufferId = fid; - glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); - if (checkError("createFramebuffer glBindFramebuffer")) return false; - - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("glBindTexture(GL_TEXTURE_2D, _textureId)"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dx, dy, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); - checkError("glTexImage2D"); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - checkError("texParameter"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - checkError("texParameter"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - checkError("texParameter"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - checkError("texParameter"); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); - checkError("glFramebufferTexture2D"); - // Always check that our framebuffer is ok - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - Log.e("glFramebufferTexture2D failed"); - res = false; - } - checkError("glCheckFramebufferStatus"); - //glClearColor(0.5f, 0, 0, 1); - glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - checkError("glClearColor"); - glClear(GL_COLOR_BUFFER_BIT); - checkError("glClear"); - checkError("after createFramebuffer"); - //CRLog::trace("CRGLSupportImpl::createFramebuffer %d,%d texture=%d, buffer=%d", dx, dy, textureId, framebufferId); - currentFramebufferId = framebufferId; - - glBindTexture(GL_TEXTURE_2D, 0); - checkError("createFramebuffer - glBindTexture(0)"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - checkError("createFramebuffer - glBindFramebuffer(0)"); - - return res; -} - -void deleteFramebuffer(ref uint framebufferId) { - //CRLog::debug("GLDrawBuf::deleteFramebuffer"); - if (framebufferId != 0) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - checkError("deleteFramebuffer - glBindFramebuffer"); - GLuint fid = framebufferId; - glDeleteFramebuffers(1, &fid); - checkError("deleteFramebuffer - glDeleteFramebuffer"); - } - //CRLog::trace("CRGLSupportImpl::deleteFramebuffer(%d)", framebufferId); - framebufferId = 0; - checkError("after deleteFramebuffer"); - currentFramebufferId = 0; -} - -bool bindFramebuffer(uint framebufferId) { - //CRLog::trace("CRGLSupportImpl::bindFramebuffer(%d)", framebufferId); - glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); - currentFramebufferId = framebufferId; - return !checkError("glBindFramebuffer"); -} - -/// projection matrix -//private mat4 m; -/// current gl buffer width -private int bufferDx; -/// current gl buffer height -private int bufferDy; - -//private float[16] matrix; -private float[16] qtmatrix; - -void QMatrix4x4_ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane) -{ - // Bail out if the projection volume is zero-sized. - if (left == right || bottom == top || nearPlane == farPlane) - return; - - // Construct the projection. - float width = right - left; - float invheight = top - bottom; - float clip = farPlane - nearPlane; - float[4][4] m; - m[0][0] = 2.0f / width; - m[1][0] = 0.0f; - m[2][0] = 0.0f; - m[3][0] = -(left + right) / width; - m[0][1] = 0.0f; - m[1][1] = 2.0f / invheight; - m[2][1] = 0.0f; - m[3][1] = -(top + bottom) / invheight; - m[0][2] = 0.0f; - m[1][2] = 0.0f; - m[2][2] = -2.0f / clip; - m[3][2] = -(nearPlane + farPlane) / clip; - m[0][3] = 0.0f; - m[1][3] = 0.0f; - m[2][3] = 0.0f; - m[3][3] = 1.0f; - for (int y = 0; y < 4; y++) - for (int x = 0; x < 4; x++) - qtmatrix[y * 4 + x] = m[y][x]; -} - -void setOrthoProjection(int dx, int dy) { - bufferDx = dx; - bufferDy = dy; - QMatrix4x4_ortho(0, dx, 0, dy, 0.5f, 50.0f); - glViewport(0, 0, dx, dy); - checkError("glViewport"); -} class GLProgram { @property abstract string vertexSource(); @@ -503,7 +215,7 @@ class SolidFillProgram : GLProgram { bind(); //glUniformMatrix4fv(matrixLocation, 1, false, m.value_ptr); //glUniformMatrix4fv(matrixLocation, 1, false, matrix.ptr); - glUniformMatrix4fv(matrixLocation, 1, false, qtmatrix.ptr); + glUniformMatrix4fv(matrixLocation, 1, false, glSupport.qtmatrix.ptr); checkError("glUniformMatrix4fv"); } @@ -704,57 +416,366 @@ class TextureProgram : SolidFillProgram { } } -__gshared TextureProgram _textureProgram; -__gshared SolidFillProgram _solidFillProgram; +__gshared GLSupport _glSupport; +@property GLSupport glSupport() { + if (!_glSupport) { + Log.f("GLSupport is not initialized"); + assert(false, "GLSupport is not initialized"); + } + if (!_glSupport.valid) { + Log.e("GLSupport programs are not initialized"); + } + return _glSupport; +} -bool initShaders() { - if (_textureProgram is null) { - _textureProgram = new TextureProgram(); - if (!_textureProgram.compile()) +class GLSupport { + + TextureProgram _textureProgram; + SolidFillProgram _solidFillProgram; + + @property bool valid() { + return _textureProgram && _solidFillProgram; + } + + bool initShaders() { + if (_textureProgram is null) { + _textureProgram = new TextureProgram(); + if (!_textureProgram.compile()) + return false; + } + if (_solidFillProgram is null) { + _solidFillProgram = new SolidFillProgram(); + if (!_solidFillProgram.compile()) + return false; + } + Log.d("Shaders compiled successfully"); + return true; + } + + bool uninitShaders() { + Log.d("Uniniting shaders"); + if (_textureProgram !is null) { + destroy(_textureProgram); + _textureProgram = null; + } + if (_solidFillProgram !is null) { + destroy(_solidFillProgram); + _solidFillProgram = null; + } + return true; + } + + bool isTexture(uint textureId) { + return glIsTexture(textureId) == GL_TRUE; + } + + void setRotation(int x, int y, int rotationAngle) { + /* + this->rotationAngle = rotationAngle; + rotationX = x; + rotationY = y; + if (!currentFramebufferId) { + rotationY = bufferDy - rotationY; + } + + QMatrix4x4 matrix2; + matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f); + if (rotationAngle) { + matrix2.translate(rotationX, rotationY, 0); + matrix2.rotate(rotationAngle, 0, 0, 1); + matrix2.translate(-rotationX, -rotationY, 0); + } + matrix2.copyDataTo(m); + */ + } + static immutable float Z_2D = -2.0f; + void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) { + float[6 * 4] colors; + LVGLFillColor(color1, colors.ptr + 4*0, 1); + LVGLFillColor(color4, colors.ptr + 4*1, 1); + LVGLFillColor(color3, colors.ptr + 4*2, 1); + LVGLFillColor(color1, colors.ptr + 4*3, 1); + LVGLFillColor(color3, colors.ptr + 4*4, 1); + LVGLFillColor(color2, colors.ptr + 4*5, 1); + float x0 = cast(float)(rc.left); + float y0 = cast(float)(bufferDy-rc.top); + float x1 = cast(float)(rc.right); + float y1 = cast(float)(bufferDy-rc.bottom); + + // don't flip for framebuffer + if (currentFramebufferId) { + y0 = cast(float)(rc.top); + y1 = cast(float)(rc.bottom); + } + + float[3 * 6] vertices = [ + x0,y0,Z_2D, + x0,y1,Z_2D, + x1,y1,Z_2D, + x0,y0,Z_2D, + x1,y1,Z_2D, + x1,y0,Z_2D]; + if (_solidFillProgram !is null) { + //Log.d("solid fill: vertices ", vertices, " colors ", colors); + _solidFillProgram.execute(vertices, colors); + } else + Log.e("No program"); + } + + 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); + } + + void drawColorAndTextureRect(uint textureId, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color, bool linear) { + float[6*4] colors; + LVGLFillColor(color, colors.ptr, 6); + float dstx0 = cast(float)xx; + float dsty0 = cast(float)(bufferDy - (yy)); + float dstx1 = cast(float)(xx + dx); + float dsty1 = cast(float)(bufferDy - (yy + dy)); + + // don't flip for framebuffer + if (currentFramebufferId) { + dsty0 = cast(float)((yy)); + dsty1 = cast(float)((yy + dy)); + } + + float srcx0 = srcx / cast(float)tdx; + float srcy0 = srcy / cast(float)tdy; + float srcx1 = (srcx + srcdx) / cast(float)tdx; + float srcy1 = (srcy + srcdy) / cast(float)tdy; + float[3 * 6] vertices = [dstx0,dsty0,Z_2D, + dstx0,dsty1,Z_2D, + dstx1,dsty1,Z_2D, + dstx0,dsty0,Z_2D, + dstx1,dsty1,Z_2D, + dstx1,dsty0,Z_2D]; + float[2 * 6] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy1, srcx0,srcy0, srcx1,srcy1, srcx1,srcy0]; + _textureProgram.execute(vertices, texcoords, colors, textureId, linear); + //drawColorAndTextureRect(vertices, texcoords, colors, textureId, linear); + } + + /// generate new texture ID + uint genTexture() { + GLuint textureId = 0; + glGenTextures(1, &textureId); + return textureId; + } + + /// delete OpenGL texture + void deleteTexture(ref uint textureId) { + if (!textureId) + return; + if (glIsTexture(textureId) != GL_TRUE) { + Log.e("Invalid texture ", textureId); + return; + } + GLuint id = textureId; + glDeleteTextures(1, &id); + checkError("glDeleteTextures"); + textureId = 0; + } + + /// call glFlush + void flushGL() { + glFlush(); + checkError("glFlush"); + } + + bool setTextureImage(uint textureId, int dx, int dy, ubyte * pixels) { + //checkError("before setTextureImage"); + glActiveTexture(GL_TEXTURE0); + checkError("updateTexture - glActiveTexture"); + glBindTexture(GL_TEXTURE_2D, 0); + checkError("updateTexture - glBindTexture(0)"); + glBindTexture(GL_TEXTURE_2D, textureId); + checkError("updateTexture - glBindTexture"); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + checkError("updateTexture - glPixelStorei"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + checkError("updateTexture - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkError("updateTexture - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + checkError("updateTexture - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + checkError("updateTexture - glTexParameteri"); + + if (!glIsTexture(textureId)) + Log.e("second test - invalid texture passed to CRGLSupportImpl::setTextureImage"); + + // ORIGINAL: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + checkError("updateTexture - glTexImage2D"); + if (glGetError() != GL_NO_ERROR) { + Log.e("Cannot set image for texture"); return false; + } + checkError("after setTextureImage"); + return true; } - if (_solidFillProgram is null) { - _solidFillProgram = new SolidFillProgram(); - if (!_solidFillProgram.compile()) + + bool setTextureImageAlpha(uint textureId, int dx, int dy, ubyte * pixels) { + checkError("before setTextureImageAlpha"); + glActiveTexture(GL_TEXTURE0); + checkError("updateTexture - glActiveTexture"); + glBindTexture(GL_TEXTURE_2D, 0); + checkError("updateTexture - glBindTexture(0)"); + glBindTexture(GL_TEXTURE_2D, textureId); + checkError("setTextureImageAlpha - glBindTexture"); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + checkError("setTextureImageAlpha - glPixelStorei"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + checkError("setTextureImageAlpha - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkError("setTextureImageAlpha - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + checkError("setTextureImageAlpha - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + checkError("setTextureImageAlpha - glTexParameteri"); + + if (!glIsTexture(textureId)) + Log.e("second test: invalid texture passed to CRGLSupportImpl::setTextureImageAlpha"); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, dx, dy, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); + checkError("setTextureImageAlpha - glTexImage2D"); + if (glGetError() != GL_NO_ERROR) { + Log.e("Cannot set image for texture"); return false; - } - Log.d("Shaders compiled successfully"); - return true; -} - -bool uninitShaders() { - Log.d("Uniniting shaders"); - if (_textureProgram !is null) { - destroy(_textureProgram); - _textureProgram = null; - } - if (_solidFillProgram !is null) { - destroy(_solidFillProgram); - _solidFillProgram = null; - } - return true; -} - -bool isTexture(uint textureId) { - return glIsTexture(textureId) == GL_TRUE; -} - -void setRotation(int x, int y, int rotationAngle) { - /* - this->rotationAngle = rotationAngle; - rotationX = x; - rotationY = y; - if (!currentFramebufferId) { - rotationY = bufferDy - rotationY; + } + glBindTexture(GL_TEXTURE_2D, 0); + checkError("updateTexture - glBindTexture(0)"); + checkError("after setTextureImageAlpha"); + return true; } - QMatrix4x4 matrix2; - matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f); - if (rotationAngle) { - matrix2.translate(rotationX, rotationY, 0); - matrix2.rotate(rotationAngle, 0, 0, 1); - matrix2.translate(-rotationX, -rotationY, 0); + private uint currentFramebufferId; + + /// returns texture ID for buffer, 0 if failed + bool createFramebuffer(ref uint textureId, ref uint framebufferId, int dx, int dy) { + checkError("before createFramebuffer"); + bool res = true; + textureId = framebufferId = 0; + textureId = genTexture(); + if (!textureId) + return false; + GLuint fid = 0; + glGenFramebuffers(1, &fid); + if (checkError("createFramebuffer glGenFramebuffersOES")) return false; + framebufferId = fid; + glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); + if (checkError("createFramebuffer glBindFramebuffer")) return false; + + glBindTexture(GL_TEXTURE_2D, textureId); + checkError("glBindTexture(GL_TEXTURE_2D, _textureId)"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dx, dy, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); + checkError("glTexImage2D"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + checkError("texParameter"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkError("texParameter"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + checkError("texParameter"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + checkError("texParameter"); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); + checkError("glFramebufferTexture2D"); + // Always check that our framebuffer is ok + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + Log.e("glFramebufferTexture2D failed"); + res = false; + } + checkError("glCheckFramebufferStatus"); + //glClearColor(0.5f, 0, 0, 1); + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + checkError("glClearColor"); + glClear(GL_COLOR_BUFFER_BIT); + checkError("glClear"); + checkError("after createFramebuffer"); + //CRLog::trace("CRGLSupportImpl::createFramebuffer %d,%d texture=%d, buffer=%d", dx, dy, textureId, framebufferId); + currentFramebufferId = framebufferId; + + glBindTexture(GL_TEXTURE_2D, 0); + checkError("createFramebuffer - glBindTexture(0)"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + checkError("createFramebuffer - glBindFramebuffer(0)"); + + return res; } - matrix2.copyDataTo(m); - */ + + void deleteFramebuffer(ref uint framebufferId) { + //CRLog::debug("GLDrawBuf::deleteFramebuffer"); + if (framebufferId != 0) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + checkError("deleteFramebuffer - glBindFramebuffer"); + GLuint fid = framebufferId; + glDeleteFramebuffers(1, &fid); + checkError("deleteFramebuffer - glDeleteFramebuffer"); + } + //CRLog::trace("CRGLSupportImpl::deleteFramebuffer(%d)", framebufferId); + framebufferId = 0; + checkError("after deleteFramebuffer"); + currentFramebufferId = 0; + } + + bool bindFramebuffer(uint framebufferId) { + //CRLog::trace("CRGLSupportImpl::bindFramebuffer(%d)", framebufferId); + glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); + currentFramebufferId = framebufferId; + return !checkError("glBindFramebuffer"); + } + + /// projection matrix + //private mat4 m; + /// current gl buffer width + private int bufferDx; + /// current gl buffer height + private int bufferDy; + //private float[16] matrix; + private float[16] qtmatrix; + + void QMatrix4x4_ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane) + { + // Bail out if the projection volume is zero-sized. + if (left == right || bottom == top || nearPlane == farPlane) + return; + + // Construct the projection. + float width = right - left; + float invheight = top - bottom; + float clip = farPlane - nearPlane; + float[4][4] m; + m[0][0] = 2.0f / width; + m[1][0] = 0.0f; + m[2][0] = 0.0f; + m[3][0] = -(left + right) / width; + m[0][1] = 0.0f; + m[1][1] = 2.0f / invheight; + m[2][1] = 0.0f; + m[3][1] = -(top + bottom) / invheight; + m[0][2] = 0.0f; + m[1][2] = 0.0f; + m[2][2] = -2.0f / clip; + m[3][2] = -(nearPlane + farPlane) / clip; + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][3] = 1.0f; + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + qtmatrix[y * 4 + x] = m[y][x]; + } + + void setOrthoProjection(int dx, int dy) { + bufferDx = dx; + bufferDy = dy; + QMatrix4x4_ortho(0, dx, 0, dy, 0.5f, 50.0f); + glViewport(0, 0, dx, dy); + checkError("glViewport"); + } + } + diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d index e7c69825..58732ddc 100644 --- a/src/dlangui/platforms/sdl/sdlapp.d +++ b/src/dlangui/platforms/sdl/sdlapp.d @@ -97,6 +97,8 @@ class SDLWindow : Window { version(USE_OPENGL) { if (_enableOpengl) windowFlags |= SDL_WINDOW_OPENGL; + if (!_glSupport) + _glSupport = new GLSupport(); } _win = SDL_CreateWindow(toUTF8(_caption).toStringz, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700, 500, @@ -127,7 +129,7 @@ class SDLWindow : Window { } else if (!_gl3Reloaded) { DerelictGL3.reload(); _gl3Reloaded = true; - if (!initShaders()) + if (!glSupport.valid && !glSupport.initShaders()) _enableOpengl = false; } } diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index 023a0423..60c65ad3 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -154,10 +154,12 @@ version (USE_OPENGL) { class Win32Window : Window { Win32Platform _platform; + HWND _hwnd; version (USE_OPENGL) { HGLRC _hGLRC; // opengl context HPALETTE _hPalette; + GLSupport _gl; } dstring _caption; Win32ColorDrawBuf _drawbuf; @@ -167,6 +169,7 @@ class Win32Window : Window { Win32Window w32parent = cast(Win32Window)parent; HWND parenthwnd = w32parent ? w32parent._hwnd : null; _platform = platform; + _gl = new GLSupport(); _caption = windowCaption; _flags = flags; uint ws = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; @@ -199,7 +202,9 @@ class Win32Window : Window { _hPalette = setupPalette(hDC); _hGLRC = wglCreateContext(hDC); if (_hGLRC) { + wglMakeCurrent(hDC, _hGLRC); + _glSupport = _gl; if (!DERELICT_GL3_RELOADED) { // run this code only once @@ -208,7 +213,7 @@ class Win32Window : Window { import derelict.opengl3.gl3; DerelictGL3.reload(); // successful - if (initShaders()) { + if (glSupport.initShaders()) { setOpenglEnabled(); useOpengl = true; } else { @@ -218,7 +223,7 @@ class Win32Window : Window { Log.e("Derelict exception", e); } } else { - if (initShaders()) { + if (glSupport.initShaders()) { setOpenglEnabled(); useOpengl = true; } else { @@ -252,6 +257,7 @@ class Win32Window : Window { //scope(exit) EndPaint(_hwnd, &ps); HDC hdc = GetDC(_hwnd); wglMakeCurrent(hdc, _hGLRC); + _glSupport = _gl; glDisable(GL_DEPTH_TEST); glViewport(0, 0, _dx, _dy); float a = 1.0f; @@ -288,7 +294,10 @@ class Win32Window : Window { version (USE_OPENGL) { import derelict.opengl3.wgl; if (_hGLRC) { - uninitShaders(); + glSupport.uninitShaders(); + delete _glSupport; + _glSupport = null; + _gl = null; wglMakeCurrent (null, null) ; wglDeleteContext(_hGLRC); _hGLRC = null; @@ -470,7 +479,7 @@ class Win32Window : Window { } void onPaint() { - Log.d("onPaint()"); + debug(DebugRedraw) Log.d("onPaint()"); long paintStart = currentTimeMillis; version (USE_OPENGL) { if (useOpengl && _hGLRC) { @@ -482,7 +491,7 @@ class Win32Window : Window { paintUsingGDI(); } long paintEnd = currentTimeMillis; - Log.d("WM_PAINT handling took ", paintEnd - paintStart, " ms"); + debug(DebugRedraw) Log.d("WM_PAINT handling took ", paintEnd - paintStart, " ms"); } protected ButtonDetails _lbutton;