| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2022 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 7 End-User License
 -    Agreement and JUCE Privacy Policy.
 - 
 -    End User License Agreement: www.juce.com/juce-7-licence
 -    Privacy Policy: www.juce.com/juce-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - @interface JuceGLView   : UIView
 - {
 - }
 - + (Class) layerClass;
 - @end
 - 
 - @implementation JuceGLView
 - + (Class) layerClass
 - {
 -     return [CAEAGLLayer class];
 - }
 - @end
 - 
 - extern "C" GLvoid glResolveMultisampleFramebufferAPPLE();
 - 
 - namespace juce
 - {
 - 
 - class OpenGLContext::NativeContext
 - {
 - public:
 -     NativeContext (Component& c,
 -                    const OpenGLPixelFormat& pixFormat,
 -                    void* contextToShare,
 -                    bool multisampling,
 -                    OpenGLVersion version)
 -         : component (c), openGLversion (version),
 -           useDepthBuffer (pixFormat.depthBufferBits > 0),
 -           useMSAA (multisampling)
 -     {
 -         JUCE_AUTORELEASEPOOL
 -         {
 -             if (auto* peer = component.getPeer())
 -             {
 -                 auto bounds = peer->getAreaCoveredBy (component);
 - 
 -                 view = [[JuceGLView alloc] initWithFrame: convertToCGRect (bounds)];
 -                 view.opaque = YES;
 -                 view.hidden = NO;
 -                 view.backgroundColor = [UIColor blackColor];
 -                 view.userInteractionEnabled = NO;
 - 
 -                 glLayer = (CAEAGLLayer*) [view layer];
 -                 glLayer.opaque = true;
 - 
 -                 updateWindowPosition (bounds);
 - 
 -                 [((UIView*) peer->getNativeHandle()) addSubview: view];
 - 
 -                 const auto shouldUseES3 = version != defaultGLVersion
 -                                        && [[UIDevice currentDevice].systemVersion floatValue] >= 7.0;
 - 
 -                 const auto gotContext = (shouldUseES3 && createContext (kEAGLRenderingAPIOpenGLES3, contextToShare))
 -                                      || createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);
 - 
 -                 jassertquiet (gotContext);
 - 
 -                 if (context != nil)
 -                 {
 -                     // I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing
 -                     // so causes mysterious timing-related failures.
 -                     [EAGLContext setCurrentContext: context.get()];
 -                     gl::loadFunctions();
 -                     createGLBuffers();
 -                     deactivateCurrentContext();
 -                 }
 -                 else
 -                 {
 -                     jassertfalse;
 -                 }
 -             }
 -             else
 -             {
 -                 jassertfalse;
 -             }
 -         }
 -     }
 - 
 -     ~NativeContext()
 -     {
 -         context.reset();
 -         [view removeFromSuperview];
 -         [view release];
 -     }
 - 
 -     InitResult initialiseOnRenderThread (OpenGLContext&)    { return InitResult::success; }
 - 
 -     void shutdownOnRenderThread()
 -     {
 -         JUCE_CHECK_OPENGL_ERROR
 -         freeGLBuffers();
 -         deactivateCurrentContext();
 -     }
 - 
 -     bool createdOk() const noexcept             { return getRawContext() != nullptr; }
 -     void* getRawContext() const noexcept        { return context.get(); }
 -     GLuint getFrameBufferID() const noexcept    { return useMSAA ? msaaBufferHandle : frameBufferHandle; }
 - 
 -     bool makeActive() const noexcept
 -     {
 -         if (! [EAGLContext setCurrentContext: context.get()])
 -             return false;
 - 
 -         glBindFramebuffer (GL_FRAMEBUFFER, useMSAA ? msaaBufferHandle
 -                                                    : frameBufferHandle);
 -         return true;
 -     }
 - 
 -     bool isActive() const noexcept
 -     {
 -         return [EAGLContext currentContext] == context.get();
 -     }
 - 
 -     static void deactivateCurrentContext()
 -     {
 -         [EAGLContext setCurrentContext: nil];
 -     }
 - 
 -     void swapBuffers()
 -     {
 -         if (useMSAA)
 -         {
 -             glBindFramebuffer (GL_DRAW_FRAMEBUFFER, frameBufferHandle);
 -             glBindFramebuffer (GL_READ_FRAMEBUFFER, msaaBufferHandle);
 - 
 -             if (openGLversion >= openGL3_2)
 -             {
 -                 auto w = roundToInt (lastBounds.getWidth()  * glLayer.contentsScale);
 -                 auto h = roundToInt (lastBounds.getHeight() * glLayer.contentsScale);
 - 
 -                 glBlitFramebuffer (0, 0, w, h,
 -                                    0, 0, w, h,
 -                                    GL_COLOR_BUFFER_BIT,
 -                                    GL_NEAREST);
 -             }
 -             else
 -             {
 -                 ::glResolveMultisampleFramebufferAPPLE();
 -             }
 -         }
 - 
 -         glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
 -         [context.get() presentRenderbuffer: GL_RENDERBUFFER];
 - 
 -         if (needToRebuildBuffers)
 -         {
 -             needToRebuildBuffers = false;
 - 
 -             freeGLBuffers();
 -             createGLBuffers();
 -             makeActive();
 -         }
 -     }
 - 
 -     void updateWindowPosition (Rectangle<int> bounds)
 -     {
 -         view.frame = convertToCGRect (bounds);
 -         glLayer.contentsScale = (CGFloat) (Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale
 -                                             / component.getDesktopScaleFactor());
 - 
 -         if (lastBounds != bounds)
 -         {
 -             lastBounds = bounds;
 -             needToRebuildBuffers = true;
 -         }
 -     }
 - 
 -     bool setSwapInterval (int numFramesPerSwap) noexcept
 -     {
 -         swapFrames = numFramesPerSwap;
 -         return false;
 -     }
 - 
 -     int getSwapInterval() const noexcept    { return swapFrames; }
 - 
 -     struct Locker
 -     {
 -         explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}
 -         const ScopedLock lock;
 -     };
 - 
 - private:
 -     CriticalSection mutex;
 -     Component& component;
 -     JuceGLView* view = nil;
 -     CAEAGLLayer* glLayer = nil;
 -     NSUniquePtr<EAGLContext> context;
 -     const OpenGLVersion openGLversion;
 -     const bool useDepthBuffer, useMSAA;
 - 
 -     GLuint frameBufferHandle = 0, colorBufferHandle = 0, depthBufferHandle = 0,
 -            msaaColorHandle = 0, msaaBufferHandle = 0;
 - 
 -     Rectangle<int> lastBounds;
 -     int swapFrames = 0;
 -     bool needToRebuildBuffers = false;
 - 
 -     bool createContext (EAGLRenderingAPI type, void* contextToShare)
 -     {
 -         jassert (context == nil);
 -         context.reset ([EAGLContext alloc]);
 - 
 -         if (contextToShare != nullptr)
 -             [context.get() initWithAPI: type  sharegroup: [(EAGLContext*) contextToShare sharegroup]];
 -         else
 -             [context.get() initWithAPI: type];
 - 
 -         return context != nil;
 -     }
 - 
 -     //==============================================================================
 -     void createGLBuffers()
 -     {
 -         glGenFramebuffers (1, &frameBufferHandle);
 -         glGenRenderbuffers (1, &colorBufferHandle);
 - 
 -         glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
 -         glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
 - 
 -         glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle);
 - 
 -         [[maybe_unused]] bool ok = [context.get() renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];
 -         jassert (ok);
 - 
 -         GLint width, height;
 -         glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
 -         glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
 - 
 -         if (useMSAA)
 -         {
 -             glGenFramebuffers (1, &msaaBufferHandle);
 -             glGenRenderbuffers (1, &msaaColorHandle);
 - 
 -             glBindFramebuffer (GL_FRAMEBUFFER, msaaBufferHandle);
 -             glBindRenderbuffer (GL_RENDERBUFFER, msaaColorHandle);
 - 
 -             glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_RGBA8, width, height);
 - 
 -             glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColorHandle);
 -         }
 - 
 -         if (useDepthBuffer)
 -         {
 -             glGenRenderbuffers (1, &depthBufferHandle);
 -             glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle);
 - 
 -             if (useMSAA)
 -                 glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, width, height);
 -             else
 -                 glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
 - 
 -             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.get() renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];
 - 
 -         deleteFrameBuffer (frameBufferHandle);
 -         deleteFrameBuffer (msaaBufferHandle);
 -         deleteRenderBuffer (colorBufferHandle);
 -         deleteRenderBuffer (depthBufferHandle);
 -         deleteRenderBuffer (msaaColorHandle);
 - 
 -         JUCE_CHECK_OPENGL_ERROR
 -     }
 - 
 -     static void deleteFrameBuffer  (GLuint& i)   { if (i != 0) glDeleteFramebuffers  (1, &i); i = 0; }
 -     static void deleteRenderBuffer (GLuint& i)   { if (i != 0) glDeleteRenderbuffers (1, &i); i = 0; }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
 - };
 - 
 - //==============================================================================
 - bool OpenGLHelpers::isContextActive()
 - {
 -     return [EAGLContext currentContext] != nil;
 - }
 - 
 - } // namespace juce
 
 
  |