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