src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Thu, 11 Jul 2013 22:59:20 -0700
changeset 7412 50211a1fd557
parent 7408 c50e165abfdf
child 7594 6abcf951af68
permissions -rw-r--r--
Fixed bug 1946 - OpenGL contexts in threads

The SDL OpenGL context code is now properly thread aware. There are two new functions which return the current OpenGL window and context for the current thread.

There are still places in the cocoa driver where the OpenGL context needs to be updated when the view changes. These will need a different solution and still use the last globally set context to avoid changing behavior.
slouken@1936
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@1936
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1936
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1936
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1936
    20
*/
slouken@1936
    21
#include "SDL_config.h"
slouken@1936
    22
slouken@1936
    23
/* NSOpenGL implementation of SDL OpenGL support */
slouken@1936
    24
slouken@1952
    25
#if SDL_VIDEO_OPENGL_CGL
slouken@6044
    26
#include "SDL_cocoavideo.h"
slouken@6044
    27
slouken@1936
    28
#include <OpenGL/CGLTypes.h>
slouken@2738
    29
#include <OpenGL/OpenGL.h>
slouken@3570
    30
#include <OpenGL/CGLRenderers.h>
slouken@1936
    31
slouken@1936
    32
#include "SDL_loadso.h"
slouken@1936
    33
#include "SDL_opengl.h"
slouken@1936
    34
icculus@6567
    35
#define DEFAULT_OPENGL  "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
slouken@1936
    36
icculus@6567
    37
slouken@6952
    38
#ifndef kCGLPFAOpenGLProfile
icculus@6567
    39
#define kCGLPFAOpenGLProfile 99
slouken@6952
    40
#endif
slouken@6952
    41
#ifndef kCGLOGLPVersion_Legacy
icculus@6567
    42
#define kCGLOGLPVersion_Legacy 0x1000
slouken@6952
    43
#endif
slouken@6952
    44
#ifndef kCGLOGLPVersion_3_2_Core
icculus@6567
    45
#define kCGLOGLPVersion_3_2_Core 0x3200
icculus@6567
    46
#endif
icculus@6567
    47
slouken@1936
    48
slouken@1936
    49
int
slouken@1936
    50
Cocoa_GL_LoadLibrary(_THIS, const char *path)
slouken@1936
    51
{
slouken@3057
    52
    /* Load the OpenGL library */
slouken@1936
    53
    if (path == NULL) {
slouken@1952
    54
        path = SDL_getenv("SDL_OPENGL_LIBRARY");
slouken@1952
    55
    }
slouken@1952
    56
    if (path == NULL) {
slouken@1952
    57
        path = DEFAULT_OPENGL;
slouken@1936
    58
    }
slouken@1936
    59
    _this->gl_config.dll_handle = SDL_LoadObject(path);
slouken@1936
    60
    if (!_this->gl_config.dll_handle) {
slouken@1936
    61
        return -1;
slouken@1936
    62
    }
slouken@1936
    63
    SDL_strlcpy(_this->gl_config.driver_path, path,
slouken@1936
    64
                SDL_arraysize(_this->gl_config.driver_path));
slouken@1936
    65
    return 0;
slouken@1936
    66
}
slouken@1936
    67
slouken@1936
    68
void *
slouken@1936
    69
Cocoa_GL_GetProcAddress(_THIS, const char *proc)
slouken@1936
    70
{
slouken@1936
    71
    return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
slouken@1936
    72
}
slouken@1936
    73
slouken@3057
    74
void
slouken@1936
    75
Cocoa_GL_UnloadLibrary(_THIS)
slouken@1936
    76
{
slouken@3057
    77
    SDL_UnloadObject(_this->gl_config.dll_handle);
slouken@3057
    78
    _this->gl_config.dll_handle = NULL;
slouken@1936
    79
}
slouken@1936
    80
slouken@1936
    81
SDL_GLContext
slouken@1936
    82
Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
slouken@1936
    83
{
icculus@6567
    84
    const int wantver = (_this->gl_config.major_version << 8) |
icculus@6567
    85
                        (_this->gl_config.minor_version);
icculus@6567
    86
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@6848
    87
    NSAutoreleasePool *pool;
slouken@5246
    88
    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
slouken@1936
    89
    SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
slouken@1936
    90
    NSOpenGLPixelFormatAttribute attr[32];
slouken@1936
    91
    NSOpenGLPixelFormat *fmt;
slouken@2178
    92
    NSOpenGLContext *context;
flibitijibibo@7152
    93
    NSOpenGLContext *share_context = nil;
slouken@1936
    94
    int i = 0;
slouken@1936
    95
icculus@6567
    96
    if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
icculus@6567
    97
        SDL_SetError ("OpenGL ES not supported on this platform");
icculus@6567
    98
        return NULL;
icculus@6567
    99
    }
icculus@6567
   100
