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