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