src/video/quartz/SDL_QuartzGL.m
author Sam Lantinga
Tue, 21 Feb 2006 02:42:05 +0000
changeset 1400 5abff0870de2
parent 1195 bb6791b0a268
child 1403 376665398b25
permissions -rw-r--r--
Date: Mon, 20 Feb 2006 19:54:51 -0500
From: Brian Barnes
Subject: [SDL] Fix for FSAA OS X bug -- Please fix in CVS Code

I stopped complaining and went in an fixed the bug myself :) SDL
always dies if you try to use FSAA on Mac OS X, the problem is in the
file:

SDL_QuartzGL.m
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2003  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 
    23 #include "SDL_QuartzVideo.h"
    24 
    25 /*
    26  * GL_ARB_Multisample is supposed to be available in 10.1, according to Apple:
    27  *
    28  *   http://developer.apple.com/opengl/extensions.html#GL_ARB_multisample
    29  *
    30  *  ...but it isn't in the system headers, according to Sam:
    31  *
    32  *   http://www.libsdl.org/pipermail/sdl/2003-December/058335.html
    33  *
    34  * These are normally enums and not #defines in the system headers.
    35  *
    36  *   --ryan.
    37  */
    38 #if (MAC_OS_X_VERSION_MAX_ALLOWED < 1020)
    39 #define NSOpenGLPFASampleBuffers ((NSOpenGLPixelFormatAttribute) 55)
    40 #define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56)
    41 #endif
    42 
    43 
    44 @implementation NSOpenGLContext (CGLContextAccess)
    45 - (CGLContextObj) cglContext;
    46 {
    47     return _contextAuxiliary;
    48 }
    49 @end
    50 
    51 /* OpenGL helper functions (used internally) */
    52 
    53 int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
    54 
    55     NSOpenGLPixelFormatAttribute attr[32];
    56     NSOpenGLPixelFormat *fmt;
    57     int i = 0;
    58     int colorBits = bpp;
    59 
    60     /* if a GL library hasn't been loaded at this point, load the default. */
    61     if (!this->gl_config.driver_loaded) {
    62         if (QZ_GL_LoadLibrary(this, NULL) == -1)
    63             return 0;
    64     }
    65 
    66     if ( flags & SDL_FULLSCREEN ) {
    67 
    68         attr[i++] = NSOpenGLPFAFullScreen;
    69     }
    70     /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
    71     else if ( colorBits != device_bpp ) {
    72 
    73         colorBits = device_bpp;
    74     }
    75 
    76     attr[i++] = NSOpenGLPFAColorSize;
    77     attr[i++] = colorBits;
    78 
    79     attr[i++] = NSOpenGLPFADepthSize;
    80     attr[i++] = this->gl_config.depth_size;
    81 
    82     if ( this->gl_config.double_buffer ) {
    83         attr[i++] = NSOpenGLPFADoubleBuffer;
    84     }
    85 
    86     if ( this->gl_config.stereo ) {
    87         attr[i++] = NSOpenGLPFAStereo;
    88     }
    89 
    90     if ( this->gl_config.stencil_size != 0 ) {
    91         attr[i++] = NSOpenGLPFAStencilSize;
    92         attr[i++] = this->gl_config.stencil_size;
    93     }
    94 
    95     if ( (this->gl_config.accum_red_size +
    96           this->gl_config.accum_green_size +
    97           this->gl_config.accum_blue_size +
    98           this->gl_config.accum_alpha_size) > 0 ) {
    99         attr[i++] = NSOpenGLPFAAccumSize;
   100         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;
   101     }
   102 
   103     if ( this->gl_config.multisamplebuffers != 0 ) {
   104         attr[i++] = NSOpenGLPFASampleBuffers;
   105         attr[i++] = this->gl_config.multisamplebuffers;
   106     }
   107 
   108     if ( this->gl_config.multisamplesamples != 0 ) {
   109         attr[i++] = NSOpenGLPFASamples;
   110         attr[i++] = this->gl_config.multisamplesamples;
   111         attr[i++] = NSOpenGLPFANoRecovery;
   112     }
   113 
   114     attr[i++] = NSOpenGLPFAScreenMask;
   115     attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
   116     attr[i] = 0;
   117 
   118     fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
   119     if (fmt == nil) {
   120         SDL_SetError ("Failed creating OpenGL pixel format");
   121         return 0;
   122     }
   123 
   124     gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
   125                                                shareContext:nil];
   126 
   127     [ fmt release ];
   128 
   129     if (gl_context == nil) {
   130         SDL_SetError ("Failed creating OpenGL context");
   131         return 0;
   132     }
   133 
   134     /*
   135      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   136      *  "You are blowing a couple of the internal OpenGL function caches. This
   137      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   138      *  the cache size by issuing the following calls right after you create
   139      *  the OpenGL context.  The default cache size is 16."    --ryan.
   140      */
   141 
   142     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   143     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   144     #endif
   145 
   146     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   147     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   148     #endif
   149 
   150     {
   151         long cache_max = 64;
   152         CGLContextObj ctx = [ gl_context cglContext ];
   153         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   154         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   155     }
   156 
   157     /* End Wisdom from Apple Engineer section. --ryan. */
   158 
   159     return 1;
   160 }
   161 
   162 void QZ_TearDownOpenGL (_THIS) {
   163 
   164     [ NSOpenGLContext clearCurrentContext ];
   165     [ gl_context clearDrawable ];
   166     [ gl_context release ];
   167 }
   168 
   169 
   170 /* SDL OpenGL functions */
   171 static const char *DEFAULT_OPENGL_LIB_NAME =
   172     "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
   173 
   174 int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
   175     if ( gl_context != NULL ) {
   176         SDL_SetError("OpenGL context already created");
   177         return -1;
   178     }
   179 
   180     if (opengl_library != NULL)
   181         SDL_UnloadObject(opengl_library);
   182 
   183     if (location == NULL)
   184         location = DEFAULT_OPENGL_LIB_NAME;
   185 
   186     opengl_library = SDL_LoadObject(location);
   187     if (opengl_library != NULL) {
   188         this->gl_config.driver_loaded = 1;
   189         return 0;
   190     }
   191 
   192     this->gl_config.driver_loaded = 0;
   193     return -1;
   194 }
   195 
   196 void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
   197     return SDL_LoadFunction(opengl_library, proc);
   198 }
   199 
   200 int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
   201 
   202     GLenum attr = 0;
   203 
   204     QZ_GL_MakeCurrent (this);
   205 
   206     switch (attrib) {
   207         case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
   208         case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
   209         case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
   210         case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
   211         case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
   212         case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
   213         case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
   214         case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
   215         case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
   216         case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
   217         case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
   218         case SDL_GL_STEREO: attr = GL_STEREO; break;
   219         case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
   220         case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
   221         case SDL_GL_BUFFER_SIZE:
   222         {
   223             GLint bits = 0;
   224             GLint component;
   225 
   226             /* there doesn't seem to be a single flag in OpenGL for this! */
   227             glGetIntegerv (GL_RED_BITS, &component);   bits += component;
   228             glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
   229             glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
   230             glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
   231 
   232             *value = bits;
   233         }
   234         return 0;
   235     }
   236 
   237     glGetIntegerv (attr, (GLint *)value);
   238     return 0;
   239 }
   240 
   241 int    QZ_GL_MakeCurrent    (_THIS) {
   242     [ gl_context makeCurrentContext ];
   243     return 0;
   244 }
   245 
   246 void   QZ_GL_SwapBuffers    (_THIS) {
   247     [ gl_context flushBuffer ];
   248 }