src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 09:28:07 -0500
changeset 6138 4c64952a58fb
parent 6044 35448a5ea044
child 6260 fd494c5f305b
permissions -rwxr-xr-x
Happy New Year!
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* NSOpenGL implementation of SDL OpenGL support */
    24 
    25 #if SDL_VIDEO_OPENGL_CGL
    26 #include "SDL_cocoavideo.h"
    27 
    28 #include <OpenGL/CGLTypes.h>
    29 #include <OpenGL/OpenGL.h>
    30 #include <OpenGL/CGLRenderers.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 int
    39 Cocoa_GL_LoadLibrary(_THIS, const char *path)
    40 {
    41     /* Load the OpenGL library */
    42     if (path == NULL) {
    43         path = SDL_getenv("SDL_OPENGL_LIBRARY");
    44     }
    45     if (path == NULL) {
    46         path = DEFAULT_OPENGL;
    47     }
    48     _this->gl_config.dll_handle = SDL_LoadObject(path);
    49     if (!_this->gl_config.dll_handle) {
    50         return -1;
    51     }
    52     SDL_strlcpy(_this->gl_config.driver_path, path,
    53                 SDL_arraysize(_this->gl_config.driver_path));
    54     return 0;
    55 }
    56 
    57 void *
    58 Cocoa_GL_GetProcAddress(_THIS, const char *proc)
    59 {
    60     return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
    61 }
    62 
    63 void
    64 Cocoa_GL_UnloadLibrary(_THIS)
    65 {
    66     SDL_UnloadObject(_this->gl_config.dll_handle);
    67     _this->gl_config.dll_handle = NULL;
    68 }
    69 
    70 SDL_GLContext
    71 Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
    72 {
    73     NSAutoreleasePool *pool;
    74     SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    75     SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
    76     NSOpenGLPixelFormatAttribute attr[32];
    77     NSOpenGLPixelFormat *fmt;
    78     NSOpenGLContext *context;
    79     int i = 0;
    80 
    81     pool = [[NSAutoreleasePool alloc] init];
    82 
    83 #ifndef FULLSCREEN_TOGGLEABLE
    84     if (window->flags & SDL_WINDOW_FULLSCREEN) {
    85         attr[i++] = NSOpenGLPFAFullScreen;
    86     }
    87 #endif
    88 
    89     attr[i++] = NSOpenGLPFAColorSize;
    90     attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
    91 
    92     attr[i++] = NSOpenGLPFADepthSize;
    93     attr[i++] = _this->gl_config.depth_size;
    94 
    95     if (_this->gl_config.double_buffer) {
    96         attr[i++] = NSOpenGLPFADoubleBuffer;
    97     }
    98 
    99     if (_this->gl_config.stereo) {
   100         attr[i++] = NSOpenGLPFAStereo;
   101     }
   102 
   103     if (_this->gl_config.stencil_size) {
   104         attr[i++] = NSOpenGLPFAStencilSize;
   105         attr[i++] = _this->gl_config.stencil_size;
   106     }
   107 
   108     if ((_this->gl_config.accum_red_size +
   109          _this->gl_config.accum_green_size +
   110          _this->gl_config.accum_blue_size +
   111          _this->gl_config.accum_alpha_size) > 0) {
   112         attr[i++] = NSOpenGLPFAAccumSize;
   113         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;
   114     }
   115 
   116     if (_this->gl_config.multisamplebuffers) {
   117         attr[i++] = NSOpenGLPFASampleBuffers;
   118         attr[i++] = _this->gl_config.multisamplebuffers;
   119     }
   120 
   121     if (_this->gl_config.multisamplesamples) {
   122         attr[i++] = NSOpenGLPFASamples;
   123         attr[i++] = _this->gl_config.multisamplesamples;
   124         attr[i++] = NSOpenGLPFANoRecovery;
   125     }
   126 
   127     if (_this->gl_config.accelerated >= 0) {
   128         if (_this->gl_config.accelerated) {
   129             attr[i++] = NSOpenGLPFAAccelerated;
   130         } else {
   131             attr[i++] = NSOpenGLPFARendererID;
   132             attr[i++] = kCGLRendererGenericFloatID;
   133         }
   134     }
   135 
   136     attr[i++] = NSOpenGLPFAScreenMask;
   137     attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
   138     attr[i] = 0;
   139 
   140     fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   141     if (fmt == nil) {
   142         SDL_SetError ("Failed creating OpenGL pixel format");
   143         [pool release];
   144         return NULL;
   145     }
   146 
   147     context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
   148 
   149     [fmt release];
   150 
   151     if (context == nil) {
   152         SDL_SetError ("Failed creating OpenGL context");
   153         [pool release];
   154         return NULL;
   155     }
   156 
   157     /*
   158      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   159      *  "You are blowing a couple of the internal OpenGL function caches. This
   160      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   161      *  the cache size by issuing the following calls right after you create
   162      *  the OpenGL context.  The default cache size is 16."    --ryan.
   163      */
   164 
   165     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   166     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   167     #endif
   168 
   169     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   170     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   171     #endif
   172 
   173     {
   174         GLint cache_max = 64;
   175         CGLContextObj ctx = [context CGLContextObj];
   176         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   177         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   178     }
   179 
   180     /* End Wisdom from Apple Engineer section. --ryan. */
   181 
   182     [pool release];
   183 
   184     if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
   185         Cocoa_GL_DeleteContext(_this, context);
   186         return NULL;
   187     }
   188 
   189     return context;
   190 }
   191 
   192 int
   193 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   194 {
   195     NSAutoreleasePool *pool;
   196 
   197     pool = [[NSAutoreleasePool alloc] init];
   198 
   199     if (context) {
   200         SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
   201         NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   202 
   203 #ifndef FULLSCREEN_TOGGLEABLE
   204         if (window->flags & SDL_WINDOW_FULLSCREEN) {
   205             [nscontext setFullScreen];
   206         } else
   207 #endif
   208         {
   209             [nscontext setView:[windowdata->nswindow 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: */