| @@ -160,7 +160,7 @@ public: | |||||
| { | { | ||||
| #if JUCE_OPENGL | #if JUCE_OPENGL | ||||
| if (shouldUseOpenGL && currentDemoId != showOpenGL) | if (shouldUseOpenGL && currentDemoId != showOpenGL) | ||||
| openGLContext.attachTo (*this); | |||||
| openGLContext.attachTo (*getTopLevelComponent()); | |||||
| else | else | ||||
| openGLContext.detach(); | openGLContext.detach(); | ||||
| #endif | #endif | ||||
| @@ -138,16 +138,17 @@ public: | |||||
| OpenGLFrameBuffer* tex1 = OpenGLImageType::getFrameBufferFrom (logoImage); | OpenGLFrameBuffer* tex1 = OpenGLImageType::getFrameBufferFrom (logoImage); | ||||
| OpenGLFrameBuffer* tex2 = OpenGLImageType::getFrameBufferFrom (dynamicTextureImage); | 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 | #endif | ||||
| } | } | ||||
| @@ -156,34 +157,41 @@ public: | |||||
| // This image is a special framebuffer-backed image, so when we draw to it, the context | // This image is a special framebuffer-backed image, so when we draw to it, the context | ||||
| // will render directly into its framebuffer | // 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() | void drawBackground2DStuff() | ||||
| { | { | ||||
| // Create an OpenGLGraphicsContext that will draw into this GL window.. | // Create an OpenGLGraphicsContext that will draw into this GL window.. | ||||
| ScopedPointer<LowLevelGraphicsContext> glRenderer (createOpenGLGraphicsContext (openGLContext)); | ScopedPointer<LowLevelGraphicsContext> 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<float> (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<float> (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() | void timerCallback() | ||||
| @@ -207,13 +215,17 @@ private: | |||||
| { | { | ||||
| Image image (Image::ARGB, 256, 256, true, OpenGLImageType()); | 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; | return image; | ||||
| } | } | ||||
| @@ -23,8 +23,6 @@ | |||||
| ============================================================================== | ============================================================================== | ||||
| */ | */ | ||||
| #if JUCE_WINDOWS | |||||
| namespace WindowsMediaCodec | namespace WindowsMediaCodec | ||||
| { | { | ||||
| @@ -345,5 +343,3 @@ AudioFormatWriter* WindowsMediaAudioFormat::createWriterFor (OutputStream* /*str | |||||
| jassertfalse; // not yet implemented! | jassertfalse; // not yet implemented! | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| #endif | |||||
| @@ -98,7 +98,6 @@ namespace juce | |||||
| #include "../juce_core/native/juce_win32_ComSmartPtr.h" | #include "../juce_core/native/juce_win32_ComSmartPtr.h" | ||||
| #endif | #endif | ||||
| // START_AUTOINCLUDE format/*.cpp, sampler/*.cpp, codecs/*.cpp | |||||
| #include "format/juce_AudioFormat.cpp" | #include "format/juce_AudioFormat.cpp" | ||||
| #include "format/juce_AudioFormatManager.cpp" | #include "format/juce_AudioFormatManager.cpp" | ||||
| #include "format/juce_AudioFormatReader.cpp" | #include "format/juce_AudioFormatReader.cpp" | ||||
| @@ -113,7 +112,9 @@ namespace juce | |||||
| #include "codecs/juce_OggVorbisAudioFormat.cpp" | #include "codecs/juce_OggVorbisAudioFormat.cpp" | ||||
| #include "codecs/juce_QuickTimeAudioFormat.cpp" | #include "codecs/juce_QuickTimeAudioFormat.cpp" | ||||
| #include "codecs/juce_WavAudioFormat.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 | |||||
| } | } | ||||
| @@ -101,17 +101,21 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void ensureFrameBufferSize (int width, int height) | |||||
| bool ensureFrameBufferSize (int width, int height) | |||||
| { | { | ||||
| const int fbW = cachedImageFrameBuffer.getWidth(); | const int fbW = cachedImageFrameBuffer.getWidth(); | ||||
| const int fbH = cachedImageFrameBuffer.getHeight(); | const int fbH = cachedImageFrameBuffer.getHeight(); | ||||
| if (fbW != width || fbH != height || ! cachedImageFrameBuffer.isValid()) | if (fbW != width || fbH != height || ! cachedImageFrameBuffer.isValid()) | ||||
| { | { | ||||
| cachedImageFrameBuffer.initialise (context, width, height); | |||||
| if (! cachedImageFrameBuffer.initialise (context, width, height)) | |||||
| return false; | |||||
| validArea.clear(); | validArea.clear(); | ||||
| JUCE_CHECK_OPENGL_ERROR | JUCE_CHECK_OPENGL_ERROR | ||||
| } | } | ||||
| return true; | |||||
| } | } | ||||
| void clearRegionInFrameBuffer (const RectangleList& list) | void clearRegionInFrameBuffer (const RectangleList& list) | ||||
| @@ -169,7 +173,8 @@ public: | |||||
| jassert (get (component) == this); | jassert (get (component) == this); | ||||
| const Rectangle<int> bounds (component.getLocalBounds()); | const Rectangle<int> bounds (component.getLocalBounds()); | ||||
| ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight()); | |||||
| if (! ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight())) | |||||
| return; | |||||
| RectangleList invalid (bounds); | RectangleList invalid (bounds); | ||||
| invalid.subtract (validArea); | invalid.subtract (validArea); | ||||
| @@ -35,8 +35,7 @@ public: | |||||
| frameBufferID (0), | frameBufferID (0), | ||||
| depthOrStencilBuffer (0), | depthOrStencilBuffer (0), | ||||
| hasDepthBuffer (false), | hasDepthBuffer (false), | ||||
| hasStencilBuffer (false), | |||||
| ok (true) | |||||
| hasStencilBuffer (false) | |||||
| { | { | ||||
| // Framebuffer objects can only be created when the current thread has an active OpenGL | // 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. | // 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() | void bind() | ||||
| { | { | ||||
| context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID); | context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, frameBufferID); | ||||
| @@ -126,7 +130,7 @@ public: | |||||
| OpenGLContext& context; | OpenGLContext& context; | ||||
| const int width, height; | const int width, height; | ||||
| GLuint textureID, frameBufferID, depthOrStencilBuffer; | GLuint textureID, frameBufferID, depthOrStencilBuffer; | ||||
| bool hasDepthBuffer, hasStencilBuffer, ok; | |||||
| bool hasDepthBuffer, hasStencilBuffer; | |||||
| private: | private: | ||||
| bool checkStatus() noexcept | bool checkStatus() noexcept | ||||
| @@ -180,7 +184,7 @@ bool OpenGLFrameBuffer::initialise (OpenGLContext& context, int width, int heigh | |||||
| pimpl = nullptr; | pimpl = nullptr; | ||||
| pimpl = new Pimpl (context, width, height, false, false); | pimpl = new Pimpl (context, width, height, false, false); | ||||
| if (! pimpl->ok) | |||||
| if (! pimpl->createdOk()) | |||||
| pimpl = nullptr; | pimpl = nullptr; | ||||
| return pimpl != nullptr; | return pimpl != nullptr; | ||||
| @@ -52,7 +52,11 @@ struct Target | |||||
| void makeActive() const noexcept | 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()); | glViewport (0, 0, bounds.getWidth(), bounds.getHeight()); | ||||
| glDisable (GL_DEPTH_TEST); | glDisable (GL_DEPTH_TEST); | ||||
| } | } | ||||
| @@ -2199,7 +2203,12 @@ public: | |||||
| texture.getHeight()), | texture.getHeight()), | ||||
| target.bounds.getWidth(), target.bounds.getHeight()); | target.bounds.getWidth(), target.bounds.getHeight()); | ||||
| glBindTexture (GL_TEXTURE_2D, 0); | 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 | JUCE_CHECK_OPENGL_ERROR | ||||
| } | } | ||||
| @@ -32,8 +32,11 @@ public: | |||||
| pixelStride (4), | pixelStride (4), | ||||
| lineStride (width * pixelStride) | lineStride (width * pixelStride) | ||||
| { | { | ||||
| frameBuffer.initialise (context, width, height); | |||||
| frameBuffer.clear (Colours::transparentBlack); | |||||
| } | |||||
| bool initialise() | |||||
| { | |||||
| return frameBuffer.initialise (context, width, height); | |||||
| } | } | ||||
| LowLevelGraphicsContext* createLowLevelContext() | LowLevelGraphicsContext* createLowLevelContext() | ||||
| @@ -175,17 +178,18 @@ int OpenGLImageType::getTypeID() const | |||||
| return 3; | 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(); | OpenGLContext* currentContext = OpenGLContext::getCurrentContext(); | ||||
| jassert (currentContext != nullptr); // an OpenGL image can only be created when a valid context is active! | jassert (currentContext != nullptr); // an OpenGL image can only be created when a valid context is active! | ||||
| OpenGLFrameBufferImage* im = new OpenGLFrameBufferImage (*currentContext, width, height); | |||||
| ScopedPointer<OpenGLFrameBufferImage> 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) | OpenGLFrameBuffer* OpenGLImageType::getFrameBufferFrom (const Image& image) | ||||