src/video/quartz/SDL_QuartzGL.m
author Ryan C. Gordon
Mon, 21 Sep 2009 06:08:23 +0000
branchSDL-1.2
changeset 4204 976bc19f8f6b
parent 4188 9701c96e2cbb
child 4370 8d67936e32ec
permissions -rw-r--r--
1.2 Quartz video: Ripped out QuickDraw and QuickTime.

Now we use the software path for YUV, and CoreGraphics for 2D stuff.

There are several other 10.6 fixes in here, too...now we can build a 64-bit
SDL for Snow Leopard!
     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 Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 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     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_QuartzVideo.h"
    25 
    26 /*
    27  * GL_ARB_Multisample is supposed to be available in 10.1, according to Apple:
    28  *
    29  *   http://developer.apple.com/graphicsimaging/opengl/extensions.html#GL_ARB_multisample
    30  *
    31  *  ...but it isn't in the system headers, according to Sam:
    32  *
    33  *   http://lists.libsdl.org/pipermail/sdl-libsdl.org/2003-December/039794.html
    34  *
    35  * These are normally enums and not #defines in the system headers.
    36  *
    37  *   --ryan.
    38  */
    39 #if (MAC_OS_X_VERSION_MAX_ALLOWED < 1020)
    40 #define NSOpenGLPFASampleBuffers ((NSOpenGLPixelFormatAttribute) 55)
    41 #define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56)
    42 #endif
    43 
    44 #ifdef __powerpc__   /* we lost this in 10.6, which has no PPC support. */
    45 @implementation NSOpenGLContext (CGLContextAccess)
    46 - (CGLContextObj) cglContext;
    47 {
    48     return _contextAuxiliary;
    49 }
    50 @end
    51 CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
    52 {
    53     return [nsctx cglContext];
    54 }
    55 #else
    56 CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx)
    57 {
    58     return (CGLContextObj) [nsctx CGLContextObj];
    59 }
    60 #endif
    61 
    62 
    63 /* OpenGL helper functions (used internally) */
    64 
    65 int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
    66 
    67     NSOpenGLPixelFormatAttribute attr[32];
    68     NSOpenGLPixelFormat *fmt;
    69     int i = 0;
    70     int colorBits = bpp;
    71 
    72     /* if a GL library hasn't been loaded at this point, load the default. */
    73     if (!this->gl_config.driver_loaded) {
    74         if (QZ_GL_LoadLibrary(this, NULL) == -1)
    75             return 0;
    76     }
    77 
    78     if ( flags & SDL_FULLSCREEN ) {
    79 
    80         attr[i++] = NSOpenGLPFAFullScreen;
    81     }
    82     /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
    83     else if ( colorBits != device_bpp ) {
    84 
    85         colorBits = device_bpp;
    86     }
    87 
    88     attr[i++] = NSOpenGLPFAColorSize;
    89     attr[i++] = colorBits;
    90 
    91     attr[i++] = NSOpenGLPFADepthSize;
    92     attr[i++] = this->gl_config.depth_size;
    93 
    94     if ( this->gl_config.double_buffer ) {
    95         attr[i++] = NSOpenGLPFADoubleBuffer;
    96     }
    97 
    98     if ( this->gl_config.stereo ) {
    99         attr[i++] = NSOpenGLPFAStereo;
   100     }
   101 
   102     if ( this->gl_config.stencil_size != 0 ) {
   103         attr[i++] = NSOpenGLPFAStencilSize;
   104         attr[i++] = this->gl_config.stencil_size;
   105     }
   106 
   107     if ( (this->gl_config.accum_red_size +
   108           this->gl_config.accum_green_size +
   109           this->gl_config.accum_blue_size +
   110           this->gl_config.accum_alpha_size) > 0 ) {
   111         attr[i++] = NSOpenGLPFAAccumSize;
   112         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;
   113     }
   114 
   115     if ( this->gl_config.multisamplebuffers != 0 ) {
   116         attr[i++] = NSOpenGLPFASampleBuffers;
   117         attr[i++] = this->gl_config.multisamplebuffers;
   118     }
   119 
   120     if ( this->gl_config.multisamplesamples != 0 ) {
   121         attr[i++] = NSOpenGLPFASamples;
   122         attr[i++] = this->gl_config.multisamplesamples;
   123         attr[i++] = NSOpenGLPFANoRecovery;
   124     }
   125 
   126     if ( this->gl_config.accelerated > 0 ) {
   127         attr[i++] = NSOpenGLPFAAccelerated;
   128     }
   129 
   130     attr[i++] = NSOpenGLPFAScreenMask;
   131     attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
   132     attr[i] = 0;
   133 
   134     fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
   135     if (fmt == nil) {
   136         SDL_SetError ("Failed creating OpenGL pixel format");
   137         return 0;
   138     }
   139 
   140     gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
   141                                                shareContext:nil];
   142 
   143     [ fmt release ];
   144 
   145     if (gl_context == nil) {
   146         SDL_SetError ("Failed creating OpenGL context");
   147         return 0;
   148     }
   149 
   150     /* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
   151      * (Apple's documentation is not completely clear about what this setting
   152      * exactly does, IMHO - for a detailed explanation see
   153      * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
   154      */
   155     if ( this->gl_config.swap_control >= 0 ) {
   156         long value;
   157         value = this->gl_config.swap_control;
   158         [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ];
   159     }
   160 
   161     /*
   162      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   163      *  "You are blowing a couple of the internal OpenGL function caches. This
   164      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   165      *  the cache size by issuing the following calls right after you create
   166      *  the OpenGL context.  The default cache size is 16."    --ryan.
   167      */
   168 
   169     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   170     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   171     #endif
   172 
   173     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   174     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   175     #endif
   176 
   177     {
   178         long cache_max = 64;
   179         CGLContextObj ctx = QZ_GetCGLContextObj(gl_context);
   180         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   181         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   182     }
   183 
   184     /* End Wisdom from Apple Engineer section. --ryan. */
   185 
   186     return 1;
   187 }
   188 
   189 void QZ_TearDownOpenGL (_THIS) {
   190 
   191     [ NSOpenGLContext clearCurrentContext ];
   192     [ gl_context clearDrawable ];
   193     [ gl_context release ];
   194 }
   195 
   196 
   197 /* SDL OpenGL functions */
   198 static const char *DEFAULT_OPENGL_LIB_NAME =
   199     "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
   200 
   201 int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
   202     if ( gl_context != NULL ) {
   203         SDL_SetError("OpenGL context already created");
   204         return -1;
   205     }
   206 
   207     if (opengl_library != NULL)
   208         SDL_UnloadObject(opengl_library);
   209 
   210     if (location == NULL)
   211         location = DEFAULT_OPENGL_LIB_NAME;
   212 
   213     opengl_library = SDL_LoadObject(location);
   214     if (opengl_library != NULL) {
   215         this->gl_config.driver_loaded = 1;
   216         return 0;
   217     }
   218 
   219     this->gl_config.driver_loaded = 0;
   220     return -1;
   221 }
   222 
   223 void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
   224     return SDL_LoadFunction(opengl_library, proc);
   225 }
   226 
   227 int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
   228 
   229     GLenum attr = 0;
   230 
   231     QZ_GL_MakeCurrent (this);
   232 
   233     switch (attrib) {
   234         case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
   235         case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
   236         case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
   237         case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
   238         case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
   239         case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
   240         case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
   241         case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
   242         case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
   243         case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
   244         case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
   245         case SDL_GL_STEREO: attr = GL_STEREO; break;
   246         case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
   247         case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
   248         case SDL_GL_BUFFER_SIZE:
   249         {
   250             GLint bits = 0;
   251             GLint component;
   252 
   253             /* there doesn't seem to be a single flag in OpenGL for this! */
   254             glGetIntegerv (GL_RED_BITS, &component);   bits += component;
   255             glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
   256             glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
   257             glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
   258 
   259             *value = bits;
   260             return 0;
   261         }
   262         case SDL_GL_ACCELERATED_VISUAL:
   263         {
   264             long val;
   265 	    /* FIXME: How do we get this information here?
   266             [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0];
   267 	    */
   268 	    val = (this->gl_config.accelerated != 0);;
   269             *value = val;
   270             return 0;
   271         }
   272         case SDL_GL_SWAP_CONTROL:
   273         {
   274             long val;
   275             [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ];
   276             *value = val;
   277             return 0;
   278         }
   279     }
   280 
   281     glGetIntegerv (attr, (GLint *)value);
   282     return 0;
   283 }
   284 
   285 int    QZ_GL_MakeCurrent    (_THIS) {
   286     [ gl_context makeCurrentContext ];
   287     return 0;
   288 }
   289 
   290 void   QZ_GL_SwapBuffers    (_THIS) {
   291     [ gl_context flushBuffer ];
   292 }