From 09e6a9a434ca4bfeee9c35509b17370880433791 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 29 Dec 2015 00:10:40 -0400 Subject: [PATCH] When multiple canvases are active at once (MRT), individual canvases can now be selectively cleared with love.graphics.clear(c1, c2, ...) by passing empty tables for the canvases that shouldn't be cleared, and color tables for the canvases that should. --- src/modules/graphics/opengl/Graphics.cpp | 24 +++++++++++--- src/modules/graphics/opengl/Graphics.h | 8 ++++- src/modules/graphics/opengl/wrap_Graphics.cpp | 32 +++++++++++-------- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 8339b0457..785371426 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -448,21 +448,29 @@ void Graphics::clear(Colorf c) glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void Graphics::clear(const std::vector &colors) +void Graphics::clear(const std::vector &colors) { if (colors.size() == 0) return; if (states.back().canvases.size() == 0) - return clear(colors[0]); + { + if (colors[0].enabled) + clear({colors[0].r, colors[0].g, colors[0].b, colors[0].a}); + + return; + } 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; + bool drawbuffermodified = false; for (int i = 0; i < (int) colors.size(); i++) { + if (!colors[i].enabled) + continue; + GLfloat c[] = {colors[i].r/255.f, colors[i].g/255.f, colors[i].b/255.f, colors[i].a/255.f}; // TODO: Investigate a potential bug on AMD drivers in Windows/Linux @@ -478,10 +486,11 @@ void Graphics::clear(const std::vector &colors) 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); + + drawbuffermodified = true; } } @@ -489,8 +498,13 @@ void Graphics::clear(const std::vector &colors) // 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 (drawbuffermodified) { + std::vector bufs; + + for (int i = 0; i < (int) states.back().canvases.size(); i++) + bufs.push_back(GL_COLOR_ATTACHMENT0 + i); + if (bufs.size() > 1) glDrawBuffers((int) bufs.size(), &bufs[0]); else diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 3fab27735..e5b49c3d2 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -62,6 +62,12 @@ class Graphics : public love::graphics::Graphics { public: + struct OptionalColorf + { + float r, g, b, a; + bool enabled; + }; + Graphics(); virtual ~Graphics(); @@ -92,7 +98,7 @@ public: /** * Clears each active canvas to a different color. **/ - void clear(const std::vector &colors); + 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 b3a888d19..5cbff5d0b 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -55,19 +55,26 @@ int w_reset(lua_State *) int w_clear(lua_State *L) { - std::vector colors(1); + Colorf color; if (lua_isnoneornil(L, 1)) - colors[0].set(0, 0, 0, 0); + color.set(0, 0, 0, 0); else if (lua_istable(L, 1)) { - colors.resize((size_t) lua_gettop(L)); + std::vector colors((size_t) lua_gettop(L)); for (int i = 0; i < lua_gettop(L); i++) { + if (lua_isnoneornil(L, i + 1) || luax_objlen(L, i + 1) == 0) + { + colors[i].enabled = false; + continue; + } + for (int j = 1; j <= 4; j++) lua_rawgeti(L, i + 1, j); + colors[i].enabled = true; colors[i].r = (float) luaL_checknumber(L, -4); colors[i].g = (float) luaL_checknumber(L, -3); colors[i].b = (float) luaL_checknumber(L, -2); @@ -75,22 +82,19 @@ int w_clear(lua_State *L) lua_pop(L, 4); } + + luax_catchexcept(L, [&]() { instance()->clear(colors); }); + return 0; } else { - colors[0].r = (float) luaL_checknumber(L, 1); - colors[0].g = (float) luaL_checknumber(L, 2); - colors[0].b = (float) luaL_checknumber(L, 3); - colors[0].a = (float) luaL_optnumber(L, 4, 255); + color.r = (float) luaL_checknumber(L, 1); + color.g = (float) luaL_checknumber(L, 2); + color.b = (float) luaL_checknumber(L, 3); + color.a = (float) luaL_optnumber(L, 4, 255); } - luax_catchexcept(L, [&]() { - if (colors.size() == 1) - instance()->clear(colors[0]); - else - instance()->clear(colors); - }); - + luax_catchexcept(L, [&]() { instance()->clear(color); }); return 0; }