|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-11 by Raw Material Software Ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the GNU General
- Public License (Version 2), as published by the Free Software Foundation.
- A copy of the license is included in the JUCE distribution, or can be found
- online at www.gnu.org/licenses.
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.rawmaterialsoftware.com/juce for more information.
-
- ==============================================================================
- */
-
- } // (juce namespace)
-
- @interface JuceGLView : UIView
- {
- }
- + (Class) layerClass;
- @end
-
- @implementation JuceGLView
- + (Class) layerClass
- {
- return [CAEAGLLayer class];
- }
- @end
-
- namespace juce
- {
-
- class OpenGLContext::NativeContext
- {
- public:
- NativeContext (Component& component,
- const OpenGLPixelFormat& pixelFormat,
- void* contextToShareWith)
- : frameBufferHandle (0), colorBufferHandle (0), depthBufferHandle (0),
- lastWidth (0), lastHeight (0), needToRebuildBuffers (false),
- swapFrames (0), useDepthBuffer (pixelFormat.depthBufferBits > 0)
- {
- JUCE_AUTORELEASEPOOL
- ComponentPeer* const peer = component.getPeer();
- jassert (peer != nullptr);
-
- const Rectangle<int> bounds (peer->getComponent().getLocalArea (&component, component.getLocalBounds()));
- lastWidth = bounds.getWidth();
- lastHeight = bounds.getHeight();
-
- view = [[JuceGLView alloc] initWithFrame: getCGRectFor (bounds)];
- view.opaque = YES;
- view.hidden = NO;
- view.backgroundColor = [UIColor blackColor];
- view.userInteractionEnabled = NO;
-
- glLayer = (CAEAGLLayer*) [view layer];
- [((UIView*) peer->getNativeHandle()) addSubview: view];
-
- context = [EAGLContext alloc];
-
- const NSUInteger type = kEAGLRenderingAPIOpenGLES2;
-
- if (contextToShareWith != nullptr)
- [context initWithAPI: type sharegroup: [(EAGLContext*) contextToShareWith sharegroup]];
- else
- [context initWithAPI: type];
-
- // I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing
- // so causes myserious timing-related failures.
- [EAGLContext setCurrentContext: context];
- createGLBuffers();
- deactivateCurrentContext();
- }
-
- ~NativeContext()
- {
- [context release];
- context = nil;
-
- [view removeFromSuperview];
- [view release];
- }
-
- void initialiseOnRenderThread() {}
-
- void shutdownOnRenderThread()
- {
- JUCE_CHECK_OPENGL_ERROR
- freeGLBuffers();
- deactivateCurrentContext();
- }
-
- bool createdOk() const noexcept { return getRawContext() != nullptr; }
- void* getRawContext() const noexcept { return context; }
- GLuint getFrameBufferID() const noexcept { return frameBufferHandle; }
-
- bool makeActive() const noexcept
- {
- if (! [EAGLContext setCurrentContext: context])
- return false;
-
- glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
- return true;
- }
-
- bool isActive() const noexcept
- {
- return [EAGLContext currentContext] == context;
- }
-
- static void deactivateCurrentContext()
- {
- [EAGLContext setCurrentContext: nil];
- }
-
- void swapBuffers()
- {
- glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
- [context presentRenderbuffer: GL_RENDERBUFFER];
-
- if (needToRebuildBuffers)
- {
- needToRebuildBuffers = false;
-
- freeGLBuffers();
- createGLBuffers();
- makeActive();
- }
- }
-
- void updateWindowPosition (const Rectangle<int>& bounds)
- {
- view.frame = getCGRectFor (bounds);
-
- if (lastWidth != bounds.getWidth() || lastHeight != bounds.getHeight())
- {
- lastWidth = bounds.getWidth();
- lastHeight = bounds.getHeight();
- needToRebuildBuffers = true;
- }
- }
-
- bool setSwapInterval (const int numFramesPerSwap) noexcept
- {
- swapFrames = numFramesPerSwap;
- return false;
- }
-
- int getSwapInterval() const noexcept { return swapFrames; }
-
- struct Locker { Locker (NativeContext&) {} };
-
- private:
- JuceGLView* view;
- CAEAGLLayer* glLayer;
- EAGLContext* context;
- GLuint frameBufferHandle, colorBufferHandle, depthBufferHandle;
- int volatile lastWidth, lastHeight;
- bool volatile needToRebuildBuffers;
- int swapFrames;
- bool useDepthBuffer;
-
- //==============================================================================
- static CGRect getCGRectFor (const Rectangle<int>& bounds)
- {
- return CGRectMake ((CGFloat) bounds.getX(),
- (CGFloat) bounds.getY(),
- (CGFloat) bounds.getWidth(),
- (CGFloat) bounds.getHeight());
- }
-
- void createGLBuffers()
- {
- glGenFramebuffers (1, &frameBufferHandle);
- glGenRenderbuffers (1, &colorBufferHandle);
-
- glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
- bool ok = [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];
- jassert (ok); (void) ok;
-
- if (useDepthBuffer)
- {
- GLint width, height;
- glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
- glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
-
- glGenRenderbuffers (1, &depthBufferHandle);
- glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle);
- glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
- }
-
- glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
-
- glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
- glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle);
-
- if (useDepthBuffer)
- glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBufferHandle);
-
- jassert (glCheckFramebufferStatus (GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
- JUCE_CHECK_OPENGL_ERROR
- }
-
- void freeGLBuffers()
- {
- JUCE_CHECK_OPENGL_ERROR
- [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];
-
- if (frameBufferHandle != 0)
- {
- glDeleteFramebuffers (1, &frameBufferHandle);
- frameBufferHandle = 0;
- }
-
- if (colorBufferHandle != 0)
- {
- glDeleteRenderbuffers (1, &colorBufferHandle);
- colorBufferHandle = 0;
- }
-
- if (depthBufferHandle != 0)
- {
- glDeleteRenderbuffers (1, &depthBufferHandle);
- depthBufferHandle = 0;
- }
-
- JUCE_CHECK_OPENGL_ERROR
- }
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext);
- };
-
- //==============================================================================
- bool OpenGLHelpers::isContextActive()
- {
- return [EAGLContext currentContext] != nil;
- }
|