src/video/quartz/SDL_QuartzGL.m
author Sam Lantinga
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1738 acfd00fbff5c
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
     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 #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/opengl/extensions.html#GL_ARB_multisample
    30  *
    31  *  ...but it isn't in the system headers, according to Sam:
    32  *
    33  *   http://www.libsdl.org/pipermail/sdl/2003-December/058335.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 
    45 @ implementation NSOpenGLContext (CGLContextAccess)
    46     - (CGLContextObj) cglContext;
    47 {
    48     return _contextAuxiliary;
    49 }
    50 
    51 @end
    52 /* OpenGL helper functions (used internally) */
    53     int
    54 QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags)
    55 {
    56 
    57     NSOpenGLPixelFormatAttribute attr[32];
    58     NSOpenGLPixelFormat *fmt;
    59     int i = 0;
    60     int colorBits = bpp;
    61 
    62     /* if a GL library hasn't been loaded at this point, load the default. */
    63     if (!this->gl_config.driver_loaded) {
    64         if (QZ_GL_LoadLibrary (this, NULL) == -1)
    65             return 0;
    66     }
    67 
    68     if (flags & SDL_FULLSCREEN) {
    69 
    70         attr[i++] = NSOpenGLPFAFullScreen;
    71     }
    72     /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
    73     else if (colorBits != device_bpp) {
    74 
    75         colorBits = device_bpp;
    76     }
    77 
    78     attr[i++] = NSOpenGLPFAColorSize;
    79     attr[i++] = colorBits;
    80 
    81     attr[i++] = NSOpenGLPFADepthSize;
    82     attr[i++] = this->gl_config.depth_size;
    83 
    84     if (this->gl_config.double_buffer) {
    85         attr[i++] = NSOpenGLPFADoubleBuffer;
    86     }
    87 
    88     if (this->gl_config.stereo) {
    89         attr[i++] = NSOpenGLPFAStereo;
    90     }
    91 
    92     if (this->gl_config.stencil_size != 0) {
    93         attr[i++] = NSOpenGLPFAStencilSize;
    94         attr[i++] = this->gl_config.stencil_size;
    95     }
    96 
    97     if ((this->gl_config.accum_red_size +
    98          this->gl_config.accum_green_size +
    99          this->gl_config.accum_blue_size +
   100          this->gl_config.accum_alpha_size) > 0) {
   101         attr[i++] = NSOpenGLPFAAccumSize;
   102         attr[i++] =
   103             this->gl_config.accum_red_size +
   104             this->gl_config.accum_green_size +
   105             this->gl_config.accum_blue_size +
   106             this->gl_config.accum_alpha_size;
   107     }
   108 
   109     if (this->gl_config.multisamplebuffers != 0) {
   110         attr[i++] = NSOpenGLPFASampleBuffers;
   111         attr[i++] = this->gl_config.multisamplebuffers;
   112     }
   113 
   114     if (this->gl_config.multisamplesamples != 0) {
   115         attr[i++] = NSOpenGLPFASamples;
   116         attr[i++] = this->gl_config.multisamplesamples;
   117         attr[i++] = NSOpenGLPFANoRecovery;
   118     }
   119 
   120     if (this->gl_config.accelerated > 0) {
   121         attr[i++] = NSOpenGLPFAAccelerated;
   122     }
   123 
   124     attr[i++] = NSOpenGLPFAScreenMask;
   125     attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
   126     attr[i] = 0;
   127 
   128   fmt =[[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   129     if (fmt == nil) {
   130         SDL_SetError ("Failed creating OpenGL pixel format");
   131         return 0;
   132     }
   133 
   134   gl_context =[[NSOpenGLContext alloc] initWithFormat: fmt shareContext:nil];
   135 
   136     [fmt release];
   137 
   138     if (gl_context == nil) {
   139         SDL_SetError ("Failed creating OpenGL context");
   140         return 0;
   141     }
   142 
   143     /* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
   144      * (Apple's documentation is not completely clear about what this setting
   145      * exactly does, IMHO - for a detailed explanation see
   146      * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
   147      */
   148     if (this->gl_config.swap_control >= 0) {
   149         long value;
   150         value = this->gl_config.swap_control;
   151       [gl_context setValues: &value forParameter:NSOpenGLCPSwapInterval];
   152     }
   153 
   154     /*
   155      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   156      *  "You are blowing a couple of the internal OpenGL function caches. This
   157      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   158      *  the cache size by issuing the following calls right after you create
   159      *  the OpenGL context.  The default cache size is 16."    --ryan.
   160      */
   161 
   162 #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   163 #define GLI_ARRAY_FUNC_CACHE_MAX 284
   164 #endif
   165 
   166 #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   167 #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   168 #endif
   169 
   170     {
   171         long cache_max = 64;
   172         CGLContextObj ctx =[gl_context cglContext];
   173         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   174         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   175     }
   176 
   177     /* End Wisdom from Apple Engineer section. --ryan. */
   178 
   179     return 1;
   180 }
   181 
   182 void
   183 QZ_TearDownOpenGL (_THIS)
   184 {
   185 
   186     [NSOpenGLContext clearCurrentContext];
   187     [gl_context clearDrawable];
   188     [gl_context release];
   189 }
   190 
   191 
   192 /* SDL OpenGL functions */
   193 static const char *DEFAULT_OPENGL_LIB_NAME =
   194     "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
   195 
   196 int
   197 QZ_GL_LoadLibrary (_THIS, const char *location)
   198 {
   199     if (gl_context != NULL) {
   200         SDL_SetError ("OpenGL context already created");
   201         return -1;
   202     }
   203 
   204     if (opengl_library != NULL)
   205         SDL_UnloadObject (opengl_library);
   206 
   207     if (location == NULL)
   208         location = DEFAULT_OPENGL_LIB_NAME;
   209 
   210     opengl_library = SDL_LoadObject (location);
   211     if (opengl_library != NULL) {
   212         this->gl_config.driver_loaded = 1;
   213         return 0;
   214     }
   215 
   216     this->gl_config.driver_loaded = 0;
   217     return -1;
   218 }
   219 
   220 void *
   221 QZ_GL_GetProcAddress (_THIS, const char *proc)
   222 {
   223     return SDL_LoadFunction (opengl_library, proc);
   224 }
   225 
   226 int
   227 QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int *value)
   228 {
   229 
   230     GLenum attr = 0;
   231 
   232     QZ_GL_MakeCurrent (this);
   233 
   234     switch (attrib) {
   235     case SDL_GL_RED_SIZE:
   236         attr = GL_RED_BITS;
   237         break;
   238     case SDL_GL_BLUE_SIZE:
   239         attr = GL_BLUE_BITS;
   240         break;
   241     case SDL_GL_GREEN_SIZE:
   242         attr = GL_GREEN_BITS;
   243         break;
   244     case SDL_GL_ALPHA_SIZE:
   245         attr = GL_ALPHA_BITS;
   246         break;
   247     case SDL_GL_DOUBLEBUFFER:
   248         attr = GL_DOUBLEBUFFER;
   249         break;
   250     case SDL_GL_DEPTH_SIZE:
   251         attr = GL_DEPTH_BITS;
   252         break;
   253     case SDL_GL_STENCIL_SIZE:
   254         attr = GL_STENCIL_BITS;
   255         break;
   256     case SDL_GL_ACCUM_RED_SIZE:
   257         attr = GL_ACCUM_RED_BITS;
   258         break;
   259     case SDL_GL_ACCUM_GREEN_SIZE:
   260         attr = GL_ACCUM_GREEN_BITS;
   261         break;
   262     case SDL_GL_ACCUM_BLUE_SIZE:
   263         attr = GL_ACCUM_BLUE_BITS;
   264         break;
   265     case SDL_GL_ACCUM_ALPHA_SIZE:
   266         attr = GL_ACCUM_ALPHA_BITS;
   267         break;
   268     case SDL_GL_STEREO:
   269         attr = GL_STEREO;
   270         break;
   271     case SDL_GL_MULTISAMPLEBUFFERS:
   272         attr = GL_SAMPLE_BUFFERS_ARB;
   273         break;
   274     case SDL_GL_MULTISAMPLESAMPLES:
   275         attr = GL_SAMPLES_ARB;
   276         break;
   277     case SDL_GL_BUFFER_SIZE:
   278         {
   279             GLint bits = 0;
   280             GLint component;
   281 
   282             /* there doesn't seem to be a single flag in OpenGL for this! */
   283             glGetIntegerv (GL_RED_BITS, &component);
   284             bits += component;
   285             glGetIntegerv (GL_GREEN_BITS, &component);
   286             bits += component;
   287             glGetIntegerv (GL_BLUE_BITS, &component);
   288             bits += component;
   289             glGetIntegerv (GL_ALPHA_BITS, &component);
   290             bits += component;
   291 
   292             *value = bits;
   293             return 0;
   294         }
   295     case SDL_GL_ACCELERATED_VISUAL:
   296         {
   297             long val;
   298             /* FIXME: How do we get this information here?
   299                [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0];
   300              */
   301             val = (this->gl_config.accelerated != 0);;
   302             *value = val;
   303             return 0;
   304         }
   305     case SDL_GL_SWAP_CONTROL:
   306         {
   307             long val;
   308           [gl_context getValues: &val forParameter:NSOpenGLCPSwapInterval];
   309             *value = val;
   310             return 0;
   311         }
   312     }
   313 
   314     glGetIntegerv (attr, (GLint *) value);
   315     return 0;
   316 }
   317 
   318 int
   319 QZ_GL_MakeCurrent (_THIS)
   320 {
   321     [gl_context makeCurrentContext];
   322     return 0;
   323 }
   324 
   325 void
   326 QZ_GL_SwapBuffers (_THIS)
   327 {
   328     [gl_context flushBuffer];
   329 }