src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Mon, 09 Feb 2009 05:32:12 +0000
changeset 3057 089a77aebb7d
parent 2859 99210400e8b9
child 3570 7812d3e9564e
permissions -rw-r--r--
Added test program for SDL_CreateWindowFrom()
Make sure OpenGL library is loaded before working with OpenGL windows,
even those created with SDL_CreateWindowFrom()
     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 
    32 #include "SDL_loadso.h"
    33 #include "SDL_opengl.h"
    34 
    35 
    36 #define DEFAULT_OPENGL  "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
    37 
    38 /* This is implemented in Mac OS X 10.3 and above */
    39 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3
    40 @implementation NSOpenGLContext(CGLContextAccess)
    41 - (CGLContextObj)CGLContextObj;
    42 {
    43     return _contextAuxiliary;
    44 }
    45 @end
    46 #endif /* < 10.3 */
    47 
    48 int
    49 Cocoa_GL_LoadLibrary(_THIS, const char *path)
    50 {
    51     /* Load the OpenGL library */
    52     if (path == NULL) {
    53         path = SDL_getenv("SDL_OPENGL_LIBRARY");
    54     }
    55     if (path == NULL) {
    56         path = DEFAULT_OPENGL;
    57     }
    58     _this->gl_config.dll_handle = SDL_LoadObject(path);
    59     if (!_this->gl_config.dll_handle) {
    60         return -1;
    61     }
    62     SDL_strlcpy(_this->gl_config.driver_path, path,
    63                 SDL_arraysize(_this->gl_config.driver_path));
    64     return 0;
    65 }
    66 
    67 void *
    68 Cocoa_GL_GetProcAddress(_THIS, const char *proc)
    69 {
    70     return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
    71 }
    72 
    73 void
    74 Cocoa_GL_UnloadLibrary(_THIS)
    75 {
    76     SDL_UnloadObject(_this->gl_config.dll_handle);
    77     _this->gl_config.dll_handle = NULL;
    78 }
    79 
    80 SDL_GLContext
    81 Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
    82 {
    83     NSAutoreleasePool *pool;
    84     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
    85     SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
    86     NSOpenGLPixelFormatAttribute attr[32];
    87     NSOpenGLPixelFormat *fmt;
    88     NSOpenGLContext *context;
    89     int i = 0;
    90 
    91     pool = [[NSAutoreleasePool alloc] init];
    92 
    93     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    94         attr[i++] = NSOpenGLPFAFullScreen;
    95     }
    96 
    97     attr[i++] = NSOpenGLPFAColorSize;
    98     attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
    99 
   100     attr[i++] = NSOpenGLPFADepthSize;
   101     attr[i++] = _this->gl_config.depth_size;
   102 
   103     if (_this->gl_config.double_buffer) {
   104         attr[i++] = NSOpenGLPFADoubleBuffer;
   105     }
   106 
   107     if (_this->gl_config.stereo) {
   108         attr[i++] = NSOpenGLPFAStereo;
   109     }
   110 
   111     if (_this->gl_config.stencil_size) {
   112         attr[i++] = NSOpenGLPFAStencilSize;
   113         attr[i++] = _this->gl_config.stencil_size;
   114     }
   115 
   116     if ((_this->gl_config.accum_red_size +
   117          _this->gl_config.accum_green_size +
   118          _this->gl_config.accum_blue_size +
   119          _this->gl_config.accum_alpha_size) > 0) {
   120         attr[i++] = NSOpenGLPFAAccumSize;
   121         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;
   122     }
   123 
   124     if (_this->gl_config.multisamplebuffers) {
   125         attr[i++] = NSOpenGLPFASampleBuffers;
   126         attr[i++] = _this->gl_config.multisamplebuffers;
   127     }
   128 
   129     if (_this->gl_config.multisamplesamples) {
   130         attr[i++] = NSOpenGLPFASamples;
   131         attr[i++] = _this->gl_config.multisamplesamples;
   132         attr[i++] = NSOpenGLPFANoRecovery;
   133     }
   134 
   135     if (_this->gl_config.accelerated > 0) {
   136         attr[i++] = NSOpenGLPFAAccelerated;
   137     }
   138 
   139     attr[i++] = NSOpenGLPFAScreenMask;
   140     attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
   141     attr[i] = 0;
   142 
   143     fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   144     if (fmt == nil) {
   145         SDL_SetError ("Failed creating OpenGL pixel format");
   146         [pool release];
   147         return NULL;
   148     }
   149 
   150     context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
   151 
   152     [fmt release];
   153 
   154     if (context == nil) {
   155         SDL_SetError ("Failed creating OpenGL context");
   156         [pool release];
   157         return NULL;
   158     }
   159 
   160     /*
   161      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   162      *  "You are blowing a couple of the internal OpenGL function caches. This
   163      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   164      *  the cache size by issuing the following calls right after you create
   165      *  the OpenGL context.  The default cache size is 16."    --ryan.
   166      */
   167 
   168     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   169     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   170     #endif
   171 
   172     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   173     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   174     #endif
   175 
   176     {
   177         long cache_max = 64;
   178         CGLContextObj ctx = [context CGLContextObj];
   179         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   180         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   181     }
   182 
   183     /* End Wisdom from Apple Engineer section. --ryan. */
   184 
   185     [pool release];
   186 
   187     if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
   188         Cocoa_GL_DeleteContext(_this, context);
   189         return NULL;
   190     }
   191 
   192     return context;
   193 }
   194 
   195 int
   196 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   197 {
   198     NSAutoreleasePool *pool;
   199 
   200     pool = [[NSAutoreleasePool alloc] init];
   201 
   202     if (context) {
   203         SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   204         NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   205 
   206         if (window->flags & SDL_WINDOW_FULLSCREEN) {
   207             [nscontext setFullScreen];
   208         } else {
   209             [nscontext setView:[windowdata->window contentView]];
   210             [nscontext update];
   211         }
   212         [nscontext makeCurrentContext];
   213     } else {
   214         [NSOpenGLContext clearCurrentContext];
   215     }
   216 
   217     [pool release];
   218     return 0;
   219 }
   220 
   221 int
   222 Cocoa_GL_SetSwapInterval(_THIS, int interval)
   223 {
   224     NSAutoreleasePool *pool;
   225     NSOpenGLContext *nscontext;
   226     GLint value;
   227     int status;
   228 
   229     pool = [[NSAutoreleasePool alloc] init];
   230 
   231     nscontext = [NSOpenGLContext currentContext];
   232     if (nscontext != nil) {
   233         value = interval;
   234         [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   235         status = 0;
   236     } else {
   237         SDL_SetError("No current OpenGL context");
   238         status = -1;
   239     }
   240 
   241     [pool release];
   242     return status;
   243 }
   244 
   245 int
   246 Cocoa_GL_GetSwapInterval(_THIS)
   247 {
   248     NSAutoreleasePool *pool;
   249     NSOpenGLContext *nscontext;
   250     GLint value;
   251     int status;
   252 
   253     pool = [[NSAutoreleasePool alloc] init];
   254 
   255     nscontext = [NSOpenGLContext currentContext];
   256     if (nscontext != nil) {
   257         [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   258         status = (int)value;
   259     } else {
   260         SDL_SetError("No current OpenGL context");
   261         status = -1;
   262     }
   263 
   264     [pool release];
   265     return status;
   266 }
   267 
   268 void
   269 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
   270 {
   271     NSAutoreleasePool *pool;
   272     NSOpenGLContext *nscontext;
   273 
   274     pool = [[NSAutoreleasePool alloc] init];
   275 
   276     /* FIXME: Do we need to get the context for the window? */
   277     nscontext = [NSOpenGLContext currentContext];
   278     if (nscontext != nil) {
   279         [nscontext flushBuffer];
   280     }
   281 
   282     [pool release];
   283 }
   284 
   285 void
   286 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
   287 {
   288     NSAutoreleasePool *pool;
   289     NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   290 
   291     pool = [[NSAutoreleasePool alloc] init];
   292 
   293     [nscontext clearDrawable];
   294     [nscontext release];
   295 
   296     [pool release];
   297 }
   298 
   299 #endif /* SDL_VIDEO_OPENGL_CGL */
   300 
   301 /* vi: set ts=4 sw=4 expandtab: */