diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index a03ac5005..70cc52396 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -424,6 +424,49 @@ void Graphics::clear(Color c) glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } +void Graphics::discard(bool color, bool stencil) +{ + if (!(GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_ES_VERSION_3_0 || GLAD_EXT_discard_framebuffer)) + return; + + std::vector attachments; + attachments.reserve(3); + + // glDiscardFramebuffer uses different attachment enums for the default FBO. + if (!Canvas::current && gl.getDefaultFBO() == 0) + { + if (color) + attachments.push_back(GL_COLOR); + + if (stencil) + { + attachments.push_back(GL_STENCIL); + attachments.push_back(GL_DEPTH); + } + } + else + { + if (color) + { + attachments.push_back(GL_COLOR_ATTACHMENT0); + for (int i = 0; i < (int) states.back().canvases.size() - 1; i++) + attachments.push_back(GL_COLOR_ATTACHMENT1 + i); + } + + if (stencil) + { + attachments.push_back(GL_STENCIL_ATTACHMENT); + attachments.push_back(GL_DEPTH_ATTACHMENT); + } + } + + // Hint for the driver that it doesn't need to save these buffers. + if (GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_ES_VERSION_3_0) + glInvalidateFramebuffer(GL_FRAMEBUFFER, (GLint) attachments.size(), &attachments[0]); + else if (GLAD_EXT_discard_framebuffer) + glDiscardFramebufferEXT(GL_FRAMEBUFFER, (GLint) attachments.size(), &attachments[0]); +} + void Graphics::present() { if (!isActive()) @@ -433,23 +476,8 @@ void Graphics::present() std::vector> canvases = states.back().canvases; setCanvas(); - if (GLAD_ES_VERSION_3_0 || GLAD_EXT_discard_framebuffer) - { - GLenum attachments[] = {GL_STENCIL, GL_DEPTH}; - - if (gl.getDefaultFBO() != 0) - { - // A non-zero FBO needs different attachment enums. - attachments[0] = GL_STENCIL_ATTACHMENT; - attachments[1] = GL_DEPTH_ATTACHMENT; - } - - // Hint for the driver that it doesn't need to save these buffers. - if (GLAD_ES_VERSION_3_0) - glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments); - else if (GLAD_EXT_discard_framebuffer) - glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments); - } + // Discard the stencil buffer before swapping. + discard(false, true); #ifdef LOVE_IOS // Hack: SDL's color renderbuffer needs to be bound when swapBuffers is called. diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index e93e2b159..6e255ada0 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -85,6 +85,11 @@ public: **/ void clear(Color c); + /** + * Discards the contents of the screen. + **/ + void discard(bool color, bool stencil); + /** * Flips buffers. (Rendered geometry is presented on screen). **/ diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index eb0f341e7..2ac8b6889 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -61,6 +61,14 @@ int w_clear(lua_State *L) return 0; } +int w_discard(lua_State *L) +{ + bool color = luax_optboolean(L, 1, true); + bool stencil = luax_optboolean(L, 2, true); + instance()->discard(color, stencil); + return 0; +} + int w_present(lua_State *) { instance()->present(); @@ -1465,6 +1473,7 @@ static const luaL_Reg functions[] = { { "reset", w_reset }, { "clear", w_clear }, + { "discard", w_discard }, { "present", w_present }, { "newImage", w_newImage }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index 6e5bf434f..5837df84d 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -42,6 +42,7 @@ namespace opengl int w_reset(lua_State *L); int w_clear(lua_State *L); +int w_discard(lua_State *L); int w_present(lua_State *L); int w_isCreated(lua_State *L); int w_isActive(lua_State *L);