Mac: Support for multiple contexts per SDL_Window.
This commit is contained in:
parent
20c8287efc
commit
9fb9406bbc
4 changed files with 72 additions and 20 deletions
|
@ -35,12 +35,14 @@ struct SDL_GLDriverData
|
|||
|
||||
@interface SDLOpenGLContext : NSOpenGLContext {
|
||||
SDL_atomic_t dirty;
|
||||
SDL_Window *window;
|
||||
}
|
||||
|
||||
- (id)initWithFormat:(NSOpenGLPixelFormat *)format
|
||||
shareContext:(NSOpenGLContext *)share;
|
||||
- (void)scheduleUpdate;
|
||||
- (void)updateIfNeeded;
|
||||
- (void)setWindow:(SDL_Window *)window;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -51,8 +51,12 @@
|
|||
- (id)initWithFormat:(NSOpenGLPixelFormat *)format
|
||||
shareContext:(NSOpenGLContext *)share
|
||||
{
|
||||
SDL_AtomicSet(&self->dirty, 0);
|
||||
return [super initWithFormat:format shareContext:share];
|
||||
self = [super initWithFormat:format shareContext:share];
|
||||
if (self) {
|
||||
SDL_AtomicSet(&self->dirty, 0);
|
||||
self->window = NULL;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)scheduleUpdate
|
||||
|
@ -78,6 +82,40 @@
|
|||
[self updateIfNeeded];
|
||||
}
|
||||
|
||||
/* Updates the drawable for the contexts and manages related state. */
|
||||
- (void)setWindow:(SDL_Window *)newWindow
|
||||
{
|
||||
if (self->window) {
|
||||
SDL_WindowData *oldwindowdata = (SDL_WindowData *)self->window->driverdata;
|
||||
|
||||
/* Make sure to remove us from the old window's context list, or we'll get scheduled updates from it too. */
|
||||
NSMutableArray *contexts = oldwindowdata->nscontexts;
|
||||
@synchronized (contexts) {
|
||||
[contexts removeObject:self];
|
||||
}
|
||||
}
|
||||
|
||||
self->window = newWindow;
|
||||
|
||||
if (newWindow) {
|
||||
SDL_WindowData *windowdata = (SDL_WindowData *)newWindow->driverdata;
|
||||
|
||||
/* Now sign up for scheduled updates for the new window. */
|
||||
NSMutableArray *contexts = windowdata->nscontexts;
|
||||
@synchronized (contexts) {
|
||||
[contexts addObject:self];
|
||||
}
|
||||
|
||||
if ([self view] != [windowdata->nswindow contentView]) {
|
||||
[self setView:[windowdata->nswindow contentView]];
|
||||
[self scheduleUpdate];
|
||||
}
|
||||
} else {
|
||||
[self clearDrawable];
|
||||
[self scheduleUpdate];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -244,14 +282,8 @@ Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
|||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (context) {
|
||||
SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
|
||||
SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
|
||||
windowdata->nscontext = nscontext;
|
||||
if ([nscontext view] != [windowdata->nswindow contentView]) {
|
||||
[nscontext setView:[windowdata->nswindow contentView]];
|
||||
[nscontext scheduleUpdate];
|
||||
}
|
||||
|
||||
[nscontext setWindow:window];
|
||||
[nscontext updateIfNeeded];
|
||||
[nscontext makeCurrentContext];
|
||||
} else {
|
||||
|
@ -309,11 +341,10 @@ void
|
|||
Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
|
||||
SDLOpenGLContext *nscontext = windowdata->nscontext;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
SDLOpenGLContext* nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
|
||||
[nscontext flushBuffer];
|
||||
[nscontext updateIfNeeded];
|
||||
|
||||
|
@ -324,11 +355,11 @@ void
|
|||
Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
|
||||
SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
[nscontext clearDrawable];
|
||||
[nscontext setWindow:NULL];
|
||||
[nscontext release];
|
||||
|
||||
[pool release];
|
||||
|
|
|
@ -83,7 +83,7 @@ struct SDL_WindowData
|
|||
{
|
||||
SDL_Window *window;
|
||||
NSWindow *nswindow;
|
||||
SDLOpenGLContext *nscontext;
|
||||
NSMutableArray *nscontexts;
|
||||
SDL_bool created;
|
||||
Cocoa_WindowListener *listener;
|
||||
struct SDL_VideoData *videodata;
|
||||
|
|
|
@ -42,6 +42,16 @@ static __inline__ void ConvertNSRect(NSRect *r)
|
|||
r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
|
||||
}
|
||||
|
||||
static void ScheduleContextUpdates(SDL_WindowData *data)
|
||||
{
|
||||
NSMutableArray *contexts = data->nscontexts;
|
||||
@synchronized (contexts) {
|
||||
for (SDLOpenGLContext *context in contexts) {
|
||||
[context scheduleUpdate];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@implementation Cocoa_WindowListener
|
||||
|
||||
- (void)listen:(SDL_WindowData *)data
|
||||
|
@ -211,7 +221,7 @@ static __inline__ void ConvertNSRect(NSRect *r)
|
|||
x = (int)rect.origin.x;
|
||||
y = (int)rect.origin.y;
|
||||
|
||||
[_data->nscontext scheduleUpdate];
|
||||
ScheduleContextUpdates(_data);
|
||||
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
|
||||
}
|
||||
|
@ -228,7 +238,7 @@ static __inline__ void ConvertNSRect(NSRect *r)
|
|||
if (SDL_IsShapedWindow(_data->window))
|
||||
Cocoa_ResizeWindowShape(_data->window);
|
||||
|
||||
[_data->nscontext scheduleUpdate];
|
||||
ScheduleContextUpdates(_data);
|
||||
|
||||
/* The window can move during a resize event, such as when maximizing
|
||||
or resizing from a corner */
|
||||
|
@ -605,6 +615,7 @@ SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created
|
|||
data->nswindow = nswindow;
|
||||
data->created = created;
|
||||
data->videodata = videodata;
|
||||
data->nscontexts = [[NSMutableArray alloc] init];
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
@ -799,7 +810,7 @@ Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
|
|||
[nswindow setFrameOrigin:rect.origin];
|
||||
s_moveHack = moveHack;
|
||||
|
||||
[windata->nscontext scheduleUpdate];
|
||||
ScheduleContextUpdates(windata);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
@ -816,7 +827,7 @@ Cocoa_SetWindowSize(_THIS, SDL_Window * window)
|
|||
size.height = window->h;
|
||||
[nswindow setContentSize:size];
|
||||
|
||||
[windata->nscontext scheduleUpdate];
|
||||
ScheduleContextUpdates(windata);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
@ -903,7 +914,7 @@ Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
|
|||
|
||||
[nswindow zoom:nil];
|
||||
|
||||
[windata->nscontext scheduleUpdate];
|
||||
ScheduleContextUpdates(windata);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
@ -1040,7 +1051,7 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
|
|||
[nswindow makeKeyAndOrderFront:nil];
|
||||
[data->listener resumeVisibleObservation];
|
||||
|
||||
[data->nscontext scheduleUpdate];
|
||||
ScheduleContextUpdates(data);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
@ -1133,6 +1144,14 @@ Cocoa_DestroyWindow(_THIS, SDL_Window * window)
|
|||
if (data->created) {
|
||||
[data->nswindow close];
|
||||
}
|
||||
|
||||
NSArray *contexts = [[data->nscontexts copy] autorelease];
|
||||
for (SDLOpenGLContext *context in contexts) {
|
||||
/* Calling setWindow:NULL causes the context to remove itself from the context list. */
|
||||
[context setWindow:NULL];
|
||||
}
|
||||
[data->nscontexts release];
|
||||
|
||||
SDL_free(data);
|
||||
}
|
||||
[pool release];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue