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.

242 lines
7.5KB

  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. #define ThreadSafeNSOpenGLView MakeObjCClassName(ThreadSafeNSOpenGLView)
  20. //==============================================================================
  21. @interface ThreadSafeNSOpenGLView : NSOpenGLView
  22. {
  23. juce::CriticalSection* contextLock;
  24. bool needsUpdate;
  25. }
  26. - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format;
  27. - (bool) makeActive;
  28. - (void) reshape;
  29. - (void) rightMouseDown: (NSEvent*) ev;
  30. - (void) rightMouseUp: (NSEvent*) ev;
  31. @end
  32. @implementation ThreadSafeNSOpenGLView
  33. - (id) initWithFrame: (NSRect) frameRect
  34. pixelFormat: (NSOpenGLPixelFormat*) format
  35. {
  36. contextLock = new juce::CriticalSection();
  37. self = [super initWithFrame: frameRect pixelFormat: format];
  38. needsUpdate = true;
  39. if (self != nil)
  40. [[NSNotificationCenter defaultCenter] addObserver: self
  41. selector: @selector (_surfaceNeedsUpdate:)
  42. name: NSViewGlobalFrameDidChangeNotification
  43. object: self];
  44. return self;
  45. }
  46. - (void) dealloc
  47. {
  48. [[NSNotificationCenter defaultCenter] removeObserver: self];
  49. delete contextLock;
  50. [super dealloc];
  51. }
  52. - (bool) makeActive
  53. {
  54. const juce::ScopedLock sl (*contextLock);
  55. if ([self openGLContext] == nil)
  56. return false;
  57. [[self openGLContext] makeCurrentContext];
  58. if (needsUpdate)
  59. {
  60. [super update];
  61. needsUpdate = false;
  62. }
  63. return true;
  64. }
  65. - (void) _surfaceNeedsUpdate: (NSNotification*) notification
  66. {
  67. (void) notification;
  68. const juce::ScopedLock sl (*contextLock);
  69. needsUpdate = true;
  70. }
  71. - (void) update
  72. {
  73. const juce::ScopedLock sl (*contextLock);
  74. needsUpdate = true;
  75. }
  76. - (void) reshape
  77. {
  78. const juce::ScopedLock sl (*contextLock);
  79. needsUpdate = true;
  80. }
  81. - (void) rightMouseDown: (NSEvent*) ev { [[self superview] rightMouseDown: ev]; }
  82. - (void) rightMouseUp: (NSEvent*) ev { [[self superview] rightMouseUp: ev]; }
  83. @end
  84. namespace juce
  85. {
  86. //==============================================================================
  87. class OpenGLContext::NativeContext
  88. {
  89. public:
  90. NativeContext (Component& component,
  91. const OpenGLPixelFormat& pixelFormat,
  92. void* contextToShareWith)
  93. {
  94. NSOpenGLPixelFormatAttribute attribs[] =
  95. {
  96. NSOpenGLPFADoubleBuffer,
  97. NSOpenGLPFAMPSafe,
  98. NSOpenGLPFAClosestPolicy,
  99. NSOpenGLPFANoRecovery,
  100. NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) (pixelFormat.redBits + pixelFormat.greenBits + pixelFormat.blueBits),
  101. NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits,
  102. NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits,
  103. NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits,
  104. NSOpenGLPFAAccumSize, (NSOpenGLPixelFormatAttribute) (pixelFormat.accumulationBufferRedBits + pixelFormat.accumulationBufferGreenBits
  105. + pixelFormat.accumulationBufferBlueBits + pixelFormat.accumulationBufferAlphaBits),
  106. pixelFormat.multisamplingLevel > 0 ? NSOpenGLPFASamples : (NSOpenGLPixelFormatAttribute) 0,
  107. (NSOpenGLPixelFormatAttribute) pixelFormat.multisamplingLevel,
  108. 0
  109. };
  110. NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
  111. view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
  112. pixelFormat: format];
  113. renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
  114. shareContext: (NSOpenGLContext*) contextToShareWith] autorelease];
  115. setSwapInterval (1);
  116. [view setOpenGLContext: renderContext];
  117. [format release];
  118. viewAttachment = NSViewComponent::attachViewToComponent (component, view);
  119. }
  120. ~NativeContext()
  121. {
  122. [renderContext clearDrawable];
  123. [renderContext setView: nil];
  124. [view setOpenGLContext: nil];
  125. renderContext = nil;
  126. }
  127. void initialiseOnRenderThread() {}
  128. void shutdownOnRenderThread() { deactivateCurrentContext(); }
  129. bool createdOk() const noexcept { return getRawContext() != nullptr; }
  130. void* getRawContext() const noexcept { return static_cast <void*> (renderContext); }
  131. GLuint getFrameBufferID() const noexcept { return 0; }
  132. bool makeActive() const noexcept
  133. {
  134. jassert (renderContext != nil);
  135. if ([renderContext view] != view)
  136. [renderContext setView: view];
  137. [view makeActive];
  138. return true;
  139. }
  140. bool isActive() const noexcept
  141. {
  142. return [NSOpenGLContext currentContext] == renderContext;
  143. }
  144. static void deactivateCurrentContext()
  145. {
  146. [NSOpenGLContext clearCurrentContext];
  147. }
  148. struct Locker
  149. {
  150. Locker (NativeContext& nc) : cglContext ((CGLContextObj) [nc.renderContext CGLContextObj])
  151. {
  152. CGLLockContext (cglContext);
  153. }
  154. ~Locker()
  155. {
  156. CGLUnlockContext (cglContext);
  157. }
  158. private:
  159. CGLContextObj cglContext;
  160. };
  161. void swapBuffers()
  162. {
  163. [renderContext flushBuffer];
  164. }
  165. void updateWindowPosition (const Rectangle<int>&) {}
  166. bool setSwapInterval (int numFramesPerSwap)
  167. {
  168. [renderContext setValues: (const GLint*) &numFramesPerSwap
  169. forParameter: NSOpenGLCPSwapInterval];
  170. return true;
  171. }
  172. int getSwapInterval() const
  173. {
  174. GLint numFrames = 0;
  175. [renderContext getValues: &numFrames
  176. forParameter: NSOpenGLCPSwapInterval];
  177. return numFrames;
  178. }
  179. private:
  180. NSOpenGLContext* renderContext;
  181. ThreadSafeNSOpenGLView* view;
  182. ReferenceCountedObjectPtr<ReferenceCountedObject> viewAttachment;
  183. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext);
  184. };
  185. //==============================================================================
  186. bool OpenGLHelpers::isContextActive()
  187. {
  188. return CGLGetCurrentContext() != 0;
  189. }