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