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.

256 lines
8.3KB

  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. 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 CriticalSection();
  38. self = [super initWithFrame: frameRect pixelFormat: format];
  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 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) makeInactive
  66. {
  67. const ScopedLock sl (*contextLock);
  68. [NSOpenGLContext clearCurrentContext];
  69. }
  70. - (void) _surfaceNeedsUpdate: (NSNotification*) notification
  71. {
  72. (void) notification;
  73. const ScopedLock sl (*contextLock);
  74. needsUpdate = true;
  75. }
  76. - (void) update
  77. {
  78. const ScopedLock sl (*contextLock);
  79. needsUpdate = true;
  80. }
  81. - (void) reshape
  82. {
  83. const ScopedLock sl (*contextLock);
  84. needsUpdate = true;
  85. }
  86. - (void) rightMouseDown: (NSEvent*) ev { [[self superview] rightMouseDown: ev]; }
  87. - (void) rightMouseUp: (NSEvent*) ev { [[self superview] rightMouseUp: ev]; }
  88. @end
  89. namespace juce
  90. {
  91. //==============================================================================
  92. class WindowedGLContext : public OpenGLContext
  93. {
  94. public:
  95. WindowedGLContext (OpenGLComponent& component,
  96. const OpenGLPixelFormat& pixelFormat,
  97. NSOpenGLContext* sharedContext)
  98. : renderContext (nil)
  99. {
  100. extensions.initialise();
  101. NSOpenGLPixelFormatAttribute attribs[] =
  102. {
  103. NSOpenGLPFADoubleBuffer,
  104. NSOpenGLPFAMPSafe,
  105. NSOpenGLPFAClosestPolicy,
  106. NSOpenGLPFANoRecovery,
  107. NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) (pixelFormat.redBits + pixelFormat.greenBits + pixelFormat.blueBits),
  108. NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits,
  109. NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits,
  110. NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits,
  111. NSOpenGLPFAAccumSize, (NSOpenGLPixelFormatAttribute) (pixelFormat.accumulationBufferRedBits + pixelFormat.accumulationBufferGreenBits
  112. + pixelFormat.accumulationBufferBlueBits + pixelFormat.accumulationBufferAlphaBits),
  113. pixelFormat.multisamplingLevel > 0 ? NSOpenGLPFASamples : (NSOpenGLPixelFormatAttribute) 0, (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. renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
  120. shareContext: sharedContext] autorelease];
  121. const GLint swapInterval = 1;
  122. [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
  123. [view setOpenGLContext: renderContext];
  124. [format release];
  125. component.setView (view);
  126. }
  127. ~WindowedGLContext()
  128. {
  129. properties.clear(); // to release any stored programs, etc that may be held in properties.
  130. makeInactive();
  131. [renderContext clearDrawable];
  132. [renderContext setView: nil];
  133. [view setOpenGLContext: nil];
  134. renderContext = nil;
  135. }
  136. bool makeActive() const noexcept
  137. {
  138. jassert (renderContext != nil);
  139. if ([renderContext view] != view)
  140. [renderContext setView: view];
  141. [view makeActive];
  142. return isActive();
  143. }
  144. bool makeInactive() const noexcept
  145. {
  146. [view makeInactive];
  147. return true;
  148. }
  149. bool isActive() const noexcept
  150. {
  151. return [NSOpenGLContext currentContext] == renderContext;
  152. }
  153. void* getRawContext() const noexcept { return renderContext; }
  154. unsigned int getFrameBufferID() const { return 0; }
  155. int getWidth() const { return [view frame].size.width; }
  156. int getHeight() const { return [view frame].size.height; }
  157. void swapBuffers()
  158. {
  159. [renderContext flushBuffer];
  160. }
  161. bool setSwapInterval (const int numFramesPerSwap)
  162. {
  163. [renderContext setValues: (const GLint*) &numFramesPerSwap
  164. forParameter: NSOpenGLCPSwapInterval];
  165. return true;
  166. }
  167. int getSwapInterval() const
  168. {
  169. GLint numFrames = 0;
  170. [renderContext getValues: &numFrames
  171. forParameter: NSOpenGLCPSwapInterval];
  172. return numFrames;
  173. }
  174. void* getNativeWindowHandle() const { return view; }
  175. //==============================================================================
  176. NSOpenGLContext* renderContext;
  177. ThreadSafeNSOpenGLView* view;
  178. private:
  179. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowedGLContext);
  180. };
  181. //==============================================================================
  182. OpenGLContext* OpenGLComponent::createContext()
  183. {
  184. ScopedPointer<WindowedGLContext> c (new WindowedGLContext (*this, preferredPixelFormat,
  185. contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : nil));
  186. return (c->renderContext != nil) ? c.release() : nullptr;
  187. }
  188. void* OpenGLComponent::getNativeWindowHandle() const
  189. {
  190. return context != nullptr ? static_cast<WindowedGLContext*> (context.get())->getNativeWindowHandle()
  191. : nullptr;
  192. }
  193. void OpenGLComponent::updateEmbeddedPosition (const Rectangle<int>&)
  194. {
  195. }
  196. //==============================================================================
  197. bool OpenGLHelpers::isContextActive()
  198. {
  199. return CGLGetCurrentContext() != 0;
  200. }