src/video/quartz/SDL_QuartzGL.m
author Sam Lantinga
Sun, 04 Jan 2004 14:55:35 +0000
changeset 761 c5b2b6d2d1fe
child 770 ac44ddb84f6f
permissions -rw-r--r--
Date: Wed, 31 Dec 2003 21:55:30 +0100
From: Max Horn
Subject: SDL: video/quartz cleanup

while doing some experimental changes in the quartz code, I was annoyed
by having to recompile that one big .o file over and over again. So I
decided to finally realize one TODO: properly splitting the code over
multiple files :-).

With two exceptions, I didn't make code changes, only rearranged files
and added new headers. Since there are several new files, making a
patch didn't work out so well, so I decided to just send you all the
new & modified files.

The one source change I made is related to showing/hiding the mouse. I
renamed cursor_visible to cursor_should_be_visible and cursor_hidden to
cursor_visible; I think that makes reading the code easier.
Then I added two new functions: QZ_ShowMouse and QZ_HideMouse. They
help manage cursor_visible (the former 'cursor_hidden'). Finally I
replaced the Carbon ShowCursor/HiderCuror calls by [NSCursor hide] and
[NSCursor unhide]. The API docs are not conclusive, but it might be
that with those the "cursor_visible" (former 'cursor_hidden') hack may
not be necessary anymore; however so far I didn't test this hypothesis,
so I left that in.

