comparison src/video/cocoa/SDL_cocoaopengl.m @ 1936:83946ee0ff1f

Implemented OpenGL support on Mac OS X The OpenGL renderer works without changes, yay! :)
author Sam Lantinga <slouken@libsdl.org>
date Tue, 25 Jul 2006 06:22:42 +0000
parents
children 420716272158
comparison
equal deleted inserted replaced
1935:8a9b367a80f3 1936:83946ee0ff1f
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include "SDL_cocoavideo.h"
25
26 /* NSOpenGL implementation of SDL OpenGL support */
27
28 #if SDL_VIDEO_OPENGL
29 #include <OpenGL/CGLTypes.h>
30
31 #include "SDL_loadso.h"
32 #include "SDL_opengl.h"
33
34
35 #define DEFAULT_OPENGL_PATH "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
36
37 /* This is implemented in Mac OS X 10.3 and above */
38 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3
39 @implementation NSOpenGLContext(CGLContextAccess)
40 - (CGLContextObj)CGLContextObj;
41 {
42 return _contextAuxiliary;
43 }
44 @end
45 #endif /* < 10.3 */
46
47 int
48 Cocoa_GL_LoadLibrary(_THIS, const char *path)
49 {
50 if (_this->gl_config.driver_loaded) {
51 if (path) {
52 SDL_SetError("OpenGL library already loaded");
53 return -1;
54 } else {
55 ++_this->gl_config.driver_loaded;
56 return 0;
57 }
58 }
59 if (path == NULL) {
60 path = DEFAULT_OPENGL_PATH;
61 }
62 _this->gl_config.dll_handle = SDL_LoadObject(path);
63 if (!_this->gl_config.dll_handle) {
64 return -1;
65 }
66 SDL_strlcpy(_this->gl_config.driver_path, path,
67 SDL_arraysize(_this->gl_config.driver_path));
68 _this->gl_config.driver_loaded = 1;
69 return 0;
70 }
71
72 void *
73 Cocoa_GL_GetProcAddress(_THIS, const char *proc)
74 {
75 return SDL_LoadFunction(_this->gl_config.dll_handle, proc);
76 }
77
78 static void
79 Cocoa_GL_UnloadLibrary(_THIS)
80 {
81 if (_this->gl_config.driver_loaded > 0) {
82 if (--_this->gl_config.driver_loaded > 0) {
83 return;
84 }
85 SDL_UnloadObject(_this->gl_config.dll_handle);
86 _this->gl_config.dll_handle = NULL;
87 }
88 }
89
90 static void
91 Cocoa_GL_Shutdown(_THIS)
92 {
93 if (!_this->gl_data || (--_this->gl_data->initialized > 0)) {
94 return;
95 }
96
97 Cocoa_GL_UnloadLibrary(_this);
98
99 SDL_free(_this->gl_data);
100 _this->gl_data = NULL;
101 }
102
103 static int
104 Cocoa_GL_Initialize(_THIS)
105 {
106 if (_this->gl_data) {
107 ++_this->gl_data->initialized;
108 return 0;
109 }
110
111 _this->gl_data =
112 (struct SDL_GLDriverData *) SDL_calloc(1,
113 sizeof(struct
114 SDL_GLDriverData));
115 if (!_this->gl_data) {
116 SDL_OutOfMemory();
117 return -1;
118 }
119 _this->gl_data->initialized = 1;
120
121 if (Cocoa_GL_LoadLibrary(_this, NULL) < 0) {
122 return -1;
123 }
124 return 0;
125 }
126
127 int
128 Cocoa_GL_SetupWindow(_THIS, SDL_Window * window)
129 {
130 if (Cocoa_GL_Initialize(_this) < 0) {
131 return -1;
132 }
133 return 0;
134 }
135
136 void
137 Cocoa_GL_CleanupWindow(_THIS, SDL_Window * window)
138 {
139 Cocoa_GL_Shutdown(_this);
140 }
141
142 SDL_GLContext
143 Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
144 {
145 NSAutoreleasePool *pool;
146 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
147 SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
148 NSOpenGLPixelFormatAttribute attr[32];
149 NSOpenGLPixelFormat *fmt;
150 NSOpenGLContext *nscontext;
151 int i = 0;
152
153 pool = [[NSAutoreleasePool alloc] init];
154
155 if (window->flags & SDL_WINDOW_FULLSCREEN) {
156 attr[i++] = NSOpenGLPFAFullScreen;
157 }
158
159 attr[i++] = NSOpenGLPFAColorSize;
160 attr[i++] = SDL_BYTESPERPIXEL(display->current_mode.format)*8;
161
162 attr[i++] = NSOpenGLPFADepthSize;
163 attr[i++] = _this->gl_config.depth_size;
164
165 if (_this->gl_config.double_buffer) {
166 attr[i++] = NSOpenGLPFADoubleBuffer;
167 }
168
169 if (_this->gl_config.stereo) {
170 attr[i++] = NSOpenGLPFAStereo;
171 }
172
173 if (_this->gl_config.stencil_size) {
174 attr[i++] = NSOpenGLPFAStencilSize;
175 attr[i++] = _this->gl_config.stencil_size;
176 }
177
178 if ((_this->gl_config.accum_red_size +
179 _this->gl_config.accum_green_size +
180 _this->gl_config.accum_blue_size +
181 _this->gl_config.accum_alpha_size) > 0) {
182 attr[i++] = NSOpenGLPFAAccumSize;
183 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;
184 }
185
186 if (_this->gl_config.multisamplebuffers) {
187 attr[i++] = NSOpenGLPFASampleBuffers;
188 attr[i++] = _this->gl_config.multisamplebuffers;
189 }
190
191 if (_this->gl_config.multisamplesamples) {
192 attr[i++] = NSOpenGLPFASamples;
193 attr[i++] = _this->gl_config.multisamplesamples;
194 attr[i++] = NSOpenGLPFANoRecovery;
195 }
196
197 if (_this->gl_config.accelerated > 0) {
198 attr[i++] = NSOpenGLPFAAccelerated;
199 }
200
201 attr[i++] = NSOpenGLPFAScreenMask;
202 attr[i++] = CGDisplayIDToOpenGLDisplayMask(displaydata->display);
203 attr[i] = 0;
204
205 fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
206 if (fmt == nil) {
207 SDL_SetError ("Failed creating OpenGL pixel format");
208 [pool release];
209 return NULL;
210 }
211
212 nscontext = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
213
214 [fmt release];
215
216 if (nscontext == nil) {
217 SDL_SetError ("Failed creating OpenGL context");
218 [pool release];
219 return NULL;
220 }
221
222 /*
223 * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
224 * "You are blowing a couple of the internal OpenGL function caches. This
225 * appears to be happening in the VAO case. You can tell OpenGL to up
226 * the cache size by issuing the following calls right after you create
227 * the OpenGL context. The default cache size is 16." --ryan.
228 */
229
230 #ifndef GLI_ARRAY_FUNC_CACHE_MAX
231 #define GLI_ARRAY_FUNC_CACHE_MAX 284
232 #endif
233
234 #ifndef GLI_SUBMIT_FUNC_CACHE_MAX
235 #define GLI_SUBMIT_FUNC_CACHE_MAX 280
236 #endif
237
238 {
239 long cache_max = 64;
240 CGLContextObj ctx = [nscontext CGLContextObj];
241 CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max);
242 CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max);
243 }
244
245 /* End Wisdom from Apple Engineer section. --ryan. */
246
247 /* FIXME: should this go somewhere else? */
248 if (window->flags & SDL_WINDOW_FULLSCREEN) {
249 [nscontext setFullScreen];
250 }
251
252 [pool release];
253 return nscontext;
254 }
255
256 int
257 Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
258 {
259 NSAutoreleasePool *pool;
260
261 pool = [[NSAutoreleasePool alloc] init];
262
263 if (context) {
264 SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata;
265 NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
266
267 [nscontext setView:[windowdata->window contentView]];
268 [nscontext makeCurrentContext];
269 } else {
270 [NSOpenGLContext clearCurrentContext];
271 }
272
273 [pool release];
274 return 0;
275 }
276
277 int
278 Cocoa_GL_SetSwapInterval(_THIS, int interval)
279 {
280 NSAutoreleasePool *pool;
281 NSOpenGLContext *nscontext;
282 long value;
283 int status;
284
285 pool = [[NSAutoreleasePool alloc] init];
286
287 nscontext = [NSOpenGLContext currentContext];
288 if (nscontext != nil) {
289 value = interval;
290 [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
291 status = 0;
292 } else {
293 SDL_SetError("No current OpenGL context");
294 status = -1;
295 }
296
297 [pool release];
298 return status;
299 }
300
301 int
302 Cocoa_GL_GetSwapInterval(_THIS)
303 {
304 NSAutoreleasePool *pool;
305 NSOpenGLContext *nscontext;
306 long value;
307 int status;
308
309 pool = [[NSAutoreleasePool alloc] init];
310
311 nscontext = [NSOpenGLContext currentContext];
312 if (nscontext != nil) {
313 [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
314 status = (int)value;
315 } else {
316 SDL_SetError("No current OpenGL context");
317 status = -1;
318 }
319
320 [pool release];
321 return status;
322 }
323
324 void
325 Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
326 {
327 NSAutoreleasePool *pool;
328 NSOpenGLContext *nscontext;
329
330 pool = [[NSAutoreleasePool alloc] init];
331
332 /* FIXME: Do we need to get the context for the window? */
333 nscontext = [NSOpenGLContext currentContext];
334 if (nscontext != nil) {
335 [nscontext flushBuffer];
336 }
337
338 [pool release];
339 }
340
341 void
342 Cocoa_GL_DeleteContext(_THIS, SDL_GLContext context)
343 {
344 NSAutoreleasePool *pool;
345 NSOpenGLContext *nscontext = (NSOpenGLContext *)context;
346
347 pool = [[NSAutoreleasePool alloc] init];
348
349 [nscontext clearDrawable];
350 [nscontext release];
351
352 [pool release];
353 }
354
355 #endif /* SDL_VIDEO_OPENGL */
356
357 /* vi: set ts=4 sw=4 expandtab: */