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.

315 lines
11KB

  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. END_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] == 0)
  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
  87. {
  88. [[self superview] rightMouseDown: ev];
  89. }
  90. - (void) rightMouseUp: (NSEvent*) ev
  91. {
  92. [[self superview] rightMouseUp: ev];
  93. }
  94. @end
  95. BEGIN_JUCE_NAMESPACE
  96. //==============================================================================
  97. class WindowedGLContext : public OpenGLContext
  98. {
  99. public:
  100. WindowedGLContext (OpenGLComponent& component,
  101. const OpenGLPixelFormat& pixelFormat_,
  102. NSOpenGLContext* sharedContext)
  103. : renderContext (nil),
  104. pixelFormat (pixelFormat_)
  105. {
  106. NSOpenGLPixelFormatAttribute attribs[] =
  107. {
  108. NSOpenGLPFADoubleBuffer,
  109. NSOpenGLPFAAccelerated,
  110. NSOpenGLPFAMPSafe,
  111. NSOpenGLPFAClosestPolicy,
  112. NSOpenGLPFANoRecovery,
  113. NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) (pixelFormat.redBits
  114. + pixelFormat.greenBits
  115. + pixelFormat.blueBits),
  116. NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits,
  117. NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits,
  118. NSOpenGLPFAStencilSize, (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits,
  119. NSOpenGLPFAAccumSize, (NSOpenGLPixelFormatAttribute) (pixelFormat.accumulationBufferRedBits
  120. + pixelFormat.accumulationBufferGreenBits
  121. + pixelFormat.accumulationBufferBlueBits
  122. + pixelFormat.accumulationBufferAlphaBits),
  123. NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute) 1,
  124. (NSOpenGLPixelFormatAttribute) 0
  125. };
  126. NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
  127. view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
  128. pixelFormat: format];
  129. renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
  130. shareContext: sharedContext] autorelease];
  131. const GLint swapInterval = 1;
  132. [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
  133. [view setOpenGLContext: renderContext];
  134. [format release];
  135. component.setView (view);
  136. }
  137. ~WindowedGLContext()
  138. {
  139. deleteContext();
  140. }
  141. void deleteContext()
  142. {
  143. makeInactive();
  144. [renderContext clearDrawable];
  145. [renderContext setView: nil];
  146. [view setOpenGLContext: nil];
  147. renderContext = nil;
  148. }
  149. bool makeActive() const noexcept
  150. {
  151. jassert (renderContext != nil);
  152. if ([renderContext view] != view)
  153. [renderContext setView: view];
  154. [view makeActive];
  155. return isActive();
  156. }
  157. bool makeInactive() const noexcept
  158. {
  159. [view makeInactive];
  160. return true;
  161. }
  162. bool isActive() const noexcept
  163. {
  164. return [NSOpenGLContext currentContext] == renderContext;
  165. }
  166. OpenGLPixelFormat getPixelFormat() const { return pixelFormat; }
  167. void* getRawContext() const noexcept { return renderContext; }
  168. void updateWindowPosition (const Rectangle<int>&) {}
  169. void swapBuffers()
  170. {
  171. [renderContext flushBuffer];
  172. }
  173. bool setSwapInterval (const int numFramesPerSwap)
  174. {
  175. [renderContext setValues: (const GLint*) &numFramesPerSwap
  176. forParameter: NSOpenGLCPSwapInterval];
  177. return true;
  178. }
  179. int getSwapInterval() const
  180. {
  181. GLint numFrames = 0;
  182. [renderContext getValues: &numFrames
  183. forParameter: NSOpenGLCPSwapInterval];
  184. return numFrames;
  185. }
  186. void repaint()
  187. {
  188. // we need to invalidate the juce view that holds this gl view, to make it
  189. // cause a repaint callback
  190. NSRect r = [view frame];
  191. // bit of a bodge here.. if we only invalidate the area of the gl component,
  192. // it's completely covered by the NSOpenGLView, so the OS throws away the
  193. // repaint message, thus never causing our paint() callback, and never repainting
  194. // the comp. So invalidating just a little bit around the edge helps..
  195. [[view superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)];
  196. }
  197. void* getNativeWindowHandle() const { return view; }
  198. //==============================================================================
  199. NSOpenGLContext* renderContext;
  200. ThreadSafeNSOpenGLView* view;
  201. private:
  202. OpenGLPixelFormat pixelFormat;
  203. //==============================================================================
  204. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowedGLContext);
  205. };
  206. //==============================================================================
  207. OpenGLContext* OpenGLComponent::createContext()
  208. {
  209. ScopedPointer<WindowedGLContext> c (new WindowedGLContext (*this, preferredPixelFormat,
  210. contextToShareListsWith != nullptr ? (NSOpenGLContext*) contextToShareListsWith->getRawContext() : nil));
  211. return (c->renderContext != nil) ? c.release() : nullptr;
  212. }
  213. void* OpenGLComponent::getNativeWindowHandle() const
  214. {
  215. return context != nullptr ? static_cast<WindowedGLContext*> (static_cast<OpenGLContext*> (context))->getNativeWindowHandle()
  216. : nullptr;
  217. }
  218. static int getPixelFormatAttribute (NSOpenGLPixelFormat* p, NSOpenGLPixelFormatAttribute att)
  219. {
  220. GLint val = 0;
  221. [p getValues: &val forAttribute: att forVirtualScreen: 0];
  222. return (int) val;
  223. }
  224. void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/,
  225. OwnedArray <OpenGLPixelFormat>& results)
  226. {
  227. NSOpenGLPixelFormatAttribute attributes[] =
  228. {
  229. NSOpenGLPFAWindow,
  230. NSOpenGLPFADoubleBuffer,
  231. NSOpenGLPFAAccelerated,
  232. NSOpenGLPFANoRecovery,
  233. NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) 16,
  234. NSOpenGLPFAAlphaSize, (NSOpenGLPixelFormatAttribute) 8,
  235. NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) 24,
  236. NSOpenGLPFAAccumSize, (NSOpenGLPixelFormatAttribute) 32,
  237. (NSOpenGLPixelFormatAttribute) 0
  238. };
  239. NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attributes];
  240. if (format != nil)
  241. {
  242. OpenGLPixelFormat* const pf = new OpenGLPixelFormat();
  243. pf->redBits = pf->greenBits = pf->blueBits = getPixelFormatAttribute (format, NSOpenGLPFAColorSize) / 3;
  244. pf->alphaBits = getPixelFormatAttribute (format, NSOpenGLPFAAlphaSize);
  245. pf->depthBufferBits = getPixelFormatAttribute (format, NSOpenGLPFADepthSize);
  246. pf->stencilBufferBits = getPixelFormatAttribute (format, NSOpenGLPFAStencilSize);
  247. pf->accumulationBufferRedBits = pf->accumulationBufferGreenBits
  248. = pf->accumulationBufferBlueBits = pf->accumulationBufferAlphaBits
  249. = getPixelFormatAttribute (format, NSOpenGLPFAAccumSize) / 4;
  250. [format release];
  251. results.add (pf);
  252. }
  253. }