From 091f75db13489305847a0e062b04da89b54b14ea Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 10 Mar 2014 17:56:21 +0400 Subject: [PATCH] trying to implement GL drawbuf --- dlanguilib.visualdproj | 1 + src/dlangui/graphics/gldrawbuf.d | 59 ++++++++++++++++ src/dlangui/graphics/glsupport.d | 93 +++++++++++++++++++++++--- src/dlangui/platforms/windows/winapp.d | 7 +- 4 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 src/dlangui/graphics/gldrawbuf.d diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index e43d4261..832c2341 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -294,6 +294,7 @@ + diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d new file mode 100644 index 00000000..b32f3442 --- /dev/null +++ b/src/dlangui/graphics/gldrawbuf.d @@ -0,0 +1,59 @@ +module dlangui.graphics.gldrawbuf; + +import dlangui.graphics.drawbuf; +import dlangui.graphics.glsupport; + +/// drawing buffer - image container which allows to perform some drawing operations +class GLDrawBuf : DrawBuf { + + int _dx; + int _dy; + bool _framebuffer; + + this(int dx, int dy, bool framebuffer = false) { + _dx = dx; + _dy = dy; + _framebuffer = framebuffer; + } + + /// returns current width + @property override int width() { return _dx; } + /// returns current height + @property override int height() { return _dy; } + + /// reserved for hardware-accelerated drawing - begins drawing batch + override void beforeDrawing() { + setOrthoProjection(_dx, _dy); + } + + /// reserved for hardware-accelerated drawing - ends drawing batch + override void afterDrawing() { + flushGL(); + } + + /// resize buffer + override void resize(int width, int height) { + _dx = width; + _dy = height; + } + + /// fill the whole buffer with solid color (no clipping applied) + override void fill(uint color) { + } + /// fill rectangle with solid color (clipping is applied) + override void fillRect(Rect rc, uint color) { + drawSolidFillRect(rc, color, color, color, color); + } + /// draw 8bit alpha image - usually font glyph using specified color (clipping is applied) + override void drawGlyph(int x, int y, ubyte[] src, int srcdx, int srcdy, uint color) { + } + /// draw source buffer rectangle contents to destination buffer + override void drawFragment(int x, int y, DrawBuf src, Rect srcrect) { + } + /// draw source buffer rectangle contents to destination buffer rectangle applying rescaling + override void drawRescaled(Rect dstrect, DrawBuf src, Rect srcrect) { + } + override void clear() { + } + ~this() { clear(); } +} diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index eace601a..95bb94b8 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -4,6 +4,7 @@ import dlangui.core.logger; private import derelict.opengl3.gl3; private import gl3n.linalg; private import dlangui.core.types; +private import std.conv; // utility function to fill 4-float array of vertex colors with converted CR 32bit color private void LVGLFillColor(uint color, float * buf, int count) { @@ -23,12 +24,79 @@ private void LVGLFillColor(uint color, float * buf, int count) { private bool checkError(string context, string file = __FILE__, int line = __LINE__) { int err = glGetError(); if (err != GL_NO_ERROR) { - Log.e("OpenGL error ", err, " at ", file, ":", line); + Log.e("OpenGL error ", err, " at ", file, ":", line, " -- ", context); return true; } return false; } +immutable float Z_2D = -1.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]; + _solidFillProgram.execute(vertices, colors); + //drawSolidFillRect(vertices, colors); +} + +void drawColorAndTextureRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) { + 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) { + //if (crconfig.getTextureFormat() == TEXTURE_ALPHA) { + // color = 0x000000; + //} + float colors[6*4]; + 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; @@ -203,7 +271,6 @@ bool bindFramebuffer(uint framebufferId) { /// projection matrix private mat4 m; -//private float[16] m; /// current gl buffer width private int bufferDx; /// current gl buffer height @@ -220,9 +287,6 @@ void setOrthoProjection(int dx, int dy) { checkError("glViewport"); } - - - class GLProgram { @property abstract string vertexSource(); @property abstract string fragmentSource(); @@ -283,9 +347,11 @@ class GLProgram { error = true; return false; } + Log.d("Program compiled successfully"); glDetachShader(program, vertexShader); glDetachShader(program, fragmentShader); glUseProgram(program); + checkError("glUseProgram " ~ to!string(program)); if (!initLocations()) { Log.e("some of locations were not found"); error = true; @@ -300,7 +366,7 @@ class GLProgram { if (!initialized) return false; glUseProgram(program); - checkError("glUseProgram"); + checkError("glUseProgram " ~ to!string(program)); return true; } void release() { @@ -350,11 +416,14 @@ class SolidFillProgram : GLProgram { void beforeExecute() { glEnable(GL_BLEND); glDisable(GL_CULL_FACE); - checkError("glEnable(GL_BLEND)"); + checkError("glDisable(GL_CULL_FACE)"); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkError("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)"); use(); + glDisable(GL_CULL_FACE); + checkError("glDisable(GL_CULL_FACE)"); glUniformMatrix4fv(matrixLocation, 1, false, m.value_ptr); + checkError("glUniformMatrix4fv"); } void afterExecute() { @@ -381,15 +450,21 @@ class SolidFillProgram : GLProgram { beforeExecute(); glEnableVertexAttribArray(vertexLocation); + checkError("glEnableVertexAttribArray"); glEnableVertexAttribArray(colAttrLocation); + checkError("glEnableVertexAttribArray"); - glVertexAttribPointer(vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, vertices.ptr); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices.ptr); + checkError("glVertexAttribPointer"); glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, colors.ptr); + checkError("glVertexAttribPointer"); glDrawArrays(GL_TRIANGLES, 0, 6); checkError("glDrawArrays"); glDisableVertexAttribArray(vertexLocation); + checkError("glDisableVertexAttribArray"); glDisableVertexAttribArray(colAttrLocation); + checkError("glDisableVertexAttribArray"); afterExecute(); glBindTexture(GL_TEXTURE_2D, 0); @@ -453,7 +528,7 @@ class TextureProgram : SolidFillProgram { glEnableVertexAttribArray(colAttrLocation); glEnableVertexAttribArray(texCoordLocation); - glVertexAttribPointer(vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, vertices.ptr); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices.ptr); glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, colors.ptr); glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords.ptr); diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index 5abce7f1..57e3cfb9 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -222,6 +222,7 @@ class Win32Window : Window { if (useOpengl && _hGLRC) { import derelict.opengl3.gl3; import derelict.opengl3.wgl; + import dlangui.graphics.gldrawbuf; //Log.d("onPaint() start drawing opengl viewport: ", _dx, "x", _dy); //PAINTSTRUCT ps; //HDC hdc = BeginPaint(_hwnd, &ps); @@ -232,8 +233,12 @@ class Win32Window : Window { glViewport(0, 0, _dx, _dy); glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + + GLDrawBuf buf = new GLDrawBuf(_dx, _dy, false); + buf.beforeDrawing(); + buf.fillRect(Rect(100, 100, 200, 200), 0x704020); + buf.afterDrawing(); //Log.d("onPaint() end drawing opengl"); - glFlush(); SwapBuffers(hdc); } else { PAINTSTRUCT ps;