comparison src/video/quartz/SDL_QuartzVideo.m @ 47:45b1c4303f87

Added initial support for Quartz video (thanks Darrell!)
author Sam Lantinga <slouken@lokigames.com>
date Thu, 07 Jun 2001 14:28:11 +0000
parents
children ce9cd2cf0d0d
comparison
equal deleted inserted replaced
46:3dcf26fa9d15 47:45b1c4303f87
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com
21 */
22
23 #include "SDL_QuartzVideo.h"
24
25 /* Some variables to share among files, put in device structure eventually */
26 static SDL_GrabMode currentGrabMode = SDL_GRAB_OFF;
27 static BOOL inForeground = YES;
28 static SDLKey keymap[256];
29 static unsigned int currentMods = 0; /* Current keyboard modifiers, to track modifier state */
30
31 /* Include files into one compile unit...break apart eventually */
32 #include "SDL_QuartzWM.m"
33 #include "SDL_QuartzEvents.m"
34 #include "SDL_QuartzWindow.m"
35
36 char QZ_Error[255]; /* Global error buffer to temporarily store more informative error messages */
37
38 /* Bootstrap binding, enables entry point into the driver */
39 VideoBootStrap QZ_bootstrap = {
40 "Quartz", "MacOS X CoreGraphics", QZ_Available, QZ_CreateDevice
41 };
42
43 /* Bootstrap functions */
44 static int QZ_Available () {
45 return 1;
46 }
47
48 static SDL_VideoDevice* QZ_CreateDevice (int device_index) {
49
50 #pragma unused (device_index)
51
52 SDL_VideoDevice *device;
53 SDL_PrivateVideoData *hidden;
54
55 device = (SDL_VideoDevice*) malloc (sizeof (*device) );
56 hidden = (SDL_PrivateVideoData*) malloc (sizeof (*hidden) );
57
58 if (device == NULL || hidden == NULL)
59 SDL_OutOfMemory ();
60
61 memset (device, 0, sizeof (*device) );
62 memset (hidden, 0, sizeof (*hidden) );
63
64 device->hidden = hidden;
65
66 device->VideoInit = QZ_VideoInit;
67 device->ListModes = QZ_ListModes;
68 device->SetVideoMode = QZ_SetVideoMode;
69 device->ToggleFullScreen = QZ_ToggleFullScreen;
70 device->SetColors = QZ_SetColors;
71 /* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */
72 device->VideoQuit = QZ_VideoQuit;
73
74 device->LockHWSurface = QZ_LockHWSurface;
75 device->UnlockHWSurface = QZ_UnlockHWSurface;
76 device->FreeHWSurface = QZ_FreeHWSurface;
77 /* device->FlipHWSurface = QZ_FlipHWSurface */;
78
79 device->SetGamma = QZ_SetGamma;
80 device->GetGamma = QZ_GetGamma;
81 device->SetGammaRamp = QZ_SetGammaRamp;
82 device->GetGammaRamp = QZ_GetGammaRamp;
83
84 device->GL_GetProcAddress = QZ_GL_GetProcAddress;
85 device->GL_GetAttribute = QZ_GL_GetAttribute;
86 device->GL_MakeCurrent = QZ_GL_MakeCurrent;
87 device->GL_SwapBuffers = QZ_GL_SwapBuffers;
88 device->GL_LoadLibrary = QZ_GL_LoadLibrary;
89
90 device->FreeWMCursor = QZ_FreeWMCursor;
91 device->CreateWMCursor = QZ_CreateWMCursor;
92 device->ShowWMCursor = QZ_ShowWMCursor;
93 device->WarpWMCursor = QZ_WarpWMCursor;
94 device->MoveWMCursor = QZ_MoveWMCursor;
95 device->CheckMouseMode = QZ_CheckMouseMode;
96 device->InitOSKeymap = QZ_InitOSKeymap;
97 device->PumpEvents = QZ_PumpEvents;
98
99 device->SetCaption = QZ_SetCaption;
100 device->SetIcon = QZ_SetIcon;
101 device->IconifyWindow = QZ_IconifyWindow;
102 /*device->GetWMInfo = QZ_GetWMInfo;*/
103 device->GrabInput = QZ_GrabInput;
104
105 device->free = QZ_DeleteDevice;
106
107 return device;
108 }
109
110 static void QZ_DeleteDevice (SDL_VideoDevice *device) {
111
112 free (device->hidden);
113 free (device);
114 }
115
116 static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) {
117
118 /* Initialize the video settings; this data persists between mode switches */
119 display_id = kCGDirectMainDisplay;
120 save_mode = CGDisplayCurrentMode (display_id);
121 mode_list = CGDisplayAvailableModes (display_id);
122 palette = CGPaletteCreateDefaultColorPalette ();
123
124 /* Gather some information that is useful to know about the display */
125 CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayBitsPerPixel),
126 kCFNumberSInt32Type, &device_bpp);
127
128 CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayWidth),
129 kCFNumberSInt32Type, &device_width);
130
131 CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayHeight),
132 kCFNumberSInt32Type, &device_height);
133
134 video_format->BitsPerPixel = device_bpp;
135 windowTitle = @"";
136
137 return 0;
138 }
139
140 static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) {
141
142 CFIndex num_modes = CFArrayGetCount (mode_list);
143 CFIndex i;
144
145 static SDL_Rect **list = NULL;
146 int list_size = 0;
147
148 /* Any windowed mode is acceptable */
149 if ( (flags & SDL_FULLSCREEN) == 0 )
150 return (SDL_Rect**)-1;
151
152 /* Free memory from previous call, if any */
153 if ( list != NULL ) {
154
155 int i = 0;
156
157 for (i = 0; list[i] != NULL; i++)
158 free (list[i]);
159
160 free (list);
161 list = NULL;
162 }
163
164 /* Build list of modes with the requested bpp */
165 for (i = num_modes-1; i >= 0; i--) {
166
167 CFDictionaryRef onemode = CFArrayGetValueAtIndex (mode_list, i);
168 CFNumberRef number;
169 int bpp;
170
171 number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel);
172 CFNumberGetValue (number, kCFNumberSInt32Type, &bpp);
173
174 if (bpp == format->BitsPerPixel) {
175
176 int intvalue;
177 SDL_Rect *rect;
178 int lastwidth = 0, lastheight = 0, width, height;
179
180 number = CFDictionaryGetValue (onemode, kCGDisplayWidth);
181 CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue);
182 width = (Uint16) intvalue;
183
184 number = CFDictionaryGetValue (onemode, kCGDisplayHeight);
185 CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue);
186 height = (Uint16) intvalue;
187
188 /* We'll get a lot of modes with the same size, so ignore them */
189 if ( width != lastwidth && height != lastheight ) {
190
191 lastwidth = width;
192 lastheight = height;
193
194 list_size++;
195
196 if ( list == NULL)
197 list = (SDL_Rect**) malloc (sizeof(*list) * list_size+1);
198 else
199 list = (SDL_Rect**) realloc (list, sizeof(*list) * list_size+1);
200
201 rect = (SDL_Rect*) malloc (sizeof(**list));
202
203 if (list == NULL || rect == NULL)
204 SDL_OutOfMemory ();
205
206 rect->w = width;
207 rect->h = height;
208
209 list[list_size-1] = rect;
210 list[list_size] = NULL;
211 }
212 }
213 }
214
215 return list;
216 }
217
218 static void QZ_UnsetVideoMode (_THIS) {
219
220 if ( mode_flags & SDL_OPENGL )
221 QZ_TearDownOpenGL (this);
222
223 /* Reset values that may change between switches */
224 this->info.blit_fill = 0;
225 this->FillHWRect = NULL;
226 this->UpdateRects = NULL;
227
228 /* Restore gamma settings */
229 CGDisplayRestoreColorSyncSettings ();
230
231 /* Restore original screen resolution */
232 if ( mode_flags & SDL_FULLSCREEN ) {
233 CGDisplaySwitchToMode (display_id, save_mode);
234 CGDisplayRelease (display_id);
235 }
236 /* Release window mode data structures */
237 else {
238 if ( (mode_flags & SDL_OPENGL) == 0 ) {
239 UnlockPortBits ( [ windowView qdPort ] );
240 [ windowView release ];
241 }
242 [ window setContentView:nil ];
243 [ window close ];
244 [ window release ];
245 }
246
247 /* Ensure the cursor will be visible and working when we quit */
248 CGDisplayShowCursor (display_id);
249 CGAssociateMouseAndMouseCursorPosition (1);
250 }
251
252 static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width,
253 int height, int bpp, Uint32 flags) {
254 int exact_match;
255
256 /* See if requested mode exists */
257 mode = CGDisplayBestModeForParameters (display_id, bpp, width,
258 height, &exact_match);
259
260 /* Require an exact match to the requested mode */
261 if ( ! exact_match ) {
262 sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp);
263 SDL_SetError (QZ_Error);
264 goto ERR_NO_MATCH;
265 }
266
267 /* Put up the blanking window (a window above all other windows) */
268 if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) {
269 SDL_SetError ("Failed capturing display");
270 goto ERR_NO_CAPTURE;
271 }
272
273 /* Do the physical switch */
274 if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) {
275 SDL_SetError ("Failed switching display resolution");
276 goto ERR_NO_SWITCH;
277 }
278
279 /* None of these methods seem to fix the fullscreen artifacts bug(s) */
280 #if USE_GDHANDLE
281 SetGDevice(GetMainDevice());
282 current->pitch = (**(** GetMainDevice() ).gdPMap).rowBytes & 0x3FFF;
283 current->pixels = (**(** GetMainDevice() ).gdPMap).baseAddr;
284 #elif USE_CREATEPORT
285 device_port = CreateNewPortForCGDisplayID((Uint32*)display_id);
286 SetPort (device_port);
287 LockPortBits ( device_port );
288 current->pixels = GetPixBaseAddr ( GetPortPixMap ( device_port ) );
289 current->pitch = GetPixRowBytes ( GetPortPixMap ( device_port ) );
290 UnlockPortBits ( device_port );
291 #else
292 current->pixels = (Uint32*) CGDisplayBaseAddress (display_id);
293 current->pitch = CGDisplayBytesPerRow (display_id);
294 #endif
295
296 current->w = width;
297 current->h = height;
298 current->flags |= SDL_FULLSCREEN;
299 current->flags |= SDL_HWSURFACE;
300
301 this->UpdateRects = QZ_DirectUpdate;
302
303 /* Setup some mode-dependant info */
304 if ( CGSDisplayCanHWFill (display_id) ) {
305 this->info.blit_fill = 1;
306 this->FillHWRect = QZ_FillHWRect;
307 }
308
309 if ( CGDisplayCanSetPalette (display_id) )
310 current->flags |= SDL_HWPALETTE;
311
312 /* Setup OpenGL for a fullscreen context */
313 if (flags & SDL_OPENGL) {
314
315 CGLError err;
316 CGLContextObj ctx;
317
318 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
319 return NULL;
320 }
321
322 ctx = [ gl_context cglContext ];
323 err = CGLSetFullScreen (ctx);
324
325 if (err) {
326 sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err));
327 SDL_SetError (QZ_Error);
328 goto ERR_NO_GL;
329 }
330
331 [ gl_context makeCurrentContext];
332
333 current->flags |= SDL_OPENGL;
334 }
335
336 /* If we don't hide menu bar, it will get events and interrupt the program */
337 HideMenuBar ();
338
339 /* Save the flags to ensure correct tear-down */
340 mode_flags = current->flags;
341
342 return current;
343
344 /* Since the blanking window covers *all* windows (even force quit) correct recovery is crutial */
345 ERR_NO_GL: CGDisplaySwitchToMode (display_id, save_mode);
346 ERR_NO_SWITCH: CGDisplayRelease (display_id);
347 ERR_NO_CAPTURE:
348 ERR_NO_MATCH: return NULL;
349 }
350
351 static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
352 int height, int bpp, Uint32 flags) {
353 NSRect rect;
354 rect = NSMakeRect (0, 0, width, height);
355
356 /* Manually create a window, avoids having a nib file resource */
357 window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect
358 styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask)
359 backing: //NSBackingStoreBuffered
360 NSBackingStoreRetained
361 defer:NO ];
362
363 if (window == nil) {
364 SDL_SetError ("Could not create the Cocoa window");
365 return NULL;
366 }
367
368 current->w = width;
369 current->h = height;
370
371 [ window setTitle:windowTitle ];
372 [ window setAcceptsMouseMovedEvents:YES ];
373 [ window center ];
374
375 /* For OpenGL, we set the content view to a NSOpenGLView */
376 if ( flags & SDL_OPENGL ) {
377
378 if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
379 return NULL;
380 }
381
382 [ gl_context setView: [ window contentView ] ];
383 [ gl_context makeCurrentContext];
384 [ window orderFront:nil ];
385 current->flags |= SDL_OPENGL;
386 }
387 /* For 2D, we set the content view to a NSQuickDrawView */
388 else {
389
390 windowView = [ [ NSQuickDrawView alloc ] init ];
391 [ window setContentView:windowView ];
392 [ window orderFront:nil ];
393
394 LockPortBits ( [ windowView qdPort ] );
395 current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ windowView qdPort ] ) );
396 current->pitch = GetPixRowBytes ( GetPortPixMap ( [ windowView qdPort ] ) );
397
398 /* Offset 22 pixels down to fill the full content region */
399 current->pixels += 22 * current->pitch;
400
401 current->flags |= SDL_SWSURFACE;
402 current->flags |= SDL_PREALLOC;
403
404 this->UpdateRects = QZ_UpdateRects;
405 }
406 return current;
407 }
408
409 static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width,
410 int height, int bpp, Uint32 flags) {
411
412 if (SDL_VideoSurface != NULL)
413 QZ_UnsetVideoMode (this);
414
415 current->flags = 0;
416
417 /* Setup full screen video */
418 if ( flags & SDL_FULLSCREEN ) {
419 current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags );
420 if (current == NULL)
421 return NULL;
422 }
423 /* Setup windowed video */
424 else {
425 /* Force bpp to the device's bpp */
426 bpp = current->format->BitsPerPixel;
427 current = QZ_SetVideoWindowed (this, current, width, height, bpp, flags);
428 if (current == NULL)
429 return NULL;
430 }
431
432 /* Setup the new pixel format */
433 {
434 int amask = 0,
435 rmask = 0,
436 gmask = 0,
437 bmask = 0;
438
439 switch (bpp) {
440 case 16: /* (1)-5-5-5 RGB */
441 amask = 0;
442 rmask = 0x7c00;
443 gmask = 0x3e0;
444 bmask = 0x1f;
445 break;
446 case 24:
447 SDL_SetError ("24bpp is not available");
448 return NULL;
449 case 32: /* (8)-8-8-8 ARGB */
450 amask = 0xFF000000;
451 rmask = 0x00FF0000;
452 gmask = 0x0000FF00;
453 bmask = 0x000000FF;
454 break;
455 }
456
457 if ( ! SDL_ReallocFormat (current, bpp,
458 rmask, gmask, bmask, amask ) ) {
459 SDL_SetError ("Couldn't reallocate pixel format");
460 return NULL;
461 }
462 }
463
464 /* Warp mouse to origin in order to get passive mouse motion events started correctly */
465 QZ_PrivateWarpCursor (this, current->flags & SDL_FULLSCREEN, height, 0, 0);
466
467 return current;
468 }
469
470 static int QZ_ToggleFullScreen (_THIS, int on) {
471 return -1;
472 }
473
474 static int QZ_SetColors (_THIS, int first_color, int num_colors,
475 SDL_Color *colors) {
476
477 CGTableCount index;
478 CGDeviceColor color;
479
480 for (index = first_color; index < first_color+num_colors; index++) {
481
482 /* Clamp colors between 0.0 and 1.0 */
483 color.red = colors->r / 255.0;
484 color.blue = colors->b / 255.0;
485 color.green = colors->g / 255.0;
486
487 colors++;
488
489 CGPaletteSetColorAtIndex (palette, color, index);
490 }
491
492 if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) )
493 return 0;
494
495 return 1;
496 }
497
498 static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) {
499 #pragma unused(this,num_rects,rects)
500 }
501
502 static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) {
503
504 if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
505 QZ_GL_SwapBuffers (this);
506 }
507 else {
508 int i;
509 RgnHandle dirty = NewRgn ();
510 RgnHandle temp = NewRgn ();
511
512 SetEmptyRgn (dirty);
513
514 /* Build the region of dirty rectangles */
515 for (i = 0; i < numRects; i++) {
516
517 MacSetRectRgn (temp, rects[i].x, rects[i].y,
518 rects[i].x + rects[i].w, rects[i].y + rects[i].h);
519 MacUnionRgn (dirty, temp, dirty);
520 }
521
522 /* Flush the dirty region */
523 QDFlushPortBuffer ( [ windowView qdPort ], dirty );
524 DisposeRgn (dirty);
525 DisposeRgn (temp);
526 }
527 }
528
529 static void QZ_VideoQuit (_THIS) {
530
531 QZ_UnsetVideoMode (this);
532 CGPaletteRelease (palette);
533 }
534
535 static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) {
536
537 CGSDisplayHWFill (display_id, rect->x, rect->y, rect->w, rect->h, color);
538 return 0;
539 }
540
541 static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) {
542
543 return 1;
544 }
545
546 static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) {
547 }
548
549 static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) {
550 }
551
552 /*
553 int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) {
554 return 0;
555 }
556 */
557
558 /* Gamma functions */
559 static int QZ_SetGamma (_THIS, float red, float green, float blue) {
560
561 const CGGammaValue min = 0.0, max = 1.0;
562
563 if ( CGDisplayNoErr != CGSetDisplayTransferByFormula
564 (display_id, min, max, red, min, max, green, min, max, blue) )
565 return -1;
566
567 return 0;
568 }
569
570 static int QZ_GetGamma (_THIS, float *red, float *green, float *blue) {
571
572 CGGammaValue dummy;
573 if ( CGDisplayNoErr != CGGetDisplayTransferByFormula
574 (display_id, &dummy, &dummy, red,
575 &dummy, &dummy, green, &dummy, &dummy, blue) )
576
577 return -1;
578
579 return 0;
580 }
581
582 static int QZ_SetGammaRamp (_THIS, Uint16 *ramp) {
583
584 const CGTableCount tableSize = 255;
585 CGGammaValue redTable[tableSize];
586 CGGammaValue greenTable[tableSize];
587 CGGammaValue blueTable[tableSize];
588
589 int i;
590
591 /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
592 for (i = 0; i < 256; i++)
593 redTable[i % 256] = ramp[i] / 65535.0;
594
595 for (i=256; i < 512; i++)
596 greenTable[i % 256] = ramp[i] / 65535.0;
597
598 for (i=512; i < 768; i++)
599 blueTable[i % 256] = ramp[i] / 65535.0;
600
601 if ( CGDisplayNoErr != CGSetDisplayTransferByTable
602 (display_id, tableSize, redTable, greenTable, blueTable) )
603 return -1;
604
605 return 0;
606 }
607
608 static int QZ_GetGammaRamp (_THIS, Uint16 *ramp) {
609
610 const CGTableCount tableSize = 255;
611 CGGammaValue redTable[tableSize];
612 CGGammaValue greenTable[tableSize];
613 CGGammaValue blueTable[tableSize];
614 CGTableCount actual;
615 int i;
616
617 if ( CGDisplayNoErr != CGGetDisplayTransferByTable
618 (display_id, tableSize, redTable, greenTable, blueTable, &actual) ||
619 actual != tableSize)
620
621 return -1;
622
623 /* Pack tables into one array, with values from 0 to 65535 */
624 for (i = 0; i < 256; i++)
625 ramp[i] = redTable[i % 256] * 65535.0;
626
627 for (i=256; i < 512; i++)
628 ramp[i] = greenTable[i % 256] * 65535.0;
629
630 for (i=512; i < 768; i++)
631 ramp[i] = blueTable[i % 256] * 65535.0;
632
633 return 0;
634 }
635
636 /* OpenGL helper functions */
637 static int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) {
638
639 NSOpenGLPixelFormatAttribute attr[32];
640 NSOpenGLPixelFormat *fmt;
641 int i = 0;
642 int colorBits = bpp;
643
644 if ( flags & SDL_FULLSCREEN ) {
645
646 attr[i++] = NSOpenGLPFAFullScreen;
647 }
648 /* In windowed mode, the OpenGL pixel depth must match device pixel depth */
649 else if ( colorBits != device_bpp ) {
650
651 colorBits = device_bpp;
652 }
653
654 attr[i++] = NSOpenGLPFAColorSize;
655 attr[i++] = colorBits;
656
657 attr[i++] = NSOpenGLPFADepthSize;
658 attr[i++] = this->gl_config.depth_size;
659
660 if ( this->gl_config.double_buffer ) {
661 attr[i++] = NSOpenGLPFADoubleBuffer;
662 }
663
664 if ( this->gl_config.stencil_size != 0 ) {
665 attr[i++] = NSOpenGLPFAStencilSize;
666 attr[i++] = this->gl_config.stencil_size;
667 }
668
669 attr[i++] = NSOpenGLPFAScreenMask;
670 attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
671 attr[i] = 0;
672
673 fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ];
674 if (fmt == nil) {
675 SDL_SetError ("Failed creating OpenGL pixel format");
676 return 0;
677 }
678
679 gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt
680 shareContext:nil];
681
682 if (gl_context == nil) {
683 SDL_SetError ("Failed creating OpenGL context");
684 return 0;
685 }
686
687 /* Convince SDL that the GL "driver" is loaded */
688 this->gl_config.driver_loaded = 1;
689
690 [ fmt release ];
691
692 return 1;
693 }
694
695 static void QZ_TearDownOpenGL (_THIS) {
696
697 [ NSOpenGLContext clearCurrentContext ];
698 [ gl_context clearDrawable ];
699 [ gl_context release ];
700 }
701
702 /* SDL OpenGL functions */
703
704 static int QZ_GL_LoadLibrary (_THIS, const char *location) {
705 return 1;
706 }
707
708 static void* QZ_GL_GetProcAddress (_THIS, const char *proc) {
709
710 /* We may want to cache the bundleRef at some point */
711 CFBundleRef bundle;
712 CFURLRef bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
713 CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
714
715 CFStringRef functionName = CFStringCreateWithCString
716 (kCFAllocatorDefault, proc, kCFStringEncodingASCII);
717
718 void *function;
719
720 bundle = CFBundleCreate (kCFAllocatorDefault, bundleURL);
721 assert (bundle != NULL);
722
723 function = CFBundleGetFunctionPointerForName (bundle, functionName);
724
725 CFRelease ( bundleURL );
726 CFRelease ( functionName );
727 CFRelease ( bundle );
728
729 return function;
730 }
731
732 static int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) {
733
734 /*
735 CGLContextRef ctx = [ gl_context cglContext ];
736 CGLContextParameter param;
737
738 switch (attrib) {
739 case SDL_GL_RED_SIZE: param = CGLContextParameter break;
740
741 }
742
743 CGLGetParameter (ctx, param, (long*)value);
744 */
745 *value = -1;
746 return -1;
747 }
748
749 static int QZ_GL_MakeCurrent (_THIS) {
750 [ gl_context makeCurrentContext ];
751 return 0;
752 }
753
754 static void QZ_GL_SwapBuffers (_THIS) {
755 [ gl_context flushBuffer ];
756 }