From 04c35b28e6d4bfe536cecbfc310629abb65afa36 Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 24 Oct 2011 21:02:56 +0100 Subject: [PATCH] OpenGL refactoring. --- extras/JuceDemo/Source/demos/OpenGLDemo.cpp | 59 +++++----------- modules/juce_graphics/images/juce_Image.h | 2 +- .../native/juce_android_OpenGLComponent.cpp | 5 +- .../native/juce_ios_OpenGLComponent.mm | 14 ++-- .../native/juce_linux_OpenGLComponent.cpp | 26 ++++--- .../native/juce_mac_OpenGLComponent.mm | 68 ++++--------------- .../native/juce_win32_OpenGLComponent.cpp | 39 ++++++----- .../opengl/juce_OpenGLComponent.cpp | 13 +--- .../juce_opengl/opengl/juce_OpenGLComponent.h | 6 +- .../juce_opengl/opengl/juce_OpenGLContext.h | 11 --- .../opengl/juce_OpenGLGraphicsContext.cpp | 2 +- .../opengl/juce_OpenGLPixelFormat.h | 10 --- 12 files changed, 81 insertions(+), 174 deletions(-) diff --git a/extras/JuceDemo/Source/demos/OpenGLDemo.cpp b/extras/JuceDemo/Source/demos/OpenGLDemo.cpp index ee1f4a8e2a..f5ddf2abc8 100644 --- a/extras/JuceDemo/Source/demos/OpenGLDemo.cpp +++ b/extras/JuceDemo/Source/demos/OpenGLDemo.cpp @@ -37,36 +37,14 @@ public: delta (1.0f) { startTimer (20); - - // Just for demo purposes, let's dump a list of all the available pixel formats.. - OwnedArray availablePixelFormats; - OpenGLPixelFormat::getAvailablePixelFormats (this, availablePixelFormats); - - for (int i = 0; i < availablePixelFormats.size(); ++i) - { - const OpenGLPixelFormat* const pixFormat = availablePixelFormats[i]; - - DBG (i << ": RGBA=(" << pixFormat->redBits - << ", " << pixFormat->greenBits - << ", " << pixFormat->blueBits - << ", " << pixFormat->alphaBits - << "), depth=" << pixFormat->depthBufferBits - << ", stencil=" << pixFormat->stencilBufferBits - << ", accum RGBA=(" << pixFormat->accumulationBufferRedBits - << ", " << pixFormat->accumulationBufferGreenBits - << ", " << pixFormat->accumulationBufferBlueBits - << ", " << pixFormat->accumulationBufferAlphaBits - << "), full-scene AA=" - << (int) pixFormat->fullSceneAntiAliasingNumSamples); - } } // when the component creates a new internal context, this is called, and // we'll use the opportunity to create the textures needed. void newOpenGLContextCreated() { - texture1 = createImage1(); - texture2 = createImage2(); + texture1.load (createImage1()); + texture2.load (createImage2()); // (no need to call makeCurrentContextActive(), as that will have // been done for us before the method call). @@ -89,20 +67,17 @@ public: void renderOpenGL() { - OpenGLHelpers::clear (Colours::darkgrey.withAlpha (0.0f)); + OpenGLHelpers::clear (Colours::darkgrey.withAlpha (1.0f)); OpenGLHelpers::prepareFor2D (getWidth(), getHeight()); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - OpenGLFrameBuffer& frameBuffer1 = dynamic_cast (texture1.getSharedImage())->frameBuffer; - OpenGLFrameBuffer& frameBuffer2 = dynamic_cast (texture2.getSharedImage())->frameBuffer; - - frameBuffer1.draw2D (50.0f, getHeight() - 50.0f, - getWidth() - 50.0f, getHeight() - 50.0f, - getWidth() - 50.0f, 50.0f, - 50.0f, 50.0f, - Colours::white.withAlpha (fabsf (::sinf (rotation / 100.0f)))); + texture1.draw2D (50.0f, getHeight() - 50.0f, + getWidth() - 50.0f, getHeight() - 50.0f, + getWidth() - 50.0f, 50.0f, + 50.0f, 50.0f, + Colours::white.withAlpha (fabsf (::sinf (rotation / 100.0f)))); glClear (GL_DEPTH_BUFFER_BIT); @@ -112,12 +87,12 @@ public: glRotatef (rotation, 0.5f, 1.0f, 0.0f); // this draws the sides of our spinning cube.. - frameBuffer1.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); - frameBuffer1.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); - frameBuffer1.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); - frameBuffer2.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); - frameBuffer2.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); - frameBuffer2.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); + texture1.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); + texture1.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); + texture1.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); + texture2.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); + texture2.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); + texture2.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); } void timerCallback() @@ -127,13 +102,13 @@ public: } private: - Image texture1, texture2; + OpenGLTexture texture1, texture2; float rotation, delta; // Functions to create a couple of images to use as textures.. static Image createImage1() { - Image image (new OpenGLFrameBufferImage (256, 256)); + Image image (Image::ARGB, 256, 256, true); Graphics g (image); @@ -148,7 +123,7 @@ private: static Image createImage2() { - Image image (new OpenGLFrameBufferImage (128, 128)); + Image image (Image::ARGB, 128, 128, true); Graphics g (image); g.fillAll (Colours::darkred.withAlpha (0.7f)); diff --git a/modules/juce_graphics/images/juce_Image.h b/modules/juce_graphics/images/juce_Image.h index 8953f7eb66..fae09943c1 100644 --- a/modules/juce_graphics/images/juce_Image.h +++ b/modules/juce_graphics/images/juce_Image.h @@ -158,7 +158,7 @@ public: /** Returns a rectangle with the same size as this image. The rectangle's origin is always (0, 0). */ - const Rectangle getBounds() const noexcept { return image == nullptr ? Rectangle() : Rectangle (image->width, image->height); } + Rectangle getBounds() const noexcept { return image == nullptr ? Rectangle() : Rectangle (image->width, image->height); } /** Returns the image's pixel format. */ PixelFormat getFormat() const noexcept { return image == nullptr ? UnknownFormat : image->format; } diff --git a/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp b/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp index ecac95a7b2..1312fe88b4 100644 --- a/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp +++ b/modules/juce_opengl/native/juce_android_OpenGLComponent.cpp @@ -34,10 +34,9 @@ void* OpenGLComponent::getNativeWindowHandle() const return nullptr; } -void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, - OwnedArray & results) +void OpenGLComponent::internalRepaint (int x, int y, int w, int h) { - + Component::internalRepaint (x, y, w, h); } bool OpenGLHelpers::isContextActive() diff --git a/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm b/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm index 9eae7bf6d7..3fbac4871f 100644 --- a/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm +++ b/modules/juce_opengl/native/juce_ios_OpenGLComponent.mm @@ -143,10 +143,6 @@ public: return numFrames; } - void repaint() - { - } - //============================================================================== void createGLBuffers() { @@ -231,9 +227,15 @@ OpenGLContext* OpenGLComponent::createContext() return nullptr; } -void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/, - OwnedArray & /*results*/) +void OpenGLComponent::internalRepaint (int x, int y, int w, int h) { + Component::internalRepaint (x, y, w, h); +} + +void OpenGLComponent::updateEmbeddedPosition (const Rectangle& bounds) +{ + if (context != nullptr) + static_cast (context.get())->updateWindowPosition (bounds); } //============================================================================== diff --git a/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp b/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp index 43d8f8a5e3..174acda8e5 100644 --- a/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp +++ b/modules/juce_opengl/native/juce_linux_OpenGLComponent.cpp @@ -151,13 +151,6 @@ public: return 0; } - void updateWindowPosition (const Rectangle& bounds) - { - ScopedXLock xlock; - XMoveResizeWindow (display, embeddedWindow, - bounds.getX(), bounds.getY(), jmax (1, bounds.getWidth()), jmax (1, bounds.getHeight())); - } - void swapBuffers() { ScopedXLock xlock; @@ -179,13 +172,12 @@ public: } int getSwapInterval() const { return swapInterval; } - void repaint() {} //============================================================================== GLXContext renderContext; + Window embeddedWindow; private: - Window embeddedWindow; OpenGLPixelFormat pixelFormat; int swapInterval; @@ -201,9 +193,21 @@ OpenGLContext* OpenGLComponent::createContext() return (c->renderContext != 0) ? c.release() : nullptr; } -void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, OwnedArray & results) +void OpenGLComponent::internalRepaint (int x, int y, int w, int h) { - results.add (new OpenGLPixelFormat()); // xxx + Component::internalRepaint (x, y, w, h); +} + +void OpenGLComponent::updateEmbeddedPosition (const Rectangle& bounds) +{ + if (context != nullptr) + { + Window embeddedWindow = static_cast (context.get())->embeddedWindow; + + ScopedXLock xlock; + XMoveResizeWindow (display, embeddedWindow, + bounds.getX(), bounds.getY(), jmax (1, bounds.getWidth()), jmax (1, bounds.getHeight())); + } } //============================================================================== diff --git a/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm b/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm index b965ee156e..e8efb6bed6 100644 --- a/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm +++ b/modules/juce_opengl/native/juce_mac_OpenGLComponent.mm @@ -209,8 +209,6 @@ public: void* getRawContext() const noexcept { return renderContext; } unsigned int getFrameBufferID() const { return 0; } - void updateWindowPosition (const Rectangle&) {} - void swapBuffers() { [renderContext flushBuffer]; @@ -231,19 +229,6 @@ public: return numFrames; } - void repaint() - { - // we need to invalidate the juce view that holds this gl view, to make it - // cause a repaint callback - NSRect r = [view frame]; - - // bit of a bodge here.. if we only invalidate the area of the gl component, - // it's completely covered by the NSOpenGLView, so the OS throws away the - // repaint message, thus never causing our paint() callback, and never repainting - // the comp. So invalidating just a little bit around the edge helps.. - [[view superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)]; - } - void* getNativeWindowHandle() const { return view; } //============================================================================== @@ -253,7 +238,6 @@ public: private: OpenGLPixelFormat pixelFormat; - //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowedGLContext); }; @@ -268,50 +252,28 @@ OpenGLContext* OpenGLComponent::createContext() void* OpenGLComponent::getNativeWindowHandle() const { - return context != nullptr ? static_cast (static_cast (context))->getNativeWindowHandle() + return context != nullptr ? static_cast (context.get())->getNativeWindowHandle() : nullptr; } -static int getPixelFormatAttribute (NSOpenGLPixelFormat* p, NSOpenGLPixelFormatAttribute att) +void OpenGLComponent::internalRepaint (int x, int y, int w, int h) { - GLint val = 0; - [p getValues: &val forAttribute: att forVirtualScreen: 0]; - return (int) val; + Component::internalRepaint (x, y, w, h); + + if (context != nullptr) + { + NSView* const v = static_cast (context.get())->view; + + // bit of a bodge here.. if we only invalidate the area of the gl component, + // it's completely covered by the NSOpenGLView, so the OS throws away the + // repaint message, thus never causing our paint() callback, and never repainting + // the comp. So invalidating just a little bit around the edge helps.. + [[v superview] setNeedsDisplayInRect: NSInsetRect ([v frame], -2.0f, -2.0f)]; + } } -void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/, - OwnedArray & results) +void OpenGLComponent::updateEmbeddedPosition (const Rectangle&) { - NSOpenGLPixelFormatAttribute attributes[] = - { - NSOpenGLPFAWindow, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAccelerated, - NSOpenGLPFANoRecovery, - NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) 16, - NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute) 8, - NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) 24, - NSOpenGLPFAAccumSize, (NSOpenGLPixelFormatAttribute) 32, - (NSOpenGLPixelFormatAttribute) 0 - }; - - NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attributes]; - - if (format != nil) - { - OpenGLPixelFormat* const pf = new OpenGLPixelFormat(); - - pf->redBits = pf->greenBits = pf->blueBits = getPixelFormatAttribute (format, NSOpenGLPFAColorSize) / 3; - pf->alphaBits = getPixelFormatAttribute (format, NSOpenGLPFAAlphaSize); - pf->depthBufferBits = getPixelFormatAttribute (format, NSOpenGLPFADepthSize); - pf->stencilBufferBits = getPixelFormatAttribute (format, NSOpenGLPFAStencilSize); - pf->accumulationBufferRedBits = pf->accumulationBufferGreenBits - = pf->accumulationBufferBlueBits = pf->accumulationBufferAlphaBits - = getPixelFormatAttribute (format, NSOpenGLPFAAccumSize) / 4; - - [format release]; - results.add (pf); - } } //============================================================================== diff --git a/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp b/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp index d0caa48e4c..ba77d4924b 100644 --- a/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp +++ b/modules/juce_opengl/native/juce_win32_OpenGLComponent.cpp @@ -269,18 +269,6 @@ public: return false; } - void updateWindowPosition (const Rectangle& bounds) - { - SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0, - bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), - SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); - } - - void repaint() - { - nativeWindow->repaint (nativeWindow->getBounds().withPosition (Point())); - } - void swapBuffers() { SwapBuffers (dc); @@ -354,9 +342,9 @@ public: //============================================================================== HGLRC renderContext; + ScopedPointer nativeWindow; private: - ScopedPointer nativeWindow; Component* const component; HDC dc; @@ -471,18 +459,29 @@ OpenGLContext* OpenGLComponent::createContext() void* OpenGLComponent::getNativeWindowHandle() const { - return context != nullptr ? static_cast (static_cast (context))->getNativeWindowHandle() : nullptr; + return context != nullptr ? static_cast (context.get())->getNativeWindowHandle() : nullptr; } -void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, - OwnedArray & results) +void OpenGLComponent::internalRepaint (int x, int y, int w, int h) { - Component tempComp; + Component::internalRepaint (x, y, w, h); + if (context != nullptr) { - WindowedGLContext wc (component, 0, OpenGLPixelFormat (8, 8, 16, 0)); - wc.makeActive(); - wc.findAlternativeOpenGLPixelFormats (results); + ComponentPeer* peer = static_cast (context.get())->nativeWindow; + peer->repaint (peer->getBounds().withPosition (Point())); + } +} + +void OpenGLComponent::updateEmbeddedPosition (const Rectangle& bounds) +{ + if (context != nullptr) + { + ComponentPeer* peer = static_cast (context.get())->nativeWindow; + + SetWindowPos ((HWND) peer->getNativeHandle(), 0, + bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); } } diff --git a/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp b/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp index 94b9fd5941..ae9296c13e 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLComponent.cpp @@ -127,7 +127,6 @@ public: { } - //============================================================================== void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) { owner->updateContextPosition(); @@ -349,9 +348,7 @@ void OpenGLComponent::updateContextPosition() if (topComp->getPeer() != nullptr) { const ScopedLock sl (contextLock); - - if (context != nullptr) - context->updateWindowPosition (topComp->getLocalArea (this, getLocalBounds())); + updateEmbeddedPosition (topComp->getLocalArea (this, getLocalBounds())); } } } @@ -425,14 +422,6 @@ bool OpenGLComponent::renderAndSwapBuffers() return true; } -void OpenGLComponent::internalRepaint (int x, int y, int w, int h) -{ - Component::internalRepaint (x, y, w, h); - - if (context != nullptr) - context->repaint(); -} - unsigned int OpenGLComponent::getFrameBufferID() const { return context != nullptr ? context->getFrameBufferID() : 0; diff --git a/modules/juce_opengl/opengl/juce_OpenGLComponent.h b/modules/juce_opengl/opengl/juce_OpenGLComponent.h index e08ea0f813..38fbb467d7 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLComponent.h +++ b/modules/juce_opengl/opengl/juce_OpenGLComponent.h @@ -72,10 +72,7 @@ public: ~OpenGLComponent(); //============================================================================== - /** Changes the pixel format used by this component. - - @see OpenGLPixelFormat::getAvailablePixelFormats() - */ + /** Changes the pixel format used by this component. */ void setPixelFormat (const OpenGLPixelFormat& formatToUse); /** Returns the pixel format that this component is currently using. */ @@ -261,6 +258,7 @@ private: void stopBackgroundThread(); void recreateContextAsync(); void internalRepaint (int x, int y, int w, int h); + void updateEmbeddedPosition (const Rectangle&); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLComponent); }; diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.h b/modules/juce_opengl/opengl/juce_OpenGLContext.h index 1eeee5e5fb..d7d8fd582f 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.h +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.h @@ -72,17 +72,6 @@ public: /** Returns the pixel format being used by this context. */ virtual OpenGLPixelFormat getPixelFormat() const = 0; - /** For windowed contexts, this moves the context within the bounds of - its parent window. - */ - virtual void updateWindowPosition (const Rectangle& bounds) = 0; - - /** For windowed contexts, this triggers a repaint of the window. - - (Not relevent on all platforms). - */ - virtual void repaint() = 0; - /** Returns an OS-dependent handle to the raw GL context. On win32, this will be a HGLRC; on the Mac, an NSOpenGLContext; on Linux, diff --git a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp index 774fed6841..19cc784ccd 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp @@ -244,7 +244,7 @@ namespace glVertexPointer (2, GL_FLOAT, 0, vertices); glTexCoordPointer (2, GL_FLOAT, 0, textureCoords); - const Rectangle targetArea (clip.transformed (transform.inverted())); + const Rectangle targetArea (clip.toFloat().transformed (transform.inverted()).getSmallestIntegerContainer()); int x = targetArea.getX() - negativeAwareModulo (targetArea.getX(), textureWidth); int y = targetArea.getY() - negativeAwareModulo (targetArea.getY(), textureHeight); const int right = targetArea.getRight(); diff --git a/modules/juce_opengl/opengl/juce_OpenGLPixelFormat.h b/modules/juce_opengl/opengl/juce_OpenGLPixelFormat.h index 035bb13633..e2a5f04ee8 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLPixelFormat.h +++ b/modules/juce_opengl/opengl/juce_OpenGLPixelFormat.h @@ -67,17 +67,7 @@ public: uint8 fullSceneAntiAliasingNumSamples; /**< The number of samples to use in full-scene anti-aliasing (if available). */ - //============================================================================== - /** Returns a list of all the pixel formats that can be used in this system. - - A reference component is needed in case there are multiple screens with different - capabilities - in which case, the one that the component is on will be used. - */ - static void getAvailablePixelFormats (Component* component, - OwnedArray & results); - private: - //============================================================================== JUCE_LEAK_DETECTOR (OpenGLPixelFormat); };