icculus@6567
   101
    /* Sadly, we'll have to update this as life progresses, since we need to
icculus@6567
   102
       set an enum for context profiles, not a context version number */
icculus@6567
   103
    if (wantver > 0x0302) {
icculus@6567
   104
        SDL_SetError ("OpenGL > 3.2 is not supported on this platform");
icculus@6567
   105
        return NULL;
icculus@6567
   106
    }
icculus@6567
   107
slouken@6848
   108
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   109
slouken@6848
   110
    /* specify a profile if we're on Lion (10.7) or later. */
slouken@6848
   111
    if (data->osversion >= 0x1070) {
slouken@6848
   112
        NSOpenGLPixelFormatAttribute profile = kCGLOGLPVersion_Legacy;
slouken@6848
   113
        if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) {
slouken@6848
   114
            if (wantver == 0x0302) {
slouken@6848
   115
                profile = kCGLOGLPVersion_3_2_Core;
alexey@6832
   116
            }
alexey@6832
   117
        }
slouken@6848
   118
        attr[i++] = kCGLPFAOpenGLProfile;
slouken@6848
   119
        attr[i++] = profile;
slouken@6848
   120
    }
slouken@1936
   121
slouken@6848
   122
    attr[i++] = NSOpenGLPFAColorSize;
slouken@6848
   123
    attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
slouken@6848
   124
slouken@6848
   125
    attr[i++] = NSOpenGLPFADepthSize;
slouken@6848
   126
    attr[i++] = _this->gl_config.depth_size;
slouken@6848
   127
slouken@6848
   128
    if (_this->gl_config.double_buffer) {
slouken@6848
   129
        attr[i++] = NSOpenGLPFADoubleBuffer;
slouken@6848
   130
    }
slouken@6848
   131
slouken@6848
   132
    if (_this->gl_config.stereo) {
slouken@6848
   133
        attr[i++] = NSOpenGLPFAStereo;
slouken@6848
   134
    }
slouken@6848
   135
slouken@6848
   136
    if (_this->gl_config.stencil_size) {
slouken@6848
   137
        attr[i++] = NSOpenGLPFAStencilSize;
slouken@6848
   138
        attr[i++] = _this->gl_config.stencil_size;
slouken@6848
   139
    }
slouken@6848
   140
slouken@6848
   141
    if ((_this->gl_config.accum_red_size +
slouken@6848
   142
         _this->gl_config.accum_green_size +
slouken@6848
   143
         _this->gl_config.accum_blue_size +
slouken@6848
   144
         _this->gl_config.accum_alpha_size) > 0) {
slouken@6848
   145
        attr[i++] = NSOpenGLPFAAccumSize;
slouken@6848
   146
        attr[i++] = _this->gl_config.accum_red_size + _this->gl_config.accum_green_size + _this->gl_config.accum_blue_size + _this->gl_config.accum_alpha_size;
slouken@6848
   147
    }
slouken@6848
   148
slouken@6848
   149
    if (_this->gl_config.multisamplebuffers) {
slouken@6848
   150
        attr[i++] = NSOpenGLPFASampleBuffers;
slouken@6848
   151
        attr[i++] = _this->gl_config.multisamplebuffers;
slouken@6848
   152
    }
slouken@6848
   153
slouken@6848
   154
    if (_this->gl_config.multisamplesamples) {
slouken@6848
   155
        attr[i++] = NSOpenGLPFASamples;
slouken@6848
   156
        attr[i++] = _this->gl_config.multisamplesamples;
slouken@6848
   157
        attr[i++] = NSOpenGLPFANoRecovery;
slouken@6848
   158
    }
slouken@6848
   159
slouken@6848
   160
    if (_this->gl_config.accelerated >= 0) {
slouken@6848
   161
        if (_this->gl_config.accelerated) {
slouken@6848
   162
            attr[i++] = NSOpenGLPFAAccelerated;
slouken@6848
   163
        } else {
slouken@6848
   164
            attr[i++] = NSOpenGLPFARendererID;
slouken@6848
   165
            attr[i++] = kCGLRendererGenericFloatID;
alexey@6832
   166
        }
slouken@6848
   167
    }
slouken@6848
   168
slouken@6848
   169
    attr[i++] = NSOpenGLPFAScreenMask;
slouken@6848
   170
    attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
slouken@6848
   171
    attr[i] = 0;
slouken@6848
   172
slouken@6848
   173
    fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
slouken@6848
   174
    if (fmt == nil) {
slouken@6848
   175
        SDL_SetError ("Failed creating OpenGL pixel format");
slouken@6848
   176
        [pool release];
slouken@6848
   177
        return NULL;
slouken@6848
   178
    }
slouken@6848
   179
flibitijibibo@7152
   180
    if (_this->gl_config.share_with_current_context) {
slouken@7412
   181
        share_context = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
flibitijibibo@7152
   182
    }
flibitijibibo@7152
   183
flibitijibibo@7152
   184
    context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];
slouken@6848
   185
