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.

237 lines
7.4KB

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