Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Mac: Don't -[NSOpenGLContext update] on (potentially) the wrong thread.
Browse files Browse the repository at this point in the history
If the user is using their context from a non-main thread, we could be
calling -[NSOpenGLContext update] on our thread, while they were
accessing it on their thread.

With this change, we schedule updates when the event comes in on the
main thread, and act on them when the user calls SDL_GL_MakeCurrent or
SDL_GL_SwapWindow.
  • Loading branch information
jorgenpt committed Aug 7, 2013
1 parent 4804438 commit 879053c
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 31 deletions.
15 changes: 15 additions & 0 deletions src/video/cocoa/SDL_cocoaopengl.h
Expand Up @@ -25,11 +25,26 @@

#if SDL_VIDEO_OPENGL_CGL

#include "SDL_atomic.h"
#import <Cocoa/Cocoa.h>

struct SDL_GLDriverData
{
int initialized;
};

@interface SDLOpenGLContext : NSOpenGLContext {
SDL_atomic_t dirty;
}

- (id)initWithFormat:(NSOpenGLPixelFormat *)format
shareContext:(NSOpenGLContext *)share;
- (void)scheduleUpdate;
- (void)updateIfNeeded;

@end


/* OpenGL functions */
extern int Cocoa_GL_LoadLibrary(_THIS, const char *path);
extern void *Cocoa_GL_GetProcAddress(_THIS, const char *proc);
Expand Down
53 changes: 45 additions & 8 deletions src/video/cocoa/SDL_cocoaopengl.m
Expand Up @@ -24,6 +24,7 @@

#if SDL_VIDEO_OPENGL_CGL
#include "SDL_cocoavideo.h"
#include "SDL_cocoaopengl.h"

#include <OpenGL/CGLTypes.h>
#include <OpenGL/OpenGL.h>
Expand All @@ -45,6 +46,40 @@
#define kCGLOGLPVersion_3_2_Core 0x3200
#endif

@implementation SDLOpenGLContext : NSOpenGLContext

- (id)initWithFormat:(NSOpenGLPixelFormat *)format
shareContext:(NSOpenGLContext *)share
{
SDL_AtomicSet(&self->dirty, 0);
return [super initWithFormat:format shareContext:share];
}

- (void)scheduleUpdate
{
SDL_AtomicAdd(&self->dirty, 1);
}

/* This should only be called on the thread on which a user is using the context. */
- (void)updateIfNeeded
{
int value = SDL_AtomicSet(&self->dirty, 0);
if (value > 0) {
/* We call the real underlying update here, since -[SDLOpenGLContext update] just calls us. */
[super update];
}
}

/* This should only be called on the thread on which a user is using the context. */
- (void)update
{
/* This ensures that regular 'update' calls clear the atomic dirty flag. */
[self scheduleUpdate];
[self updateIfNeeded];
}

@end


int
Cocoa_GL_LoadLibrary(_THIS, const char *path)
Expand Down Expand Up @@ -89,7 +124,7 @@
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
NSOpenGLPixelFormatAttribute attr[32];
NSOpenGLPixelFormat *fmt;
NSOpenGLContext *context;
SDLOpenGLContext *context;
NSOpenGLContext *share_context = nil;
int i = 0;

Expand Down Expand Up @@ -181,7 +216,7 @@
share_context = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
}

