| @@ -60,7 +60,8 @@ public: | |||||
| addAndMakeVisible (&sizeSlider); | addAndMakeVisible (&sizeSlider); | ||||
| sizeSlider.setBounds ("parent.width * 0.05, parent.height - 35, parent.width * 0.6, top + 24"); | sizeSlider.setBounds ("parent.width * 0.05, parent.height - 35, parent.width * 0.6, top + 24"); | ||||
| openGLContext.setRenderer (this, true); | |||||
| openGLContext.setRenderer (this); | |||||
| openGLContext.setComponentPaintingEnabled (true); | |||||
| openGLContext.attachTo (*this); | openGLContext.attachTo (*this); | ||||
| startTimer (1000 / 30); | startTimer (1000 / 30); | ||||
| @@ -72,7 +72,6 @@ public: | |||||
| } | } | ||||
| bool makeActive() const noexcept { return isInsideGLCallback; } | bool makeActive() const noexcept { return isInsideGLCallback; } | ||||
| bool makeInactive() const noexcept { return true; } | |||||
| bool isActive() const noexcept { return isInsideGLCallback; } | bool isActive() const noexcept { return isInsideGLCallback; } | ||||
| void swapBuffers() const noexcept {} | void swapBuffers() const noexcept {} | ||||
| @@ -116,11 +116,6 @@ public: | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool makeInactive() const noexcept | |||||
| { | |||||
| return (! isActive()) || [EAGLContext setCurrentContext: nil]; | |||||
| } | |||||
| bool isActive() const noexcept | bool isActive() const noexcept | ||||
| { | { | ||||
| return [EAGLContext currentContext] == context; | return [EAGLContext currentContext] == context; | ||||
| @@ -114,7 +114,7 @@ public: | |||||
| void shutdownOnRenderThread() | void shutdownOnRenderThread() | ||||
| { | { | ||||
| makeInactive(); | |||||
| glXMakeCurrent (display, None, 0); | |||||
| glXDestroyContext (display, renderContext); | glXDestroyContext (display, renderContext); | ||||
| renderContext = nullptr; | renderContext = nullptr; | ||||
| } | } | ||||
| @@ -125,11 +125,6 @@ public: | |||||
| && glXMakeCurrent (display, embeddedWindow, renderContext); | && glXMakeCurrent (display, embeddedWindow, renderContext); | ||||
| } | } | ||||
| bool makeInactive() const noexcept | |||||
| { | |||||
| return (! isActive()) || glXMakeCurrent (display, None, 0); | |||||
| } | |||||
| bool isActive() const noexcept | bool isActive() const noexcept | ||||
| { | { | ||||
| return glXGetCurrentContext() == renderContext && renderContext != 0; | return glXGetCurrentContext() == renderContext && renderContext != 0; | ||||
| @@ -36,7 +36,6 @@ | |||||
| - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format; | - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format; | ||||
| - (bool) makeActive; | - (bool) makeActive; | ||||
| - (void) makeInactive; | |||||
| - (void) reshape; | - (void) reshape; | ||||
| - (void) rightMouseDown: (NSEvent*) ev; | - (void) rightMouseDown: (NSEvent*) ev; | ||||
| - (void) rightMouseUp: (NSEvent*) ev; | - (void) rightMouseUp: (NSEvent*) ev; | ||||
| @@ -84,12 +83,6 @@ | |||||
| return true; | return true; | ||||
| } | } | ||||
| - (void) makeInactive | |||||
| { | |||||
| const juce::ScopedLock sl (*contextLock); | |||||
| [NSOpenGLContext clearCurrentContext]; | |||||
| } | |||||
| - (void) _surfaceNeedsUpdate: (NSNotification*) notification | - (void) _surfaceNeedsUpdate: (NSNotification*) notification | ||||
| { | { | ||||
| (void) notification; | (void) notification; | ||||
| @@ -187,12 +180,6 @@ public: | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool makeInactive() const noexcept | |||||
| { | |||||
| [view makeInactive]; | |||||
| return true; | |||||
| } | |||||
| bool isActive() const noexcept | bool isActive() const noexcept | ||||
| { | { | ||||
| return [NSOpenGLContext currentContext] == renderContext; | return [NSOpenGLContext currentContext] == renderContext; | ||||
| @@ -50,7 +50,7 @@ public: | |||||
| initialiseGLExtensions(); | initialiseGLExtensions(); | ||||
| const int wglFormat = wglChoosePixelFormatExtension (pixelFormat); | const int wglFormat = wglChoosePixelFormatExtension (pixelFormat); | ||||
| makeInactive(); | |||||
| wglMakeCurrent (0, 0); | |||||
| if (wglFormat != pixFormat && wglFormat != 0) | if (wglFormat != pixFormat && wglFormat != 0) | ||||
| { | { | ||||
| @@ -94,11 +94,6 @@ public: | |||||
| return wglMakeCurrent (dc, renderContext) != FALSE; | return wglMakeCurrent (dc, renderContext) != FALSE; | ||||
| } | } | ||||
| bool makeInactive() const noexcept | |||||
| { | |||||
| return (! isActive()) || (wglMakeCurrent (0, 0) != FALSE); | |||||
| } | |||||
| bool isActive() const noexcept | bool isActive() const noexcept | ||||
| { | { | ||||
| return wglGetCurrentContext() == renderContext; | return wglGetCurrentContext() == renderContext; | ||||
| @@ -350,11 +350,8 @@ void OpenGLContext::NativeContext::renderCallback() | |||||
| class OpenGLContext::Attachment : public ComponentMovementWatcher | class OpenGLContext::Attachment : public ComponentMovementWatcher | ||||
| { | { | ||||
| public: | public: | ||||
| Attachment (OpenGLContext& context_, Component& comp, | |||||
| const OpenGLPixelFormat& pixelFormat_, | |||||
| const OpenGLContext* contextToShareWith_) | |||||
| : ComponentMovementWatcher (&comp), context (context_), | |||||
| pixelFormat (pixelFormat_), contextToShareWith (contextToShareWith_) | |||||
| Attachment (OpenGLContext& context_, Component& comp) | |||||
| : ComponentMovementWatcher (&comp), context (context_) | |||||
| { | { | ||||
| if (canBeAttached (comp)) | if (canBeAttached (comp)) | ||||
| attach(); | attach(); | ||||
| @@ -418,8 +415,6 @@ public: | |||||
| private: | private: | ||||
| OpenGLContext& context; | OpenGLContext& context; | ||||
| OpenGLPixelFormat pixelFormat; | |||||
| const OpenGLContext* contextToShareWith; | |||||
| static bool canBeAttached (const Component& comp) noexcept | static bool canBeAttached (const Component& comp) noexcept | ||||
| { | { | ||||
| @@ -435,7 +430,8 @@ private: | |||||
| { | { | ||||
| Component* const comp = getComponent(); | Component* const comp = getComponent(); | ||||
| comp->setCachedComponentImage (new CachedImage (context, *comp, | comp->setCachedComponentImage (new CachedImage (context, *comp, | ||||
| pixelFormat, contextToShareWith)); | |||||
| context.pixelFormat, | |||||
| context.contextToShareWith)); | |||||
| } | } | ||||
| void detach() | void detach() | ||||
| @@ -446,7 +442,7 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| OpenGLContext::OpenGLContext() | OpenGLContext::OpenGLContext() | ||||
| : nativeContext (nullptr), renderer (nullptr), | |||||
| : nativeContext (nullptr), renderer (nullptr), contextToShareWith (nullptr), | |||||
| width (0), height (0), renderComponents (true) | width (0), height (0), renderComponents (true) | ||||
| { | { | ||||
| } | } | ||||
| @@ -456,37 +452,55 @@ OpenGLContext::~OpenGLContext() | |||||
| detach(); | detach(); | ||||
| } | } | ||||
| void OpenGLContext::setRenderer (OpenGLRenderer* rendererToUse, | |||||
| bool shouldAlsoPaintComponent) noexcept | |||||
| void OpenGLContext::setRenderer (OpenGLRenderer* rendererToUse) noexcept | |||||
| { | { | ||||
| // This method must not be called when the context has already been attached! | // This method must not be called when the context has already been attached! | ||||
| // Call it before attaching your context, or use detach() first, before calling this! | // Call it before attaching your context, or use detach() first, before calling this! | ||||
| jassert (nativeContext == nullptr); | jassert (nativeContext == nullptr); | ||||
| renderer = rendererToUse; | renderer = rendererToUse; | ||||
| renderComponents = shouldAlsoPaintComponent; | |||||
| } | } | ||||
| void OpenGLContext::attachTo (Component& component, | |||||
| const OpenGLPixelFormat& pixelFormat, | |||||
| const OpenGLContext* contextToShareWith) | |||||
| void OpenGLContext::setComponentPaintingEnabled (bool shouldPaintComponent) noexcept | |||||
| { | { | ||||
| if (getTargetComponent() != &component) | |||||
| { | |||||
| detach(); | |||||
| // This method must not be called when the context has already been attached! | |||||
| // Call it before attaching your context, or use detach() first, before calling this! | |||||
| jassert (nativeContext == nullptr); | |||||
| width = component.getWidth(); | |||||
| height = component.getHeight(); | |||||
| renderComponents = shouldPaintComponent; | |||||
| } | |||||
| attachment = new Attachment (*this, component, | |||||
| pixelFormat, contextToShareWith); | |||||
| } | |||||
| void OpenGLContext::setPixelFormat (const OpenGLPixelFormat& preferredPixelFormat) noexcept | |||||
| { | |||||
| // This method must not be called when the context has already been attached! | |||||
| // Call it before attaching your context, or use detach() first, before calling this! | |||||
| jassert (nativeContext == nullptr); | |||||
| pixelFormat = preferredPixelFormat; | |||||
| } | |||||
| void OpenGLContext::setContextToShareWith (const OpenGLContext* context) noexcept | |||||
| { | |||||
| // This method must not be called when the context has already been attached! | |||||
| // Call it before attaching your context, or use detach() first, before calling this! | |||||
| jassert (nativeContext == nullptr); | |||||
| contextToShareWith = context; | |||||
| } | } | ||||
| void OpenGLContext::attachTo (Component& component) | void OpenGLContext::attachTo (Component& component) | ||||
| { | { | ||||
| component.repaint(); | component.repaint(); | ||||
| attachTo (component, OpenGLPixelFormat(), nullptr); | |||||
| if (getTargetComponent() != &component) | |||||
| { | |||||
| detach(); | |||||
| width = component.getWidth(); | |||||
| height = component.getHeight(); | |||||
| attachment = new Attachment (*this, component); | |||||
| } | |||||
| } | } | ||||
| void OpenGLContext::detach() | void OpenGLContext::detach() | ||||
| @@ -522,7 +536,6 @@ OpenGLContext* OpenGLContext::getCurrentContext() | |||||
| } | } | ||||
| bool OpenGLContext::makeActive() const noexcept { return nativeContext != nullptr && nativeContext->makeActive(); } | bool OpenGLContext::makeActive() const noexcept { return nativeContext != nullptr && nativeContext->makeActive(); } | ||||
| bool OpenGLContext::makeInactive() const noexcept { return nativeContext != nullptr && nativeContext->makeInactive(); } | |||||
| bool OpenGLContext::isActive() const noexcept { return nativeContext != nullptr && nativeContext->isActive(); } | bool OpenGLContext::isActive() const noexcept { return nativeContext != nullptr && nativeContext->isActive(); } | ||||
| void OpenGLContext::triggerRepaint() | void OpenGLContext::triggerRepaint() | ||||
| @@ -575,7 +588,7 @@ bool OpenGLContext::areShadersAvailable() const | |||||
| return c != nullptr && c->shadersAvailable; | return c != nullptr && c->shadersAvailable; | ||||
| } | } | ||||
| ReferenceCountedObjectPtr<ReferenceCountedObject> OpenGLContext::getAssociatedObject (const char* name) const | |||||
| ReferenceCountedObject* OpenGLContext::getAssociatedObject (const char* name) const | |||||
| { | { | ||||
| jassert (name != nullptr); | jassert (name != nullptr); | ||||
| @@ -635,7 +648,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea, | |||||
| static const OverlayShaderProgram& select (OpenGLContext& context) | static const OverlayShaderProgram& select (OpenGLContext& context) | ||||
| { | { | ||||
| static const char programValueID[] = "juceGLComponentOverlayShader"; | static const char programValueID[] = "juceGLComponentOverlayShader"; | ||||
| OverlayShaderProgram* program = static_cast <OverlayShaderProgram*> (context.getAssociatedObject (programValueID).getObject()); | |||||
| OverlayShaderProgram* program = static_cast <OverlayShaderProgram*> (context.getAssociatedObject (programValueID)); | |||||
| if (program == nullptr) | if (program == nullptr) | ||||
| { | { | ||||
| @@ -716,7 +729,9 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea, | |||||
| JUCE_CHECK_OPENGL_ERROR | JUCE_CHECK_OPENGL_ERROR | ||||
| glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); | glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); | ||||
| extensions.glUseProgram (0); | extensions.glUseProgram (0); | ||||
| extensions.glDisableVertexAttribArray (program.params.positionAttribute.attributeID); | |||||
| } | } | ||||
| #if JUCE_USE_OPENGL_FIXED_FUNCTION | #if JUCE_USE_OPENGL_FIXED_FUNCTION | ||||
| else | else | ||||
| @@ -31,6 +31,10 @@ | |||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| A base class that should be implemented by classes which want to render openGL | |||||
| on a background thread. | |||||
| @see OpenGLContext | |||||
| */ | */ | ||||
| class JUCE_API OpenGLRenderer | class JUCE_API OpenGLRenderer | ||||
| { | { | ||||
| @@ -38,24 +42,42 @@ public: | |||||
| OpenGLRenderer() {} | OpenGLRenderer() {} | ||||
| virtual ~OpenGLRenderer() {} | virtual ~OpenGLRenderer() {} | ||||
| /** | |||||
| /** Called when a new GL context has been created. | |||||
| You can use this as an opportunity to create your textures, shaders, etc. | |||||
| When the method is invoked, the new GL context will be active. | |||||
| Note that this callback will be made on a background thread, so make sure | |||||
| that your implementation is thread-safe. | |||||
| */ | */ | ||||
| virtual void newOpenGLContextCreated() = 0; | virtual void newOpenGLContextCreated() = 0; | ||||
| /** | |||||
| /** Called when you should render the next openGL frame. | |||||
| Note that this callback will be made on a background thread, so make sure | |||||
| that your implementation is thread-safe. | |||||
| */ | */ | ||||
| virtual void renderOpenGL() = 0; | virtual void renderOpenGL() = 0; | ||||
| /** | |||||
| /** Called when the current openGL context is about to close. | |||||
| You can use this opportunity to release any GL resources that you may have | |||||
| created. | |||||
| Note that this callback will be made on a background thread, so make sure | |||||
| that your implementation is thread-safe. | |||||
| (Also note that on Android, this callback won't happen, because there's currently | |||||
| no way to implement it..) | |||||
| */ | */ | ||||
| virtual void openGLContextClosing() = 0; | virtual void openGLContextClosing() = 0; | ||||
| }; | }; | ||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| A base class for types of OpenGL context. | |||||
| Creates an OpenGL context, which can be attached to a component. | |||||
| An OpenGLComponent will supply its own context for drawing in its window. | |||||
| To render some OpenGL in a component, you should create an instance of an OpenGLContext, | |||||
| and call attachTo() to make it use your component as its render target. | |||||
| To free the context, either call detach(), or delete the OpenGLContext. | |||||
| @see OpenGLRenderer | |||||
| */ | */ | ||||
| class JUCE_API OpenGLContext | class JUCE_API OpenGLContext | ||||
| { | { | ||||
| @@ -66,63 +88,76 @@ public: | |||||
| ~OpenGLContext(); | ~OpenGLContext(); | ||||
| //============================================================================== | //============================================================================== | ||||
| /** */ | |||||
| void setRenderer (OpenGLRenderer* rendererToUse, | |||||
| bool shouldAlsoPaintComponent) noexcept; | |||||
| /** */ | |||||
| void attachTo (Component& component); | |||||
| /** Gives the context an OpenGLRenderer to use to do the drawing. | |||||
| The object that you give it will not be owned by the context, so it's the caller's | |||||
| responsibility to manage its lifetime and make sure that it doesn't get deleted | |||||
| while the context may be using it. To stop the context using a renderer, just call | |||||
| this method with a null pointer. | |||||
| Note: This must be called BEFORE attaching your context to a target component! | |||||
| */ | |||||
| void setRenderer (OpenGLRenderer* rendererToUse) noexcept; | |||||
| /** */ | |||||
| void attachTo (Component& component, | |||||
| const OpenGLPixelFormat& preferredPixelFormat, | |||||
| const OpenGLContext* contextToShareWith); | |||||
| /** */ | |||||
| void detach(); | |||||
| /** Enables or disables the use of the GL context to perform 2D rendering | |||||
| of the component to which it is attached. | |||||
| If this is false, then only your OpenGLRenderer will be used to perform | |||||
| any rendering. If true, then each time your target's paint() method needs | |||||
| to be called, an OpenGLGraphicsContext will be used to render it, (after | |||||
| calling your OpenGLRenderer if there is one). | |||||
| /** */ | |||||
| bool isAttached() const noexcept; | |||||
| By default this is set to true. If you're not using any paint() method functionality | |||||
| and are doing all your rendering in an OpenGLRenderer, you should disable it | |||||
| to improve performance. | |||||
| //============================================================================== | |||||
| /** Makes this context the currently active one. */ | |||||
| bool makeActive() const noexcept; | |||||
| /** If this context is currently active, it is disactivated. */ | |||||
| bool makeInactive() const noexcept; | |||||
| /** Returns true if this context is currently active. */ | |||||
| bool isActive() const noexcept; | |||||
| Note: This must be called BEFORE attaching your context to a target component! | |||||
| */ | |||||
| void setComponentPaintingEnabled (bool shouldPaintComponent) noexcept; | |||||
| /** Returns the component to which this context is currently attached, or nullptr. */ | |||||
| Component* getTargetComponent() const noexcept; | |||||
| /** Sets the pixel format which you'd like to use for the target GL surface. | |||||
| Note: This must be called BEFORE attaching your context to a target component! | |||||
| */ | |||||
| void setPixelFormat (const OpenGLPixelFormat& preferredPixelFormat) noexcept; | |||||
| /** Returns the context that's currently in active use by the calling thread, or | |||||
| nullptr if no context is active. | |||||
| /** Provides a context with which you'd like this context's resources to be shared. | |||||
| The object passed-in here must not be deleted while the context may still be | |||||
| using it! To turn off sharing, you can call this method with a null pointer. | |||||
| Note: This must be called BEFORE attaching your context to a target component! | |||||
| */ | */ | ||||
| static OpenGLContext* getCurrentContext(); | |||||
| void setContextToShareWith (const OpenGLContext* contextToShareWith) noexcept; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Swaps the buffers (if the context can do this). | |||||
| There's normally no need to call this directly - the buffers will be swapped | |||||
| automatically after your OpenGLRenderer::renderOpenGL() method has been called. | |||||
| */ | |||||
| void swapBuffers(); | |||||
| /** Attaches the context to a target component. | |||||
| /** Sets whether the context checks the vertical sync before swapping. | |||||
| If the component is not fully visible, this call will wait until the component | |||||
| is shown before actually creating a native context for it. | |||||
| The value is the number of frames to allow between buffer-swapping. This is | |||||
| fairly system-dependent, but 0 turns off syncing, 1 makes it swap on frame-boundaries, | |||||
| and greater numbers indicate that it should swap less often. | |||||
| When a native context is created, a thread is started, and will be used to call | |||||
| the OpenGLRenderer methods. The context will be floated above the target component, | |||||
| and when the target moves, it will track it. If the component is hidden/shown, the | |||||
| context may be deleted and re-created. | |||||
| */ | |||||
| void attachTo (Component& component); | |||||
| Returns true if it sets the value successfully - some platforms won't support | |||||
| this setting. | |||||
| /** Detaches the context from its target component and deletes any native resources. | |||||
| If the context has not been attached, this will do nothing. Otherwise, it will block | |||||
| until the context and its thread have been cleaned up. | |||||
| */ | */ | ||||
| bool setSwapInterval (int numFramesPerSwap); | |||||
| void detach(); | |||||
| /** Returns the current swap-sync interval. | |||||
| See setSwapInterval() for info about the value returned. | |||||
| /** Returns true if the context is attached to a component and is on-screen. | |||||
| Note that if you call attachTo() for a non-visible component, this method will | |||||
| return false until the component is made visible. | |||||
| */ | */ | ||||
| int getSwapInterval() const; | |||||
| bool isAttached() const noexcept; | |||||
| /** */ | |||||
| /** Returns the component to which this context is currently attached, or nullptr. */ | |||||
| Component* getTargetComponent() const noexcept; | |||||
| /** Returns the context that's currently in active use by the calling thread, or | |||||
| nullptr if no context is active. | |||||
| */ | |||||
| static OpenGLContext* getCurrentContext(); | |||||
| /** Asynchronously causes a repaint to be made. */ | |||||
| void triggerRepaint(); | void triggerRepaint(); | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -133,7 +168,7 @@ public: | |||||
| inline int getHeight() const noexcept { return height; } | inline int getHeight() const noexcept { return height; } | ||||
| /** If this context is backed by a frame buffer, this returns its ID number, | /** If this context is backed by a frame buffer, this returns its ID number, | ||||
| or 0 if the context has no accessible framebuffer. | |||||
| or 0 if the context does not use a framebuffer. | |||||
| */ | */ | ||||
| unsigned int getFrameBufferID() const noexcept; | unsigned int getFrameBufferID() const noexcept; | ||||
| @@ -143,12 +178,13 @@ public: | |||||
| /** This structure holds a set of dynamically loaded GL functions for use on this context. */ | /** This structure holds a set of dynamically loaded GL functions for use on this context. */ | ||||
| OpenGLExtensionFunctions extensions; | OpenGLExtensionFunctions extensions; | ||||
| //============================================================================== | |||||
| /** This retrieves an object that was previously stored with setAssociatedObject(). | /** This retrieves an object that was previously stored with setAssociatedObject(). | ||||
| If no object is found with the given name, this will return nullptr. | If no object is found with the given name, this will return nullptr. | ||||
| This method must only be called from within the GL rendering methods. | This method must only be called from within the GL rendering methods. | ||||
| @see setAssociatedObject | @see setAssociatedObject | ||||
| */ | */ | ||||
| ReferenceCountedObjectPtr<ReferenceCountedObject> getAssociatedObject (const char* name) const; | |||||
| ReferenceCountedObject* getAssociatedObject (const char* name) const; | |||||
| /** Attaches a named object to the context, which will be deleted when the context is | /** Attaches a named object to the context, which will be deleted when the context is | ||||
| destroyed. | destroyed. | ||||
| @@ -161,6 +197,39 @@ public: | |||||
| */ | */ | ||||
| void setAssociatedObject (const char* name, ReferenceCountedObject* newObject); | void setAssociatedObject (const char* name, ReferenceCountedObject* newObject); | ||||
| //============================================================================== | |||||
| /** Makes this context the currently active one. | |||||
| You should never need to call this in normal use - the context will already be | |||||
| active when OpenGLRenderer::renderOpenGL() is invoked. | |||||
| */ | |||||
| bool makeActive() const noexcept; | |||||
| /** Returns true if this context is currently active for the calling thread. */ | |||||
| bool isActive() const noexcept; | |||||
| //============================================================================== | |||||
| /** Swaps the buffers (if the context can do this). | |||||
| There's normally no need to call this directly - the buffers will be swapped | |||||
| automatically after your OpenGLRenderer::renderOpenGL() method has been called. | |||||
| */ | |||||
| void swapBuffers(); | |||||
| /** Sets whether the context checks the vertical sync before swapping. | |||||
| The value is the number of frames to allow between buffer-swapping. This is | |||||
| fairly system-dependent, but 0 turns off syncing, 1 makes it swap on frame-boundaries, | |||||
| and greater numbers indicate that it should swap less often. | |||||
| Returns true if it sets the value successfully - some platforms won't support | |||||
| this setting. | |||||
| */ | |||||
| bool setSwapInterval (int numFramesPerSwap); | |||||
| /** Returns the current swap-sync interval. | |||||
| See setSwapInterval() for info about the value returned. | |||||
| */ | |||||
| int getSwapInterval() const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns an OS-dependent handle to some kind of underlting OS-provided GL context. | /** Returns an OS-dependent handle to some kind of underlting OS-provided GL context. | ||||
| @@ -197,6 +266,8 @@ private: | |||||
| NativeContext* nativeContext; | NativeContext* nativeContext; | ||||
| OpenGLRenderer* renderer; | OpenGLRenderer* renderer; | ||||
| ScopedPointer<Attachment> attachment; | ScopedPointer<Attachment> attachment; | ||||
| OpenGLPixelFormat pixelFormat; | |||||
| const OpenGLContext* contextToShareWith; | |||||
| int width, height; | int width, height; | ||||
| bool renderComponents; | bool renderComponents; | ||||
| @@ -1021,7 +1021,7 @@ struct StateHelpers | |||||
| GLuint colour; | GLuint colour; | ||||
| }; | }; | ||||
| #if ! JUCE_MAC | |||||
| #if ! (JUCE_MAC || JUCE_ANDROID || JUCE_IOS) | |||||
| enum { numQuads = 64 }; // (had problems with my drivers segfaulting when these buffers are any larger) | enum { numQuads = 64 }; // (had problems with my drivers segfaulting when these buffers are any larger) | ||||
| #else | #else | ||||
| enum { numQuads = 8192 }; | enum { numQuads = 8192 }; | ||||
| @@ -1051,7 +1051,7 @@ struct StateHelpers | |||||
| activeShader (nullptr) | activeShader (nullptr) | ||||
| { | { | ||||
| const char programValueID[] = "GraphicsContextPrograms"; | const char programValueID[] = "GraphicsContextPrograms"; | ||||
| programs = static_cast <ShaderPrograms*> (context.getAssociatedObject (programValueID).getObject()); | |||||
| programs = static_cast <ShaderPrograms*> (context.getAssociatedObject (programValueID)); | |||||
| if (programs == nullptr) | if (programs == nullptr) | ||||
| { | { | ||||
| @@ -1154,6 +1154,9 @@ public: | |||||
| #if defined (GL_INDEX_ARRAY) | #if defined (GL_INDEX_ARRAY) | ||||
| glDisableClientState (GL_INDEX_ARRAY); | glDisableClientState (GL_INDEX_ARRAY); | ||||
| #endif | #endif | ||||
| target.context.extensions.glBindBuffer (GL_ARRAY_BUFFER, 0); | |||||
| target.context.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); | |||||
| } | } | ||||
| void flush() | void flush() | ||||
| @@ -142,7 +142,9 @@ void OpenGLTexture::release() | |||||
| { | { | ||||
| if (textureID != 0) | if (textureID != 0) | ||||
| { | { | ||||
| glDeleteTextures (1, &textureID); | |||||
| if (OpenGLHelpers::isContextActive()) | |||||
| glDeleteTextures (1, &textureID); | |||||
| textureID = 0; | textureID = 0; | ||||
| width = 0; | width = 0; | ||||
| height = 0; | height = 0; | ||||