src/video/cocoa/SDL_cocoaopengl.m
author Edgar Simo <bobbens@gmail.com>
Sun, 20 Jul 2008 21:34:04 +0000
branchgsoc2008_force_feedback
changeset 2540 56cf872c723a
parent 2178 114a541cfae2
child 2738 79c1bd651f04
permissions -rw-r--r--
Synced with trunk.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 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 
    31 #include "SDL_loadso.h"
    32 #include "SDL_opengl.h"
    33 
    34 
    35 #define DEFAULT_OPENGL  "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
    36 
    37 /* This is implemented in Mac OS X 10.3 and above */
    38 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3
    39 @implementation NSOpenGLContext(CGLContextAccess)
    40 - (CGLContextObj)CGLContextObj;
    41 {
    42     return _contextAuxiliary;
    43 }
    44 @end
    45 #endif /* < 10.3 */
    46 
    47 int
    48 Cocoa_GL_LoadLibrary(_THIS, const char *path)
    49 {
    50     if (_this->gl_config.driver_loaded) {
    51         if (path) {
    52             SDL_SetError("OpenGL library already loaded");
    53             return -1;
    54         } else {
    55             ++_this->gl_config.driver_loaded;
    56             return 0;
    57         }
    58     }
    59     if (path == NULL) {
    60         path = SDL_getenv("SDL_OPENGL_LIBRARY");
    61     }
    62     if (path == NULL) {
    63         path = DEFAULT_OPENGL;
    64     }
    65     _this->gl_config.dll_handle = SDL_LoadObject(path);
    66     if (!_this->gl_config.dll_handle) {
    67         return -1;
    68     }
    69     SDL_strlcpy(_this->gl_config.driver_path, path,
    70                 SDL_arraysize(_this->gl_config.driver_path));
    71     _this->gl_config.driver_loaded = 1;
    72     return 0;
    73 }
    74 
    75 void *
    76 Cocoa_GL_GetProcAddress(_THIS, const char *proc)
    77 {
    78     return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
    79 }
    80 
    81 static void
    82 Cocoa_GL_UnloadLibrary(_THIS)
    83 {
    84     if (_this->gl_config.driver_loaded > 0) {
    85         if (--_this->gl_config.driver_loaded > 0) {
    86             return;
    87         }
    88         SDL_UnloadObject(_this->gl_config.dll_handle);
    89         _this->gl_config.dll_handle = NULL;
    90     }
    91 }
    92 
    93 static int
    94 Cocoa_GL_Initialize(_THIS)
    95 {
    96     if (_this->gl_data) {
    97         ++_this->gl_data->initialized;
    98         return 0;
    99     }
   100 
   101     _this->gl_data =
   102         (struct SDL_GLDriverData *) SDL_calloc(1,
   103                                                sizeof(struct
   104                                                       SDL_GLDriverData));
   105     if (!_this->gl_data) {
   106         SDL_OutOfMemory();
   107         return -1;
   108     }
   109     _this->gl_data->initialized = 1;
   110 
   111     if (Cocoa_GL_LoadLibrary(_this, NULL) < 0) {
   112         return -1;
   113     }
   114     return 0;
   115 }
   116 
   117 static void
   118 Cocoa_GL_Shutdown(_THIS)
   119 {
   120     if (!_this->gl_data || (--_this->gl_data->initialized > 0)) {
   121         return;
   122     }
   123 
   124     Cocoa_GL_UnloadLibrary(_this);
   125 
   126     SDL_free(_this->gl_data);
   127     _this->gl_data = NULL;
   128 }
   129 
   130 int
   131 Cocoa_GL_SetupWindow(_THIS, SDL_Window * window)
   132 {
   133     if (Cocoa_GL_Initialize(_this) < 0) {
   134         return -1;
   135     }
   136     return 0;
   137 }
   138 
   139 void
   140 Cocoa_GL_CleanupWindow(_THIS, SDL_Window * window)
   141 {
   142     Cocoa_GL_Shutdown(_this);
   143 }
   144 
   145 SDL_GLContext
   146 Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
   147 {
   148     NSAutoreleasePool *pool;
   149     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   150     SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
   151     NSOpenGLPixelFormatAttribute attr[32];
   152     NSOpenGLPixelFormat *fmt;
   153     NSOpenGLContext *context;
   154     int i = 0;
   155 
   156     pool = [[NSAutoreleasePool alloc] init];
   157 
   158     if (window->flags & SDL_WINDOW_FULLSCREEN) {
   159         attr[i++] = NSOpenGLPFAFullScreen;
   160     }
   161 
   162     attr[i++] = NSOpenGLPFAColorSize;
   163     attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
   164 
   165     attr[i++] = NSOpenGLPFADepthSize;
   166     attr[i++] = _this->gl_config.depth_size;
   167 
   168     if (_this->gl_config.double_buffer) {
   169         attr[i++] = NSOpenGLPFADoubleBuffer;
   170     }
   171 
   172     if (_this->gl_config.stereo) {
   173         attr[i++] = NSOpenGLPFAStereo;
   174     }
   175 
   176     if (_this->gl_config.stencil_size) {
   177         attr[i++] = NSOpenGLPFAStencilSize;
   178         attr[i++] = _this->gl_config.stencil_size;
   179     }
   180 
   181     if ((_this->gl_config.accum_red_size +
   182          _this->gl_config.accum_green_size +
   183          _this->gl_config.accum_blue_size +
   184          _this->gl_config.accum_alpha_size) > 0) {
   185         attr[i++] = NSOpenGLPFAAccumSize;
   186         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;
   187     }
   188 
   189     if (_this->gl_config.multisamplebuffers) {
   190         attr[i++] = NSOpenGLPFASampleBuffers;
   191         attr[i++] = _this->gl_config.multisamplebuffers;
   192     }
   193 
   194     if (_this->gl_config.multisamplesamples) {
   195         attr[i++] = NSOpenGLPFASamples;
   196         attr[i++] = _this->gl_config.multisamplesamples;
   197         attr[i++] = NSOpenGLPFANoRecovery;
   198     }
   199 
   200     if (_this->gl_config.accelerated > 0) {
   201         attr[i++] = NSOpenGLPFAAccelerated;
   202     }
   203 
   204     attr[i++] = NSOpenGLPFAScreenMask;
   205     attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
   206     attr[i] = 0;
   207 
   208     fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   209     if (fmt == nil) {
   210         SDL_SetError ("Failed creating OpenGL pixel format");
   211         [pool release];
   212         return NULL;
   213     }
   214 
   215     context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
   216 
   217     [fmt release];
   218 
   219     if (context == nil) {
   220         SDL_SetError ("Failed creating OpenGL context");
   221         [pool release];
   222         return NULL;
   223     }
   224 
   225     /*
   226      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   227      *  "You are blowing a couple of the internal OpenGL function caches. This
   228      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   229      *  the cache size by issuing the following calls right after you create
   230      *  the OpenGL context.  The default cache size is 16."    --ryan.
   231      */
   232 
   233     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   234     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   235     #endif
   236 
   237     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   238     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   239     #endif
   240 
   241     {
   242         long cache_max = 64;
   243         CGLContextObj ctx = [context CGLContextObj];
   244         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   245         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   246     }
   247 
   248     /* End Wisdom from Apple Engineer section. --ryan. */
   249 
   250     [pool release];
   251 
   252     if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
   253         Cocoa_GL_DeleteContext(_this, context);
   254         return NULL;
   255     }
   256 
   257     return context;
   258 }
   259 
   260 int
   261 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   262 {
   263     NSAutoreleasePool *pool;
   264 
   265     pool = [[NSAutoreleasePool alloc] init];
   266 
   267     if (context) {
   268         SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   269         NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   270 
   271         if (window->flags & SDL_WINDOW_FULLSCREEN) {
   272             [nscontext setFullScreen];
   273         } else {
   274             [nscontext setView:[windowdata->window contentView]];
   275             [nscontext update];
   276         }
   277         [nscontext makeCurrentContext];
   278     } else {
   279         [NSOpenGLContext clearCurrentContext];
   280     }
   281 
   282     [pool release];
   283     return 0;
   284 }
   285 
   286 int
   287 Cocoa_GL_SetSwapInterval(_THIS, int interval)
   288 {
   289     NSAutoreleasePool *pool;
   290     NSOpenGLContext *nscontext;
   291     GLint value;
   292     int status;
   293 
   294     pool = [[NSAutoreleasePool alloc] init];
   295 
   296     nscontext = [NSOpenGLContext currentContext];
   297     if (nscontext != nil) {
   298         value = interval;
   299         [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   300         status = 0;
   301     } else {
   302         SDL_SetError("No current OpenGL context");
   303         status = -1;
   304     }
   305 
   306     [pool release];
   307     return status;
   308 }
   309 
   310 int
   311 Cocoa_GL_GetSwapInterval(_THIS)
   312 {
   313     NSAutoreleasePool *pool;
   314     NSOpenGLContext *nscontext;
   315     GLint value;
   316     int status;
   317 
   318     pool = [[NSAutoreleasePool alloc] init];
   319 
   320     nscontext = [NSOpenGLContext currentContext];
   321     if (nscontext != nil) {
   322         [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   323         status = (int)value;
   324     } else {
   325         SDL_SetError("No current OpenGL context");
   326         status = -1;
   327     }
   328 
   329     [pool release];
   330     return status;
   331 }
   332 
   333 void
   334 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
   335 {
   336     NSAutoreleasePool *pool;
   337     NSOpenGLContext *nscontext;
   338 
   339     pool = [[NSAutoreleasePool alloc] init];
   340 
   341     /* FIXME: Do we need to get the context for the window? */
   342     nscontext = [NSOpenGLContext currentContext];
   343     if (nscontext != nil) {
   344         [nscontext flushBuffer];
   345     }
   346 
   347     [pool release];
   348 }
   349 
   350 void
   351 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
   352 {
   353     NSAutoreleasePool *pool;
   354     NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   355 
   356     pool = [[NSAutoreleasePool alloc] init];
   357 
   358     [nscontext clearDrawable];
   359     [nscontext release];
   360 
   361     [pool release];
   362 }
   363 
   364 #endif /* SDL_VIDEO_OPENGL_CGL */
   365 
   366 /* vi: set ts=4 sw=4 expandtab: */