| @@ -160,7 +160,7 @@ public: | |||
| { | |||
| #if JUCE_OPENGL | |||
| if (shouldUseOpenGL && currentDemoId != showOpenGL) | |||
| openGLContext.attachTo (*this); | |||
| openGLContext.attachTo (*getTopLevelComponent()); | |||
| else | |||
| openGLContext.detach(); | |||
| #endif | |||
| @@ -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<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() | |||
| @@ -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; | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| } | |||
| @@ -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<int> bounds (component.getLocalBounds()); | |||
| ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight()); | |||
| if (! ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight())) | |||
| return; | |||
| RectangleList invalid (bounds); | |||
| invalid.subtract (validArea); | |||
| @@ -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; | |||
| @@ -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 | |||
| } | |||
| @@ -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<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) | |||