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.

323 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. // (This file gets included by juce_mac_NativeCode.mm, rather than being
  24. // compiled on its own).
  25. #if JUCE_INCLUDED_FILE && JUCE_OPENGL
  26. END_JUCE_NAMESPACE
  27. //==============================================================================
  28. @interface ThreadSafeNSOpenGLView : NSOpenGLView
  29. {
  30. CriticalSection* contextLock;
  31. bool needsUpdate;
  32. }
  33. - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format;
  34. - (bool) makeActive;
  35. - (void) makeInactive;
  36. - (void) reshape;
  37. @end
  38. @implementation ThreadSafeNSOpenGLView
  39. - (id) initWithFrame: (NSRect) frameRect
  40. pixelFormat: (NSOpenGLPixelFormat*) format
  41. {
  42. contextLock = new CriticalSection();
  43. self = [super initWithFrame: frameRect pixelFormat: format];
  44. if (self != nil)
  45. [[NSNotificationCenter defaultCenter] addObserver: self
  46. selector: @selector (_surfaceNeedsUpdate:)
  47. name: NSViewGlobalFrameDidChangeNotification
  48. object: self];
  49. return self;
  50. }
  51. - (void) dealloc
  52. {
  53. [[NSNotificationCenter defaultCenter] removeObserver: self];
  54. delete contextLock;
  55. [super dealloc];
  56. }
  57. - (bool) makeActive
  58. {
  59. const ScopedLock sl (*contextLock);
  60. if ([self openGLContext] == 0)
  61. return false;
  62. [[self openGLContext] makeCurrentContext];
  63. if (needsUpdate)
  64. {
  65. [super update];
  66. needsUpdate = false;
  67. }
  68. return true;
  69. }
  70. - (void) makeInactive
  71. {
  72. const ScopedLock sl (*contextLock);
  73. [NSOpenGLContext clearCurrentContext];
  74. }
  75. - (void) _surfaceNeedsUpdate: (NSNotification*) notification
  76. {
  77. const ScopedLock sl (*contextLock);
  78. needsUpdate = true;
  79. }
  80. - (void) update
  81. {
  82. const ScopedLock sl (*contextLock);
  83. needsUpdate = true;
  84. }
  85. - (void) reshape
  86. {
  87. const ScopedLock sl (*contextLock);
  88. needsUpdate = true;
  89. }
  90. @end
  91. BEGIN_JUCE_NAMESPACE
  92. //==============================================================================
  93. class WindowedGLContext : public OpenGLContext
  94. {
  95. public:
  96. WindowedGLContext (Component* const component,
  97. const OpenGLPixelFormat& pixelFormat_,
  98. NSOpenGLContext* sharedContext)
  99. : renderContext (0),
  100. pixelFormat (pixelFormat_)
  101. {
  102. jassert (component != 0);
  103. NSOpenGLPixelFormatAttribute attribs [64];
  104. int n = 0;
  105. attribs[n++] = NSOpenGLPFADoubleBuffer;
  106. attribs[n++] = NSOpenGLPFAAccelerated;
  107. attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer
  108. attribs[n++] = NSOpenGLPFAColorSize;
  109. attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits,
  110. pixelFormat.greenBits,
  111. pixelFormat.blueBits);
  112. attribs[n++] = NSOpenGLPFAAlphaSize;
  113. attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits;
  114. attribs[n++] = NSOpenGLPFADepthSize;
  115. attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits;
  116. attribs[n++] = NSOpenGLPFAStencilSize;
  117. attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits;
  118. attribs[n++] = NSOpenGLPFAAccumSize;
  119. attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.accumulationBufferRedBits,
  120. pixelFormat.accumulationBufferGreenBits,
  121. pixelFormat.accumulationBufferBlueBits,
  122. pixelFormat.accumulationBufferAlphaBits);
  123. // xxx not sure how to do fullSceneAntiAliasingNumSamples..
  124. attribs[n++] = NSOpenGLPFASampleBuffers;
  125. attribs[n++] = (NSOpenGLPixelFormatAttribute) 1;
  126. attribs[n++] = NSOpenGLPFAClosestPolicy;
  127. attribs[n++] = NSOpenGLPFANoRecovery;
  128. attribs[n++] = (NSOpenGLPixelFormatAttribute) 0;
  129. NSOpenGLPixelFormat* format
  130. = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
  131. view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
  132. pixelFormat: format];
  133. renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
  134. shareContext: sharedContext] autorelease];
  135. const GLint swapInterval = 1;
  136. [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
  137. [view setOpenGLContext: renderContext];
  138. [renderContext setView: view];
  139. [format release];
  140. viewHolder = new NSViewComponentInternal (view, component);
  141. }
  142. ~WindowedGLContext()
  143. {
  144. makeInactive();
  145. [renderContext setView: nil];
  146. delete viewHolder;
  147. }
  148. bool makeActive() const throw()
  149. {
  150. jassert (renderContext != 0);
  151. [view makeActive];
  152. return isActive();
  153. }
  154. bool makeInactive() const throw()
  155. {
  156. [view makeInactive];
  157. return true;
  158. }
  159. bool isActive() const throw()
  160. {
  161. return [NSOpenGLContext currentContext] == renderContext;
  162. }
  163. const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; }
  164. void* getRawContext() const throw() { return renderContext; }
  165. void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight)
  166. {
  167. }
  168. void swapBuffers()
  169. {
  170. [renderContext flushBuffer];
  171. }
  172. bool setSwapInterval (const int numFramesPerSwap)
  173. {
  174. [renderContext setValues: (const GLint*) &numFramesPerSwap
  175. forParameter: NSOpenGLCPSwapInterval];
  176. return true;
  177. }
  178. int getSwapInterval() const
  179. {
  180. GLint numFrames = 0;
  181. [renderContext getValues: &numFrames
  182. forParameter: NSOpenGLCPSwapInterval];
  183. return numFrames;
  184. }
  185. void repaint()
  186. {
  187. // we need to invalidate the juce view that holds this gl view, to make it
  188. // cause a repaint callback
  189. NSView* v = (NSView*) viewHolder->view;
  190. NSRect r = [v 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. [[v superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)];
  196. }
  197. void* getNativeWindowHandle() const { return viewHolder->view; }
  198. //==============================================================================
  199. juce_UseDebuggingNewOperator
  200. NSOpenGLContext* renderContext;
  201. ThreadSafeNSOpenGLView* view;
  202. private:
  203. OpenGLPixelFormat pixelFormat;
  204. NSViewComponentInternal* viewHolder;
  205. //==============================================================================
  206. WindowedGLContext (const WindowedGLContext&);
  207. const WindowedGLContext& operator= (const WindowedGLContext&);
  208. };
  209. //==============================================================================
  210. OpenGLContext* OpenGLContext::createContextForWindow (Component* const component,
  211. const OpenGLPixelFormat& pixelFormat,
  212. const OpenGLContext* const contextToShareWith)
  213. {
  214. WindowedGLContext* c = new WindowedGLContext (component, pixelFormat,
  215. contextToShareWith != 0 ? (NSOpenGLContext*) contextToShareWith->getRawContext() : 0);
  216. if (c->renderContext == 0)
  217. deleteAndZero (c);
  218. return c;
  219. }
  220. void* OpenGLComponent::getNativeWindowHandle() const
  221. {
  222. return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle()
  223. : 0;
  224. }
  225. void juce_glViewport (const int w, const int h)
  226. {
  227. glViewport (0, 0, w, h);
  228. }
  229. void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/,
  230. OwnedArray <OpenGLPixelFormat>& results)
  231. {
  232. /* GLint attribs [64];
  233. int n = 0;
  234. attribs[n++] = AGL_RGBA;
  235. attribs[n++] = AGL_DOUBLEBUFFER;
  236. attribs[n++] = AGL_ACCELERATED;
  237. attribs[n++] = AGL_NO_RECOVERY;
  238. attribs[n++] = AGL_NONE;
  239. AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs);
  240. while (p != 0)
  241. {
  242. OpenGLPixelFormat* const pf = new OpenGLPixelFormat();
  243. pf->redBits = getAGLAttribute (p, AGL_RED_SIZE);
  244. pf->greenBits = getAGLAttribute (p, AGL_GREEN_SIZE);
  245. pf->blueBits = getAGLAttribute (p, AGL_BLUE_SIZE);
  246. pf->alphaBits = getAGLAttribute (p, AGL_ALPHA_SIZE);
  247. pf->depthBufferBits = getAGLAttribute (p, AGL_DEPTH_SIZE);
  248. pf->stencilBufferBits = getAGLAttribute (p, AGL_STENCIL_SIZE);
  249. pf->accumulationBufferRedBits = getAGLAttribute (p, AGL_ACCUM_RED_SIZE);
  250. pf->accumulationBufferGreenBits = getAGLAttribute (p, AGL_ACCUM_GREEN_SIZE);
  251. pf->accumulationBufferBlueBits = getAGLAttribute (p, AGL_ACCUM_BLUE_SIZE);
  252. pf->accumulationBufferAlphaBits = getAGLAttribute (p, AGL_ACCUM_ALPHA_SIZE);
  253. results.add (pf);
  254. p = aglNextPixelFormat (p);
  255. }*/
  256. //jassertfalse //xxx can't see how you do this in cocoa!
  257. }
  258. #endif