src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Thu, 21 Jan 2010 07:28:01 +0000
changeset 3688 6512cba48440
parent 3685 64ce267332c6
child 4498 3d91e31fcf71
permissions -rw-r--r--
Fixed Cocoa and OpenGL builds
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 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 /* This is implemented in Mac OS X 10.3 and above */
    40 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3
    41 @implementation NSOpenGLContext(CGLContextAccess)
    42 - (CGLContextObj)CGLContextObj;
    43 {
    44     return _contextAuxiliary;
    45 }
    46 @end
    47 #endif /* < 10.3 */
    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     NSAutoreleasePool *pool;
    85     SDL_VideoDisplay *display = window->display;
    86     SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
    87     NSOpenGLPixelFormatAttribute attr[32];
    88     NSOpenGLPixelFormat *fmt;
    89     NSOpenGLContext *context;
    90     int i = 0;
    91 
    92     pool = [[NSAutoreleasePool alloc] init];
    93 
    94     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    95         attr[i++] = NSOpenGLPFAFullScreen;
    96     }
    97 
    98     attr[i++] = NSOpenGLPFAColorSize;
    99     attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
   100 
   101     attr[i++] = NSOpenGLPFADepthSize;
   102     attr[i++] = _this->gl_config.depth_size;
   103 
   104     if (_this->gl_config.double_buffer) {
   105         attr[i++] = NSOpenGLPFADoubleBuffer;
   106     }
   107 
   108     if (_this->gl_config.stereo) {
   109         attr[i++] = NSOpenGLPFAStereo;
   110     }
   111 
   112     if (_this->gl_config.stencil_size) {
   113         attr[i++] = NSOpenGLPFAStencilSize;
   114         attr[i++] = _this->gl_config.stencil_size;
   115     }
   116 
   117     if ((_this->gl_config.accum_red_size +
   118          _this->gl_config.accum_green_size +
   119          _this->gl_config.accum_blue_size +
   120          _this->gl_config.accum_alpha_size) > 0) {
   121         attr[i++] = NSOpenGLPFAAccumSize;
   122         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;
   123     }
   124 
   125     if (_this->gl_config.multisamplebuffers) {
   126         attr[i++] = NSOpenGLPFASampleBuffers;
   127         attr[i++] = _this->gl_config.multisamplebuffers;
   128     }
   129 
   130     if (_this->gl_config.multisamplesamples) {
   131         attr[i++] = NSOpenGLPFASamples;
   132         attr[i++] = _this->gl_config.multisamplesamples;
   133         attr[i++] = NSOpenGLPFANoRecovery;
   134     }
   135 
   136     if (_this->gl_config.accelerated >= 0) {
   137         if (_this->gl_config.accelerated) {
   138             attr[i++] = NSOpenGLPFAAccelerated;
   139         } else {
   140             attr[i++] = NSOpenGLPFARendererID;
   141             attr[i++] = kCGLRendererGenericFloatID;
   142         }
   143     }
   144 
   145     attr[i++] = NSOpenGLPFAScreenMask;
   146     attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
   147     attr[i] = 0;
   148 
   149     fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   150     if (fmt == nil) {
   151         SDL_SetError ("Failed creating OpenGL pixel format");
   152         [pool release];
   153         return NULL;
   154     }
   155 
   156     context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
   157 
   158     [fmt release];
   159 
   160     if (context == nil) {
   161         SDL_SetError ("Failed creating OpenGL context");
   162         [pool release];
   163         return NULL;
   164     }
   165 
   166     /*
   167      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   168      *  "You are blowing a couple of the internal OpenGL function caches. This
   169      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   170      *  the cache size by issuing the following calls right after you create
   171      *  the OpenGL context.  The default cache size is 16."    --ryan.
   172      */
   173 
   174     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   175     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   176     #endif
   177 
   178     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   179     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   180     #endif
   181 
   182     {
   183         long cache_max = 64;
   184         CGLContextObj ctx = [context CGLContextObj];
   185         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   186         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   187     }
   188 
   189     /* End Wisdom from Apple Engineer section. --ryan. */
   190 
   191     [pool release];
   192 
   193     if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
   194         Cocoa_GL_DeleteContext(_this, context);
   195         return NULL;
   196     }
   197 
   198     return context;
   199 }
   200 
   201 int
   202 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   203 {
   204     NSAutoreleasePool *pool;
   205 
   206     pool = [[NSAutoreleasePool alloc] init];
   207 
   208     if (context) {
   209         SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   210         NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   211 
   212         if (window->flags & SDL_WINDOW_FULLSCREEN) {
   213             [nscontext setFullScreen];
   214         } else {
   215             [nscontext setView:[windowdata->nswindow contentView]];
   216             [nscontext update];
   217         }
   218         [nscontext makeCurrentContext];
   219     } else {
   220         [NSOpenGLContext clearCurrentContext];
   221     }
   222 
   223     [pool release];
   224     return 0;
   225 }
   226 
   227 int
   228 Cocoa_GL_SetSwapInterval(_THIS, int interval)
   229 {
   230     NSAutoreleasePool *pool;
   231     NSOpenGLContext *nscontext;
   232     GLint value;
   233     int status;
   234 
   235     pool = [[NSAutoreleasePool alloc] init];
   236 
   237     nscontext = [NSOpenGLContext currentContext];
   238     if (nscontext != nil) {
   239         value = interval;
   240         [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   241         status = 0;
   242     } else {
   243         SDL_SetError("No current OpenGL context");
   244         status = -1;
   245     }
   246 
   247     [pool release];
   248     return status;
   249 }
   250 
   251 int
   252 Cocoa_GL_GetSwapInterval(_THIS)
   253 {
   254     NSAutoreleasePool *pool;
   255     NSOpenGLContext *nscontext;
   256     GLint value;
   257     int status;
   258 
   259     pool = [[NSAutoreleasePool alloc] init];
   260 
   261     nscontext = [NSOpenGLContext currentContext];
   262     if (nscontext != nil) {
   263         [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   264         status = (int)value;
   265     } else {
   266         SDL_SetError("No current OpenGL context");
   267         status = -1;
   268     }
   269 
   270     [pool release];
   271     return status;
   272 }
   273 
   274 void
   275 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
   276 {
   277     NSAutoreleasePool *pool;
   278     NSOpenGLContext *nscontext;
   279 
   280     pool = [[NSAutoreleasePool alloc] init];
   281 
   282     /* FIXME: Do we need to get the context for the window? */
   283     nscontext = [NSOpenGLContext currentContext];
   284     if (nscontext != nil) {
   285         [nscontext flushBuffer];
   286     }
   287 
   288     [pool release];
   289 }
   290 
   291 void
   292 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
   293 {
   294     NSAutoreleasePool *pool;
   295     NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   296 
   297     pool = [[NSAutoreleasePool alloc] init];
   298 
   299     [nscontext clearDrawable];
   300     [nscontext release];
   301 
   302     [pool release];
   303 }
   304 
   305 #endif /* SDL_VIDEO_OPENGL_CGL */
   306 
   307 /* vi: set ts=4 sw=4 expandtab: */