Mac: Support for multiple contexts per SDL_Window.
authorJørgen P. Tjernø <jorgen@valvesoftware.com>
Wed, 07 Aug 2013 16:29:25 -0700
changeset 7595ede2237fcebf
parent 7594 6abcf951af68
child 7596 45e5c263c096
Mac: Support for multiple contexts per SDL_Window.
src/video/cocoa/SDL_cocoaopengl.h
src/video/cocoa/SDL_cocoaopengl.m
src/video/cocoa/SDL_cocoawindow.h
src/video/cocoa/SDL_cocoawindow.m
     1.1 --- a/src/video/cocoa/SDL_cocoaopengl.h	Wed Aug 07 16:29:21 2013 -0700
     1.2 +++ b/src/video/cocoa/SDL_cocoaopengl.h	Wed Aug 07 16:29:25 2013 -0700
     1.3 @@ -35,12 +35,14 @@
     1.4  
     1.5  @interface SDLOpenGLContext : NSOpenGLContext {
     1.6      SDL_atomic_t dirty;
     1.7 +    SDL_Window *window;
     1.8  }
     1.9  
    1.10  - (id)initWithFormat:(NSOpenGLPixelFormat *)format
    1.11          shareContext:(NSOpenGLContext *)share;
    1.12  - (void)scheduleUpdate;
    1.13  - (void)updateIfNeeded;
    1.14 +- (void)setWindow:(SDL_Window *)window;
    1.15  
    1.16  @end
    1.17  
     2.1 --- a/src/video/cocoa/SDL_cocoaopengl.m	Wed Aug 07 16:29:21 2013 -0700
     2.2 +++ b/src/video/cocoa/SDL_cocoaopengl.m	Wed Aug 07 16:29:25 2013 -0700
     2.3 @@ -51,8 +51,12 @@
     2.4  - (id)initWithFormat:(NSOpenGLPixelFormat *)format
     2.5          shareContext:(NSOpenGLContext *)share
     2.6  {
     2.7 -    SDL_AtomicSet(&self->dirty, 0);
     2.8 -    return [super initWithFormat:format shareContext:share];
     2.9 +    self = [super initWithFormat:format shareContext:share];
    2.10 +    if (self) {
    2.11 +        SDL_AtomicSet(&self->dirty, 0);
    2.12 +        self->window = NULL;
    2.13 +    }
    2.14 +    return self;
    2.15  }
    2.16  
    2.17  - (void)scheduleUpdate
    2.18 @@ -78,6 +82,40 @@
    2.19      [self updateIfNeeded];
    2.20  }
    2.21  
    2.22 +/* Updates the drawable for the contexts and manages related state. */
    2.23 +- (void)setWindow:(SDL_Window *)newWindow
    2.24 +{
    2.25 +    if (self->window) {
    2.26 +        SDL_WindowData *oldwindowdata = (SDL_WindowData *)self->window->driverdata;
    2.27 +
    2.28 +        /* Make sure to remove us from the old window's context list, or we'll get scheduled updates from it too. */
    2.29 +        NSMutableArray *contexts = oldwindowdata->nscontexts;
    2.30 +        @synchronized (contexts) {
    2.31 +            [contexts removeObject:self];
    2.32 +        }
    2.33 +    }
    2.34 +
    2.35 +    self->window = newWindow;
    2.36 +
    2.37 +    if (newWindow) {
    2.38 +        SDL_WindowData *windowdata = (SDL_WindowData *)newWindow->driverdata;
    2.39 +
    2.40 +        /* Now sign up for scheduled updates for the new window. */
    2.41 +        NSMutableArray *contexts = windowdata->nscontexts;
    2.42 +        @synchronized (contexts) {
    2.43 +            [contexts addObject:self];
    2.44 +        }
    2.45 +
    2.46 +        if ([self view] != [windowdata->nswindow contentView]) {
    2.47 +            [self setView:[windowdata->nswindow contentView]];
    2.48 +            [self scheduleUpdate];
    2.49 +        }
    2.50 +    } else {
    2.51 +        [self clearDrawable];
    2.52 +        [self scheduleUpdate];
    2.53 +    }
    2.54 +}
    2.55 +
    2.56  @end
    2.57  
    2.58  
    2.59 @@ -244,14 +282,8 @@
    2.60      pool = [[NSAutoreleasePool alloc] init];
    2.61  
    2.62      if (context) {
    2.63 -        SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
    2.64          SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
    2.65 -        windowdata->nscontext = nscontext;
    2.66 -        if ([nscontext view] != [windowdata->nswindow contentView]) {
    2.67 -            [nscontext setView:[windowdata->nswindow contentView]];
    2.68 -            [nscontext scheduleUpdate];
    2.69 -        }
    2.70 -
    2.71 +        [nscontext setWindow:window];
    2.72          [nscontext updateIfNeeded];
    2.73          [nscontext makeCurrentContext];
    2.74      } else {
    2.75 @@ -309,11 +341,10 @@
    2.76  Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
    2.77  {
    2.78      NSAutoreleasePool *pool;
    2.79 -    SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
    2.80 -    SDLOpenGLContext *nscontext = windowdata->nscontext;
    2.81  
    2.82      pool = [[NSAutoreleasePool alloc] init];
    2.83  
    2.84 +    SDLOpenGLContext* nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
    2.85      [nscontext flushBuffer];
    2.86      [nscontext updateIfNeeded];
    2.87  
    2.88 @@ -324,11 +355,11 @@
    2.89  Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
    2.90  {
    2.91      NSAutoreleasePool *pool;
    2.92 -    NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
    2.93 +    SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
    2.94  
    2.95      pool = [[NSAutoreleasePool alloc] init];
    2.96  
    2.97 -    [nscontext clearDrawable];
    2.98 +    [nscontext setWindow:NULL];
    2.99      [nscontext release];
   2.100  
   2.101      [pool release];
     3.1 --- a/src/video/cocoa/SDL_cocoawindow.h	Wed Aug 07 16:29:21 2013 -0700
     3.2 +++ b/src/video/cocoa/SDL_cocoawindow.h	Wed Aug 07 16:29:25 2013 -0700
     3.3 @@ -83,7 +83,7 @@
     3.4  {
     3.5      SDL_Window *window;
     3.6      NSWindow *nswindow;
     3.7 -    SDLOpenGLContext *nscontext;
     3.8 +    NSMutableArray *nscontexts;
     3.9      SDL_bool created;
    3.10      Cocoa_WindowListener *listener;
    3.11      struct SDL_VideoData *videodata;
     4.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Wed Aug 07 16:29:21 2013 -0700
     4.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Wed Aug 07 16:29:25 2013 -0700
     4.3 @@ -42,6 +42,16 @@
     4.4      r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
     4.5  }
     4.6  
     4.7 +static void ScheduleContextUpdates(SDL_WindowData *data)
     4.8 +{
     4.9 +    NSMutableArray *contexts = data->nscontexts;
    4.10 +    @synchronized (contexts) {
    4.11 +        for (SDLOpenGLContext *context in contexts) {
    4.12 +            [context scheduleUpdate];
    4.13 +        }
    4.14 +    }
    4.15 +}
    4.16 +
    4.17  @implementation Cocoa_WindowListener
    4.18  
    4.19  - (void)listen:(SDL_WindowData *)data
    4.20 @@ -211,7 +221,7 @@
    4.21      x = (int)rect.origin.x;
    4.22      y = (int)rect.origin.y;
    4.23  
    4.24 -    [_data->nscontext scheduleUpdate];
    4.25 +    ScheduleContextUpdates(_data);
    4.26  
    4.27      SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
    4.28  }
    4.29 @@ -228,7 +238,7 @@
    4.30      if (SDL_IsShapedWindow(_data->window))
    4.31          Cocoa_ResizeWindowShape(_data->window);
    4.32  
    4.33 -    [_data->nscontext scheduleUpdate];
    4.34 +    ScheduleContextUpdates(_data);
    4.35  
    4.36      /* The window can move during a resize event, such as when maximizing
    4.37         or resizing from a corner */
    4.38 @@ -605,6 +615,7 @@
    4.39      data->nswindow = nswindow;
    4.40      data->created = created;
    4.41      data->videodata = videodata;
    4.42 +    data->nscontexts = [[NSMutableArray alloc] init];
    4.43  
    4.44      pool = [[NSAutoreleasePool alloc] init];
    4.45  
    4.46 @@ -799,7 +810,7 @@
    4.47      [nswindow setFrameOrigin:rect.origin];
    4.48      s_moveHack = moveHack;
    4.49  
    4.50 -    [windata->nscontext scheduleUpdate];
    4.51 +    ScheduleContextUpdates(windata);
    4.52  
    4.53      [pool release];
    4.54  }
    4.55 @@ -816,7 +827,7 @@
    4.56      size.height = window->h;
    4.57      [nswindow setContentSize:size];
    4.58  
    4.59 -    [windata->nscontext scheduleUpdate];
    4.60 +    ScheduleContextUpdates(windata);
    4.61  
    4.62      [pool release];
    4.63  }
    4.64 @@ -903,7 +914,7 @@
    4.65  
    4.66      [nswindow zoom:nil];
    4.67  
    4.68 -    [windata->nscontext scheduleUpdate];
    4.69 +    ScheduleContextUpdates(windata);
    4.70  
    4.71      [pool release];
    4.72  }
    4.73 @@ -1040,7 +1051,7 @@
    4.74      [nswindow makeKeyAndOrderFront:nil];
    4.75      [data->listener resumeVisibleObservation];
    4.76  
    4.77 -    [data->nscontext scheduleUpdate];
    4.78 +    ScheduleContextUpdates(data);
    4.79  
    4.80      [pool release];
    4.81  }
    4.82 @@ -1133,6 +1144,14 @@
    4.83          if (data->created) {
    4.84              [data->nswindow close];
    4.85          }
    4.86 +
    4.87 +        NSArray *contexts = [[data->nscontexts copy] autorelease];
    4.88 +        for (SDLOpenGLContext *context in contexts) {
    4.89 +            /* Calling setWindow:NULL causes the context to remove itself from the context list. */            
    4.90 +            [context setWindow:NULL];
    4.91 +        }
    4.92 +        [data->nscontexts release];
    4.93 +
    4.94          SDL_free(data);
    4.95      }
    4.96      [pool release];