src/video/quartz/SDL_QuartzGL.m
author Ryan C. Gordon
Tue, 22 Nov 2005 08:21:39 +0000
changeset 1181 49d3efec6651
parent 1177 e967ab22e6fd
child 1189 c96b326b90ba
permissions -rw-r--r--
Quartz driver OpenGL updates:

Driver can now open whatever library is specified in SDL_GL_LoadLibrary()
call (previously, it ignored this parameter), and uses the default system
library when NULL is specified.

Also, library is loaded once in SDL_GL_LoadLibrary() and not every call to
SDL_GL_GetProcAddress().
     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 ( flags & SDL_FULLSCREEN ) {
    61 
    62         attr[i++] = NSOpenGLPFAFullScreen;
    63     }
    64     /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
    65     else if ( colorBits != device_bpp ) {
    66 
    67         colorBits = device_bpp;
    68     }
    69 
    70     attr[i++] = NSOpenGLPFAColorSize;
    71     attr[i++] = colorBits;
    72 
    73     attr[i++] = NSOpenGLPFADepthSize;
    74     attr[i++] = this->gl_config.depth_size;
    75 
    76     if ( this->gl_config.double_buffer ) {
    77         attr[i++] = NSOpenGLPFADoubleBuffer;
    78     }
    79 
    80     if ( this->gl_config.stereo ) {
    81         attr[i++] = NSOpenGLPFAStereo;
    82     }
    83 
    84     if ( this->gl_config.stencil_size != 0 ) {
    85         attr[i++] = NSOpenGLPFAStencilSize;
    86         attr[i++] = this->gl_config.stencil_size;
    87     }
    88 
    89     if ( (this->gl_config.accum_red_size +
    90           this->gl_config.accum_green_size +
    91           this->gl_config.accum_blue_size +
    92           this->gl_config.accum_alpha_size) > 0 ) {
    93         attr[i++] = NSOpenGLPFAAccumSize;
    94         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;
    95     }
    96 
    97     if ( this->gl_config.multisamplebuffers != 0 ) {
    98         attr[i++] = NSOpenGLPFASampleBuffers;
    99         attr[i++] = this->gl_config.multisamplebuffers;
   100     }
   101 
   102     if ( this->gl_config.multisamplesamples != 0 ) {
   103         attr[i++] = NSOpenGLPFASamples;
   104         attr[i++] = this->gl_config.multisamplesamples;
   105         attr[i++] = NSOpenGLPFANoRecovery;
   106         attr[i++] = (NSOpenGLPixelFormatAttribute)nil;
   107     }
   108 
   109     attr[i++] = NSOpenGLPFAScreenMask;
   110     attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
   111     attr[i] = 0;
   112 
   113     fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
   114     if (fmt == nil) {
   115         SDL_SetError ("Failed creating OpenGL pixel format");
   116         return 0;
   117     }
   118 
   119     gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
   120                                                shareContext:nil];
   121 
   122     [ fmt release ];
   123 
   124     if (gl_context == nil) {
   125         SDL_SetError ("Failed creating OpenGL context");
   126         return 0;
   127     }
   128 
   129     /*
   130      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   131      *  "You are blowing a couple of the internal OpenGL function caches. This
   132      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   133      *  the cache size by issuing the following calls right after you create
   134      *  the OpenGL context.  The default cache size is 16."    --ryan.
   135      */
   136 
   137     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   138     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   139     #endif
   140 
   141     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   142     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   143     #endif
   144 
   145     {
   146         long cache_max = 64;
   147         CGLContextObj ctx = [ gl_context cglContext ];
   148         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   149         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   150     }
   151 
   152     /* End Wisdom from Apple Engineer section. --ryan. */
   153 
   154     /* Convince SDL that the GL "driver" is loaded */
   155     this->gl_config.driver_loaded = 1;
   156 
   157     return 1;
   158 }
   159 
   160 void QZ_TearDownOpenGL (_THIS) {
   161 
   162     [ NSOpenGLContext clearCurrentContext ];
   163     [ gl_context clearDrawable ];
   164     [ gl_context release ];
   165 }
   166 
   167 
   168 /* SDL OpenGL functions */
   169 
   170 int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
   171     CFURLRef bundleURL;
   172     CFStringRef cfstr;
   173 
   174     if ( gl_context != NULL ) {
   175         SDL_SetError("OpenGL context already created");
   176         return -1;
   177     }
   178 
   179     if (opengl_bundle != NULL)
   180         CFRelease(opengl_bundle);
   181 
   182     opengl_bundle = NULL;
   183     this->gl_config.driver_loaded = 0;
   184 
   185     if (location == NULL)
   186         location = "/System/Library/Frameworks/OpenGL.framework";
   187 
   188     cfstr = CFStringCreateWithCString(kCFAllocatorDefault, location,
   189                                       kCFStringEncodingUTF8);
   190     if (cfstr == NULL) {
   191         SDL_OutOfMemory();
   192         return -1;
   193     }
   194 
   195     bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
   196                         cfstr, kCFURLPOSIXPathStyle, true);
   197 
   198     CFRelease(cfstr);
   199 
   200     if (bundleURL == NULL) {
   201         SDL_OutOfMemory();
   202         return -1;
   203     }
   204 
   205     opengl_bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
   206 
   207     CFRelease(bundleURL);
   208 
   209     if (opengl_bundle != NULL) {
   210         this->gl_config.driver_loaded = 1;
   211         return 0;
   212     }
   213 
   214     /* not exactly descriptive, but okay... */
   215     SDL_SetError("Could not load OpenGL library");
   216     return -1;
   217 }
   218 
   219 void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
   220     CFStringRef funcName = CFStringCreateWithCString
   221         (kCFAllocatorDefault, proc, kCFStringEncodingASCII);
   222 
   223     void *func = CFBundleGetFunctionPointerForName(opengl_bundle, funcName);
   224     CFRelease (funcName);
   225     return func;
   226 }
   227 
   228 int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
   229 
   230     GLenum attr = 0;
   231 
   232     QZ_GL_MakeCurrent (this);
   233 
   234     switch (attrib) {
   235         case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
   236         case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
   237         case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
   238         case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
   239         case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
   240         case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
   241         case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
   242         case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
   243         case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
   244         case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
   245         case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
   246         case SDL_GL_STEREO: attr = GL_STEREO; break;
   247         case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
   248         case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
   249         case SDL_GL_BUFFER_SIZE:
   250         {
   251             GLint bits = 0;
   252             GLint component;
   253 
   254             /* there doesn't seem to be a single flag in OpenGL for this! */
   255             glGetIntegerv (GL_RED_BITS, &component);   bits += component;
   256             glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
   257             glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
   258             glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
   259 
   260             *value = bits;
   261         }
   262         return 0;
   263     }
   264 
   265     glGetIntegerv (attr, (GLint *)value);
   266     return 0;
   267 }
   268 
   269 int    QZ_GL_MakeCurrent    (_THIS) {
   270     [ gl_context makeCurrentContext ];
   271     return 0;
   272 }
   273 
   274 void   QZ_GL_SwapBuffers    (_THIS) {
   275     [ gl_context flushBuffer ];
   276 }