diff --git a/src/modules/graphics/Canvas.cpp b/src/modules/graphics/Canvas.cpp index c54253619..ac5b65463 100644 --- a/src/modules/graphics/Canvas.cpp +++ b/src/modules/graphics/Canvas.cpp @@ -71,6 +71,69 @@ Canvas::Canvas(const Settings &settings) filter.mipmap = defaultMipmapFilter; } + auto gfx = Module::getInstance(Module::M_GRAPHICS); + + if (!gfx->isCanvasFormatSupported(format, readable)) + { + const char *fstr = "rgba8"; + const char *readablestr = ""; + if (readable != !isPixelFormatDepthStencil(format)) + readablestr = readable ? " readable" : " non-readable"; + love::getConstant(format, fstr); + throw love::Exception("The %s%s canvas format is not supported by your graphics drivers.", fstr, readablestr); + } + + if (getRequestedMSAA() > 1 && texType != TEXTURE_2D) + throw love::Exception("MSAA is only supported for 2D texture types."); + + if (!readable && texType != TEXTURE_2D) + throw love::Exception("Non-readable pixel formats are only supported for 2D texture types."); + + if (!gfx->isTextureTypeSupported(texType)) + { + const char *textypestr = "unknown"; + Texture::getConstant(texType, textypestr); + throw love::Exception("%s textures are not supported on this system!", textypestr); + } + + int maxsize = 0; + switch (texType) + { + case TEXTURE_2D: + maxsize = gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE); + if (pixelWidth > maxsize) + throw TextureTooLargeException("width", pixelWidth); + else if (pixelHeight > maxsize) + throw TextureTooLargeException("height", pixelHeight); + break; + case TEXTURE_VOLUME: + maxsize = gfx->getSystemLimit(Graphics::LIMIT_VOLUME_TEXTURE_SIZE); + if (pixelWidth > maxsize) + throw TextureTooLargeException("width", pixelWidth); + else if (pixelHeight > maxsize) + throw TextureTooLargeException("height", pixelHeight); + else if (depth > maxsize) + throw TextureTooLargeException("depth", depth); + break; + case TEXTURE_2D_ARRAY: + maxsize = gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE); + if (pixelWidth > maxsize) + throw TextureTooLargeException("width", pixelWidth); + else if (pixelHeight > maxsize) + throw TextureTooLargeException("height", pixelHeight); + else if (layers > gfx->getSystemLimit(Graphics::LIMIT_TEXTURE_LAYERS)) + throw TextureTooLargeException("array layer count", layers); + break; + case TEXTURE_CUBE: + if (pixelWidth != pixelHeight) + throw love::Exception("Cubemap textures must have equal width and height."); + else if (pixelWidth > gfx->getSystemLimit(Graphics::LIMIT_CUBE_TEXTURE_SIZE)) + throw TextureTooLargeException("width", pixelWidth); + break; + default: + break; + } + canvasCount++; } diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 56bd75221..ed8c68a98 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -514,11 +514,6 @@ public: virtual void setStencilTest() = 0; void getStencilTest(CompareMode &compare, int &value); - /** - * Clear the stencil buffer in the active Canvas(es.) - **/ - virtual void clearStencil(int value) = 0; - /** * Sets the enabled color components when rendering. **/ @@ -705,6 +700,11 @@ public: **/ virtual bool isSupported(Feature feature) const = 0; + /** + * Gets whether the given texture type is supported on this system. + **/ + virtual bool isTextureTypeSupported(TextureType textype) const = 0; + /** * Gets the system-dependent numeric limit for the specified parameter. **/ diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 31f6f4f0c..afd7593a4 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -178,66 +178,6 @@ bool Canvas::loadVolatile() if (texture != 0) return true; - if (!Canvas::isSupported()) - throw love::Exception("Canvases are not supported by your OpenGL drivers!"); - - if (!Canvas::isFormatSupported(format, readable)) - { - const char *fstr = "rgba8"; - const char *readablestr = ""; - if (readable != !isPixelFormatDepthStencil(format)) - readablestr = readable ? " readable" : " non-readable"; - love::getConstant(Canvas::getSizedFormat(format), fstr); - throw love::Exception("The %s%s canvas format is not supported by your OpenGL drivers.", fstr, readablestr); - } - - if (getRequestedMSAA() > 1 && texType != TEXTURE_2D) - throw love::Exception("MSAA is only supported for 2D texture types."); - - if (!readable && texType != TEXTURE_2D) - throw love::Exception("Non-readable pixel formats are only supported for 2D texture types."); - - if (!gl.isTextureTypeSupported(texType)) - { - const char *textypestr = "unknown"; - Texture::getConstant(texType, textypestr); - throw love::Exception("%s textures are not supported on this system!", textypestr); - } - - switch (texType) - { - case TEXTURE_2D: - if (pixelWidth > gl.getMax2DTextureSize()) - throw TextureTooLargeException("width", pixelWidth); - else if (pixelHeight > gl.getMax2DTextureSize()) - throw TextureTooLargeException("height", pixelHeight); - break; - case TEXTURE_VOLUME: - if (pixelWidth > gl.getMax3DTextureSize()) - throw TextureTooLargeException("width", pixelWidth); - else if (pixelHeight > gl.getMax3DTextureSize()) - throw TextureTooLargeException("height", pixelHeight); - else if (depth > gl.getMax3DTextureSize()) - throw TextureTooLargeException("depth", depth); - break; - case TEXTURE_2D_ARRAY: - if (pixelWidth > gl.getMax2DTextureSize()) - throw TextureTooLargeException("width", pixelWidth); - else if (pixelHeight > gl.getMax2DTextureSize()) - throw TextureTooLargeException("height", pixelHeight); - else if (layers > gl.getMaxTextureLayers()) - throw TextureTooLargeException("array layer count", layers); - break; - case TEXTURE_CUBE: - if (pixelWidth != pixelHeight) - throw love::Exception("Cubemap textures must have equal width and height."); - else if (pixelWidth > gl.getMaxCubeTextureSize()) - throw TextureTooLargeException("width", pixelWidth); - break; - default: - break; - } - OpenGL::TempDebugGroup debuggroup("Canvas load"); fbo = texture = 0; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 3613a7a18..bac024424 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -735,7 +735,7 @@ void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth if (flags != 0) glClear(flags); - if (flags != 0 && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current) + if (c.hasValue && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current) { // This seems to be enough to fix the bug for me. Other methods I've // tried (e.g. dummy draws) don't work in all cases. @@ -1249,12 +1249,6 @@ void Graphics::setStencilTest() setStencilTest(COMPARE_ALWAYS, 0); } -void Graphics::clearStencil(int value) -{ - glClearStencil(value); - glClear(GL_STENCIL_BUFFER_BIT); -} - void Graphics::setColor(Colorf c) { c.r = std::min(std::max(c.r, 0.0f), 1.0f); @@ -1468,6 +1462,11 @@ bool Graphics::isSupported(Feature feature) const } } +bool Graphics::isTextureTypeSupported(TextureType textype) const +{ + return gl.isTextureTypeSupported(textype); +} + bool Graphics::isCanvasFormatSupported(PixelFormat format) const { return Canvas::isFormatSupported(format); diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 019cbdce6..2ded0566a 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -109,8 +109,6 @@ public: void setStencilTest(CompareMode compare, int value) override; void setStencilTest() override; - void clearStencil(int value) override; - void setColorMask(ColorMask mask) override; void setBlendMode(BlendMode mode, BlendAlpha alphamode) override; @@ -120,6 +118,7 @@ public: void setWireframe(bool enable) override; bool isSupported(Feature feature) const override; + bool isTextureTypeSupported(TextureType textype) const override; double getSystemLimit(SystemLimit limittype) const override; bool isCanvasFormatSupported(PixelFormat format) const override; bool isCanvasFormatSupported(PixelFormat format, bool readable) const override; diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 99a5902c3..b2a896dc7 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -527,14 +527,18 @@ int w_stencil(lua_State *L) int stencilvalue = (int) luaL_optnumber(L, 3, 1); // Fourth argument: whether to keep the contents of the stencil buffer. + OptionalInt stencilclear; int argtype = lua_type(L, 4); if (argtype == LUA_TNONE || argtype == LUA_TNIL || (argtype == LUA_TBOOLEAN && luax_toboolean(L, 4) == false)) - instance()->clearStencil(0); + stencilclear.set(0); else if (argtype == LUA_TNUMBER) - instance()->clearStencil((int) luaL_checkinteger(L, 4)); + stencilclear.set((int) luaL_checkinteger(L, 4)); else if (argtype != LUA_TBOOLEAN) luaL_checktype(L, 4, LUA_TBOOLEAN); + if (stencilclear.hasValue) + instance()->clear(OptionalColorf(), stencilclear, OptionalDouble()); + luax_catchexcept(L, [&](){ instance()->drawToStencilBuffer(action, stencilvalue); }); // Call stencilfunc()