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.

245 lines
8.0KB

  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. //==============================================================================
  33. class GLESContext : public OpenGLContext
  34. {
  35. public:
  36. GLESContext (UIView* parentView,
  37. Component* const component_,
  38. const OpenGLPixelFormat& pixelFormat,
  39. const GLESContext* const sharedContext,
  40. const bool isGLES2_)
  41. : component (component_), glLayer (nil), context (nil),
  42. useDepthBuffer (pixelFormat.depthBufferBits > 0), isGLES2 (isGLES2_),
  43. frameBufferHandle (0), colorBufferHandle (0),
  44. depthBufferHandle (0), lastWidth (0), lastHeight (0)
  45. {
  46. view = [[JuceGLView alloc] initWithFrame: CGRectMake (0, 0, 64, 64)];
  47. view.opaque = YES;
  48. view.hidden = NO;
  49. view.backgroundColor = [UIColor blackColor];
  50. view.userInteractionEnabled = NO;
  51. glLayer = (CAEAGLLayer*) [view layer];
  52. [parentView addSubview: view];
  53. NSUInteger apiType = isGLES2_ ? kEAGLRenderingAPIOpenGLES2
  54. : kEAGLRenderingAPIOpenGLES1;
  55. if (sharedContext != nullptr)
  56. context = [[EAGLContext alloc] initWithAPI: apiType
  57. sharegroup: [sharedContext->context sharegroup]];
  58. else
  59. context = [[EAGLContext alloc] initWithAPI: apiType];
  60. createGLBuffers();
  61. }
  62. ~GLESContext()
  63. {
  64. properties.clear(); // to release any stored programs, etc that may be held in properties.
  65. makeInactive();
  66. [context release];
  67. context = nil;
  68. [view removeFromSuperview];
  69. [view release];
  70. freeGLBuffers();
  71. }
  72. bool makeActive() const noexcept
  73. {
  74. jassert (context != nil);
  75. [EAGLContext setCurrentContext: context];
  76. glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
  77. return true;
  78. }
  79. void swapBuffers()
  80. {
  81. glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
  82. [context presentRenderbuffer: GL_RENDERBUFFER];
  83. }
  84. bool makeInactive() const noexcept
  85. {
  86. return [EAGLContext setCurrentContext: nil];
  87. }
  88. bool isActive() const noexcept { return [EAGLContext currentContext] == context; }
  89. void* getRawContext() const noexcept { return glLayer; }
  90. unsigned int getFrameBufferID() const { return (unsigned int) frameBufferHandle; }
  91. int getWidth() const { return lastWidth; }
  92. int getHeight() const { return lastHeight; }
  93. bool areShadersAvailable() const { return isGLES2; }
  94. void updateWindowPosition (const Rectangle<int>& bounds)
  95. {
  96. // For some strange reason, the view seems to fail unless its width is a multiple of 8...
  97. view.frame = CGRectMake ((CGFloat) bounds.getX(), (CGFloat) bounds.getY(),
  98. (CGFloat) (bounds.getWidth() & ~7),
  99. (CGFloat) bounds.getHeight());
  100. if (lastWidth != bounds.getWidth() || lastHeight != bounds.getHeight())
  101. {
  102. lastWidth = bounds.getWidth();
  103. lastHeight = bounds.getHeight();
  104. freeGLBuffers();
  105. createGLBuffers();
  106. }
  107. }
  108. bool setSwapInterval (const int numFramesPerSwap)
  109. {
  110. numFrames = numFramesPerSwap;
  111. return true;
  112. }
  113. int getSwapInterval() const
  114. {
  115. return numFrames;
  116. }
  117. //==============================================================================
  118. void createGLBuffers()
  119. {
  120. makeActive();
  121. glGenFramebuffers (1, &frameBufferHandle);
  122. glGenRenderbuffers (1, &colorBufferHandle);
  123. glGenRenderbuffers (1, &depthBufferHandle);
  124. glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
  125. bool ok = [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];
  126. jassert (ok); (void) ok;
  127. GLint width, height;
  128. glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
  129. glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
  130. if (useDepthBuffer)
  131. {
  132. glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle);
  133. glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
  134. }
  135. glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);
  136. glBindFramebuffer (GL_FRAMEBUFFER, frameBufferHandle);
  137. glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle);
  138. if (useDepthBuffer)
  139. glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBufferHandle);
  140. jassert (glCheckFramebufferStatus (GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  141. }
  142. void freeGLBuffers()
  143. {
  144. [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];
  145. if (frameBufferHandle != 0)
  146. {
  147. glDeleteFramebuffers (1, &frameBufferHandle);
  148. frameBufferHandle = 0;
  149. }
  150. if (colorBufferHandle != 0)
  151. {
  152. glDeleteRenderbuffers (1, &colorBufferHandle);
  153. colorBufferHandle = 0;
  154. }
  155. if (depthBufferHandle != 0)
  156. {
  157. glDeleteRenderbuffers (1, &depthBufferHandle);
  158. depthBufferHandle = 0;
  159. }
  160. }
  161. private:
  162. WeakReference<Component> component;
  163. JuceGLView* view;
  164. CAEAGLLayer* glLayer;
  165. EAGLContext* context;
  166. bool useDepthBuffer, isGLES2;
  167. GLuint frameBufferHandle, colorBufferHandle, depthBufferHandle;
  168. int numFrames;
  169. int lastWidth, lastHeight;
  170. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GLESContext);
  171. };
  172. OpenGLContext* OpenGLComponent::createContext()
  173. {
  174. JUCE_AUTORELEASEPOOL
  175. ComponentPeer* peer = getPeer();
  176. if (peer != nullptr)
  177. return new GLESContext ((UIView*) peer->getNativeHandle(), this, preferredPixelFormat,
  178. dynamic_cast <const GLESContext*> (contextToShareListsWith),
  179. (flags & openGLES2) != 0);
  180. return nullptr;
  181. }
  182. void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>& bounds)
  183. {
  184. const ScopedLock sl (contextLock);
  185. if (context != nullptr)
  186. static_cast <GLESContext*> (context.get())->updateWindowPosition (bounds);
  187. }
  188. //==============================================================================
  189. bool OpenGLHelpers::isContextActive()
  190. {
  191. return [EAGLContext currentContext] != nil;
  192. }