1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-27 02:20:05 +00:00
JUCE/src/native/mac/juce_mac_OpenGLComponent.mm

316 lines
11 KiB
Text

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
// (This file gets included by juce_mac_NativeCode.mm, rather than being
// compiled on its own).
#if JUCE_INCLUDED_FILE && JUCE_OPENGL
END_JUCE_NAMESPACE
//==============================================================================
@interface ThreadSafeNSOpenGLView : NSOpenGLView
{
CriticalSection* contextLock;
bool needsUpdate;
}
- (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format;
- (bool) makeActive;
- (void) makeInactive;
- (void) reshape;
@end
@implementation ThreadSafeNSOpenGLView
- (id) initWithFrame: (NSRect) frameRect
pixelFormat: (NSOpenGLPixelFormat*) format
{
contextLock = new CriticalSection();
self = [super initWithFrame: frameRect pixelFormat: format];
if (self != nil)
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector (_surfaceNeedsUpdate:)
name: NSViewGlobalFrameDidChangeNotification
object: self];
return self;
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
delete contextLock;
[super dealloc];
}
- (bool) makeActive
{
const ScopedLock sl (*contextLock);
if ([self openGLContext] == 0)
return false;
[[self openGLContext] makeCurrentContext];
if (needsUpdate)
{
[super update];
needsUpdate = false;
}
return true;
}
- (void) makeInactive
{
const ScopedLock sl (*contextLock);
[NSOpenGLContext clearCurrentContext];
}
- (void) _surfaceNeedsUpdate: (NSNotification*) notification
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}
- (void) update
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}
- (void) reshape
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}
@end
BEGIN_JUCE_NAMESPACE
//==============================================================================
class WindowedGLContext : public OpenGLContext
{
public:
WindowedGLContext (Component* const component,
const OpenGLPixelFormat& pixelFormat_,
NSOpenGLContext* sharedContext)
: renderContext (0),
pixelFormat (pixelFormat_)
{
jassert (component != 0);
NSOpenGLPixelFormatAttribute attribs [64];
int n = 0;
attribs[n++] = NSOpenGLPFADoubleBuffer;
attribs[n++] = NSOpenGLPFAAccelerated;
attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer
attribs[n++] = NSOpenGLPFAColorSize;
attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits,
pixelFormat.greenBits,
pixelFormat.blueBits);
attribs[n++] = NSOpenGLPFAAlphaSize;
attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits;
attribs[n++] = NSOpenGLPFADepthSize;
attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits;
attribs[n++] = NSOpenGLPFAStencilSize;
attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits;
attribs[n++] = NSOpenGLPFAAccumSize;
attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.accumulationBufferRedBits,
pixelFormat.accumulationBufferGreenBits,
pixelFormat.accumulationBufferBlueBits,
pixelFormat.accumulationBufferAlphaBits);
// xxx not sure how to do fullSceneAntiAliasingNumSamples..
attribs[n++] = NSOpenGLPFASampleBuffers;
attribs[n++] = (NSOpenGLPixelFormatAttribute) 1;
attribs[n++] = NSOpenGLPFAClosestPolicy;
attribs[n++] = NSOpenGLPFANoRecovery;
attribs[n++] = (NSOpenGLPixelFormatAttribute) 0;
NSOpenGLPixelFormat* format
= [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
pixelFormat: format];
renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
shareContext: sharedContext] autorelease];
const GLint swapInterval = 1;
[renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
[view setOpenGLContext: renderContext];
[renderContext setView: view];
[format release];
viewHolder = new NSViewComponentInternal (view, component);
}
~WindowedGLContext()
{
makeInactive();
[renderContext setView: nil];
delete viewHolder;
}
bool makeActive() const throw()
{
jassert (renderContext != 0);
[view makeActive];
return isActive();
}
bool makeInactive() const throw()
{
[view makeInactive];
return true;
}
bool isActive() const throw()
{
return [NSOpenGLContext currentContext] == renderContext;
}
const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; }
void* getRawContext() const throw() { return renderContext; }
void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight)
{
}
void swapBuffers()
{
[renderContext flushBuffer];
}
bool setSwapInterval (const int numFramesPerSwap)
{
[renderContext setValues: (const GLint*) &numFramesPerSwap
forParameter: NSOpenGLCPSwapInterval];
return true;
}
int getSwapInterval() const
{
GLint numFrames = 0;
[renderContext getValues: &numFrames
forParameter: NSOpenGLCPSwapInterval];
return numFrames;
}
void repaint()
{
// we need to invalidate the juce view that holds this gl view, to make it
// cause a repaint callback
NSView* v = (NSView*) viewHolder->view;
NSRect r = [v frame];
// bit of a bodge here.. if we only invalidate the area of the gl component,
// it's completely covered by the NSOpenGLView, so the OS throws away the
// repaint message, thus never causing our paint() callback, and never repainting
// the comp. So invalidating just a little bit around the edge helps..
[[v superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)];
}
void* getNativeWindowHandle() const { return viewHolder->view; }
//==============================================================================
juce_UseDebuggingNewOperator
NSOpenGLContext* renderContext;
ThreadSafeNSOpenGLView* view;
private:
OpenGLPixelFormat pixelFormat;
NSViewComponentInternal* viewHolder;
//==============================================================================
WindowedGLContext (const WindowedGLContext&);
const WindowedGLContext& operator= (const WindowedGLContext&);
};
//==============================================================================
OpenGLContext* OpenGLContext::createContextForWindow (Component* const component,
const OpenGLPixelFormat& pixelFormat,
const OpenGLContext* const contextToShareWith)
{
WindowedGLContext* c = new WindowedGLContext (component, pixelFormat,
contextToShareWith != 0 ? (NSOpenGLContext*) contextToShareWith->getRawContext() : 0);
if (c->renderContext == 0)
deleteAndZero (c);
return c;
}
void* OpenGLComponent::getNativeWindowHandle() const
{
return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle()
: 0;
}
void juce_glViewport (const int w, const int h)
{
glViewport (0, 0, w, h);
}
void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/,
OwnedArray <OpenGLPixelFormat>& results)
{
/* GLint attribs [64];
int n = 0;
attribs[n++] = AGL_RGBA;
attribs[n++] = AGL_DOUBLEBUFFER;
attribs[n++] = AGL_ACCELERATED;
attribs[n++] = AGL_NO_RECOVERY;
attribs[n++] = AGL_NONE;
AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs);
while (p != 0)
{
OpenGLPixelFormat* const pf = new OpenGLPixelFormat();
pf->redBits = getAGLAttribute (p, AGL_RED_SIZE);
pf->greenBits = getAGLAttribute (p, AGL_GREEN_SIZE);
pf->blueBits = getAGLAttribute (p, AGL_BLUE_SIZE);
pf->alphaBits = getAGLAttribute (p, AGL_ALPHA_SIZE);
pf->depthBufferBits = getAGLAttribute (p, AGL_DEPTH_SIZE);
pf->stencilBufferBits = getAGLAttribute (p, AGL_STENCIL_SIZE);
pf->accumulationBufferRedBits = getAGLAttribute (p, AGL_ACCUM_RED_SIZE);
pf->accumulationBufferGreenBits = getAGLAttribute (p, AGL_ACCUM_GREEN_SIZE);
pf->accumulationBufferBlueBits = getAGLAttribute (p, AGL_ACCUM_BLUE_SIZE);
pf->accumulationBufferAlphaBits = getAGLAttribute (p, AGL_ACCUM_ALPHA_SIZE);
results.add (pf);
p = aglNextPixelFormat (p);
}*/
//jassertfalse //xxx can't see how you do this in cocoa!
}
#endif