src/video/cocoa/SDL_cocoaopengl.m
author Sam Lantinga <slouken@libsdl.org>
Sun, 22 Jan 2012 21:46:06 -0500
changeset 6260 fd494c5f305b
parent 6138 4c64952a58fb
child 6382 64d54101773a
permissions -rwxr-xr-x
Fixed loading textures when the window starts hidden.
The viewport automatically resets to the window size when you programmatically resize the window.
     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         if (window->flags & SDL_WINDOW_SHOWN) {
   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         }
   214         [nscontext makeCurrentContext];
   215     } else {
   216         [NSOpenGLContext clearCurrentContext];
   217     }
   218 
   219     [pool release];
   220     return 0;
   221 }
   222 
   223 int
   224 Cocoa_GL_SetSwapInterval(_THIS, int interval)
   225 {
   226     NSAutoreleasePool *pool;
   227     NSOpenGLContext *nscontext;
   228     GLint value;
   229     int status;
   230 
   231     pool = [[NSAutoreleasePool alloc] init];
   232 
   233     nscontext = [NSOpenGLContext currentContext];
   234     if (nscontext != nil) {
   235         value = interval;
   236         [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   237         status = 0;
   238     } else {
   239         SDL_SetError("No current OpenGL context");
   240         status = -1;
   241     }
   242 
   243     [pool release];
   244     return status;
   245 }
   246 
   247 int
   248 Cocoa_GL_GetSwapInterval(_THIS)
   249 {
   250     NSAutoreleasePool *pool;
   251     NSOpenGLContext *nscontext;
   252     GLint value;
   253     int status;
   254 
   255     pool = [[NSAutoreleasePool alloc] init];
   256 
   257     nscontext = [NSOpenGLContext currentContext];
   258     if (nscontext != nil) {
   259         [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   260         status = (int)value;
   261     } else {
   262         SDL_SetError("No current OpenGL context");
   263         status = -1;
   264     }
   265 
   266     [pool release];
   267     return status;
   268 }
   269 
   270 void
   271 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
   272 {
   273     NSAutoreleasePool *pool;
   274     NSOpenGLContext *nscontext;
   275 
   276     pool = [[NSAutoreleasePool alloc] init];
   277 
   278     /* FIXME: Do we need to get the context for the window? */
   279     nscontext = [NSOpenGLContext currentContext];
   280     if (nscontext != nil) {
   281         [nscontext flushBuffer];
   282     }
   283 
   284     [pool release];
   285 }
   286 
   287 void
   288 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
   289 {
   290     NSAutoreleasePool *pool;
   291     NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
   292 
   293     pool = [[NSAutoreleasePool alloc] init];
   294 
   295     [nscontext clearDrawable];
   296     [nscontext release];
   297 
   298     [pool release];
   299 }
   300 
   301 #endif /* SDL_VIDEO_OPENGL_CGL */
   302 
   303 /* vi: set ts=4 sw=4 expandtab: */