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