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.

240 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. const NativeContext* 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. NSOpenGLContext* const sharedContext
  114. = contextToShareWith != nullptr ? contextToShareWith->renderContext : nil;
  115. renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
  116. shareContext: sharedContext] autorelease];
  117. setSwapInterval (1);
  118. [view setOpenGLContext: renderContext];
  119. [format release];
  120. viewAttachment = NSViewComponent::attachViewToComponent (component, view);
  121. }
  122. ~NativeContext()
  123. {
  124. [renderContext clearDrawable];
  125. [renderContext setView: nil];
  126. [view setOpenGLContext: nil];
  127. renderContext = nil;
  128. }
  129. void initialiseOnRenderThread() {}
  130. void shutdownOnRenderThread() {}
  131. bool createdOk() const noexcept { return getRawContext() != nullptr; }
  132. void* getRawContext() const noexcept { return static_cast <void*> (renderContext); }
  133. GLuint getFrameBufferID() const noexcept { return 0; }
  134. bool makeActive() const noexcept
  135. {
  136. jassert (renderContext != nil);
  137. if ([renderContext view] != view)
  138. [renderContext setView: view];
  139. [view makeActive];
  140. return true;
  141. }
  142. bool isActive() const noexcept
  143. {
  144. return [NSOpenGLContext currentContext] == renderContext;
  145. }
  146. struct Locker
  147. {
  148. Locker (NativeContext& nc) : cglContext ((CGLContextObj) [nc.renderContext CGLContextObj])
  149. {
  150. CGLLockContext (cglContext);
  151. }
  152. ~Locker()
  153. {
  154. CGLUnlockContext (cglContext);
  155. }
  156. private:
  157. CGLContextObj cglContext;
  158. };
  159. void swapBuffers()
  160. {
  161. [renderContext flushBuffer];
  162. }
  163. void updateWindowPosition (const Rectangle<int>&) {}
  164. bool setSwapInterval (int numFramesPerSwap)
  165. {
  166. [renderContext setValues: (const GLint*) &numFramesPerSwap
  167. forParameter: NSOpenGLCPSwapInterval];
  168. return true;
  169. }
  170. int getSwapInterval() const
  171. {
  172. GLint numFrames = 0;
  173. [renderContext getValues: &numFrames
  174. forParameter: NSOpenGLCPSwapInterval];
  175. return numFrames;
  176. }
  177. private:
  178. NSOpenGLContext* renderContext;
  179. ThreadSafeNSOpenGLView* view;
  180. ReferenceCountedObjectPtr<ReferenceCountedObject> viewAttachment;
  181. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext);
  182. };
  183. //==============================================================================
  184. bool OpenGLHelpers::isContextActive()
  185. {
  186. return CGLGetCurrentContext() != 0;
  187. }