src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 00:25:44 -0800
changeset 5249 7a963be087ef
parent 5246 58265e606e4e
child 5262 b530ef003506
permissions -rw-r--r--
Mostly fixed fullscreen mode on Mac OS X, and you can toggle it on and off.

There are still some problems with the ConvertNSRect() calculations when switching video modes, which causes wierd window positioning issues, and the fullscreen window is still minimized on exit.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_cocoavideo.h"
    25 
    26 /* NSOpenGL implementation of SDL OpenGL support */
    27 
    28 #if SDL_VIDEO_OPENGL_CGL
    29 #include <OpenGL/CGLTypes.h>
    30 #include <OpenGL/OpenGL.h>
    31 #include <OpenGL/CGLRenderers.h>
    32 
    33 #include "SDL_loadso.h"
    34 #include "SDL_opengl.h"
    35 
    36 
    37 #define DEFAULT_OPENGL  "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
    38 
    39 int
    40 Cocoa_GL_LoadLibrary(_THIS, const char *path)
    41 {
    42     /* Load the OpenGL library */
    43     if (path == NULL) {
    44         path = SDL_getenv("SDL_OPENGL_LIBRARY");
    45     }
    46     if (path == NULL) {
    47         path = DEFAULT_OPENGL;
    48     }
    49     _this->gl_config.dll_handle = SDL_LoadObject(path);
    50     if (!_this->gl_config.dll_handle) {
    51         return -1;
    52     }
    53     SDL_strlcpy(_this->gl_config.driver_path, path,
    54                 SDL_arraysize(_this->gl_config.driver_path));
    55     return 0;
    56 }
    57 
    58 void *
    59 Cocoa_GL_GetProcAddress(_THIS, const char *proc)
    60 {
    61     return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
    62 }
    63 
    64 void
    65 Cocoa_GL_UnloadLibrary(_THIS)
    66 {
    67     SDL_UnloadObject(_this->gl_config.dll_handle);
    68     _this->gl_config.dll_handle = NULL;
    69 }
    70 
    71 SDL_GLContext
    72 Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
    73 {
    74     NSAutoreleasePool *pool;
    75     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    76     SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
    77     NSOpenGLPixelFormatAttribute attr[32];
    78     NSOpenGLPixelFormat *fmt;
    79     NSOpenGLContext *context;
    80     int i = 0;
    81 
    82     pool = [[NSAutoreleasePool alloc] init];
    83 
    84 #ifndef FULLSCREEN_TOGGLEABLE
    85     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    86         attr[i++] = NSOpenGLPFAFullScreen;
    87     }
    88 #endif
    89 
    90     attr[i++] = NSOpenGLPFAColorSize;
    91     attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
    92 
    93     attr[i++] = NSOpenGLPFADepthSize;
    94     attr[i++] = _this->gl_config.depth_size;
    95 
    96     if (_this->gl_config.double_buffer) {
    97         attr[i++] = NSOpenGLPFADoubleBuffer;
    98     }
    99 
   100     if (_this->gl_config.stereo) {
   101         attr[i++] = NSOpenGLPFAStereo;
   102     }
   103 
   104     if (_this->gl_config.stencil_size) {
   105         attr[i++] = NSOpenGLPFAStencilSize;
   106         attr[i++] = _this->gl_config.stencil_size;
   107     }
   108 
   109     if ((_this->gl_config.accum_red_size +
   110          _this->gl_config.accum_green_size +
   111          _this->gl_config.accum_blue_size +
   112          _this->gl_config.accum_alpha_size) > 0) {
   113         attr[i++] = NSOpenGLPFAAccumSize;
   114         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;
   115     }
   116 
   117     if (_this->gl_config.multisamplebuffers) {
   118         attr[i++] = NSOpenGLPFASampleBuffers;
   119         attr[i++] = _this->gl_config.multisamplebuffers;
   120     }
   121 
   122     if (_this->gl_config.multisamplesamples) {
   123         attr[i++] = NSOpenGLPFASamples;
   124         attr[i++] = _this->gl_config.multisamplesamples;
   125         attr[i++] = NSOpenGLPFANoRecovery;
   126     }
   127 
   128     if (_this->gl_config.accelerated >= 0) {
   129         if (_this->gl_config.accelerated) {
   130             attr[i++] = NSOpenGLPFAAccelerated;
   131         } else {
   132             attr[i++] = NSOpenGLPFARendererID;
   133             attr[i++] = kCGLRendererGenericFloatID;
   134         }
   135     }
   136 
   137     attr[i++] = NSOpenGLPFAScreenMask;
   138     attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
   139     attr[i] = 0;
   140 
   141     fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   142     if (fmt == nil) {
   143         SDL_SetError ("Failed creating OpenGL pixel format");
   144         [pool release];
   145         return NULL;
   146     }
   147 
   148     context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
   149 
   150     [fmt release];
   151 
   152     if (context == nil) {
   153         SDL_SetError ("Failed creating OpenGL context");
   154         [pool release];
   155         return NULL;
   156     }
   157 
   158     /*
   159      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   160      *  "You are blowing a couple of the internal OpenGL function caches. This
   161      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   162      *  the cache size by issuing the following calls right after you create
   163      *  the OpenGL context.  The default cache size is 16."    --ryan.
   164      */
   165 
   166     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   167     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   168     #endif
   169 
   170     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   171     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   172     #endif
   173 
   174     {
   175         GLint cache_max = 64;
   176         CGLContextObj ctx = [context CGLContextObj];
   177         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   178         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   179     }
   180 
   181     /* End Wisdom from Apple Engineer section. --ryan. */
   182 
   183     [pool release];
   184 
   185     if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
   186         Cocoa_GL_DeleteContext(_this, context);
   187         return NULL;
   188     }
   189 
   190     return context;
   191 }
   192 
   193 int
   194 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   195 {
   196     NSAutoreleasePool *pool;
   197 
   198     pool = [[NSAutoreleasePool alloc] init];
   199 
   200     if (context) {
   201         SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   202         NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   203 
   204 #ifndef FULLSCREEN_TOGGLEABLE
   205         if (window->flags & SDL_WINDOW_FULLSCREEN) {
   206             [nscontext setFullScreen];
   207         } else
   208 #endif
   209         {
   210             [nscontext setView:[windowdata->nswindow contentView]];
   211             [nscontext update];
   212         }
   213         [nscontext makeCurrentContext];
   214     } else {
   215         [NSOpenGLContext clearCurrentContext];
   216     }
   217 
   218     [pool release];
   219     return 0;
   220 }
   221 
   222 int
   223 Cocoa_GL_SetSwapInterval(_THIS, int interval)
   224 {
   225     NSAutoreleasePool *pool;
   226     NSOpenGLContext *nscontext;
   227     GLint value;
   228     int status;
   229 
   230     pool = [[NSAutoreleasePool alloc] init];
   231 
   232     nscontext = [NSOpenGLContext currentContext];
   233     if (nscontext != nil) {
   234         value = interval;
   235         [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   236         status = 0;
   237     } else {
   238         SDL_SetError("No current OpenGL context");
   239         status = -1;
   240     }
   241 
   242     [pool release];
   243     return status;
   244 }
   245 
   246 int
   247 Cocoa_GL_GetSwapInterval(_THIS)
   248 {
   249     NSAutoreleasePool *pool;
   250     NSOpenGLContext *nscontext;
   251     GLint value;
   252     int status;
   253 
   254     pool = [[NSAutoreleasePool alloc] init];
   255 
   256     nscontext = [NSOpenGLContext currentContext];
   257     if (nscontext != nil) {
   258         [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   259         status = (int)value;
   260     } else {
   261         SDL_SetError("No current OpenGL context");
   262         status = -1;
   263     }
   264 
   265     [pool release];
   266     return status;
   267 }
   268 
   269 void
   270 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
   271 {
   272     NSAutoreleasePool *pool;
   273     NSOpenGLContext *nscontext;
   274 
   275     pool = [[NSAutoreleasePool alloc] init];
   276 
   277     /* FIXME: Do we need to get the context for the window? */
   278     nscontext = [NSOpenGLContext currentContext];
   279     if (nscontext != nil) {
   280         [nscontext flushBuffer];
   281     }
   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: */