src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Fri, 11 Feb 2011 22:37:15 -0800
changeset 5262 b530ef003506
parent 5249 7a963be087ef
child 5535 96594ac5fd1a
permissions -rw-r--r--
Happy 2011! :)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2011 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: */