Mercurial > sdl-ios-xcode
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: */ |