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.

243 lines
8.7KB

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