• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@end
51
52/* OpenGL helper functions (used internally) */
53
54int 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
178void QZ_TearDownOpenGL (_THIS) {
179
180    [ NSOpenGLContext clearCurrentContext ];
181    [ gl_context clearDrawable ];
182    [ gl_context release ];
183}
184
185
186/* SDL OpenGL functions */
187static const char *DEFAULT_OPENGL_LIB_NAME =
188    "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib";
189
190int    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
212void*  QZ_GL_GetProcAddress (_THIS, const char *proc) {
213    return SDL_LoadFunction(opengl_library, proc);
214}
215
216int    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
274int    QZ_GL_MakeCurrent    (_THIS) {
275    [ gl_context makeCurrentContext ];
276    return 0;
277}
278
279void   QZ_GL_SwapBuffers    (_THIS) {
280    [ gl_context flushBuffer ];
281}
282