context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];
context = [[SDLOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];

[fmt release];

Expand Down Expand Up @@ -210,13 +245,14 @@

if (context) {
SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
NSOpenGLContext *nscontext = (NSOpenGLContext *)context;

SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
windowdata->nscontext = nscontext;
if ([nscontext view] != [windowdata->nswindow contentView]) {
[nscontext setView:[windowdata->nswindow contentView]];
[nscontext update];
[nscontext scheduleUpdate];
}

[nscontext updateIfNeeded];
[nscontext makeCurrentContext];
} else {
[NSOpenGLContext clearCurrentContext];
Expand All @@ -236,7 +272,7 @@

pool = [[NSAutoreleasePool alloc] init];

nscontext = [NSOpenGLContext currentContext];
nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
if (nscontext != nil) {
value = interval;
[nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
Expand All @@ -259,7 +295,7 @@

pool = [[NSAutoreleasePool alloc] init];

nscontext = [NSOpenGLContext currentContext];
nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
if (nscontext != nil) {
[nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
status = (int)value;
Expand All @@ -274,11 +310,12 @@
{
NSAutoreleasePool *pool;
SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
NSOpenGLContext *nscontext = windowdata->nscontext;
SDLOpenGLContext *nscontext = windowdata->nscontext;

pool = [[NSAutoreleasePool alloc] init];

[nscontext flushBuffer];
[nscontext updateIfNeeded];

[pool release];
}
Expand Down
4 changes: 3 additions & 1 deletion src/video/cocoa/SDL_cocoawindow.h
Expand Up @@ -77,11 +77,13 @@ typedef enum {
@end
/* *INDENT-ON* */

@class SDLOpenGLContext;

struct SDL_WindowData
{
SDL_Window *window;
NSWindow *nswindow;
NSOpenGLContext *nscontext;
SDLOpenGLContext *nscontext;
SDL_bool created;
Cocoa_WindowListener *listener;
struct SDL_VideoData *videodata;
Expand Down
33 changes: 11 additions & 22 deletions src/video/cocoa/SDL_cocoawindow.m
Expand Up @@ -32,6 +32,7 @@
#include "SDL_cocoavideo.h"
#include "SDL_cocoashape.h"
#include "SDL_cocoamouse.h"
#include "SDL_cocoaopengl.h"


static Uint32 s_moveHack;
Expand Down Expand Up @@ -187,7 +188,6 @@ - (void)windowDidExpose:(NSNotification *)aNotification
- (void)windowDidMove:(NSNotification *)aNotification
{
int x, y;
SDL_VideoDevice *device = SDL_GetVideoDevice();
SDL_Window *window = _data->window;
NSWindow *nswindow = _data->nswindow;
NSRect rect = [nswindow contentRectForFrameRect:[nswindow frame]];
Expand All @@ -211,16 +211,13 @@ - (void)windowDidMove:(NSNotification *)aNotification
x = (int)rect.origin.x;
y = (int)rect.origin.y;

if (window == device->current_glwin) {
[((NSOpenGLContext *) device->current_glctx) update];
}
[_data->nscontext scheduleUpdate];

SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y);
}

- (void)windowDidResize:(NSNotification *)aNotification
{
SDL_VideoDevice *device = SDL_GetVideoDevice();
int x, y, w, h;
NSRect rect = [_data->nswindow contentRectForFrameRect:[_data->nswindow frame]];
ConvertNSRect(&rect);
Expand All @@ -231,9 +228,7 @@ - (void)windowDidResize:(NSNotification *)aNotification
if (SDL_IsShapedWindow(_data->window))
Cocoa_ResizeWindowShape(_data->window);

if (_data->window == device->current_glwin) {
[((NSOpenGLContext *) device->current_glctx) update];
}
[_data->nscontext scheduleUpdate];

/* The window can move during a resize event, such as when maximizing
or resizing from a corner */
Expand Down Expand Up @@ -788,7 +783,8 @@ - (void)resetCursorRects
Cocoa_SetWindowPosition(_THIS, SDL_Window * window)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = windata->nswindow;
NSRect rect;
Uint32 moveHack;

Expand All @@ -803,9 +799,7 @@ - (void)resetCursorRects
[nswindow setFrameOrigin:rect.origin];
s_moveHack = moveHack;

if (window == _this->current_glwin) {
[((NSOpenGLContext *) _this->current_glctx) update];
}
[windata->nscontext scheduleUpdate];

[pool release];
}
Expand All @@ -822,9 +816,7 @@ - (void)resetCursorRects
size.height = window->h;
[nswindow setContentSize:size];

if (window == _this->current_glwin) {
[((NSOpenGLContext *) _this->current_glctx) update];
}
[windata->nscontext scheduleUpdate];

[pool release];
}
Expand Down Expand Up @@ -906,13 +898,12 @@ - (void)resetCursorRects
Cocoa_MaximizeWindow(_THIS, SDL_Window * window)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = windata->nswindow;

[nswindow zoom:nil];

if (window == _this->current_glwin) {
[((NSOpenGLContext *) _this->current_glctx) update];
}
[windata->nscontext scheduleUpdate];

[pool release];
}
Expand Down Expand Up @@ -1049,9 +1040,7 @@ - (void)resetCursorRects
[nswindow makeKeyAndOrderFront:nil];
[data->listener resumeVisibleObservation];

if (window == _this->current_glwin) {
[((NSOpenGLContext *) _this->current_glctx) update];
}
[data->nscontext scheduleUpdate];

[pool release];
}
Expand Down

0 comments on commit 879053c

Please sign in to comment.