From 280d97eb79f7710a6ebd03fa6551529c9447d6f5 Mon Sep 17 00:00:00 2001 From: reuk Date: Wed, 30 Jun 2021 19:20:09 +0100 Subject: [PATCH] OpenGL: Check at runtime whether non-power-of-two textures are supported --- .../juce_opengl/opengl/juce_OpenGLContext.cpp | 27 +++++++++++++++++++ .../juce_opengl/opengl/juce_OpenGLContext.h | 3 +++ .../juce_opengl/opengl/juce_OpenGLTexture.cpp | 16 +++++------ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index fa255c754a..b14bff59a0 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -69,6 +69,24 @@ private: extern JUCE_API double getScaleFactorForWindow (HWND); #endif +static bool contextHasTextureNpotFeature() +{ + if (getOpenGLVersion() >= Version (2)) + return true; + + // If the version is < 2, we can't use the newer extension-checking API + // so we have to use glGetString + const auto* extensionsBegin = glGetString (GL_EXTENSIONS); + + if (extensionsBegin == nullptr) + return false; + + const auto* extensionsEnd = findNullTerminator (extensionsBegin); + const std::string extensionsString (extensionsBegin, extensionsEnd); + const auto stringTokens = StringArray::fromTokens (extensionsString.c_str(), false); + return stringTokens.contains ("GL_ARB_texture_non_power_of_two"); +} + //============================================================================== class OpenGLContext::CachedImage : public CachedComponentImage, private ThreadPoolJob @@ -530,6 +548,8 @@ public: shadersAvailable = OpenGLShaderProgram::getLanguageVersion() > 0; clearGLError(); + textureNpotSupported = contextHasTextureNpotFeature(); + if (context.renderer != nullptr) context.renderer->newOpenGLContextCreated(); @@ -665,6 +685,7 @@ public: #else bool shadersAvailable = false; #endif + bool textureNpotSupported = false; std::atomic hasInitialised { false }, needsUpdate { true }, destroying { false }; uint32 lastMMLockReleaseTime = 0; @@ -1068,6 +1089,12 @@ bool OpenGLContext::areShadersAvailable() const return c != nullptr && c->shadersAvailable; } +bool OpenGLContext::isTextureNpotSupported() const +{ + auto* c = getCachedImage(); + return c != nullptr && c->textureNpotSupported; +} + ReferenceCountedObject* OpenGLContext::getAssociatedObject (const char* name) const { jassert (name != nullptr); diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.h b/modules/juce_opengl/opengl/juce_OpenGLContext.h index f4ffd12589..d2c3cddd26 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.h +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.h @@ -130,6 +130,9 @@ public: /** Returns true if shaders can be used in this context. */ bool areShadersAvailable() const; + /** Returns true if non-power-of-two textures are supported in this context. */ + bool isTextureNpotSupported() const; + /** OpenGL versions, used by setOpenGLVersionRequired(). */ enum OpenGLVersion { diff --git a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp index c358e8aeee..b5b38e5c04 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp @@ -26,15 +26,6 @@ namespace juce { -static int getAllowedTextureSize (int x) -{ - #if JUCE_OPENGL_ALLOW_NON_POWER_OF_TWO_TEXTURES - return x; - #else - return nextPowerOfTwo (x); - #endif -} - OpenGLTexture::OpenGLTexture() : textureID (0), width (0), height (0), ownerContext (nullptr) { @@ -80,6 +71,13 @@ void OpenGLTexture::create (const int w, const int h, const void* pixels, GLenum glPixelStorei (GL_UNPACK_ALIGNMENT, 1); JUCE_CHECK_OPENGL_ERROR + const auto textureNpotSupported = ownerContext->isTextureNpotSupported(); + + const auto getAllowedTextureSize = [&] (int n) + { + return textureNpotSupported ? n : nextPowerOfTwo (n); + }; + width = getAllowedTextureSize (w); height = getAllowedTextureSize (h);