slouken@6848
   186
    [fmt release];
slouken@6848
   187
slouken@6848
   188
    if (context == nil) {
slouken@6848
   189
        SDL_SetError ("Failed creating OpenGL context");
slouken@6848
   190
        [pool release];
slouken@6848
   191
        return NULL;
slouken@6848
   192
    }
slouken@6848
   193
slouken@6848
   194
    [pool release];
slouken@1936
   195
slouken@2178
   196
    if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
slouken@2178
   197
        Cocoa_GL_DeleteContext(_this, context);
slouken@2178
   198
        return NULL;
slouken@2178
   199
    }
slouken@2178
   200
slouken@2178
   201
    return context;
slouken@1936
   202
}
slouken@1936
   203
slouken@1936
   204
int
slouken@1936
   205
Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
slouken@1936
   206
{
slouken@6848
   207
    NSAutoreleasePool *pool;
slouken@1936
   208
slouken@6848
   209
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   210
slouken@6848
   211
    if (context) {
slouken@6848
   212
        SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
slouken@6848
   213
        NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
slouken@6848
   214
slouken@7408
   215
        windowdata->nscontext = nscontext;
icculus@7347
   216
        if ([nscontext view] != [windowdata->nswindow contentView]) {
jorgen@7085
   217
            [nscontext setView:[windowdata->nswindow contentView]];
jorgen@7085
   218
            [nscontext update];
slouken@1973
   219
        }
slouken@6848
   220
        [nscontext makeCurrentContext];
slouken@6848
   221
    } else {
slouken@6848
   222
        [NSOpenGLContext clearCurrentContext];
slouken@1936
   223
    }
slouken@1936
   224
slouken@6848
   225
    [pool release];
slouken@1936
   226
    return 0;
slouken@1936
   227
}
slouken@1936
   228
slouken@1936
   229
int
slouken@1936
   230
Cocoa_GL_SetSwapInterval(_THIS, int interval)
slouken@1936
   231
{
slouken@6848
   232
    NSAutoreleasePool *pool;
slouken@1936
   233
    NSOpenGLContext *nscontext;
slouken@2703
   234
    GLint value;
slouken@1936
   235
    int status;
slouken@1936
   236
slouken@6848
   237
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   238
slouken@6848
   239
    nscontext = [NSOpenGLContext currentContext];
slouken@6848
   240
    if (nscontext != nil) {
slouken@6848
   241
        value = interval;
slouken@6848
   242
        [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
slouken@6848
   243
        status = 0;
slouken@6848
   244
    } else {
icculus@7037
   245
        status = SDL_SetError("No current OpenGL context");
slouken@1936
   246
    }
slouken@1936
   247
slouken@6848
   248
    [pool release];
slouken@1936
   249
    return status;
slouken@1936
   250
}
slouken@1936
   251
slouken@1936
   252
int
slouken@1936
   253
Cocoa_GL_GetSwapInterval(_THIS)
slouken@1936
   254
{
slouken@6848
   255
    NSAutoreleasePool *pool;
slouken@1936
   256
    NSOpenGLContext *nscontext;
slouken@2703
   257
    GLint value;
icculus@6382
   258
    int status = 0;
slouken@1936
   259
slouken@6848
   260
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   261
slouken@6848
   262
    nscontext = [NSOpenGLContext currentContext];
slouken@6848
   263
    if (nscontext != nil) {
slouken@6848
   264
        [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
slouken@6848
   265
        status = (int)value;
slouken@1936
   266
    }
slouken@1936
   267
slouken@6848
   268
    [pool release];
slouken@1936
   269
    return status;
slouken@1936
   270
}
slouken@1936
   271
slouken@1936
   272
void
slouken@1936
   273
Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
slouken@1936
   274
{
slouken@6848
   275
    NSAutoreleasePool *pool;
slouken@7408
   276
    SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
slouken@7408
   277
    NSOpenGLContext *nscontext = windowdata->nscontext;
slouken@1936
   278
slouken@6848
   279
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   280
slouken@7408
   281
    [nscontext flushBuffer];
slouken@6848
   282
slouken@6848
   283
    [pool release];
slouken@1936
   284
}
slouken@1936
   285
slouken@1936
   286
void
slouken@1936
   287
Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
slouken@1936
   288
{
slouken@6848
   289
    NSAutoreleasePool *pool;
slouken@1936
   290
    NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
slouken@1936
   291
slouken@6848
   292
    pool = [[NSAutoreleasePool alloc] init];
slouken@6848
   293
slouken@6848
   294
    [nscontext clearDrawable];
slouken@6848
   295
    [nscontext release];
slouken@6848
   296
slouken@6848
   297
    [pool release];
slouken@1936
   298
}
slouken@1936
   299
slouken@1952
   300
#endif /* SDL_VIDEO_OPENGL_CGL */
slouken@1936
   301
slouken@1936
   302
/* vi: set ts=4 sw=4 expandtab: */