|  | /*
  ==============================================================================
   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.
  ==============================================================================
*/
END_JUCE_NAMESPACE
@interface JuceGLView   : UIView
{
}
+ (Class) layerClass;
@end
@implementation JuceGLView
+ (Class) layerClass
{
    return [CAEAGLLayer class];
}
@end
BEGIN_JUCE_NAMESPACE
//==============================================================================
class GLESContext   : public OpenGLContext
{
public:
    GLESContext (UIView* parentView,
                 Component* const component_,
                 const OpenGLPixelFormat& pixelFormat_,
                 const GLESContext* const sharedContext,
                 NSUInteger apiType)
        : component (component_), pixelFormat (pixelFormat_), glLayer (nil), context (nil),
          useDepthBuffer (pixelFormat_.depthBufferBits > 0), frameBufferHandle (0), colorBufferHandle (0),
          depthBufferHandle (0), lastWidth (0), lastHeight (0)
    {
        view = [[JuceGLView alloc] initWithFrame: CGRectMake (0, 0, 64, 64)];
        view.opaque = YES;
        view.hidden = NO;
        view.backgroundColor = [UIColor blackColor];
        view.userInteractionEnabled = NO;
        glLayer = (CAEAGLLayer*) [view layer];
        [parentView addSubview: view];
        if (sharedContext != nullptr)
            context = [[EAGLContext alloc] initWithAPI: apiType
                                            sharegroup: [sharedContext->context sharegroup]];
        else
            context = [[EAGLContext alloc] initWithAPI: apiType];
        createGLBuffers();
    }
    ~GLESContext()
    {
        deleteContext();
        [view removeFromSuperview];
        [view release];
        freeGLBuffers();
    }
    void deleteContext()
    {
        makeInactive();
        [context release];
        context = nil;
    }
    bool makeActive() const noexcept
    {
        jassert (context != nil);
        [EAGLContext setCurrentContext: context];
        glBindFramebufferOES (GL_FRAMEBUFFER_OES, frameBufferHandle);
        return true;
    }
    void swapBuffers()
    {
        glBindRenderbufferOES (GL_RENDERBUFFER_OES, colorBufferHandle);
        [context presentRenderbuffer: GL_RENDERBUFFER_OES];
    }
    bool makeInactive() const noexcept
    {
        return [EAGLContext setCurrentContext: nil];
    }
    bool isActive() const noexcept
    {
        return [EAGLContext currentContext] == context;
    }
    OpenGLPixelFormat getPixelFormat() const        { return pixelFormat; }
    void* getRawContext() const noexcept            { return glLayer; }
    void updateWindowPosition (const Rectangle<int>& bounds)
    {
        // For some strange reason, the view seems to fail unless its width is a multiple of 8...
        view.frame = CGRectMake ((CGFloat) bounds.getX(), (CGFloat) bounds.getY(),
                                 (CGFloat) (bounds.getWidth() & ~7),
                                 (CGFloat) bounds.getHeight());
        if (lastWidth != bounds.getWidth() || lastHeight != bounds.getHeight())
        {
            lastWidth = bounds.getWidth();
            lastHeight = bounds.getHeight();
            freeGLBuffers();
            createGLBuffers();
        }
    }
    bool setSwapInterval (const int numFramesPerSwap)
    {
        numFrames = numFramesPerSwap;
        return true;
    }
    int getSwapInterval() const
    {
        return numFrames;
    }
    void repaint()
    {
    }
    //==============================================================================
    void createGLBuffers()
    {
        makeActive();
        glGenFramebuffersOES (1, &frameBufferHandle);
        glGenRenderbuffersOES (1, &colorBufferHandle);
        glGenRenderbuffersOES (1, &depthBufferHandle);
        glBindRenderbufferOES (GL_RENDERBUFFER_OES, colorBufferHandle);
        [context renderbufferStorage: GL_RENDERBUFFER_OES fromDrawable: glLayer];
        GLint width, height;
        glGetRenderbufferParameterivOES (GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &width);
        glGetRenderbufferParameterivOES (GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &height);
        if (useDepthBuffer)
        {
            glBindRenderbufferOES (GL_RENDERBUFFER_OES, depthBufferHandle);
            glRenderbufferStorageOES (GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, width, height);
        }
        glBindRenderbufferOES (GL_RENDERBUFFER_OES, colorBufferHandle);
        glBindFramebufferOES (GL_FRAMEBUFFER_OES, frameBufferHandle);
        glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorBufferHandle);
        if (useDepthBuffer)
            glFramebufferRenderbufferOES (GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthBufferHandle);
        jassert (glCheckFramebufferStatusOES (GL_FRAMEBUFFER_OES) == GL_FRAMEBUFFER_COMPLETE_OES);
    }
    void freeGLBuffers()
    {
        if (frameBufferHandle != 0)
        {
            glDeleteFramebuffersOES (1, &frameBufferHandle);
            frameBufferHandle = 0;
        }
        if (colorBufferHandle != 0)
        {
            glDeleteRenderbuffersOES (1, &colorBufferHandle);
            colorBufferHandle = 0;
        }
        if (depthBufferHandle != 0)
        {
            glDeleteRenderbuffersOES (1, &depthBufferHandle);
            depthBufferHandle = 0;
        }
    }
    //==============================================================================
private:
    WeakReference<Component> component;
    OpenGLPixelFormat pixelFormat;
    JuceGLView* view;
    CAEAGLLayer* glLayer;
    EAGLContext* context;
    bool useDepthBuffer;
    GLuint frameBufferHandle, colorBufferHandle, depthBufferHandle;
    int numFrames;
    int lastWidth, lastHeight;
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GLESContext);
};
OpenGLContext* OpenGLComponent::createContext()
{
    JUCE_AUTORELEASEPOOL
    ComponentPeer* peer = getPeer();
    if (peer != nullptr)
        return new GLESContext ((UIView*) peer->getNativeHandle(), this, preferredPixelFormat,
                                dynamic_cast <const GLESContext*> (contextToShareListsWith),
                                type == openGLES2 ? kEAGLRenderingAPIOpenGLES2 : kEAGLRenderingAPIOpenGLES1);
    return nullptr;
}
void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/,
                                                  OwnedArray <OpenGLPixelFormat>& /*results*/)
{
}
 |