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.

241 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. [view setOpenGLContext: renderContext];
  116. [format release];
  117. viewAttachment = NSViewComponent::attachViewToComponent (component, view);
  118. }
  119. ~NativeContext()
  120. {
  121. [[NSNotificationCenter defaultCenter] removeObserver: view];
  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. ThreadSafeNSOpenGLViewClass::makeActive (view);
  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. NSOpenGLView* 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. }