diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d index a0659a70..3b944750 100644 --- a/src/dlangui/graphics/gldrawbuf.d +++ b/src/dlangui/graphics/gldrawbuf.d @@ -71,12 +71,14 @@ class GLDrawBuf : DrawBuf, GLConfigCallback { _scene.reset(); } _scene = new Scene(this); + glSupport.prepareShaders(); } /// reserved for hardware-accelerated drawing - ends drawing batch override void afterDrawing() { glSupport.setOrthoProjection(Rect(0, 0, _dx, _dy), Rect(0, 0, _dx, _dy)); _scene.draw(); + GLProgram.unbind(); glSupport.flushGL(); destroy(_scene); _scene = null; diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index bba31a18..2fd1fc0f 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -220,14 +220,19 @@ class GLProgram { return true; } + static GLuint currentProgram; /// binds program to current context void bind() { - checkgl!glUseProgram(program); + if(program != currentProgram) { + checkgl!glUseProgram(program); + currentProgram = program; + } } /// unbinds program from current context - void unbind() { + static void unbind() { checkgl!glUseProgram(0); + currentProgram = 0; } /// get uniform location from program, returns -1 if location is not found @@ -274,18 +279,6 @@ class SolidFillProgram : GLProgram { }; } - void beforeExecute() { - glEnable(GL_BLEND); - checkgl!glDisable(GL_CULL_FACE); - checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - bind(); - checkgl!glUniformMatrix4fv(matrixLocation, 1, false, glSupport.projectionMatrix.m.ptr); - } - - void afterExecute() { - unbind(); - } - protected GLint matrixLocation; protected GLint vertexLocation; protected GLint colAttrLocation; @@ -296,28 +289,49 @@ class SolidFillProgram : GLProgram { return matrixLocation >= 0 && vertexLocation >= 0 && colAttrLocation >= 0; } + VAO vao; + VBO vbo; + bool needToCreateVAO = true; + void createVAO(float[] vertices, float[] colors) { + if(vao) + destroy(vao); + vao = new VAO; + + if(vbo) + destroy(vbo); + vbo = new VBO; + + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); + glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * float.sizeof)); + + glEnableVertexAttribArray(vertexLocation); + glEnableVertexAttribArray(colAttrLocation); + + needToCreateVAO = false; + } + + void beforeExecute() { + glEnable(GL_BLEND); + checkgl!glDisable(GL_CULL_FACE); + checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + bind(); + checkgl!glUniformMatrix4fv(matrixLocation, 1, false, glSupport.projectionMatrix.m.ptr); + } + bool execute(float[] vertices, float[] colors) { if(!check()) return false; beforeExecute(); - VAO vao = new VAO(); + if(needToCreateVAO) + createVAO(vertices, colors); - VBO vbo = new VBO(); + vbo.bind(); 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); - glEnableVertexAttribArray(colAttrLocation); - - checkgl!glDrawArrays(GL_TRIANGLES, 0, cast(int)vertices.length/3); - - afterExecute(); - - destroy(vbo); - destroy(vao); + vao.bind(); + checkgl!glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + vao.unbind(); return true; } } @@ -328,23 +342,15 @@ class LineProgram : SolidFillProgram { return false; beforeExecute(); - VAO vao = new VAO(); + if(needToCreateVAO) + createVAO(vertices, colors); - VBO vbo = new VBO(); + vbo.bind(); 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); - glEnableVertexAttribArray(colAttrLocation); - - checkgl!glDrawArrays(GL_LINES, 0, cast(int)vertices.length/3); - - afterExecute(); - - destroy(vbo); - destroy(vao); + vao.bind(); + checkgl!glDrawArrays(GL_LINES, 0, 2); + vao.unbind(); return true; } } @@ -387,6 +393,26 @@ class TextureProgram : SolidFillProgram { return res && texCoordLocation >= 0; } + void createVAO(float[] vertices, float[] colors, float[] texcoords) { + if(vao) + destroy(vao); + vao = new VAO; + + if(vbo) + destroy(vbo); + vbo = new VBO; + + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0); + glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * float.sizeof)); + glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) ((vertices.length + colors.length) * float.sizeof)); + + glEnableVertexAttribArray(vertexLocation); + glEnableVertexAttribArray(colAttrLocation); + glEnableVertexAttribArray(texCoordLocation); + + needToCreateVAO = false; + } + bool execute(float[] vertices, float[] colors, float[] texcoords, Tex2D texture, bool linear) { if(!check()) return false; @@ -395,29 +421,15 @@ class TextureProgram : SolidFillProgram { texture.setup(); texture.setSamplerParams(linear); - VAO vao = new VAO(); + if(needToCreateVAO) + createVAO(vertices, colors, texcoords); - VBO vbo = new VBO(); + vbo.bind(); 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)); - - glEnableVertexAttribArray(vertexLocation); - glEnableVertexAttribArray(colAttrLocation); - glEnableVertexAttribArray(texCoordLocation); - - checkgl!glDrawArrays(GL_TRIANGLES, 0, cast(int)vertices.length/3); - - glDisableVertexAttribArray(vertexLocation); - glDisableVertexAttribArray(colAttrLocation); - glDisableVertexAttribArray(texCoordLocation); - - afterExecute(); - - destroy(vbo); - destroy(vao); + vao.bind(); + checkgl!glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + vao.unbind(); texture.unbind(); return true; @@ -587,6 +599,12 @@ class GLSupport { return true; } + void prepareShaders() { + _solidFillProgram.needToCreateVAO = true; + _lineProgram.needToCreateVAO = true; + _textureProgram.needToCreateVAO = true; + } + void setRotation(int x, int y, int rotationAngle) { /* this->rotationAngle = rotationAngle; @@ -634,13 +652,11 @@ class GLSupport { static immutable float Z_2D = -2.0f; void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) { - Color[6] colors; + Color[4] colors; FillColor(color1, colors[0..1]); - FillColor(color4, colors[1..2]); + FillColor(color2, colors[1..2]); FillColor(color3, colors[2..3]); - FillColor(color1, colors[3..4]); - FillColor(color3, colors[4..5]); - FillColor(color2, colors[5..6]); + FillColor(color4, colors[3..4]); float x0 = cast(float)(rc.left); float y0 = cast(float)(bufferDy-rc.top); float x1 = cast(float)(rc.right); @@ -652,13 +668,11 @@ class GLSupport { y1 = cast(float)(rc.bottom); } - float[3 * 6] vertices = [ + float[3 * 4] 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]; + x1,y0,Z_2D, + x1,y1,Z_2D]; if (_legacyMode) { glColor4f(1,1,1,1); @@ -671,7 +685,7 @@ class GLSupport { checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)vertices.ptr); checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)colors); - checkgl!glDrawArrays(GL_TRIANGLES, 0, 6); + checkgl!glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); @@ -690,7 +704,7 @@ class GLSupport { } 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) { - Color[6] colors; + Color[4] colors; FillColor(color, colors); float dstx0 = cast(float)xx; float dsty0 = cast(float)(bufferDy - (yy)); @@ -707,14 +721,12 @@ 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 * 4] 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]; + dstx1,dsty0,Z_2D, + dstx1,dsty1,Z_2D]; + float[2 * 4] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy0, srcx1,srcy1]; if (_legacyMode) { glDisable(GL_CULL_FACE); @@ -735,7 +747,7 @@ class GLSupport { checkgl!glTexCoordPointer(2, GL_FLOAT, 0, cast(void*)texcoords.ptr); checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)colors.ptr); - checkgl!glDrawArrays(GL_TRIANGLES, 0, 6); + checkgl!glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d index ce07ca73..c2471251 100644 --- a/src/dlangui/platforms/sdl/sdlapp.d +++ b/src/dlangui/platforms/sdl/sdlapp.d @@ -47,7 +47,7 @@ static if (ENABLE_OPENGL) { import dlangui.graphics.gldrawbuf; import dlangui.graphics.glsupport; } - + private derelict.util.exception.ShouldThrow missingSymFunc( string symName ) { import std.algorithm : equal; foreach(s; ["SDL_DestroyRenderer", "SDL_GL_DeleteContext", "SDL_DestroyWindow", "SDL_PushEvent", @@ -114,16 +114,16 @@ class SDLWindow : Window { } - static if (ENABLE_OPENGL) { + static if (ENABLE_OPENGL) + { static private bool _gl3Reloaded = false; private SDL_GLContext _context; - } - static if (ENABLE_OPENGL) { protected bool createContext(int versionMajor, int versionMinor) { Log.i("Trying to create OpenGL ", versionMajor, ".", versionMinor, " context"); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, versionMajor); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, versionMinor); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); _context = SDL_GL_CreateContext(_win); // Create the actual context and make it current if (!_context) Log.e("SDL_GL_CreateContext failed: ", fromStringz(SDL_GetError())); @@ -176,9 +176,7 @@ class SDLWindow : Window { static if (ENABLE_OPENGL) { if (_enableOpengl) { - Log.i("Trying to create OpenGL 3.2 context"); createContext(3, 2); - //_context = SDL_GL_CreateContext(_win); // Create the actual context and make it current if (!_context) { Log.e("SDL_GL_CreateContext failed: ", fromStringz(SDL_GetError())); Log.w("trying other versions of OpenGL"); @@ -237,7 +235,7 @@ class SDLWindow : Window { return SDL_GetWindowID(_win); return 0; } - + override void show() { Log.d("SDLWindow.show()"); if (_mainWidget && !(_flags & WindowFlag.Resizable)) { @@ -453,7 +451,7 @@ class SDLWindow : Window { SDL_RenderPresent(_renderer); } } - + ColorDrawBuf _drawbuf; //bool _exposeSent; @@ -743,7 +741,7 @@ class SDLWindow : Window { return 0x10000 | keyCode; } } - + uint convertKeyFlags(uint flags) { uint res; if (flags & KMOD_CTRL) @@ -766,7 +764,7 @@ class SDLWindow : Window { res |= KeyFlag.LAlt | KeyFlag.Alt; return res; } - + bool processTextInput(const char * s) { string str = fromStringz(s).dup; dstring ds = toUTF32(str); @@ -838,7 +836,7 @@ class SDLWindow : Window { override void invalidate() { _platform.sendRedrawEvent(windowId, ++_lastRedrawEventCode); } - + void processRedrawEvent(uint code) { if (code == _lastRedrawEventCode) redraw(); @@ -887,23 +885,16 @@ private __gshared bool _enableOpengl; class SDLPlatform : Platform { this() { - } + + private SDLWindow[uint] _windowMap; + ~this() { foreach(ref SDLWindow wnd; _windowMap) { destroy(wnd); wnd = null; } destroy(_windowMap); - disconnect(); - } - void disconnect() { - /* Cleanup */ - } - bool connect() { - - - return true; } SDLWindow getWindow(uint id) { @@ -944,7 +935,6 @@ class SDLPlatform : Platform { event.user.windowID = windowId; event.user.code = code; SDL_PushEvent(&event); - } override Window createWindow(dstring windowCaption, Window parent, uint flags = WindowFlag.Resizable, uint width = 0, uint height = 0) { @@ -982,8 +972,6 @@ class SDLPlatform : Platform { bool skipNextQuit = false; while(!quit) { //redrawWindows(); - - //if (SDL_PollEvent(&event)) { if (SDL_WaitEvent(&event)) { //Log.d("Event.type = ", event.type); @@ -1150,9 +1138,7 @@ class SDLPlatform : Platform { } _windowToClose = null; } - // if (_windowMap.length == 0) { - //quit = true; SDL_Quit(); quit = true; } @@ -1161,7 +1147,7 @@ class SDLPlatform : Platform { Log.i("exiting message loop"); return 0; } - + /// retrieves text from clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) override dstring getClipboardText(bool mouseBuffer = false) { if (!SDL_HasClipboardText()) @@ -1173,14 +1159,12 @@ class SDLPlatform : Platform { SDL_free(txt); return toUTF32(s); } - + /// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) override void setClipboardText(dstring text, bool mouseBuffer = false) { string s = toUTF8(text); SDL_SetClipboardText(s.toStringz); } - - protected SDLWindow[uint] _windowMap; } version (Windows) { @@ -1321,13 +1305,9 @@ int sdlmain(string[] args) { USER_EVENT_ID = SDL_RegisterEvents(1); TIMER_EVENT_ID = SDL_RegisterEvents(1); - int request = SDL_GetDesktopDisplayMode(0,&displayMode); + int request = SDL_GetDesktopDisplayMode(0, &displayMode); static if (ENABLE_OPENGL) { - // we want OpenGL 3.2 - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // Set OpenGL attributes SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); @@ -1335,10 +1315,7 @@ int sdlmain(string[] args) { SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); } - SDLPlatform sdl = new SDLPlatform(); - if (!sdl.connect()) { - return 1; - } + auto sdl = new SDLPlatform; Platform.setInstance(sdl); diff --git a/src/dlangui/platforms/x11/x11app.d b/src/dlangui/platforms/x11/x11app.d index bd252e0f..4f987046 100644 --- a/src/dlangui/platforms/x11/x11app.d +++ b/src/dlangui/platforms/x11/x11app.d @@ -966,7 +966,7 @@ class X11Platform : Platform { this() { } - X11Window[XWindow] _windowMap; + private X11Window[XWindow] _windowMap; /** * create window