diff --git a/src/modules/graphics/opengl/Canvas.h b/src/modules/graphics/opengl/Canvas.h index dd69140e7..ae07ce9c7 100644 --- a/src/modules/graphics/opengl/Canvas.h +++ b/src/modules/graphics/opengl/Canvas.h @@ -49,6 +49,27 @@ namespace opengl bool loadVolatile(); void unloadVolatile(); + /// Unbind the current canvas on construction and rebind it upon destruction. + // Exception safe temporary unbinding/rebinding for techniques that require + // the default canvas to work (e.g. stencils). + // XXX: If a canvas is switched between creating and destroying an unbinder + // object, the canvas will not be switched back. + struct TemporaryUnbinder + { + Canvas * canvas; + inline TemporaryUnbinder() : canvas(Canvas::current) + { + if (NULL != canvas) + Canvas::bindDefaultCanvas(); + } + + inline ~TemporaryUnbinder() + { + if (NULL != canvas && NULL == Canvas::current) + canvas->startGrab(); + } + }; + private: friend class PixelEffect; GLuint getTextureName() const { return img; } diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 0de2d5e10..6faaefb53 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace love { @@ -168,6 +169,9 @@ namespace opengl static int setStencil(lua_State * L, bool invert) { + // stencils require the default fb to work properly + Canvas::TemporaryUnbinder unbinder; + // no argument -> clear mask if (lua_isnoneornil(L, 1)) { instance->discardStencil();