diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 5b43b8bbd..8dbfd21da 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -182,6 +182,7 @@ StringMap Graphics::lineJoins( StringMap::Entry Graphics::supportEntries[] = { { "multicanvasformats", SUPPORT_MULTI_CANVAS_FORMATS }, + { "clampzero", SUPPORT_CLAMP_ZERO }, }; StringMap Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries)); diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 81326da4c..ede4eba0d 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -99,6 +99,7 @@ public: enum Support { SUPPORT_MULTI_CANVAS_FORMATS, + SUPPORT_CLAMP_ZERO, SUPPORT_MAX_ENUM }; diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index d1e268dd7..fd21c947f 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -114,18 +114,19 @@ bool Texture::getConstant(WrapMode in, const char *&out) StringMap::Entry Texture::filterModeEntries[] = { - { "linear", Texture::FILTER_LINEAR }, - { "nearest", Texture::FILTER_NEAREST }, - { "none", Texture::FILTER_NONE }, + { "linear", FILTER_LINEAR }, + { "nearest", FILTER_NEAREST }, + { "none", FILTER_NONE }, }; StringMap Texture::filterModes(Texture::filterModeEntries, sizeof(Texture::filterModeEntries)); StringMap::Entry Texture::wrapModeEntries[] = { - { "clamp", Texture::WRAP_CLAMP }, - { "repeat", Texture::WRAP_REPEAT }, - { "mirroredrepeat", Texture::WRAP_MIRRORED_REPEAT }, + { "clamp", WRAP_CLAMP }, + { "clampzero", WRAP_CLAMP_ZERO }, + { "repeat", WRAP_REPEAT }, + { "mirroredrepeat", WRAP_MIRRORED_REPEAT }, }; StringMap Texture::wrapModes(Texture::wrapModeEntries, sizeof(Texture::wrapModeEntries)); diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index fb6082a75..3176c0b1d 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -43,6 +43,7 @@ public: enum WrapMode { WRAP_CLAMP, + WRAP_CLAMP_ZERO, WRAP_REPEAT, WRAP_MIRRORED_REPEAT, WRAP_MAX_ENUM diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 1770a81e5..d173bc30b 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -407,9 +407,6 @@ void Canvas::startGrab(const std::vector &canvases) if (canvases.size() > 0) { - if (!isMultiCanvasSupported()) - throw love::Exception("Multi-canvas rendering is not supported on this system."); - if ((int) canvases.size() + 1 > gl.getMaxRenderTargets()) throw love::Exception("This system can't simultaneously render to %d canvases.", canvases.size()+1); @@ -804,15 +801,9 @@ bool Canvas::isSupported() return GLAD_ES_VERSION_2_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object || GLAD_EXT_framebuffer_object; } -bool Canvas::isMultiCanvasSupported() -{ - // system must support at least 4 simultaneous active canvases. - return gl.getMaxRenderTargets() >= 4; -} - bool Canvas::isMultiFormatMultiCanvasSupported() { - return isMultiCanvasSupported() && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object); + return gl.getMaxRenderTargets() > 1 && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object); } bool Canvas::supportedFormats[] = {false}; diff --git a/src/modules/graphics/opengl/Canvas.h b/src/modules/graphics/opengl/Canvas.h index 23e89c215..45c5367ee 100644 --- a/src/modules/graphics/opengl/Canvas.h +++ b/src/modules/graphics/opengl/Canvas.h @@ -118,7 +118,6 @@ public: } static bool isSupported(); - static bool isMultiCanvasSupported(); static bool isMultiFormatMultiCanvasSupported(); static bool isFormatSupported(Format format); diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 956a6e83e..8331c57ca 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1491,6 +1491,8 @@ bool Graphics::isSupported(Support feature) const { case SUPPORT_MULTI_CANVAS_FORMATS: return Canvas::isMultiFormatMultiCanvasSupported(); + case SUPPORT_CLAMP_ZERO: + return gl.isClampZeroTextureWrapSupported(); default: return false; } diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index dcf7c9727..72032db5a 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -602,24 +602,35 @@ void OpenGL::setTextureFilter(graphics::Texture::Filter &f) f.anisotropy = 1.0f; } +GLint OpenGL::getGLWrapMode(Texture::WrapMode wmode) +{ + if (wmode == Texture::WRAP_CLAMP_ZERO && !isClampZeroTextureWrapSupported()) + wmode = Texture::WRAP_CLAMP; + + switch (wmode) + { + case Texture::WRAP_CLAMP: + default: + return GL_CLAMP_TO_EDGE; + case Texture::WRAP_CLAMP_ZERO: + return GL_CLAMP_TO_BORDER; + case Texture::WRAP_REPEAT: + return GL_REPEAT; + case Texture::WRAP_MIRRORED_REPEAT: + return GL_MIRRORED_REPEAT; + } + +} + void OpenGL::setTextureWrap(const graphics::Texture::Wrap &w) { - auto glWrapMode = [](Texture::WrapMode wmode) -> GLint - { - switch (wmode) - { - case Texture::WRAP_CLAMP: - default: - return GL_CLAMP_TO_EDGE; - case Texture::WRAP_REPEAT: - return GL_REPEAT; - case Texture::WRAP_MIRRORED_REPEAT: - return GL_MIRRORED_REPEAT; - } - }; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGLWrapMode(w.s)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGLWrapMode(w.t)); +} - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapMode(w.s)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapMode(w.t)); +bool OpenGL::isClampZeroTextureWrapSupported() const +{ + return GLAD_VERSION_1_3 || GLAD_EXT_texture_border_clamp || GLAD_NV_texture_border_clamp; } int OpenGL::getMaxTextureSize() const diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index d4ec16deb..33b6c0b1d 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -312,6 +312,8 @@ public: **/ void setTextureWrap(const graphics::Texture::Wrap &w); + bool isClampZeroTextureWrapSupported() const; + /** * Returns the maximum supported width or height of a texture. **/ @@ -354,6 +356,8 @@ private: void initMatrices(); void createDefaultTexture(); + GLint getGLWrapMode(Texture::WrapMode wmode); + bool contextInitialized; float maxAnisotropy;