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.

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