From 109f0a32a4fdecfc9a9694aa46a30de7577803dc Mon Sep 17 00:00:00 2001 From: jules Date: Thu, 1 Mar 2012 12:10:37 +0000 Subject: [PATCH] OpenGL: added internal checks to catch GL errors (in debug mode). More Android GL progress. --- .../Builds/Android/src/com/juce/JuceDemo.java | 7 +- .../native/java/JuceAppActivity.java | 7 +- modules/juce_opengl/juce_opengl.cpp | 42 ++++++++++- .../native/juce_MissingGLDefinitions.h | 7 ++ .../native/juce_android_OpenGLComponent.cpp | 36 ++++++++- .../opengl/juce_OpenGLComponent.cpp | 16 ++++ .../opengl/juce_OpenGLFrameBuffer.cpp | 9 ++- .../opengl/juce_OpenGLGraphicsContext.cpp | 73 +++++++++++++++---- .../juce_opengl/opengl/juce_OpenGLHelpers.cpp | 5 ++ .../opengl/juce_OpenGLShaderProgram.cpp | 2 + .../juce_opengl/opengl/juce_OpenGLTexture.cpp | 9 ++- 11 files changed, 176 insertions(+), 37 deletions(-) diff --git a/extras/JuceDemo/Builds/Android/src/com/juce/JuceDemo.java b/extras/JuceDemo/Builds/Android/src/com/juce/JuceDemo.java index bdd89377cd..087f338779 100644 --- a/extras/JuceDemo/Builds/Android/src/com/juce/JuceDemo.java +++ b/extras/JuceDemo/Builds/Android/src/com/juce/JuceDemo.java @@ -81,12 +81,6 @@ public final class JuceDemo extends Activity private native void quitApp(); private native void setScreenSize (int screenWidth, int screenHeight); - //============================================================================== - public static final void printToConsole (String s) - { - android.util.Log.i ("Juce", s); - } - //============================================================================== public native void deliverMessage (long value); private android.os.Handler messageHandler = new android.os.Handler(); @@ -351,6 +345,7 @@ public final class JuceDemo extends Activity super (context); setEGLContextClientVersion (2); setRenderer (this); + setRenderMode (RENDERMODE_WHEN_DIRTY); } @Override diff --git a/modules/juce_core/native/java/JuceAppActivity.java b/modules/juce_core/native/java/JuceAppActivity.java index 5aef477638..e48a4554c7 100644 --- a/modules/juce_core/native/java/JuceAppActivity.java +++ b/modules/juce_core/native/java/JuceAppActivity.java @@ -81,12 +81,6 @@ public final class JuceAppActivity extends Activity private native void quitApp(); private native void setScreenSize (int screenWidth, int screenHeight); - //============================================================================== - public static final void printToConsole (String s) - { - android.util.Log.i ("Juce", s); - } - //============================================================================== public native void deliverMessage (long value); private android.os.Handler messageHandler = new android.os.Handler(); @@ -351,6 +345,7 @@ public final class JuceAppActivity extends Activity super (context); setEGLContextClientVersion (2); setRenderer (this); + setRenderMode (RENDERMODE_WHEN_DIRTY); } @Override diff --git a/modules/juce_opengl/juce_opengl.cpp b/modules/juce_opengl/juce_opengl.cpp index 8745c7b3ab..fad7b4c5e7 100644 --- a/modules/juce_opengl/juce_opengl.cpp +++ b/modules/juce_opengl/juce_opengl.cpp @@ -149,15 +149,53 @@ void OpenGLExtensionFunctions::initialise() #undef JUCE_GL_EXTENSION_FUNCTIONS #if JUCE_OPENGL_ES - #define JUCE_LOWP "lowp" #define JUCE_MEDIUMP "mediump" #define JUCE_HIGHP "highp" #else - #define JUCE_LOWP #define JUCE_MEDIUMP #define JUCE_HIGHP #endif +static const char* getGLErrorMessage (GLenum e) +{ + switch (e) + { + case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; + #ifdef GL_STACK_OVERFLOW + case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW"; + #endif + #ifdef GL_STACK_OVERFLOW + case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW"; + #endif + case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; + default: break; + } + + return "Unknown error"; +} + +#if JUCE_DEBUG && ! defined (JUCE_CHECK_OPENGL_ERROR) +static void checkGLError (const char* file, const int line) +{ + for (;;) + { + GLenum e = glGetError(); + + if (e == GL_NO_ERROR) + break; + + DBG ("***** " << getGLErrorMessage (e) << " at " << file << " : " << line); + jassertfalse; + } +} + + #define JUCE_CHECK_OPENGL_ERROR checkGLError (__FILE__, __LINE__); +#else + #define JUCE_CHECK_OPENGL_ERROR ; +#endif + //============================================================================== // START_AUTOINCLUDE opengl/*.cpp #include "opengl/juce_OpenGLComponent.cpp" diff --git a/modules/juce_opengl/native/juce_MissingGLDefinitions.h b/modules/juce_opengl/native/juce_MissingGLDefinitions.h index 45033f2071..f624180934 100644 --- a/modules/juce_opengl/native/juce_MissingGLDefinitions.h +++ b/modules/juce_opengl/native/juce_MissingGLDefinitions.h @@ -53,6 +53,13 @@ namespace enum { GL_DEPTH24_STENCIL8 = 0x88F0 }; #endif + #if JUCE_ANDROID + enum { JUCE_RGBA_FORMAT = GL_RGBA }; + #else + enum { JUCE_RGBA_FORMAT = GL_BGRA_EXT }; + #endif + + #if JUCE_WINDOWS enum { diff --git a/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp b/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp index 1163faf7f9..c0dfdd9761 100644 --- a/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp +++ b/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp @@ -48,9 +48,11 @@ public: isInsideGLCallback (false) { jassert (peer != nullptr); - getContextList().add (this); glView = GlobalRef (createOpenGLView (peer)); + + const ScopedLock sl (getContextListLock()); + getContextList().add (this); } ~AndroidGLContext() @@ -60,6 +62,7 @@ public: android.activity.callVoidMethod (JuceAppActivity.deleteView, glView.get()); glView.clear(); + const ScopedLock sl (getContextListLock()); getContextList().removeValue (this); } @@ -97,6 +100,8 @@ public: //============================================================================== void contextCreatedCallback() { + properties.clear(); + isInsideGLCallback = true; if (component != nullptr) @@ -116,6 +121,12 @@ public: } //============================================================================== + static CriticalSection& getContextListLock() + { + static CriticalSection lock; + return lock; + } + static Array& getContextList() { static Array contexts; @@ -124,6 +135,7 @@ public: static AndroidGLContext* findContextFor (JNIEnv* env, jobject glView) { + const ScopedLock sl (getContextListLock()); const Array& contexts = getContextList(); for (int i = contexts.size(); --i >= 0;) @@ -139,6 +151,7 @@ public: static bool isAnyContextActive() { + const ScopedLock sl (getContextListLock()); const Array& contexts = getContextList(); for (int i = contexts.size(); --i >= 0;) @@ -201,14 +214,29 @@ void triggerAndroidOpenGLRepaint (OpenGLContext* context) //============================================================================== JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024OpenGLView), contextCreated, void, (JNIEnv* env, jobject view)) { - AndroidGLContext* const context = AndroidGLContext::findContextFor (env, view); + JUCE_CHECK_OPENGL_ERROR - if (context != nullptr) - context->contextCreatedCallback(); + for (int i = 100; --i >= 0;) + { + AndroidGLContext* const context = AndroidGLContext::findContextFor (env, view); + + if (context != nullptr) + { + context->contextCreatedCallback(); + return; + } + + Thread::sleep (20); + } + + DBG ("*** GL start failure!"); + jassertfalse; } JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024OpenGLView), render, void, (JNIEnv* env, jobject view)) { + JUCE_CHECK_OPENGL_ERROR + AndroidGLContext* const context = AndroidGLContext::findContextFor (env, view); if (context != nullptr) diff --git a/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp b/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp index 27422d135f..6782e06464 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp @@ -407,24 +407,32 @@ unsigned int OpenGLComponent::getFrameBufferID() const bool OpenGLComponent::performRender() { + JUCE_CHECK_OPENGL_ERROR + const ScopedLock sl (contextLock); #if JUCE_LINUX updateContext(); #endif + JUCE_CHECK_OPENGL_ERROR + if (context != nullptr) { if (! makeCurrentRenderingTarget()) return false; + JUCE_CHECK_OPENGL_ERROR + if (needToUpdateViewport) { needToUpdateViewport = false; glViewport (0, 0, getWidth(), getHeight()); } + JUCE_CHECK_OPENGL_ERROR renderOpenGL(); + JUCE_CHECK_OPENGL_ERROR if ((flags & allowSubComponents) != 0) { @@ -440,6 +448,7 @@ bool OpenGLComponent::performRender() const Rectangle bounds (getLocalBounds()); OpenGLFrameBuffer& frameBuffer = cachedImage->getFrameBuffer (bounds.getWidth(), bounds.getHeight()); + JUCE_CHECK_OPENGL_ERROR if (needToRepaint) { @@ -455,26 +464,33 @@ bool OpenGLComponent::performRender() { OpenGLGraphicsContext g (*getCurrentContext(), frameBuffer); + JUCE_CHECK_OPENGL_ERROR g.clipToRectangleList (invalid); g.setFill (Colours::transparentBlack); g.fillRect (bounds, true); g.setFill (Colours::black); + JUCE_CHECK_OPENGL_ERROR paintSelf (g); + JUCE_CHECK_OPENGL_ERROR } makeCurrentRenderingTarget(); } } + JUCE_CHECK_OPENGL_ERROR + #if ! JUCE_ANDROID glEnable (GL_TEXTURE_2D); + #endif context->extensions.glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, frameBuffer.getTextureID()); jassert (bounds.getPosition() == Point()); context->copyTexture (bounds, bounds); glBindTexture (GL_TEXTURE_2D, 0); + JUCE_CHECK_OPENGL_ERROR } swapBuffers(); diff --git a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp index ebfe1f81f9..04c0d88430 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp @@ -196,7 +196,9 @@ bool OpenGLFrameBuffer::initialise (OpenGLFrameBuffer& other) { pimpl->bind(); + #if ! JUCE_ANDROID glEnable (GL_TEXTURE_2D); + #endif glBindTexture (GL_TEXTURE_2D, p->textureID); pimpl->context.copyTexture (area, area); glBindTexture (GL_TEXTURE_2D, 0); @@ -292,9 +294,11 @@ bool OpenGLFrameBuffer::readPixels (PixelARGB* target, const Rectangle& are return false; glPixelStorei (GL_PACK_ALIGNMENT, 4); - glReadPixels (area.getX(), area.getY(), area.getWidth(), area.getHeight(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, target); + glReadPixels (area.getX(), area.getY(), area.getWidth(), area.getHeight(), + JUCE_RGBA_FORMAT, GL_UNSIGNED_BYTE, target); pimpl->context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, 0); glPixelStorei (GL_PACK_ALIGNMENT, 0); + JUCE_CHECK_OPENGL_ERROR; return true; } @@ -305,6 +309,7 @@ bool OpenGLFrameBuffer::writePixels (const PixelARGB* data, const Rectangle glDisable (GL_DEPTH_TEST); glDisable (GL_BLEND); + JUCE_CHECK_OPENGL_ERROR; OpenGLTexture tex; tex.loadARGBFlipped (data, area.getWidth(), area.getHeight()); @@ -359,7 +364,9 @@ void OpenGLFrameBuffer::drawAt (float x1, float y1) const { if (pimpl != nullptr) { + #if ! JUCE_ANDROID glEnable (GL_TEXTURE_2D); + #endif glBindTexture (GL_TEXTURE_2D, pimpl->textureID); glDisableClientState (GL_COLOR_ARRAY); diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp index 247e7cca1c..9ee0a81b90 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -224,10 +224,11 @@ public: ShaderProgramHolder (OpenGLContext& context, const char* fragmentShader) : program (context) { + JUCE_CHECK_OPENGL_ERROR program.addShader ("attribute vec2 position;" "attribute vec4 colour;" "uniform vec4 screenBounds;" - "varying " JUCE_LOWP " vec4 frontColour;" + "varying " JUCE_MEDIUMP " vec4 frontColour;" "varying " JUCE_HIGHP " vec2 pixelPos;" "void main()" "{" @@ -240,6 +241,7 @@ public: program.addShader (fragmentShader, GL_FRAGMENT_SHADER); program.link(); + JUCE_CHECK_OPENGL_ERROR } OpenGLShaderProgram program; @@ -298,7 +300,7 @@ public: }; //============================================================================== - #define JUCE_DECLARE_VARYING_COLOUR "varying " JUCE_LOWP " vec4 frontColour;" + #define JUCE_DECLARE_VARYING_COLOUR "varying " JUCE_MEDIUMP " vec4 frontColour;" #define JUCE_DECLARE_VARYING_PIXELPOS "varying " JUCE_HIGHP " vec2 pixelPos;" struct SolidColourProgram : public ShaderBase @@ -312,6 +314,12 @@ public: {} }; + #if JUCE_ANDROID + #define JUCE_DECLARE_SWIZZLE_FUNCTION "\n" JUCE_MEDIUMP " vec4 swizzleRGBOrder (in " JUCE_MEDIUMP " vec4 c) { return vec4 (c.b, c.g, c.r, c.a); }\n" + #else + #define JUCE_DECLARE_SWIZZLE_FUNCTION "\n" JUCE_MEDIUMP " vec4 swizzleRGBOrder (in " JUCE_MEDIUMP " vec4 c) { return c; }\n" + #endif + #define JUCE_DECLARE_MASK_UNIFORMS "uniform sampler2D maskTexture;" \ "uniform ivec4 maskBounds;" #define JUCE_FRAGCOORD_TO_MASK_POS "vec2 ((pixelPos.x - float (maskBounds.x)) / float (maskBounds.z)," \ @@ -357,13 +365,13 @@ public: #define JUCE_DECLARE_RADIAL_UNIFORMS "uniform sampler2D gradientTexture;" JUCE_DECLARE_MATRIX_UNIFORM #define JUCE_MATRIX_TIMES_FRAGCOORD "(mat2 (matrix[0], matrix[3], matrix[1], matrix[4]) * pixelPos" \ " + vec2 (matrix[2], matrix[5]))" - #define JUCE_GET_TEXTURE_COLOUR "(frontColour.a * texture2D (gradientTexture, vec2 (gradientPos, 0.5)))" + #define JUCE_GET_TEXTURE_COLOUR "(frontColour.a * swizzleRGBOrder (texture2D (gradientTexture, vec2 (gradientPos, 0.5))))" struct RadialGradientProgram : public ShaderBase { RadialGradientProgram (OpenGLContext& context) : ShaderBase (context, JUCE_DECLARE_VARYING_PIXELPOS - JUCE_DECLARE_RADIAL_UNIFORMS JUCE_DECLARE_VARYING_COLOUR + JUCE_DECLARE_RADIAL_UNIFORMS JUCE_DECLARE_VARYING_COLOUR JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_MEDIUMP " float gradientPos = length (" JUCE_MATRIX_TIMES_FRAGCOORD ");" @@ -380,7 +388,7 @@ public: RadialGradientMaskedProgram (OpenGLContext& context) : ShaderBase (context, JUCE_DECLARE_VARYING_PIXELPOS JUCE_DECLARE_RADIAL_UNIFORMS JUCE_DECLARE_VARYING_COLOUR - JUCE_DECLARE_MASK_UNIFORMS + JUCE_DECLARE_MASK_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_MEDIUMP " float gradientPos = length (" JUCE_MATRIX_TIMES_FRAGCOORD ");" @@ -406,7 +414,8 @@ public: }; #define JUCE_DECLARE_LINEAR_UNIFORMS "uniform sampler2D gradientTexture;" \ - "uniform " JUCE_MEDIUMP " vec4 gradientInfo;" JUCE_DECLARE_VARYING_COLOUR JUCE_DECLARE_VARYING_PIXELPOS + "uniform " JUCE_MEDIUMP " vec4 gradientInfo;" \ + JUCE_DECLARE_VARYING_COLOUR JUCE_DECLARE_VARYING_PIXELPOS #define JUCE_CALC_LINEAR_GRAD_POS1 JUCE_MEDIUMP " float gradientPos = (pixelPos.y - (gradientInfo.y + (gradientInfo.z * (pixelPos.x - gradientInfo.x)))) / gradientInfo.w;" #define JUCE_CALC_LINEAR_GRAD_POS2 JUCE_MEDIUMP " float gradientPos = (pixelPos.x - (gradientInfo.x + (gradientInfo.z * (pixelPos.y - gradientInfo.y)))) / gradientInfo.w;" @@ -414,6 +423,7 @@ public: { LinearGradient1Program (OpenGLContext& context) : ShaderBase (context, JUCE_DECLARE_LINEAR_UNIFORMS // gradientInfo: x = x1, y = y1, z = (y2 - y1) / (x2 - x1), w = length + JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_CALC_LINEAR_GRAD_POS1 @@ -429,7 +439,7 @@ public: { LinearGradient1MaskedProgram (OpenGLContext& context) : ShaderBase (context, JUCE_DECLARE_LINEAR_UNIFORMS // gradientInfo: x = x1, y = y1, z = (y2 - y1) / (x2 - x1), w = length - JUCE_DECLARE_MASK_UNIFORMS + JUCE_DECLARE_MASK_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_CALC_LINEAR_GRAD_POS1 @@ -447,6 +457,7 @@ public: { LinearGradient2Program (OpenGLContext& context) : ShaderBase (context, JUCE_DECLARE_LINEAR_UNIFORMS // gradientInfo: x = x1, y = y1, z = (x2 - x1) / (y2 - y1), y = y1, w = length + JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_CALC_LINEAR_GRAD_POS2 @@ -462,7 +473,7 @@ public: { LinearGradient2MaskedProgram (OpenGLContext& context) : ShaderBase (context, JUCE_DECLARE_LINEAR_UNIFORMS // gradientInfo: x = x1, y = y1, z = (x2 - x1) / (y2 - y1), y = y1, w = length - JUCE_DECLARE_MASK_UNIFORMS + JUCE_DECLARE_MASK_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_CALC_LINEAR_GRAD_POS2 @@ -519,14 +530,14 @@ public: #define JUCE_DECLARE_IMAGE_UNIFORMS "uniform sampler2D imageTexture;" \ "uniform " JUCE_MEDIUMP " vec4 imageLimits;" \ JUCE_DECLARE_MATRIX_UNIFORM JUCE_DECLARE_VARYING_COLOUR JUCE_DECLARE_VARYING_PIXELPOS - #define JUCE_GET_IMAGE_PIXEL "texture2D (imageTexture, vec2 (texturePos.x, 1.0 - texturePos.y))" + #define JUCE_GET_IMAGE_PIXEL "swizzleRGBOrder (texture2D (imageTexture, vec2 (texturePos.x, 1.0 - texturePos.y)))" #define JUCE_CLAMP_TEXTURE_COORD JUCE_HIGHP " vec2 texturePos = clamp (" JUCE_MATRIX_TIMES_FRAGCOORD ", imageLimits.xy, imageLimits.zw);" #define JUCE_MOD_TEXTURE_COORD JUCE_HIGHP " vec2 texturePos = clamp (mod (" JUCE_MATRIX_TIMES_FRAGCOORD ", imageLimits.zw + imageLimits.xy), imageLimits.xy, imageLimits.zw);" struct ImageProgram : public ShaderBase { ImageProgram (OpenGLContext& context) - : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS + : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_CLAMP_TEXTURE_COORD @@ -541,7 +552,7 @@ public: struct ImageMaskedProgram : public ShaderBase { ImageMaskedProgram (OpenGLContext& context) - : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_MASK_UNIFORMS + : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_MASK_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_CLAMP_TEXTURE_COORD @@ -558,7 +569,7 @@ public: struct TiledImageProgram : public ShaderBase { TiledImageProgram (OpenGLContext& context) - : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS + : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_MOD_TEXTURE_COORD @@ -573,7 +584,7 @@ public: struct TiledImageMaskedProgram : public ShaderBase { TiledImageMaskedProgram (OpenGLContext& context) - : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_MASK_UNIFORMS + : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_MASK_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_MOD_TEXTURE_COORD @@ -590,7 +601,7 @@ public: struct CopyTextureProgram : public ShaderBase { CopyTextureProgram (OpenGLContext& context) - : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS + : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_MOD_TEXTURE_COORD @@ -605,11 +616,11 @@ public: struct MaskTextureProgram : public ShaderBase { MaskTextureProgram (OpenGLContext& context) - : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS + : ShaderBase (context, JUCE_DECLARE_IMAGE_UNIFORMS JUCE_DECLARE_SWIZZLE_FUNCTION "void main()" "{" JUCE_HIGHP " vec2 texturePos = " JUCE_MATRIX_TIMES_FRAGCOORD ";" - "const float roundingError = 0.00001;" + JUCE_HIGHP " float roundingError = 0.00001;" "if (texturePos.x >= imageLimits.x - roundingError" "&& texturePos.y >= imageLimits.y - roundingError" "&& texturePos.x <= imageLimits.z + roundingError" @@ -946,7 +957,9 @@ struct StateHelpers if ((texturesEnabled & (1 << i)) != (textureIndexMask & (1 << i))) { setActiveTexture (i); + JUCE_CHECK_OPENGL_ERROR + #if ! JUCE_ANDROID if ((textureIndexMask & (1 << i)) != 0) glEnable (GL_TEXTURE_2D); else @@ -954,6 +967,9 @@ struct StateHelpers glDisable (GL_TEXTURE_2D); currentTextureID[i] = 0; } + + JUCE_CHECK_OPENGL_ERROR + #endif } } @@ -977,6 +993,7 @@ struct StateHelpers template void setTwoTextureMode (QuadQueueType& quadQueue, GLuint texture1, GLuint texture2) { + JUCE_CHECK_OPENGL_ERROR setTexturesEnabled (quadQueue, 3); if (currentActiveTexture == 0) @@ -992,6 +1009,7 @@ struct StateHelpers setActiveTexture (0); bindTexture (texture1); } + JUCE_CHECK_OPENGL_ERROR } void setActiveTexture (const int index) noexcept @@ -1000,9 +1018,11 @@ struct StateHelpers { currentActiveTexture = index; context.extensions.glActiveTexture (GL_TEXTURE0 + index); + JUCE_CHECK_OPENGL_ERROR #if JUCE_USE_OPENGL_FIXED_FUNCTION context.extensions.glClientActiveTexture (GL_TEXTURE0 + index); + JUCE_CHECK_OPENGL_ERROR #endif } } @@ -1013,6 +1033,7 @@ struct StateHelpers { currentTextureID [currentActiveTexture] = textureID; glBindTexture (GL_TEXTURE_2D, textureID); + JUCE_CHECK_OPENGL_ERROR } else { @@ -1085,6 +1106,7 @@ struct StateHelpers activeGradientIndex = (activeGradientIndex + 1) % numGradientTexturesToCache; } + JUCE_CHECK_OPENGL_ERROR; PixelARGB lookup [gradientTextureSize]; gradient.createLookupTable (lookup, gradientTextureSize); gradientTextures.getUnchecked (activeGradientIndex)->loadARGB (lookup, gradientTextureSize, 1); @@ -1118,6 +1140,8 @@ struct StateHelpers void initialise() noexcept { + JUCE_CHECK_OPENGL_ERROR + for (int i = 0, v = 0; i < numQuads * 6; i += 6, v += 4) { indexData[i] = (GLushort) v; @@ -1130,6 +1154,8 @@ struct StateHelpers context.extensions.glBindBuffer (GL_ARRAY_BUFFER, buffers[0]); context.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffers[1]); context.extensions.glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indexData), indexData, GL_STATIC_DRAW); + + JUCE_CHECK_OPENGL_ERROR } void add (const int x, const int y, const int w, const int h, const PixelARGB& colour) noexcept @@ -1252,6 +1278,8 @@ struct StateHelpers currentBounds = bounds; shader.set2DBounds (bounds.toFloat()); + + JUCE_CHECK_OPENGL_ERROR } else if (bounds != currentBounds) { @@ -1305,6 +1333,7 @@ public: // This object can only be created and used when the current thread has an active OpenGL context. jassert (OpenGLHelpers::isContextActive()); + JUCE_CHECK_OPENGL_ERROR target.makeActiveFor2D(); blendMode.resync(); @@ -1312,6 +1341,8 @@ public: currentColour.resync(); #endif + JUCE_CHECK_OPENGL_ERROR + #ifdef GL_COLOR_ARRAY glDisableClientState (GL_COLOR_ARRAY); glDisableClientState (GL_NORMAL_ARRAY); @@ -1341,6 +1372,7 @@ public: } #endif + JUCE_CHECK_OPENGL_ERROR activeTextures.clear(); #if JUCE_USE_OPENGL_FIXED_FUNCTION @@ -1352,6 +1384,8 @@ public: #if JUCE_USE_OPENGL_SHADERS shaderQuadQueue.initialise(); #endif + + JUCE_CHECK_OPENGL_ERROR } ~GLState() @@ -1378,6 +1412,8 @@ public: #if JUCE_USE_OPENGL_FIXED_FUNCTION quadQueue.flush(); #endif + + JUCE_CHECK_OPENGL_ERROR } #if JUCE_USE_OPENGL_FIXED_FUNCTION @@ -1653,13 +1689,16 @@ public: void setShader (ShaderPrograms::ShaderBase& shader) { currentShader.setShader (target, shaderQuadQueue, shader); + JUCE_CHECK_OPENGL_ERROR } void setShaderForGradientFill (const ColourGradient& g, const AffineTransform& transform, const int maskTextureID, const Rectangle* const maskArea) { + JUCE_CHECK_OPENGL_ERROR activeTextures.disableTextures (shaderQuadQueue); blendMode.setPremultipliedBlendingMode (shaderQuadQueue); + JUCE_CHECK_OPENGL_ERROR; if (maskArea != nullptr) { @@ -1749,6 +1788,8 @@ public: if (maskParams != nullptr) maskParams->setBounds (*maskArea, target, 1); + + JUCE_CHECK_OPENGL_ERROR } void setShaderForTiledImageFill (const OpenGLTextureFromImage& image, const AffineTransform& transform, diff --git a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp index aad51f9485..0e4163318a 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp @@ -187,7 +187,9 @@ void OpenGLHelpers::drawQuad3D (float x1, float y1, float z1, void OpenGLHelpers::drawTriangleStrip (const GLfloat* const vertices, const GLfloat* const textureCoords, const int numVertices) noexcept { + #if ! JUCE_ANDROID glEnable (GL_TEXTURE_2D); + #endif glDisableClientState (GL_COLOR_ARRAY); glDisableClientState (GL_NORMAL_ARRAY); glEnableClientState (GL_VERTEX_ARRAY); @@ -257,6 +259,7 @@ OpenGLTextureFromImage::OpenGLTextureFromImage (const Image& image) : imageWidth (image.getWidth()), imageHeight (image.getHeight()) { + JUCE_CHECK_OPENGL_ERROR; OpenGLFrameBuffer* const fb = OpenGLImageType::getFrameBufferFrom (image); if (fb != nullptr) @@ -274,6 +277,8 @@ OpenGLTextureFromImage::OpenGLTextureFromImage (const Image& image) fullWidthProportion = imageWidth / (float) texture->getWidth(); fullHeightProportion = imageHeight / (float) texture->getHeight(); } + + JUCE_CHECK_OPENGL_ERROR; } OpenGLTextureFromImage::~OpenGLTextureFromImage() {} diff --git a/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp b/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp index 70697ca8ee..0811b3f2df 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.cpp @@ -76,6 +76,7 @@ bool OpenGLShaderProgram::addShader (const char* const code, GLenum type) context.extensions.glAttachShader (programID, shaderID); context.extensions.glDeleteShader (shaderID); + JUCE_CHECK_OPENGL_ERROR; return true; } @@ -99,6 +100,7 @@ bool OpenGLShaderProgram::link() noexcept #endif } + JUCE_CHECK_OPENGL_ERROR; return status != GL_FALSE; } diff --git a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp index 2af7a758a7..ad8f6ad139 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLTexture.cpp @@ -51,21 +51,26 @@ void OpenGLTexture::create (const int w, const int h, const void* pixels, GLenum if (textureID == 0) { + JUCE_CHECK_OPENGL_ERROR; glGenTextures (1, &textureID); glBindTexture (GL_TEXTURE_2D, textureID); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + JUCE_CHECK_OPENGL_ERROR; } else { glBindTexture (GL_TEXTURE_2D, textureID); + JUCE_CHECK_OPENGL_ERROR; } glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + JUCE_CHECK_OPENGL_ERROR; glTexImage2D (GL_TEXTURE_2D, 0, type == GL_ALPHA ? GL_ALPHA : GL_RGBA, w, h, 0, type, GL_UNSIGNED_BYTE, pixels); + JUCE_CHECK_OPENGL_ERROR; } template @@ -107,13 +112,13 @@ void OpenGLTexture::loadImage (const Image& image) default: break; } - create (textureW, textureH, dataCopy, GL_BGRA_EXT); + create (textureW, textureH, dataCopy, JUCE_RGBA_FORMAT); } void OpenGLTexture::loadARGB (const PixelARGB* pixels, const int w, const int h) { jassert (isValidSize (w, h)); - create (w, h, pixels, GL_BGRA_EXT); + create (w, h, pixels, JUCE_RGBA_FORMAT); } void OpenGLTexture::loadAlpha (const uint8* pixels, int w, int h)