src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Dec 2009 20:36:31 +0000
changeset 3570 7812d3e9564e
parent 3057 089a77aebb7d
child 3571 19691cebb866
permissions -rw-r--r--
OpenGL hardware acceleration defaults on
     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 = SDL_GetDisplayFromWindow(window);
    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) {
   137         attr[i++] = NSOpenGLPFAAccelerated;
   138     } else {
   139         attr[i++] = NSOpenGLPFARendererID;
   140         attr[i++] = kCGLRendererGenericFloatID;
   141     }
   142 
   143     attr[i++] = NSOpenGLPFAScreenMask;
   144     attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
   145     attr[i] = 0;
   146 
   147     fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   148     if (fmt == nil) {
   149         SDL_SetError ("Failed creating OpenGL pixel format");
   150         [pool release];
   151         return NULL;
   152     }
   153 
   154     context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
   155 
   156     [fmt release];
   157 
   158     if (context == nil) {
   159         SDL_SetError ("Failed creating OpenGL context");
   160         [pool release];
   161         return NULL;
   162     }
   163 
   164     /*
   165      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   166      *  "You are blowing a couple of the internal OpenGL function caches. This
   167      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   168      *  the cache size by issuing the following calls right after you create
   169      *  the OpenGL context.  The default cache size is 16."    --ryan.
   170      */
   171 
   172     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   173     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   174     #endif
   175 
   176     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   177     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   178     #endif
   179 
   180     {
   181         long cache_max = 64;
   182         CGLContextObj ctx = [context CGLContextObj];
   183         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   184         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   185     }
   186 
   187     /* End Wisdom from Apple Engineer section. --ryan. */
   188 
   189     [pool release];
   190 
   191     if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
   192         Cocoa_GL_DeleteContext(_this, context);
   193         return NULL;
   194     }
   195 
   196     return context;
   197 }
   198 
   199 int
   200 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   201 {
   202     NSAutoreleasePool *pool;
   203 
   204     pool = [[NSAutoreleasePool alloc] init];
   205 
   206     if (context) {
   207         SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   208         NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   209 
   210         if (window->flags & SDL_WINDOW_FULLSCREEN) {
   211             [nscontext setFullScreen];
   212         } else {
   213             [nscontext setView:[windowdata->window contentView]];
   214             [nscontext update];
   215         }
   216         [nscontext makeCurrentContext];
   217     } else {
   218         [NSOpenGLContext clearCurrentContext];
   219     }
   220 
   221     [pool release];
   222     return 0;
   223 }
   224 
   225 int
   226 Cocoa_GL_SetSwapInterval(_THIS, int interval)
   227 {
   228     NSAutoreleasePool *pool;
   229     NSOpenGLContext *nscontext;
   230     GLint value;
   231     int status;
   232 
   233     pool = [[NSAutoreleasePool alloc] init];
   234 
   235     nscontext = [NSOpenGLContext currentContext];
   236     if (nscontext != nil) {
   237         value = interval;
   238         [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   239         status = 0;
   240     } else {
   241         SDL_SetError("No current OpenGL context");
   242         status = -1;
   243     }
   244 
   245     [pool release];
   246     return status;
   247 }
   248 
   249 int
   250 Cocoa_GL_GetSwapInterval(_THIS)
   251 {
   252     NSAutoreleasePool *pool;
   253     NSOpenGLContext *nscontext;
   254     GLint value;
   255     int status;
   256 
   257     pool = [[NSAutoreleasePool alloc] init];
   258 
   259     nscontext = [NSOpenGLContext currentContext];
   260     if (nscontext != nil) {
   261         [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   262         status = (int)value;
   263     } else {
   264         SDL_SetError("No current OpenGL context");
   265         status = -1;
   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     NSOpenGLContext *nscontext;
   277 
   278     pool = [[NSAutoreleasePool alloc] init];
   279 
   280     /* FIXME: Do we need to get the context for the window? */
   281     nscontext = [NSOpenGLContext currentContext];
   282     if (nscontext != nil) {
   283         [nscontext flushBuffer];
   284     }
   285 
   286     [pool release];
   287 }
   288 
   289 void
   290 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
   291 {
   292     NSAutoreleasePool *pool;
   293     NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   294 
   295     pool = [[NSAutoreleasePool alloc] init];
   296 
   297     [nscontext clearDrawable];
   298     [nscontext release];
   299 
   300     [pool release];
   301 }
   302 
   303 #endif /* SDL_VIDEO_OPENGL_CGL */
   304 
   305 /* vi: set ts=4 sw=4 expandtab: */