From 468127eed4bce873fcb061805443815dd92d6ba9 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 15 Mar 2015 15:15:21 -0300 Subject: [PATCH] Added a variant of love.graphics.clear which accepts a color table argument for each active canvas, allowing it to clear active canvases to different colors without having to call love.graphics.setCanvas. --- src/modules/graphics/opengl/Graphics.cpp | 41 +++++++++++++++++++ src/modules/graphics/opengl/Graphics.h | 5 +++ src/modules/graphics/opengl/wrap_Graphics.cpp | 39 +++++++++++------- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index a21ce4655..334e9bb3e 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -424,6 +424,47 @@ void Graphics::clear(Color c) glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } +void Graphics::clear(const std::vector &colors) +{ + if (colors.size() == 0) + return; + + if (states.back().canvases.size() == 0) + return clear(colors[0]); + + if (colors.size() != states.back().canvases.size()) + throw love::Exception("Number of clear colors must match the number of active canvases (%ld)", states.back().canvases.size()); + + std::vector bufs; + + for (int i = 0; i < (int) colors.size(); i++) + { + const GLfloat c[] = {colors[i].r/255.f, colors[i].g/255.f, colors[i].b/255.f, colors[i].a/255.f}; + + if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0) + glClearBufferfv(GL_COLOR, i, c); + else + { + bufs.push_back(GL_COLOR_ATTACHMENT0 + i); + glDrawBuffer(GL_COLOR_ATTACHMENT0 + i); + glClearColor(c[0], c[1], c[2], c[3]); + glClear(GL_COLOR_BUFFER_BIT); + } + } + + glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Revert to the expected draw buffers once we're done, if glClearBuffer + // wasn't supported. + if (!(GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0)) + { + if (bufs.size() > 1) + glDrawBuffers((int) bufs.size(), &bufs[0]); + else + glDrawBuffer(GL_COLOR_ATTACHMENT0); + } +} + void Graphics::discard(bool color, bool stencil) { if (!(GLAD_VERSION_4_3 || GLAD_ARB_invalidate_subdata || GLAD_ES_VERSION_3_0 || GLAD_EXT_discard_framebuffer)) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index ff343bbff..a9ed6d944 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -86,6 +86,11 @@ public: **/ void clear(Color c); + /** + * Clears each active canvas to a different color. + **/ + void clear(const std::vector &colors); + /** * Discards the contents of the screen. **/ diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 80367a3e7..dae71db08 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -47,31 +47,42 @@ int w_reset(lua_State *) int w_clear(lua_State *L) { - Color color; + std::vector colors(1); if (lua_isnoneornil(L, 1)) - color.set(0, 0, 0, 0); + colors[0].set(0, 0, 0, 0); else if (lua_istable(L, 1)) { - for (int i = 1; i <= 4; i++) - lua_rawgeti(L, 1, i); + colors.resize((size_t) lua_gettop(L)); - color.r = (unsigned char) luaL_checkinteger(L, -4); - color.g = (unsigned char) luaL_checkinteger(L, -3); - color.b = (unsigned char) luaL_checkinteger(L, -2); - color.a = (unsigned char) luaL_optinteger(L, -1, 255); + for (int i = 0; i < lua_gettop(L); i++) + { + for (int j = 1; j <= 4; j++) + lua_rawgeti(L, i + 1, j); - lua_pop(L, 4); + colors[i].r = (unsigned char) luaL_checkinteger(L, -4); + colors[i].g = (unsigned char) luaL_checkinteger(L, -3); + colors[i].b = (unsigned char) luaL_checkinteger(L, -2); + colors[i].a = (unsigned char) luaL_optinteger(L, -1, 255); + + lua_pop(L, 4); + } } else { - color.r = (unsigned char) luaL_checkinteger(L, 1); - color.g = (unsigned char) luaL_checkinteger(L, 2); - color.b = (unsigned char) luaL_checkinteger(L, 3); - color.a = (unsigned char) luaL_optinteger(L, 4, 255); + colors[0].r = (unsigned char) luaL_checkinteger(L, 1); + colors[0].g = (unsigned char) luaL_checkinteger(L, 2); + colors[0].b = (unsigned char) luaL_checkinteger(L, 3); + colors[0].a = (unsigned char) luaL_optinteger(L, 4, 255); } - instance()->clear(color); + luax_catchexcept(L, [&]() { + if (colors.size() == 1) + instance()->clear(colors[0]); + else + instance()->clear(colors); + }); + return 0; }