The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
7.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. } // (juce namespace)
  19. @interface JuceGLView : UIView
  20. {
  21. }
  22. + (Class) layerClass;
  23. @end
  24. @implementation JuceGLView
  25. + (Class) layerClass
  26. {
  27. return [CAEAGLLayer class];
  28. }
  29. @end
  30. namespace juce
  31. {
  32. class OpenGLContext::NativeContext
  33. {
  34. public:
  35. NativeContext (Component& component,
  36. const OpenGLPixelFormat& pixelFormat,
  37. void* contextToShareWith)
  38. : frameBufferHandle (0), colorBufferHandle (0), depthBufferHandle (0),
  39. lastWidth (0), lastHeight (0), needToRebuildBuffers (false),
  40. swapFrames (0), useDepthBuffer (pixelFormat.depthBufferBits > 0)
  41. {
  42. JUCE_AUTORELEASEPOOL
  43. {
  44. ComponentPeer* const peer = component.getPeer();
  45. jassert (peer != nullptr);
  46. const Rectangle<int> bounds (peer->getComponent().getLocalArea (&component, component.getLocalBounds()));
  47. lastWidth = bounds.getWidth();
  48. lastHeight = bounds.getHeight();
  49. view = [[JuceGLView alloc] initWithFrame: convertToCGRect (bounds)];
  50. view.opaque = YES;
  51. view.hidden = NO;
  52. view.backgroundColor = [UIColor blackColor];
  53. view.userInteractionEnabled = NO;
  54. glLayer = (CAEAGLLayer*) [view layer];
  55. glLayer.contentsScale = Desktop::getInstance().getDisplays().getMainDisplay().scale;
  56. [((UIView*) peer->getNativeHandle()) addSubview: view];
  57. context = [EAGLContext alloc];
  58. const NSUInteger type = kEAGLRenderingAPIOpenGLES2;
  59. if (contextToShareWith != nullptr)
  60. [context initWithAPI: type sharegroup: [(EAGLContext*) contextToShareWith sharegroup]];
  61. else
  62. [context initWithAPI: type];
  63. // I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing
  64. // so causes myserious timing-related failures.
  65. [EAGLContext setCurrentContext: context];
  66. createGLBuffers();
  67. deactivateCurrentContext();
  68. }
  69. }
  70. ~NativeContext()
  71. {
  72. [context release];
  73. context = nil;
  74. [view removeFromSuperview];
  75. [view release];
  76. }
  77. void initialiseOnRenderThread (OpenGLContext&) {}
  78. void shutdownOnRenderThread()
  79. {
  80. JUCE_CHECK_OPENGL_ERROR
  81. freeGLBuffers();
  82. deactivateCurrentContext();
  83. }
  84. bool createdOk() const noexcept { return getRawContext() != nullptr; }
  85. void* getRawContext() const noexcept { return context; }
  86. GLuint getFrameBufferID() const noexcept { return frameBufferHandle; }
  87. bool makeActive() const noexcept
  88. {
  89. if (! [EAGLContext setCurrentContext: context])
  90. return false;
  91. glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
  92. return true;
  93. }
  94. bool isActive() const noexcept
  95. {
  96. return [EAGLContext currentContext] == context;
  97. }
  98. static void deactivateCurrentContext()
  99. {
  100. [EAGLContext setCurrentContext: nil];
  101. }
  102. void swapBuffers()
  103. {
  104. glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
  105. [context presentRenderbuffer: GL_RENDERBUFFER];
  106. if (needToRebuildBuffers)
  107. {
  108. needToRebuildBuffers = false;
  109. freeGLBuffers();
  110. createGLBuffers();
  111. makeActive();
  112. }
  113. }
  114. void updateWindowPosition (const Rectangle<int>& bounds)
  115. {
  116. view.frame = convertToCGRect (bounds);
  117. if (lastWidth != bounds.getWidth() || lastHeight != bounds.getHeight())
  118. {
  119. lastWidth = bounds.getWidth();
  120. lastHeight = bounds.getHeight();
  121. needToRebuildBuffers = true;
  122. }
  123. }
  124. bool setSwapInterval (const int numFramesPerSwap) noexcept
  125. {
  126. swapFrames = numFramesPerSwap;
  127. return false;
  128. }
  129. int getSwapInterval() const noexcept { return swapFrames; }
  130. struct Locker { Locker (NativeContext&) {} };
  131. private:
  132. JuceGLView* view;
  133. CAEAGLLayer* glLayer;
  134. EAGLContext* context;
  135. GLuint frameBufferHandle, colorBufferHandle, depthBufferHandle;
  136. int volatile lastWidth, lastHeight;
  137. bool volatile needToRebuildBuffers;
  138. int swapFrames;
  139. bool useDepthBuffer;
  140. //==============================================================================
  141. void createGLBuffers()
  142. {
  143. glGenFramebuffers (1, &frameBufferHandle);
  144. glGenRenderbuffers (1, &colorBufferHandle);
  145. glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
  146. bool ok = [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];
  147. jassert (ok); (void) ok;
  148. if (useDepthBuffer)
  149. {
  150. GLint width, height;
  151. glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
  152. glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
  153. glGenRenderbuffers (1, &depthBufferHandle);
  154. glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle);
  155. glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
  156. }
  157. glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
  158. glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
  159. glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle);
  160. if (useDepthBuffer)
  161. glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBufferHandle);
  162. jassert (glCheckFramebufferStatus (GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  163. JUCE_CHECK_OPENGL_ERROR
  164. }
  165. void freeGLBuffers()
  166. {
  167. JUCE_CHECK_OPENGL_ERROR
  168. [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];
  169. if (frameBufferHandle != 0)
  170. {
  171. glDeleteFramebuffers (1, &frameBufferHandle);
  172. frameBufferHandle = 0;
  173. }
  174. if (colorBufferHandle != 0)
  175. {
  176. glDeleteRenderbuffers (1, &colorBufferHandle);
  177. colorBufferHandle = 0;
  178. }
  179. if (depthBufferHandle != 0)
  180. {
  181. glDeleteRenderbuffers (1, &depthBufferHandle);
  182. depthBufferHandle = 0;
  183. }
  184. JUCE_CHECK_OPENGL_ERROR
  185. }
  186. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)
  187. };
  188. //==============================================================================
  189. bool OpenGLHelpers::isContextActive()
  190. {
  191. return [EAGLContext currentContext] != nil;
  192. }