src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Thu, 11 Jul 2013 21:51:09 -0700
changeset 7408 c50e165abfdf
parent 7389 361d1a0c90f6
child 7412 50211a1fd557
permissions -rw-r--r--
Fixed bug 1958 - Cocoa SwapWindow doesn't swap the specified window

Ryan C. Gordon

We have this in Cocoa_GL_SwapWindow()...

/* FIXME: Do we need to get the context for the window? */
[[NSOpenGLContext currentContext] flushBuffer];

...which means if the current GL context is not the one in (window), we swap a different one than requested.

Right now, we don't store information about which context is assigned to which window, and the OS doesn't give you a way to retrieve it from an NSView. We would have to track this per-window during SDL_GL_MakeCurrent() (and SDL_GL_CreateContext) calls.
     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     attr[i++] = NSOpenGLPFAColorSize;
   123     attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
   124 
   125     attr[i++] = NSOpenGLPFADepthSize;
   126     attr[i++] = _this->gl_config.depth_size;
   127 
   128     if (_this->gl_config.double_buffer) {
   129         attr[i++] = NSOpenGLPFADoubleBuffer;
   130     }
   131 
   132     if (_this->gl_config.stereo) {
   133         attr[i++] = NSOpenGLPFAStereo;
   134     }
   135 
   136     if (_this->gl_config.stencil_size) {
   137         attr[i++] = NSOpenGLPFAStencilSize;
   138         attr[i++] = _this->gl_config.stencil_size;
   139     }
   140 
   141     if ((_this->gl_config.accum_red_size +
   142          _this->gl_config.accum_green_size +
   143          _this->gl_config.accum_blue_size +
   144          _this->gl_config.accum_alpha_size) > 0) {
   145         attr[i++] = NSOpenGLPFAAccumSize;
   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;
   147     }
   148 
   149     if (_this->gl_config.multisamplebuffers) {
   150         attr[i++] = NSOpenGLPFASampleBuffers;
   151         attr[i++] = _this->gl_config.multisamplebuffers;
   152     }
   153 
   154     if (_this->gl_config.multisamplesamples) {
   155         attr[i++] = NSOpenGLPFASamples;
   156         attr[i++] = _this->gl_config.multisamplesamples;
   157         attr[i++] = NSOpenGLPFANoRecovery;
   158     }
   159 
   160     if (_this->gl_config.accelerated >= 0) {
   161         if (_this->gl_config.accelerated) {
   162             attr[i++] = NSOpenGLPFAAccelerated;
   163         } else {
   164             attr[i++] = NSOpenGLPFARendererID;
   165             attr[i++] = kCGLRendererGenericFloatID;
   166         }
   167     }
   168 
   169     attr[i++] = NSOpenGLPFAScreenMask;
   170     attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
   171     attr[i] = 0;
   172 
   173     fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   174     if (fmt == nil) {
   175         SDL_SetError ("Failed creating OpenGL pixel format");
   176         [pool release];
   177         return NULL;
   178     }
   179 
   180     if (_this->gl_config.share_with_current_context) {
   181         share_context = (NSOpenGLContext*)(_this->current_glctx);
   182     }
   183 
   184     context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];
   185 
   186     [fmt release];
   187 
   188     if (context == nil) {
   189         SDL_SetError ("Failed creating OpenGL context");
   190         [pool release];
   191         return NULL;
   192     }
   193 
   194     [pool release];
   195 
   196     if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
   197         Cocoa_GL_DeleteContext(_this, context);
   198         return NULL;
   199     }
   200 
   201     return context;
   202 }
   203 
   204 int
   205 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   206 {
   207     NSAutoreleasePool *pool;
   208 
   209     pool = [[NSAutoreleasePool alloc] init];
   210 
   211     if (context) {
   212         SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   213         NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   214 
   215         windowdata->nscontext = nscontext;
   216         if ([nscontext view] != [windowdata->nswindow contentView]) {
   217             [nscontext setView:[windowdata->nswindow contentView]];
   218             [nscontext update];
   219         }
   220         [nscontext makeCurrentContext];
   221     } else {
   222         [NSOpenGLContext clearCurrentContext];
   223     }
   224 
   225     [pool release];
   226     return 0;
   227 }
   228 
   229 int
   230 Cocoa_GL_SetSwapInterval(_THIS, int interval)
   231 {
   232     NSAutoreleasePool *pool;
   233     NSOpenGLContext *nscontext;
   234     GLint value;
   235     int status;
   236 
   237     pool = [[NSAutoreleasePool alloc] init];
   238 
   239     nscontext = [NSOpenGLContext currentContext];
   240     if (nscontext != nil) {
   241         value = interval;
   242         [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   243         status = 0;
   244     } else {
   245         status = SDL_SetError("No current OpenGL context");
   246     }
   247 
   248     [pool release];
   249     return status;
   250 }
   251 
   252 int
   253 Cocoa_GL_GetSwapInterval(_THIS)
   254 {
   255     NSAutoreleasePool *pool;
   256     NSOpenGLContext *nscontext;
   257     GLint value;
   258     int status = 0;
   259 
   260     pool = [[NSAutoreleasePool alloc] init];
   261 
   262     nscontext = [NSOpenGLContext currentContext];
   263     if (nscontext != nil) {
   264         [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   265         status = (int)value;
   266     }
   267 
   268     [pool release];
   269     return status;
   270 }
   271 
   272 void
   273 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
   274 {
   275     NSAutoreleasePool *pool;
   276     SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   277     NSOpenGLContext *nscontext = windowdata->nscontext;
   278 
   279     pool = [[NSAutoreleasePool alloc] init];
   280 
   281     [nscontext flushBuffer];
   282 
   283     [pool release];
   284 }
   285 
   286 void
   287 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
   288 {
   289     NSAutoreleasePool *pool;
   290     NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   291 
   292     pool = [[NSAutoreleasePool alloc] init];
   293 
   294     [nscontext clearDrawable];
   295     [nscontext release];
   296 
   297     [pool release];
   298 }
   299 
   300 #endif /* SDL_VIDEO_OPENGL_CGL */
   301 
   302 /* vi: set ts=4 sw=4 expandtab: */