From 04c2d6cfc1c5228bca3346ead6a821784a4238a7 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 3 Apr 2012 14:51:22 +0100 Subject: [PATCH] Added some GL error handling and tweaks to support older PC builds. --- extras/JuceDemo/Source/MainDemoWindow.cpp | 2 +- extras/JuceDemo/Source/demos/OpenGLDemo.cpp | 82 +++++++++++-------- .../codecs/juce_WindowsMediaAudioFormat.cpp | 4 - .../juce_audio_formats/juce_audio_formats.cpp | 7 +- .../juce_opengl/opengl/juce_OpenGLContext.cpp | 11 ++- .../opengl/juce_OpenGLFrameBuffer.cpp | 12 ++- .../opengl/juce_OpenGLGraphicsContext.cpp | 13 ++- .../juce_opengl/opengl/juce_OpenGLImage.cpp | 18 ++-- 8 files changed, 90 insertions(+), 59 deletions(-) diff --git a/extras/JuceDemo/Source/MainDemoWindow.cpp b/extras/JuceDemo/Source/MainDemoWindow.cpp index 19392581d4..e020b74207 100644 --- a/extras/JuceDemo/Source/MainDemoWindow.cpp +++ b/extras/JuceDemo/Source/MainDemoWindow.cpp @@ -160,7 +160,7 @@ public: { #if JUCE_OPENGL if (shouldUseOpenGL && currentDemoId != showOpenGL) - openGLContext.attachTo (*this); + openGLContext.attachTo (*getTopLevelComponent()); else openGLContext.detach(); #endif diff --git a/extras/JuceDemo/Source/demos/OpenGLDemo.cpp b/extras/JuceDemo/Source/demos/OpenGLDemo.cpp index 9b8506d704..0da9bc2180 100644 --- a/extras/JuceDemo/Source/demos/OpenGLDemo.cpp +++ b/extras/JuceDemo/Source/demos/OpenGLDemo.cpp @@ -138,16 +138,17 @@ public: OpenGLFrameBuffer* tex1 = OpenGLImageType::getFrameBufferFrom (logoImage); OpenGLFrameBuffer* tex2 = OpenGLImageType::getFrameBufferFrom (dynamicTextureImage); - jassert (tex1 != nullptr && tex2 != nullptr); // (this would mean that our images weren't created correctly) - - // This draws the sides of our spinning cube. - // I've used some of the juce helper functions, but you can also just use normal GL calls here too. - tex1->draw3D (-1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, Colours::white); - tex1->draw3D (-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, Colours::white); - tex1->draw3D (-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, Colours::white); - tex2->draw3D (-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, Colours::white); - tex2->draw3D ( 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, Colours::white); - tex2->draw3D (-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, Colours::white); + if (tex1 != nullptr && tex2 != nullptr) + { + // This draws the sides of our spinning cube. + // I've used some of the juce helper functions, but you can also just use normal GL calls here too. + tex1->draw3D (-1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, Colours::white); + tex1->draw3D (-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, Colours::white); + tex1->draw3D (-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, Colours::white); + tex2->draw3D (-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, Colours::white); + tex2->draw3D ( 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, Colours::white); + tex2->draw3D (-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, Colours::white); + } #endif } @@ -156,34 +157,41 @@ public: // This image is a special framebuffer-backed image, so when we draw to it, the context // will render directly into its framebuffer - dynamicTextureImage.clear (dynamicTextureImage.getBounds(), - Colours::red.withRotatedHue (fabsf (::sinf (rotation / 300.0f))).withAlpha (0.7f)); + if (dynamicTextureImage.isValid()) + { + dynamicTextureImage.clear (dynamicTextureImage.getBounds(), + Colours::red.withRotatedHue (fabsf (::sinf (rotation / 300.0f))).withAlpha (0.7f)); - Graphics g (dynamicTextureImage); + Graphics g (dynamicTextureImage); - g.setFont (dynamicTextureImage.getHeight() / 3.0f); - g.setColour (Colours::black); - drawScrollingMessage (g, dynamicTextureImage.getHeight() / 2); + g.setFont (dynamicTextureImage.getHeight() / 3.0f); + g.setColour (Colours::black); + drawScrollingMessage (g, dynamicTextureImage.getHeight() / 2); + } } void drawBackground2DStuff() { // Create an OpenGLGraphicsContext that will draw into this GL window.. ScopedPointer glRenderer (createOpenGLGraphicsContext (openGLContext)); - Graphics g (glRenderer); - - // This stuff just creates a spinning star shape and fills it.. - Path p; - const float scale = getHeight() * 0.4f; - p.addStar (Point (getWidth() * 0.7f, getHeight() * 0.4f), 7, - scale * (float) sizeSlider.getValue(), scale, - rotation / 50.0f); - - g.setGradientFill (ColourGradient (Colours::green.withRotatedHue (fabsf (::sinf (rotation / 300.0f))), - 0, 0, - Colours::green.withRotatedHue (fabsf (::cosf (rotation / -431.0f))), - 0, (float) getHeight(), false)); - g.fillPath (p); + + if (createOpenGLGraphicsContext != nullptr) + { + Graphics g (glRenderer); + + // This stuff just creates a spinning star shape and fills it.. + Path p; + const float scale = getHeight() * 0.4f; + p.addStar (Point (getWidth() * 0.7f, getHeight() * 0.4f), 7, + scale * (float) sizeSlider.getValue(), scale, + rotation / 50.0f); + + g.setGradientFill (ColourGradient (Colours::green.withRotatedHue (fabsf (::sinf (rotation / 300.0f))), + 0, 0, + Colours::green.withRotatedHue (fabsf (::cosf (rotation / -431.0f))), + 0, (float) getHeight(), false)); + g.fillPath (p); + } } void timerCallback() @@ -207,13 +215,17 @@ private: { Image image (Image::ARGB, 256, 256, true, OpenGLImageType()); - Graphics g (image); + if (image.isValid()) + { + Graphics g (image); - g.fillAll (Colours::lightgrey.withAlpha (0.8f)); - g.drawImageWithin (ImageFileFormat::loadFrom (BinaryData::juce_png, BinaryData::juce_pngSize), - 0, 0, image.getWidth(), image.getHeight(), RectanglePlacement::stretchToFit); + g.fillAll (Colours::lightgrey.withAlpha (0.8f)); + g.drawImageWithin (ImageFileFormat::loadFrom (BinaryData::juce_png, BinaryData::juce_pngSize), + 0, 0, image.getWidth(), image.getHeight(), RectanglePlacement::stretchToFit); + + drawRandomStars (g, image.getWidth(), image.getHeight()); + } - drawRandomStars (g, image.getWidth(), image.getHeight()); return image; } diff --git a/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp b/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp index 500025e806..47db879ec9 100644 --- a/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp +++ b/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp @@ -23,8 +23,6 @@ ============================================================================== */ -#if JUCE_WINDOWS - namespace WindowsMediaCodec { @@ -345,5 +343,3 @@ AudioFormatWriter* WindowsMediaAudioFormat::createWriterFor (OutputStream* /*str jassertfalse; // not yet implemented! return nullptr; } - -#endif diff --git a/modules/juce_audio_formats/juce_audio_formats.cpp b/modules/juce_audio_formats/juce_audio_formats.cpp index a35978173f..ed543703e5 100644 --- a/modules/juce_audio_formats/juce_audio_formats.cpp +++ b/modules/juce_audio_formats/juce_audio_formats.cpp @@ -98,7 +98,6 @@ namespace juce #include "../juce_core/native/juce_win32_ComSmartPtr.h" #endif -// START_AUTOINCLUDE format/*.cpp, sampler/*.cpp, codecs/*.cpp #include "format/juce_AudioFormat.cpp" #include "format/juce_AudioFormatManager.cpp" #include "format/juce_AudioFormatReader.cpp" @@ -113,7 +112,9 @@ namespace juce #include "codecs/juce_OggVorbisAudioFormat.cpp" #include "codecs/juce_QuickTimeAudioFormat.cpp" #include "codecs/juce_WavAudioFormat.cpp" -#include "codecs/juce_WindowsMediaAudioFormat.cpp" -// END_AUTOINCLUDE + +#if JUCE_WINDOWS && JUCE_USE_WINDOWS_MEDIA_FORMAT + #include "codecs/juce_WindowsMediaAudioFormat.cpp" +#endif } diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index 033b27858d..431482af74 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -101,17 +101,21 @@ public: } //============================================================================== - void ensureFrameBufferSize (int width, int height) + bool ensureFrameBufferSize (int width, int height) { const int fbW = cachedImageFrameBuffer.getWidth(); const int fbH = cachedImageFrameBuffer.getHeight(); if (fbW != width || fbH != height || ! cachedImageFrameBuffer.isValid()) { - cachedImageFrameBuffer.initialise (context, width, height); + if (! cachedImageFrameBuffer.initialise (context, width, height)) + return false; + validArea.clear(); JUCE_CHECK_OPENGL_ERROR } + + return true; } void clearRegionInFrameBuffer (const RectangleList& list) @@ -169,7 +173,8 @@ public: jassert (get (component) == this); const Rectangle bounds (component.getLocalBounds()); - ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight()); + if (! ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight())) + return; RectangleList invalid (bounds); invalid.subtract (validArea); diff --git a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp index e6c56ee3f4..3cf0900db9 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp @@ -35,8 +35,7 @@ public: frameBufferID (0), depthOrStencilBuffer (0), hasDepthBuffer (false), - hasStencilBuffer (false), - ok (true) + hasStencilBuffer (false) { // Framebuffer objects can only be created when the current thread has an active OpenGL // context. You'll need to create this object in one of the OpenGLContext's callbacks. @@ -111,6 +110,11 @@ public: } } + bool createdOk() const + { + return frameBufferID != 0 && textureID != 0; + } + void bind() { context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID); @@ -126,7 +130,7 @@ public: OpenGLContext& context; const int width, height; GLuint textureID, frameBufferID, depthOrStencilBuffer; - bool hasDepthBuffer, hasStencilBuffer, ok; + bool hasDepthBuffer, hasStencilBuffer; private: bool checkStatus() noexcept @@ -180,7 +184,7 @@ bool OpenGLFrameBuffer::initialise (OpenGLContext& context, int width, int heigh pimpl = nullptr; pimpl = new Pimpl (context, width, height, false, false); - if (! pimpl->ok) + if (! pimpl->createdOk()) pimpl = nullptr; return pimpl != nullptr; diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp index 5fb76a82d7..44e058dfd4 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -52,7 +52,11 @@ struct Target void makeActive() const noexcept { - context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID); + #if JUCE_WINDOWS + if (context.extensions.glBindFramebuffer != nullptr) + #endif + context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID); + glViewport (0, 0, bounds.getWidth(), bounds.getHeight()); glDisable (GL_DEPTH_TEST); } @@ -2199,7 +2203,12 @@ public: texture.getHeight()), target.bounds.getWidth(), target.bounds.getHeight()); glBindTexture (GL_TEXTURE_2D, 0); - target.context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, previousFrameBufferTarget); + + #if JUCE_WINDOWS + if (target.context.extensions.glBindFramebuffer != nullptr) + #endif + target.context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, previousFrameBufferTarget); + JUCE_CHECK_OPENGL_ERROR } diff --git a/modules/juce_opengl/opengl/juce_OpenGLImage.cpp b/modules/juce_opengl/opengl/juce_OpenGLImage.cpp index 7d9581b2ea..5843490262 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLImage.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLImage.cpp @@ -32,8 +32,11 @@ public: pixelStride (4), lineStride (width * pixelStride) { - frameBuffer.initialise (context, width, height); - frameBuffer.clear (Colours::transparentBlack); + } + + bool initialise() + { + return frameBuffer.initialise (context, width, height); } LowLevelGraphicsContext* createLowLevelContext() @@ -175,17 +178,18 @@ int OpenGLImageType::getTypeID() const return 3; } -ImagePixelData* OpenGLImageType::create (Image::PixelFormat, int width, int height, bool shouldClearImage) const +ImagePixelData* OpenGLImageType::create (Image::PixelFormat, int width, int height, bool /*shouldClearImage*/) const { OpenGLContext* currentContext = OpenGLContext::getCurrentContext(); jassert (currentContext != nullptr); // an OpenGL image can only be created when a valid context is active! - OpenGLFrameBufferImage* im = new OpenGLFrameBufferImage (*currentContext, width, height); + ScopedPointer im (new OpenGLFrameBufferImage (*currentContext, width, height)); - if (shouldClearImage) - im->frameBuffer.clear (Colours::transparentBlack); + if (! im->initialise()) + return nullptr; - return im; + im->frameBuffer.clear (Colours::transparentBlack); + return im.release(); } OpenGLFrameBuffer* OpenGLImageType::getFrameBufferFrom (const Image& image)