diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d index a10b59e5..9f69a788 100644 --- a/src/dlangui/graphics/gldrawbuf.d +++ b/src/dlangui/graphics/gldrawbuf.d @@ -105,8 +105,8 @@ class GLDrawBuf : DrawBuf, GLConfigCallback { if (!isFullyTransparentColor(color) && applyClipping(rc)) _scene.add(new SolidRectSceneItem(rc, color)); } - /// draw pixel at (x, y) with specified color - override void drawPixel(int x, int y, uint color) { + /// draw pixel at (x, y) with specified color + override void drawPixel(int x, int y, uint color) { assert(_scene !is null); if (!_clipRect.isPointInside(x, y)) return; @@ -114,7 +114,7 @@ class GLDrawBuf : DrawBuf, GLConfigCallback { if (isFullyTransparentColor(color)) return; _scene.add(new SolidRectSceneItem(Rect(x, y, x + 1, y + 1), color)); - } + } /// draw 8bit alpha image - usually font glyph using specified color (clipping is applied) override void drawGlyph(int x, int y, Glyph * glyph, uint color) { assert(_scene !is null); @@ -280,7 +280,7 @@ private class GLImageCache { private GLImageCachePage _page; @property GLImageCachePage page() { return _page; } - + uint _objectId; Rect _rc; bool _deleted; @@ -298,7 +298,7 @@ private class GLImageCache { private int _x; private bool _closed; private bool _needUpdateTexture; - private uint _textureId; + private Tex2D _texture; private int _itemCount; this(GLImageCache cache, int dx, int dy) { @@ -314,26 +314,26 @@ private class GLImageCache { destroy(_drawbuf); _drawbuf = null; } - if (_textureId != 0) { - glSupport.deleteTexture(_textureId); - _textureId = 0; + if (_texture.ID != 0) { + destroy(_texture); + _texture = null; } } void updateTexture() { if (_drawbuf is null) return; // no draw buffer!!! - if (_textureId == 0) { - _textureId = glSupport.genTexture(); - Log.d("updateTexture - new texture id=", _textureId); - if (!_textureId) + if (_texture is null || _texture.ID == 0) { + _texture = new Tex2D(); + Log.d("updateTexture - new texture id=", _texture.ID); + if (!_texture.ID) return; } - Log.d("updateTexture for image cache page - setting image ", _drawbuf.width, "x", _drawbuf.height, " tx=", _textureId); + Log.d("updateTexture for image cache page - setting image ", _drawbuf.width, "x", _drawbuf.height, " tx=", _texture.ID); uint * pixels = _drawbuf.scanLine(0); - if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) { - glSupport.deleteTexture(_textureId); - _textureId = 0; + if (!glSupport.setTextureImage(_texture, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) { + destroy(_texture); + _texture = null; return; } _needUpdateTexture = false; @@ -409,11 +409,7 @@ private class GLImageCache { //CRLog::trace("drawing item at %d,%d %dx%d <= %d,%d %dx%d ", x, y, dx, dy, srcx, srcy, srcdx, srcdy); if (_needUpdateTexture) updateTexture(); - if (_textureId != 0) { - if (!glSupport.isTexture(_textureId)) { - Log.e("Invalid texture ", _textureId); - return; - } + if (_texture.ID != 0) { //rotationAngle = 0; int rx = dstrc.middlex; int ry = dstrc.middley; @@ -442,8 +438,8 @@ private class GLImageCache { dstrc.bottom -= clip.bottom; } if (!dstrc.empty) - glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()); - //drawColorAndTextureRect(vertices, texcoords, color, _textureId); + glSupport.drawColorAndTextureRect(_texture, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()); + //drawColorAndTextureRect(vertices, texcoords, color, _texture); if (rotationAngle) { // unset rotation @@ -482,7 +478,7 @@ private class GLImageCache { private void updateTextureSize() { if (!tdx) { // TODO - tdx = tdy = 1024; //getMaxTextureSize(); + tdx = tdy = 1024; //getMaxTextureSize(); if (tdx > 1024) tdx = tdy = 1024; } @@ -627,7 +623,7 @@ private class GLGlyphCache { private int _x; private bool _closed; private bool _needUpdateTexture; - private uint _textureId; + private Tex2D _texture; private int _itemCount; this(GLGlyphCache cache, int dx, int dy) { @@ -643,26 +639,26 @@ private class GLGlyphCache { destroy(_drawbuf); _drawbuf = null; } - if (_textureId != 0) { - glSupport.deleteTexture(_textureId); - _textureId = 0; + if (_texture.ID != 0) { + destroy(_texture); + _texture = null; } } void updateTexture() { if (_drawbuf is null) return; // no draw buffer!!! - if (_textureId == 0) { - _textureId = glSupport.genTexture(); - //Log.d("updateTexture - new texture ", _textureId); - if (!_textureId) + if (_texture is null || _texture.ID == 0) { + _texture = new Tex2D(); + //Log.d("updateTexture - new texture ", _texture.ID); + if (!_texture.ID) return; } - //Log.d("updateTexture for font glyph page - setting image ", _drawbuf.width, "x", _drawbuf.height, " tx=", _textureId); + //Log.d("updateTexture for font glyph page - setting image ", _drawbuf.width, "x", _drawbuf.height, " tx=", _texture.ID); int len = _drawbuf.width * _drawbuf.height; - if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte *)_drawbuf.scanLine(0))) { - glSupport.deleteTexture(_textureId); - _textureId = 0; + if (!glSupport.setTextureImage(_texture, _drawbuf.width, _drawbuf.height, cast(ubyte *)_drawbuf.scanLine(0))) { + destroy(_texture); + _texture = null; return; } _needUpdateTexture = false; @@ -724,11 +720,7 @@ private class GLGlyphCache { //CRLog::trace("drawing item at %d,%d %dx%d <= %d,%d %dx%d ", x, y, dx, dy, srcx, srcy, srcdx, srcdy); if (_needUpdateTexture) updateTexture(); - if (_textureId != 0) { - if (!glSupport.isTexture(_textureId)) { - Log.e("Invalid texture ", _textureId); - return; - } + if (_texture.ID != 0) { // convert coordinates to cached texture srcrc.offset(item._rc.left, item._rc.top); if (clip) { @@ -751,8 +743,8 @@ private class GLGlyphCache { } if (!dstrc.empty) { //Log.d("drawing glyph with color ", color); - glSupport.drawColorAndTextureGlyphRect(_textureId, _tdx, _tdy, srcrc, dstrc, color); - //glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); + glSupport.drawColorAndTextureGlyphRect(_texture, _tdx, _tdy, srcrc, dstrc, color); + //glSupport.drawColorAndTextureRect(_texture, _tdx, _tdy, srcrc, dstrc, color, false); } } @@ -782,7 +774,7 @@ private class GLGlyphCache { private void updateTextureSize() { if (!tdx) { // TODO - tdx = tdy = 1024; //getMaxTextureSize(); + tdx = tdy = 1024; //getMaxTextureSize(); if (tdx > 1024) tdx = tdy = 1024; } diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index f194f491..a0be22fd 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -31,12 +31,12 @@ import std.array; derelict.util.exception.ShouldThrow gl3MissingSymFunc( string symName ) { import std.algorithm : equal; - foreach(s; ["glGetError", "glShaderSource", "glCompileShader", - "glGetShaderiv", "glGetShaderInfoLog", "glGetString", - "glCreateProgram", "glUseProgram", "glDeleteProgram", - "glDeleteShader", "glEnable", "glDisable", "glBlendFunc", - "glUniformMatrix4fv", "glGetAttribLocation", "glGetUniformLocation", - "glGenVertexArrays", "glBindVertexArray", "glBufferData", + foreach(s; ["glGetError", "glShaderSource", "glCompileShader", + "glGetShaderiv", "glGetShaderInfoLog", "glGetString", + "glCreateProgram", "glUseProgram", "glDeleteProgram", + "glDeleteShader", "glEnable", "glDisable", "glBlendFunc", + "glUniformMatrix4fv", "glGetAttribLocation", "glGetUniformLocation", + "glGenVertexArrays", "glBindVertexArray", "glBufferData", "glBindBuffer", "glBufferSubData"]) { if (symName.equal(s)) // Symbol is used return derelict.util.exception.ShouldThrow.Yes; @@ -74,7 +74,7 @@ static this() { 0x0507: "GL_CONTEXT_LOST" ]; } -/** +/** * Convenient wrapper around glGetError() * TODO use one of the DEBUG extensions instead */ @@ -103,7 +103,7 @@ class GLProgram { protected char[] glslversionString; this() { } - + private void compatibilityFixes(ref char[] code, GLuint type) { if (glslversionInt < 150) { code = replace(code, " texture(", " texture2D("); @@ -111,7 +111,7 @@ class GLProgram { code = replace(code, "out ", ""); } } - + private GLuint compileShader(string src, GLuint type) { import core.stdc.stdlib; import std.string; @@ -122,7 +122,7 @@ class GLProgram { sourceCode ~= "\n"; sourceCode ~= src; compatibilityFixes(sourceCode, type); - + Log.d("compileShader glsl=", glslversion, " type:", (type == GL_VERTEX_SHADER ? "GL_VERTEX_SHADER" : (type == GL_FRAGMENT_SHADER ? "GL_FRAGMENT_SHADER" : "UNKNOWN")), " code:\n", sourceCode); GLuint shader = glCreateShader(type); const char * psrc = sourceCode.toStringz; @@ -134,15 +134,15 @@ class GLProgram { // compiled successfully return shader; } else { - GLint blen = 0; + GLint blen = 0; GLsizei slen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH , &blen); + glGetShaderiv(shader, GL_INFO_LOG_LENGTH , &blen); if (blen > 1) { GLchar[] msg = new GLchar[blen + 1]; glGetShaderInfoLog(shader, blen, &slen, msg.ptr); Log.d("Shader compilation error: ", fromStringz(msg.ptr)); - } + } return 0; } } @@ -260,12 +260,22 @@ class SolidFillProgram : GLProgram { }; } + bool check() + { + if (error) + return false; + if (!initialized) + if (!compile()) + return false; + return true; + } + void beforeExecute() { glEnable(GL_BLEND); glDisable(GL_CULL_FACE); checkError("glDisable(GL_CULL_FACE)"); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); checkError("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)"); bind(); //glUniformMatrix4fv(matrixLocation, 1, false, m.value_ptr); @@ -281,18 +291,9 @@ class SolidFillProgram : GLProgram { protected GLint matrixLocation; protected GLint vertexLocation; protected GLint colAttrLocation; - protected GLuint vertexBuffer; - protected GLuint colAttrBuffer; override bool initLocations() { bool res = super.initLocations(); - //glGenBuffers(1, &vertexBuffer); - //glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - //glBufferData(GL_ARRAY_BUFFER, float.sizeof * 3 * 6, null, GL_DYNAMIC_DRAW); - //glGenBuffers(1, &colAttrBuffer); - //glBindBuffer(GL_ARRAY_BUFFER, colAttrBuffer); - //glBufferData(GL_ARRAY_BUFFER, float.sizeof * 4 * 6, null, GL_DYNAMIC_DRAW); - matrixLocation = glGetUniformLocation(program, "matrix"); checkError("glGetUniformLocation matrix"); if (matrixLocation == -1) @@ -309,121 +310,62 @@ class SolidFillProgram : GLProgram { } bool execute(float[] vertices, float[] colors) { - if (error) + if(!check()) return false; - if (!initialized) - if (!compile()) - return false; beforeExecute(); - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + VAO vao = new VAO(); - GLuint vbo; - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof, - null, - GL_STREAM_DRAW); - glBufferSubData( - GL_ARRAY_BUFFER, - 0, - vertices.length * vertices[0].sizeof, - vertices.ptr); - glBufferSubData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof, - colors.length * colors[0].sizeof, colors.ptr); + VBO vbo = new VBO(); + vbo.fill([vertices, colors]); + + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); + glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof)); glEnableVertexAttribArray(vertexLocation); - checkError("glEnableVertexAttribArray"); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); - checkError("glVertexAttribPointer"); - glEnableVertexAttribArray(colAttrLocation); - checkError("glEnableVertexAttribArray"); - glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (float.sizeof*3*6)); - checkError("glVertexAttribPointer"); - glDrawArrays(GL_TRIANGLES, 0, 6); + glDrawArrays(GL_TRIANGLES, 0, cast(int)vertices.length/3); checkError("glDrawArrays"); glDisableVertexAttribArray(vertexLocation); - checkError("glDisableVertexAttribArray"); glDisableVertexAttribArray(colAttrLocation); - checkError("glDisableVertexAttribArray"); afterExecute(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &vbo); - - glBindVertexArray(0); - glDeleteVertexArrays(1, &vao); + destroy(vbo); + destroy(vao); return true; } } class LineProgram : SolidFillProgram { override bool execute(float[] vertices, float[] colors) { - if (error) + if(!check()) return false; - if (!initialized) - if (!compile()) - return false; beforeExecute(); - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + VAO vao = new VAO(); - GLuint vbo; - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof, - null, - GL_STREAM_DRAW); - glBufferSubData( - GL_ARRAY_BUFFER, - 0, - vertices.length * vertices[0].sizeof, - vertices.ptr); - glBufferSubData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof, - colors.length * colors[0].sizeof, - colors.ptr); + VBO vbo = new VBO(); + vbo.fill([vertices, colors]); + + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); + glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof)); glEnableVertexAttribArray(vertexLocation); - checkError("glEnableVertexAttribArray"); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); - checkError("glVertexAttribPointer"); - glEnableVertexAttribArray(colAttrLocation); - checkError("glEnableVertexAttribArray"); - glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (float.sizeof*3*2)); - checkError("glVertexAttribPointer"); - glDrawArrays(GL_LINES, 0, 2); + glDrawArrays(GL_LINES, 0, cast(int)vertices.length/3); checkError("glDrawArrays"); glDisableVertexAttribArray(vertexLocation); - checkError("glDisableVertexAttribArray"); glDisableVertexAttribArray(colAttrLocation); - checkError("glDisableVertexAttribArray"); afterExecute(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &vbo); - - glBindVertexArray(0); - glDeleteVertexArrays(1, &vao); + destroy(vbo); + destroy(vao); return true; } } @@ -466,61 +408,28 @@ class TextureProgram : SolidFillProgram { return res && texCoordLocation >= 0; } - bool execute(float[] vertices, float[] texcoords, float[] colors, uint textureId, bool linear) { - if (error) + bool execute(float[] vertices, float[] texcoords, float[] colors, Tex2D texture, bool linear) { + if(!check()) return false; - if (!initialized) - if (!compile()) - return false; beforeExecute(); - glActiveTexture(GL_TEXTURE0); - checkError("glActiveTexture GL_TEXTURE0"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("glBindTexture"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + texture.setup(); + texture.setSamplerParams(linear); - GLuint vbo; - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof + - colors.length * colors[0].sizeof + - texcoords.length * texcoords[0].sizeof, - null, - GL_STREAM_DRAW); - glBufferSubData( - GL_ARRAY_BUFFER, - 0, - vertices.length * vertices[0].sizeof, - vertices.ptr); - glBufferSubData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof, - colors.length * colors[0].sizeof, - colors.ptr); - glBufferSubData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof, - texcoords.length * texcoords[0].sizeof, - texcoords.ptr); + VAO vao = new VAO(); - glEnableVertexAttribArray(vertexLocation); - glEnableVertexAttribArray(colAttrLocation); - glEnableVertexAttribArray(texCoordLocation); + VBO vbo = new VBO(); + vbo.fill([vertices, colors, texcoords]); glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof)); glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof)); - glDrawArrays(GL_TRIANGLES, 0, 6); + glEnableVertexAttribArray(vertexLocation); + glEnableVertexAttribArray(colAttrLocation); + glEnableVertexAttribArray(texCoordLocation); + + glDrawArrays(GL_TRIANGLES, 0, cast(int)vertices.length/3); checkError("glDrawArrays"); glDisableVertexAttribArray(vertexLocation); @@ -529,14 +438,10 @@ class TextureProgram : SolidFillProgram { afterExecute(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &vbo); + destroy(vbo); + destroy(vao); - glBindVertexArray(0); - glDeleteVertexArrays(1, &vao); - - glBindTexture(GL_TEXTURE_2D, 0); - checkError("glBindTexture"); + texture.unbind(); return true; } } @@ -599,61 +504,28 @@ class FontProgram : SolidFillProgram { super.afterExecute(); } - bool execute(float[] vertices, float[] texcoords, float[] colors, uint textureId, bool linear) { - if (error) + bool execute(float[] vertices, float[] texcoords, float[] colors, Tex2D texture, bool linear) { + if(!check()) return false; - if (!initialized) - if (!compile()) - return false; beforeExecute(); - glActiveTexture(GL_TEXTURE0); - checkError("glActiveTexture GL_TEXTURE0"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("glBindTexture"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + texture.setup(); + texture.setSamplerParams(linear); - GLuint vbo; - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof + - colors.length * colors[0].sizeof + - texcoords.length * texcoords[0].sizeof, - null, - GL_STREAM_DRAW); - glBufferSubData( - GL_ARRAY_BUFFER, - 0, - vertices.length * vertices[0].sizeof, - vertices.ptr); - glBufferSubData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof, - colors.length * colors[0].sizeof, - colors.ptr); - glBufferSubData( - GL_ARRAY_BUFFER, - vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof, - texcoords.length * texcoords[0].sizeof, - texcoords.ptr); + VAO vao = new VAO(); - glEnableVertexAttribArray(vertexLocation); - glEnableVertexAttribArray(colAttrLocation); - glEnableVertexAttribArray(texCoordLocation); + VBO vbo = new VBO(); + vbo.fill([vertices, colors, texcoords]); glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof)); glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof)); - glDrawArrays(GL_TRIANGLES, 0, 6); + glEnableVertexAttribArray(vertexLocation); + glEnableVertexAttribArray(colAttrLocation); + glEnableVertexAttribArray(texCoordLocation); + + glDrawArrays(GL_TRIANGLES, 0, cast(int)vertices.length/3); checkError("glDrawArrays"); glDisableVertexAttribArray(vertexLocation); @@ -662,14 +534,10 @@ class FontProgram : SolidFillProgram { afterExecute(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &vbo); + destroy(vbo); + destroy(vao); - glBindVertexArray(0); - glDeleteVertexArrays(1, &vao); - - glBindTexture(GL_TEXTURE_2D, 0); - checkError("glBindTexture"); + texture.unbind(); return true; } } @@ -754,10 +622,6 @@ class GLSupport { return true; } - bool isTexture(uint textureId) { - return glIsTexture(textureId) == GL_TRUE; - } - void setRotation(int x, int y, int rotationAngle) { /* this->rotationAngle = rotationAngle; @@ -788,7 +652,7 @@ class GLSupport { float y1 = cast(float)(bufferDy-p2.y); // don't flip for framebuffer - if (currentFramebufferId) { + if (currentFBO) { y0 = cast(float)(p1.y); y1 = cast(float)(p2.y); } @@ -819,7 +683,7 @@ class GLSupport { float y1 = cast(float)(bufferDy-rc.bottom); // don't flip for framebuffer - if (currentFramebufferId) { + if (currentFBO) { y0 = cast(float)(rc.top); y1 = cast(float)(rc.bottom); } @@ -847,10 +711,10 @@ class GLSupport { checkError("glVertexPointer(3, GL_FLOAT, 0, vertices)"); glColorPointer(4, GL_FLOAT, 0, cast(void*)colors); checkError("glColorPointer(4, GL_FLOAT, 0, colors)"); - + glDrawArrays(GL_TRIANGLES, 0, 6); checkError("glDrawArrays(GL_TRIANGLES, 0, 6)"); - + glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_ALPHA_TEST); @@ -864,12 +728,12 @@ class GLSupport { } } - void drawColorAndTextureGlyphRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color) { - //Log.v("drawColorAndGlyphRect tx=", textureId, " src=", srcrc, " dst=", dstrc); - drawColorAndTextureGlyphRect(textureId, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color); + void drawColorAndTextureGlyphRect(Tex2D texture, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color) { + //Log.v("drawColorAndGlyphRect tx=", texture.ID, " src=", srcrc, " dst=", dstrc); + drawColorAndTextureGlyphRect(texture, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color); } - void drawColorAndTextureGlyphRect(uint textureId, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color) { + void drawColorAndTextureGlyphRect(Tex2D texture, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color) { float[6*4] colors; LVGLFillColor(color, colors.ptr, 6); float dstx0 = cast(float)xx; @@ -878,7 +742,7 @@ class GLSupport { float dsty1 = cast(float)(bufferDy - (yy + dy)); // don't flip for framebuffer - if (currentFramebufferId) { + if (currentFBO) { dsty0 = cast(float)((yy)); dsty1 = cast(float)((yy + dy)); } @@ -887,7 +751,7 @@ class GLSupport { float srcy0 = srcy / cast(float)tdy; float srcx1 = (srcx + srcdx) / cast(float)tdx; float srcy1 = (srcy + srcdy) / cast(float)tdy; - float[3 * 6] vertices = + float[3 * 6] vertices = [dstx0, dsty0, Z_2D, dstx0, dsty1, Z_2D, dstx1, dsty1, Z_2D, @@ -899,24 +763,17 @@ class GLSupport { if (_legacyMode) { bool linear = dx != srcdx || dy != srcdy; glDisable(GL_CULL_FACE); - glActiveTexture(GL_TEXTURE0); - checkError("glActiveTexture"); glEnable(GL_TEXTURE_2D); - checkError("glEnable(GL_TEXTURE_2D)"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("glBindTexture"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - + texture.setup(); + texture.setSamplerParams(linear); + glColor4f(1,1,1,1); glDisable(GL_ALPHA_TEST); - + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkError("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)"); - + glEnableClientState(GL_COLOR_ARRAY); checkError("glEnableClientState(GL_COLOR_ARRAY)"); glEnableClientState(GL_VERTEX_ARRAY); @@ -929,10 +786,10 @@ class GLSupport { checkError("glTexCoordPointer(2, GL_FLOAT, 0, texcoords)"); glColorPointer(4, GL_FLOAT, 0, cast(void*)colors.ptr); checkError("glColorPointer(4, GL_FLOAT, 0, colors)"); - + glDrawArrays(GL_TRIANGLES, 0, 6); checkError("glDrawArrays"); - + glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); @@ -940,17 +797,17 @@ class GLSupport { glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); } else { - _fontProgram.execute(vertices, texcoords, colors, textureId, false); + _fontProgram.execute(vertices, texcoords, colors, texture, false); } - //drawColorAndTextureRect(vertices, texcoords, colors, textureId, linear); + //drawColorAndTextureRect(vertices, texcoords, colors, texture, linear); } - 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(Tex2D texture, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) { + //Log.v("drawColorAndTextureRect tx=", texture.ID, " src=", srcrc, " dst=", dstrc); + drawColorAndTextureRect(texture, 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) { + void drawColorAndTextureRect(Tex2D texture, 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; @@ -959,7 +816,7 @@ class GLSupport { float dsty1 = cast(float)(bufferDy - (yy + dy)); // don't flip for framebuffer - if (currentFramebufferId) { + if (currentFBO) { dsty0 = cast(float)((yy)); dsty1 = cast(float)((yy + dy)); } @@ -978,24 +835,17 @@ class GLSupport { if (_legacyMode) { glDisable(GL_CULL_FACE); - glActiveTexture(GL_TEXTURE0); - checkError("glActiveTexture"); glEnable(GL_TEXTURE_2D); - checkError("glEnable(GL_TEXTURE_2D)"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("glBindTexture"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); - checkError("drawColorAndTextureRect - glTexParameteri"); - + texture.setup(); + texture.setSamplerParams(linear); + glColor4f(1,1,1,1); glDisable(GL_ALPHA_TEST); - + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkError("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)"); - + glEnableClientState(GL_COLOR_ARRAY); checkError("glEnableClientState(GL_COLOR_ARRAY)"); glEnableClientState(GL_VERTEX_ARRAY); @@ -1008,10 +858,10 @@ class GLSupport { checkError("glTexCoordPointer(2, GL_FLOAT, 0, texcoords)"); glColorPointer(4, GL_FLOAT, 0, cast(void*)colors.ptr); checkError("glColorPointer(4, GL_FLOAT, 0, colors)"); - + glDrawArrays(GL_TRIANGLES, 0, 6); checkError("glDrawArrays"); - + glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); @@ -1019,30 +869,9 @@ class GLSupport { glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); } else { - _textureProgram.execute(vertices, texcoords, colors, textureId, linear); + _textureProgram.execute(vertices, texcoords, colors, texture, 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; + //drawColorAndTextureRect(vertices, texcoords, colors, texture, linear); } /// call glFlush @@ -1051,32 +880,16 @@ class GLSupport { checkError("glFlush"); } - bool setTextureImage(uint textureId, int dx, int dy, ubyte * pixels) { + bool setTextureImage(Tex2D texture, 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"); + texture.setup(); 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"); + texture.setSamplerParams(true, true); // 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) { + if (checkError("updateTexture - glTexImage2D")) { Log.e("Cannot set image for texture"); return false; } @@ -1084,72 +897,44 @@ class GLSupport { return true; } - bool setTextureImageAlpha(uint textureId, int dx, int dy, ubyte * pixels) { + bool setTextureImageAlpha(Tex2D texture, 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"); + texture.setup(); 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"); + texture.setSamplerParams(true, true); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, dx, dy, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); - checkError("setTextureImageAlpha - glTexImage2D"); - if (glGetError() != GL_NO_ERROR) { + if (checkError("setTextureImageAlpha - glTexImage2D")) { Log.e("Cannot set image for texture"); return false; } - glBindTexture(GL_TEXTURE_2D, 0); - checkError("updateTexture - glBindTexture(0)"); + texture.unbind(); checkError("after setTextureImageAlpha"); return true; } - private uint currentFramebufferId; + private FBO currentFBO; - /// returns texture ID for buffer, 0 if failed - bool createFramebuffer(ref uint textureId, ref uint framebufferId, int dx, int dy) { + /// returns texture for buffer, null if failed + bool createFramebuffer(out Tex2D texture, out FBO fbo, int dx, int dy) { checkError("before createFramebuffer"); bool res = true; - textureId = framebufferId = 0; - textureId = genTexture(); - if (!textureId) + texture = new Tex2D(); + if (!texture.ID) 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; + checkError("glBindTexture GL_TEXTURE_2D"); + FBO f = new FBO(); + if (!f.ID) + return false; + fbo = f; - 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"); + texture.setSamplerParams(true, true); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.ID, 0); checkError("glFramebufferTexture2D"); // Always check that our framebuffer is ok if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { @@ -1164,35 +949,26 @@ class GLSupport { checkError("glClear"); checkError("after createFramebuffer"); //CRLog::trace("CRGLSupportImpl::createFramebuffer %d,%d texture=%d, buffer=%d", dx, dy, textureId, framebufferId); - currentFramebufferId = framebufferId; + currentFBO = fbo; - glBindTexture(GL_TEXTURE_2D, 0); - checkError("createFramebuffer - glBindTexture(0)"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - checkError("createFramebuffer - glBindFramebuffer(0)"); + texture.unbind(); + fbo.unbind(); return res; } - void deleteFramebuffer(ref uint framebufferId) { + void deleteFramebuffer(ref FBO fbo) { //CRLog::debug("GLDrawBuf::deleteFramebuffer"); - if (framebufferId != 0) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - checkError("deleteFramebuffer - glBindFramebuffer"); - GLuint fid = framebufferId; - glDeleteFramebuffers(1, &fid); - checkError("deleteFramebuffer - glDeleteFramebuffer"); + if (fbo.ID != 0) { + destroy(fbo); } - //CRLog::trace("CRGLSupportImpl::deleteFramebuffer(%d)", framebufferId); - framebufferId = 0; - checkError("after deleteFramebuffer"); - currentFramebufferId = 0; + currentFBO = null; } - bool bindFramebuffer(uint framebufferId) { + bool bindFramebuffer(FBO fbo) { //CRLog::trace("CRGLSupportImpl::bindFramebuffer(%d)", framebufferId); - glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); - currentFramebufferId = framebufferId; + fbo.bind(); + currentFBO = fbo; return !checkError("glBindFramebuffer"); } @@ -1301,3 +1077,83 @@ class GLSupport { } } + +enum GLObjectTypes { Buffer, VertexArray, Texture, Framebuffer }; +class GLObject(GLObjectTypes type, GLuint target = 0) { + @property auto ID() const { return id; } + //alias ID this; // good, but it confuses destroy() + + private GLuint id; + + this() { + mixin("glGen" ~ to!string(type) ~ "s(1, &id);"); + checkError("glGen" ~ to!string(type)); + bind(); + } + + ~this() { + unbind(); + mixin("glDelete" ~ to!string(type) ~ "s(1, &id);"); + checkError("glDelete" ~ to!string(type)); + } + + void bind() { + static if(target != 0) + mixin("glBind" ~ to!string(type) ~ "(" ~ to!string(target) ~ ", id);"); + else + mixin("glBind" ~ to!string(type) ~ "(id);"); + } + + void unbind() { + static if(target != 0) + mixin("glBind" ~ to!string(type) ~ "(" ~ to!string(target) ~ ", 0);"); + else + mixin("glBind" ~ to!string(type) ~ "(0);"); + checkError("unbind " ~ to!string(type)); + } + + static if(type == GLObjectTypes.Buffer) + { + void fill(float[][] buffs) { + int length; + foreach(b; buffs) + length += b.length; + glBufferData(target, + length * float.sizeof, + null, + GL_STREAM_DRAW); + int offset; + foreach(b; buffs) { + glBufferSubData(target, + offset, + b.length * float.sizeof, + b.ptr); + offset += b.length * float.sizeof; + } + } + } + + static if(type == GLObjectTypes.Texture) + { + void setSamplerParams(bool linear, bool clamp = false) { + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); + checkError("filtering - glTexParameteri"); + if(clamp) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkError("clamp - glTexParameteri"); + } + } + + void setup(GLuint binding = 0) { + glActiveTexture(GL_TEXTURE0 + binding); + glBindTexture(target, id); + checkError("setup texture"); + } + } +} +alias VAO = GLObject!(GLObjectTypes.VertexArray); +alias VBO = GLObject!(GLObjectTypes.Buffer, GL_ARRAY_BUFFER); +alias Tex2D = GLObject!(GLObjectTypes.Texture, GL_TEXTURE_2D); +alias FBO = GLObject!(GLObjectTypes.Framebuffer, GL_FRAMEBUFFER);