The other change was to remove in_foreground and use [NSApp isActive]
instead: Manually keeping track of whether we are in the foreground is
error prone. This should work better in some corner cases.
     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     This is a workaround to directly access NSOpenGLContext's CGL context
    27     We need this to check for errors NSOpenGLContext doesn't support
    28 */
    29 @interface NSOpenGLContext (CGLContextAccess)
    30 - (CGLContextObj) cglContext;
    31 @end
    32 
    33 @implementation NSOpenGLContext (CGLContextAccess)
    34 - (CGLContextObj) cglContext;
    35 {
    36     return _contextAuxiliary;
    37 }
    38 @end
    39 
    40 /* OpenGL helper functions (used internally) */
    41 
    42 int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
    43 
    44     NSOpenGLPixelFormatAttribute attr[32];
    45     NSOpenGLPixelFormat *fmt;
    46     int i = 0;
    47     int colorBits = bpp;
    48 
    49     if ( flags & SDL_FULLSCREEN ) {
    50 
    51         attr[i++] = NSOpenGLPFAFullScreen;
    52     }
    53     /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
    54     else if ( colorBits != device_bpp ) {
    55 
    56         colorBits = device_bpp;
    57     }
    58 
    59     attr[i++] = NSOpenGLPFAColorSize;
    60     attr[i++] = colorBits;
    61 
    62     attr[i++] = NSOpenGLPFADepthSize;
    63     attr[i++] = this->gl_config.depth_size;
    64 
    65     if ( this->gl_config.double_buffer ) {
    66         attr[i++] = NSOpenGLPFADoubleBuffer;
    67     }
    68 
    69     if ( this->gl_config.stereo ) {
    70         attr[i++] = NSOpenGLPFAStereo;
    71     }
    72 
    73     if ( this->gl_config.stencil_size != 0 ) {
    74         attr[i++] = NSOpenGLPFAStencilSize;
    75         attr[i++] = this->gl_config.stencil_size;
    76     }
    77 
    78 #if NSOPENGL_CURRENT_VERSION > 1  /* What version should this be? */
    79     if ( this->gl_config.multisamplebuffers != 0 ) {
    80         attr[i++] = NSOpenGLPFASampleBuffers;
    81         attr[i++] = this->gl_config.multisamplebuffers;
    82     }
    83 
    84     if ( this->gl_config.multisamplesamples != 0 ) {
    85         attr[i++] = NSOpenGLPFASamples;
    86         attr[i++] = this->gl_config.multisamplesamples;
    87     }
    88 #endif
    89 
    90     attr[i++] = NSOpenGLPFAScreenMask;
    91     attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
    92     attr[i] = 0;
    93 
    94     fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
    95     if (fmt == nil) {
    96         SDL_SetError ("Failed creating OpenGL pixel format");
    97         return 0;
    98     }
    99 
   100     gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
   101                                                shareContext:nil];
   102 
   103     if (gl_context == nil) {
   104         SDL_SetError ("Failed creating OpenGL context");
   105         return 0;
   106     }
   107 
   108     /*
   109      * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
   110      *  "You are blowing a couple of the internal OpenGL function caches. This
   111      *  appears to be happening in the VAO case.  You can tell OpenGL to up
   112      *  the cache size by issuing the following calls right after you create
   113      *  the OpenGL context.  The default cache size is 16."    --ryan.
   114      */
   115 
   116     #ifndef GLI_ARRAY_FUNC_CACHE_MAX
   117     #define GLI_ARRAY_FUNC_CACHE_MAX 284
   118     #endif
   119 
   120     #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
   121     #define GLI_SUBMIT_FUNC_CACHE_MAX 280
   122     #endif
   123 
   124     {
   125         long cache_max = 64;
   126         CGLContextObj ctx = [ gl_context cglContext ];
   127         CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
   128         CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
   129     }
   130 
   131     /* End Wisdom from Apple Engineer section. --ryan. */
   132 
   133     /* Convince SDL that the GL "driver" is loaded */
   134     this->gl_config.driver_loaded = 1;
   135 
   136     [ fmt release ];
   137 
   138     return 1;
   139 }
   140 
   141 void QZ_TearDownOpenGL (_THIS) {
   142 
   143     [ NSOpenGLContext clearCurrentContext ];
   144     [ gl_context clearDrawable ];
   145     [ gl_context release ];
   146 }
   147 
   148 
   149 /* SDL OpenGL functions */
   150 
   151 int    QZ_GL_LoadLibrary    (_THIS, const char *location) {
   152     this->gl_config.driver_loaded = 1;
   153     return 1;
   154 }
   155 
   156 void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
   157 
   158     /* We may want to cache the bundleRef at some point */
   159     CFBundleRef bundle;
   160     CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
   161                                                         CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
   162 
   163     CFStringRef functionName = CFStringCreateWithCString
   164         (kCFAllocatorDefault, proc, kCFStringEncodingASCII);
   165 
   166     void *function;
   167 
   168     bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
   169     assert (bundle != NULL);
   170 
   171     function = CFBundleGetFunctionPointerForName (bundle, functionName);
   172 
   173     CFRelease ( bundleURL );
   174     CFRelease ( functionName );
   175     CFRelease ( bundle );
   176 
   177     return function;
   178 }
   179 
   180 int    QZ_GL_GetAttribute   (_THIS, SDL_GLattr attrib, int* value) {
   181 
   182     GLenum attr = 0;
   183 
   184     QZ_GL_MakeCurrent (this);
   185 
   186     switch (attrib) {
   187         case SDL_GL_RED_SIZE: attr = GL_RED_BITS;   break;
   188         case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS;  break;
   189         case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break;
   190         case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break;
   191         case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break;
   192         case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS;  break;
   193         case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break;
   194         case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break;
   195         case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break;
   196         case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break;
   197         case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break;
   198         case SDL_GL_STEREO: attr = GL_STEREO; break;
   199         case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break;
   200         case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break;
   201         case SDL_GL_BUFFER_SIZE:
   202         {
   203             GLint bits = 0;
   204             GLint component;
   205 
   206             /* there doesn't seem to be a single flag in OpenGL for this! */
   207             glGetIntegerv (GL_RED_BITS, &component);   bits += component;
   208             glGetIntegerv (GL_GREEN_BITS,&component);  bits += component;
   209             glGetIntegerv (GL_BLUE_BITS, &component);  bits += component;
   210             glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
   211 
   212             *value = bits;
   213         }
   214         return 0;
   215     }
   216 
   217     glGetIntegerv (attr, (GLint *)value);
   218     return 0;
   219 }
   220 
   221 int    QZ_GL_MakeCurrent    (_THIS) {
   222     [ gl_context makeCurrentContext ];
   223     return 0;
   224 }
   225 
   226 void   QZ_GL_SwapBuffers    (_THIS) {
   227     [ gl_context flushBuffer ];
   228 }