SDL-1.2.14
[sdl_omap.git] / src / video / macdsp / SDL_dspvideo.c
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 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/*
25 Written by Darrell Walisser <dwaliss1@purdue.edu>
26
27 Implementation notes ----------------------------------------------------------------------
28
29 A bit on GWorlds in VRAM from technote 1182:
30
31 There are two important things to note about GWorld's allocated in
32 VRAM. First, the base address retrieved through GetPixBaseAddr or
33 read directly from the PixMap structure can become invalid anytime
34 memory is allocated in VRAM. This can occur either by explicit
35 allocations, such as calls to NewGWorld, or by implicit ones, such as
36 those associated with the internal texture allocation of OpenGL. The
37 stored pixel images themselves will still be valid but may have been
38 moved in VRAM, thus rendering any stored base addresses invalid.
39 You should never store an image's base address for longer than is
40 necessary and especially never across calls to NewGWorld or
41 texture-creation routines.
42
43 Secondly, an offscreen pixel image allocated in VRAM can be
44 purged at system task time by the display driver. This means any
45 time your application yields time such by calling WaitNextEvent or
46 SystemTask you can lose your VRAM GWorld contents. While this
47 happens infrequently, usually associated with display resolution or
48 pixel depth changes you must code for this eventuality. This purge
49 can occur whether or not the GWorld is locked or not. A return value
50 of false from LockPixels, a NULL return value from GetPixBaseAddr
51 or NULL in the baseAddr field of the PixMap mean that the pixel
52 image has been purged. To reallocate it you can either call
53 UpdateGWorld or Dispose your current GWorld through
54 DisposeGWorld and reallocate it via NewGWorld. Either way you must
55 then rebuild the pixel image.
56
57------------------------------------------------------------------------------------
58
59 Currently, I don't account for (1). In my testing, NewGWorld never invalidated
60 other existing GWorlds in VRAM. However, I do have protection for (2).
61 Namely, I am using GetOSEvent() instead of WaitNextEvent() so that there are no
62 context switches (the app hogs the CPU). Eventually a book-keeping system should
63 be coded to take care of (1) and (2).
64
65------------------------------------------------------------------------------------
66
67 System requirements (* denotes optional):
68
69 1. DrawSprocket 1.7.3
70 2. *MacOS 9 or later (but *not* Mac OS X) for hardware accelerated blit / fill
71 3. *May also require certain graphics hardware for (2). I trust that all Apple OEM
72 hardware will work. Third party accelerators may work if they have QuickDraw
73 acceleration in the drivers and the drivers have been updated for OS 9. The current
74 Voodoo 3 drivers (1.0b12) do not work.
75
76 Coding suggestions:
77
78 1. Use SDL_UpdateRects !
79
80 If no QuickDraw acceleration is present, double-buffered surfaces will use a back buffer
81 in System memory. I recommend you use SDL_UpdateRects with double-buffered surfaces
82 for best performance on these cards, since the overhead is nearly zero for VRAM back buffer.
83
84 2. Load most-resident surfaces first.
85
86 If you fill up VRAM or AGP memory, there is no contingency for purging to make room for the next one.
87 Therefore, you should load the surfaces you plan to use the most frequently first.
88 Sooner or later, I will code LRU replacement to help this.
89
90 TODO:
91 Some kind of posterized mode for resolutions < 640x480.
92 Window support / fullscreen toggle.
93 Figure out how much VRAM is available. Put in video->info->video_mem.
94 Track VRAM usage.
95
96 BUGS:
97 I can't create a hardware surface the same size as the screen?! How to fix?
98
99
100
101 COMPILE OPTIONS:
102
103 DSP_TRY_CC_AND_AA - Define if you want to try HWA color-key and alpha blitters
104 HW color-key blitting gives substantial improvements,
105 but hw alpha is neck-and-neck with SDL's soft bitter.
106
107 DSP_NO_SYNC_VBL - Define for HWA double-buffered surfaces: don't sync
108 pseudo-flip to monitor redraw.
109
110 DSP_NO_SYNC_OPENGL - Define for OpenGL surfaces: don't sync buffer swap. Synching buffer
111 swap may result in reduced performance, but can eliminate some
112 tearing artifacts.
113 CHANGELOG:
114 09/17/00 Lots of little tweaks. Build modelist in reverse order so largest contexts
115 list first. Compared various methods with ROM methods and fixed rez switch
116 crashing bug in GL Tron. (Woohoo!)
117*/
118
119#define DSP_TRY_CC_AND_AA
120
121/* #define DSP_NO_SYNC_VBL */
122
123#define DSP_NO_SYNC_OPENGL
124
125
126#if defined(__APPLE__) && defined(__MACH__)
127#include <Carbon/Carbon.h>
128#include <DrawSprocket/DrawSprocket.h>
129#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
130#include <Carbon.h>
131#include <DrawSprocket.h>
132#else
133#include <LowMem.h>
134#include <Gestalt.h>
135#include <Devices.h>
136#include <DiskInit.h>
137#include <QDOffscreen.h>
138#include <DrawSprocket.h>
139#endif
140
141#include "SDL_video.h"
142#include "SDL_syswm.h"
143#include "../SDL_sysvideo.h"
144#include "../SDL_blit.h"
145#include "../SDL_pixels_c.h"
146#include "SDL_dspvideo.h"
147#include "../maccommon/SDL_macgl_c.h"
148#include "../maccommon/SDL_macwm_c.h"
149#include "../maccommon/SDL_macmouse_c.h"
150#include "../maccommon/SDL_macevents_c.h"
151
152/* Initialization/Query functions */
153static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat);
154static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
155static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
156static int DSp_SetColors(_THIS, int firstcolor, int ncolors,
157 SDL_Color *colors);
158static int DSp_CreatePalette(_THIS);
159static int DSp_DestroyPalette(_THIS);
160static void DSp_VideoQuit(_THIS);
161
162static int DSp_GetMainDevice (_THIS, GDHandle *device);
163static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat);
164static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);
165static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);
166
167/* Hardware surface functions */
168static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha);
169static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
170static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height);
171static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface);
172static int DSp_LockHWSurface(_THIS, SDL_Surface *surface);
173static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface);
174static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface);
175static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface);
176static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest);
177static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
178 SDL_Surface *dst, SDL_Rect *dstrect);
179static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
180
181#if SDL_VIDEO_OPENGL
182 static void DSp_GL_SwapBuffers (_THIS);
183#endif
184
185#if ! TARGET_API_MAC_CARBON
186
187 #define GetPortPixRowBytes(x) ( (*(x->portPixMap))->rowBytes )
188 #define GetGDevPixMap(x) ((**(x)).gdPMap)
189 #define GetPortPixMap(x) ((*(x)).portPixMap)
190
191 #define GetPixDepth(y) ((**(y)).pixelSize)
192 //#define GetPixRowBytes(y) ((**(y)).rowBytes)
193 //#define GetPixBaseAddr(y) ((**(y)).baseAddr)
194 #define GetPixCTab(y) ((**(y)).pmTable)
195 #define GetPortBitMapForCopyBits(x) (&(((GrafPtr)(x))->portBits))
196
197#else
198 #define GetPortPixRowBytes(x) (GetPixRowBytes(GetPortPixMap(x)) )
199 #define GetGDevPixMap(x) ((**(x)).gdPMap)
200
201#endif
202
203typedef struct private_hwdata {
204
205 GWorldPtr offscreen; // offscreen gworld in VRAM or AGP
206
207 #ifdef DSP_TRY_CC_AND_AA
208 GWorldPtr mask; // transparent mask
209 RGBColor alpha; // alpha color
210 RGBColor trans; // transparent color
211 #endif
212
213} private_hwdata;
214
215typedef private_hwdata private_swdata ; /* have same fields */
216
217/* Macintosh toolbox driver bootstrap functions */
218
219static int DSp_Available(void)
220{
221 /* Check for DrawSprocket */
222#if ! TARGET_API_MAC_OSX
223 /* This check is only meaningful if you weak-link DrawSprocketLib */
224 return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress);
225#else
226 return 1; // DrawSprocket.framework doesn't have it all, but it's there
227#endif
228}
229
230static void DSp_DeleteDevice(SDL_VideoDevice *device)
231{
232 /* -dw- taking no chances with null pointers */
233 if (device) {
234
235 if (device->hidden) {
236
237 if (device->hidden->dspinfo)
238 SDL_free(device->hidden->dspinfo);
239
240 SDL_free(device->hidden);
241 }
242 SDL_free(device);
243 }
244}
245
246static SDL_VideoDevice *DSp_CreateDevice(int devindex)
247{
248 SDL_VideoDevice *device;
249
250 /* Initialize all variables that we clean on shutdown */
251 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
252 if ( device ) {
253 SDL_memset(device, 0, sizeof (*device));
254 device->hidden = (struct SDL_PrivateVideoData *)
255 SDL_malloc((sizeof *device->hidden));
256 if (device->hidden)
257 SDL_memset(device->hidden, 0, sizeof ( *(device->hidden) ) );
258 }
259 if ( (device == NULL) || (device->hidden == NULL) ) {
260 SDL_OutOfMemory();
261
262 if ( device ) {
263
264 if (device->hidden)
265 SDL_free(device->hidden);
266
267 SDL_free(device);
268 }
269
270 return(NULL);
271 }
272
273 /* Allocate DrawSprocket information */
274 device->hidden->dspinfo = (struct DSpInfo *)SDL_malloc(
275 (sizeof *device->hidden->dspinfo));
276 if ( device->hidden->dspinfo == NULL ) {
277 SDL_OutOfMemory();
278 SDL_free(device->hidden);
279 SDL_free(device);
280 return(0);
281 }
282 SDL_memset(device->hidden->dspinfo, 0, (sizeof *device->hidden->dspinfo));
283
284 /* Set the function pointers */
285 device->VideoInit = DSp_VideoInit;
286 device->ListModes = DSp_ListModes;
287 device->SetVideoMode = DSp_SetVideoMode;
288 device->SetColors = DSp_SetColors;
289 device->UpdateRects = NULL;
290 device->VideoQuit = DSp_VideoQuit;
291 device->AllocHWSurface = DSp_AllocHWSurface;
292 device->CheckHWBlit = NULL;
293 device->FillHWRect = NULL;
294 device->SetHWColorKey = NULL;
295 device->SetHWAlpha = NULL;
296 device->LockHWSurface = DSp_LockHWSurface;
297 device->UnlockHWSurface = DSp_UnlockHWSurface;
298 device->FlipHWSurface = DSp_FlipHWSurface;
299 device->FreeHWSurface = DSp_FreeHWSurface;
300#if SDL_MACCLASSIC_GAMMA_SUPPORT
301 device->SetGammaRamp = Mac_SetGammaRamp;
302 device->GetGammaRamp = Mac_GetGammaRamp;
303#endif
304#if SDL_VIDEO_OPENGL
305 device->GL_MakeCurrent = Mac_GL_MakeCurrent;
306 device->GL_SwapBuffers = DSp_GL_SwapBuffers;
307 device->GL_LoadLibrary = Mac_GL_LoadLibrary;
308 device->GL_GetProcAddress = Mac_GL_GetProcAddress;
309#endif
310 device->SetCaption = NULL;
311 device->SetIcon = NULL;
312 device->IconifyWindow = NULL;
313 device->GrabInput = NULL;
314 device->GetWMInfo = NULL;
315 device->FreeWMCursor = Mac_FreeWMCursor;
316 device->CreateWMCursor = Mac_CreateWMCursor;
317 device->ShowWMCursor = Mac_ShowWMCursor;
318 device->WarpWMCursor = Mac_WarpWMCursor;
319 device->InitOSKeymap = Mac_InitOSKeymap;
320 device->PumpEvents = Mac_PumpEvents;
321
322 device->GrabInput = NULL;
323 device->CheckMouseMode = NULL;
324
325 device->free = DSp_DeleteDevice;
326
327 return device;
328}
329
330VideoBootStrap DSp_bootstrap = {
331 "DSp", "MacOS DrawSprocket",
332 DSp_Available, DSp_CreateDevice
333};
334
335/* Use DSp/Display Manager to build mode list for given screen */
336static SDL_Rect** DSp_BuildModeList (const GDHandle gDevice, int *displayWidth, int *displayHeight)
337{
338 DSpContextAttributes attributes;
339 DSpContextReference context;
340 DisplayIDType displayID;
341 SDL_Rect temp_list [16];
342 SDL_Rect **mode_list;
343 int width, height, i, j;
344
345 #if TARGET_API_MAC_OSX
346
347 displayID = 0;
348
349 #else
350 /* Ask Display Manager for integer id of screen device */
351 if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) {
352 return NULL;
353 }
354 #endif
355 /* Get the first possible DSp context on this device */
356 if ( DSpGetFirstContext (displayID, &context) != noErr ) {
357 return NULL;
358 }
359
360 if ( DSpContext_GetAttributes (context, &attributes) != noErr )
361 return NULL;
362
363 *displayWidth = attributes.displayWidth;
364 *displayHeight = attributes.displayHeight;
365
366 for ( i = 0; i < SDL_arraysize(temp_list); i++ ) {
367 width = attributes.displayWidth;
368 height = attributes.displayHeight;
369
370 temp_list [i].x = 0 | attributes.displayBestDepth;
371 temp_list [i].y = 0;
372 temp_list [i].w = width;
373 temp_list [i].h = height;
374
375 /* DSp will report many different contexts with the same width and height. */
376 /* They will differ in bit depth and refresh rate. */
377 /* We will ignore them until we reach one with a different width/height */
378 /* When there are no more contexts to look at, we will quit building the list*/
379 while ( width == attributes.displayWidth && height == attributes.displayHeight ) {
380
381 OSStatus err = DSpGetNextContext (context, &context);
382 if (err != noErr)
383 if (err == kDSpContextNotFoundErr)
384 goto done;
385 else
386 return NULL;
387
388 if ( DSpContext_GetAttributes (context, &attributes) != noErr )
389 return NULL;
390
391 temp_list [i].x |= attributes.displayBestDepth;
392 }
393 }
394done:
395 i++; /* i was not incremented before kicking out of the loop */
396
397 mode_list = (SDL_Rect**) SDL_malloc (sizeof (SDL_Rect*) * (i+1));
398 if (mode_list) {
399
400 /* -dw- new stuff: build in reverse order so largest sizes list first */
401 for (j = i-1; j >= 0; j--) {
402 mode_list [j] = (SDL_Rect*) SDL_malloc (sizeof (SDL_Rect));
403 if (mode_list [j])
404 SDL_memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect));
405 else {
406 SDL_OutOfMemory ();
407 return NULL;
408 }
409 }
410 mode_list [i] = NULL; /* append null to the end */
411 }
412 else {
413 SDL_OutOfMemory ();
414 return NULL;
415 }
416
417 return mode_list;
418}
419
420static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat)
421{
422 /*
423 VRAM GWorlds are only available on OS 9 or later.
424 Even with OS 9, some display drivers won't support it,
425 so we create a test GWorld and check for errors.
426 */
427
428 long versionSystem;
429
430 dsp_vram_available = SDL_FALSE;
431 dsp_agp_available = SDL_FALSE;
432
433 Gestalt ('sysv', &versionSystem);
434 if (0x00000860 < (versionSystem & 0x0000FFFF)) {
435
436 GWorldPtr offscreen;
437 OSStatus err;
438 Rect bounds;
439
440 SetRect (&bounds, 0, 0, 320, 240);
441
442#if useDistantHdwrMem && useLocalHdwrMem
443 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice);
444 if (err == noErr) {
445 dsp_vram_available = SDL_TRUE;
446 DisposeGWorld (offscreen);
447 }
448
449 err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice);
450 if (err == noErr) {
451 DisposeGWorld (offscreen);
452 dsp_agp_available = SDL_TRUE;
453 }
454#endif
455 }
456}
457
458static int DSp_GetMainDevice (_THIS, GDHandle *device)
459{
460
461#if TARGET_API_MAC_OSX
462 /* DSpUserSelectContext not available on OS X */
463 *device = GetMainDevice();
464 return 0;
465#else
466
467 DSpContextAttributes attrib;
468 DSpContextReference context;
469 DisplayIDType display_id;
470 GDHandle main_device;
471 GDHandle device_list;
472
473 device_list = GetDeviceList ();
474 main_device = GetMainDevice ();
475
476 /* Quick check to avoid slower method when only one display exists */
477 if ( (**device_list).gdNextGD == NULL ) {
478 *device = main_device;
479 return 0;
480 }
481
482 SDL_memset (&attrib, 0, sizeof (DSpContextAttributes));
483
484 /* These attributes are hopefully supported on all devices...*/
485 attrib.displayWidth = 640;
486 attrib.displayHeight = 480;
487 attrib.displayBestDepth = 8;
488 attrib.backBufferBestDepth = 8;
489 attrib.displayDepthMask = kDSpDepthMask_All;
490 attrib.backBufferDepthMask = kDSpDepthMask_All;
491 attrib.colorNeeds = kDSpColorNeeds_Require;
492 attrib.pageCount = 1;
493
494 if (noErr != DMGetDisplayIDByGDevice (main_device, &display_id, SDL_FALSE)) {
495 SDL_SetError ("Display Manager couldn't associate GDevice with a Display ID");
496 return (-1);
497 }
498
499 /* Put up dialog on main display to select which display to use */
500 if (noErr != DSpUserSelectContext (&attrib, display_id, NULL, &context)) {
501 SDL_SetError ("DrawSprocket couldn't create a context");
502 return (-1);
503 }
504
505 if (noErr != DSpContext_GetDisplayID (context, &display_id)) {
506 SDL_SetError ("DrawSprocket couldn't get display ID");
507 return (-1);
508 }
509
510 if (noErr != DMGetGDeviceByDisplayID (display_id, &main_device, SDL_FALSE)) {
511 SDL_SetError ("Display Manager couldn't associate Display ID with GDevice");
512 return (-1);
513 }
514
515 *device = main_device;
516 return (0);
517#endif
518}
519
520static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat)
521{
522 NumVersion dsp_version = { 0x01, 0x00, 0x00, 0x00 };
523
524#if UNIVERSAL_INTERFACES_VERSION > 0x0320
525 dsp_version = DSpGetVersion ();
526#endif
527
528 if ( (dsp_version.majorRev == 1 && dsp_version.minorAndBugRev < 0x73) ||
529 (dsp_version.majorRev < 1) ) {
530
531 /* StandardAlert (kAlertStopAlert, "\pError!",
532 "\pI need DrawSprocket 1.7.3 or later!\n"
533 "You can find a newer version at http://www.apple.com/swupdates.",
534 NULL, NULL);
535 */
536 SDL_SetError ("DrawSprocket version is too old. Need 1.7.3 or later.");
537 return (-1);
538 }
539
540 if ( DSpStartup () != noErr ) {
541 SDL_SetError ("DrawSprocket couldn't startup");
542 return(-1);
543 }
544
545 /* Start DSpintosh events */
546 Mac_InitEvents(this);
547
548 /* Get a handle to the main monitor, or choose one on multiple monitor setups */
549 if ( DSp_GetMainDevice(this, &SDL_Display) < 0)
550 return (-1);
551
552 /* Determine pixel format */
553 vformat->BitsPerPixel = GetPixDepth ( (**SDL_Display).gdPMap );
554 dsp_old_depth = vformat->BitsPerPixel;
555
556 switch (vformat->BitsPerPixel) {
557 case 16:
558 vformat->Rmask = 0x00007c00;
559 vformat->Gmask = 0x000003e0;
560 vformat->Bmask = 0x0000001f;
561 break;
562 default:
563 break;
564 }
565
566 if ( DSp_CreatePalette (this) < 0 ) {
567 SDL_SetError ("Could not create palette");
568 return (-1);
569 }
570
571 /* Get a list of available fullscreen modes */
572 SDL_modelist = DSp_BuildModeList (SDL_Display,
573 &this->info.current_w, &this->info.current_h);
574 if (SDL_modelist == NULL) {
575 SDL_SetError ("DrawSprocket could not build a mode list");
576 return (-1);
577 }
578
579 /* Check for VRAM and AGP GWorlds for HW Blitting */
580 DSp_IsHWAvailable (this, vformat);
581
582 this->info.wm_available = 0;
583
584 if (dsp_vram_available || dsp_agp_available) {
585
586 this->info.hw_available = SDL_TRUE;
587
588 this->CheckHWBlit = DSp_CheckHWBlit;
589 this->info.blit_hw = SDL_TRUE;
590
591 this->FillHWRect = DSp_FillHWRect;
592 this->info.blit_fill = SDL_TRUE;
593
594 #ifdef DSP_TRY_CC_AND_AA
595 this->SetHWColorKey = DSp_SetHWColorKey;
596 this->info.blit_hw_CC = SDL_TRUE;
597
598 this->SetHWAlpha = DSp_SetHWAlpha;
599 this->info.blit_hw_A = SDL_TRUE;
600 #endif
601
602 }
603
604 return(0);
605}
606
607static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
608{
609 static SDL_Rect *dsp_modes[16];
610 int i = 0, j = 0;
611
612 if ( format->BitsPerPixel == 0 )
613 return ( (SDL_Rect**) NULL );
614
615 while (SDL_modelist[i] != NULL) {
616
617 if (SDL_modelist[i]->x & format->BitsPerPixel) {
618 dsp_modes[j] = SDL_modelist[i];
619 j++;
620 }
621 i++;
622 }
623
624 dsp_modes[j] = NULL;
625
626 return dsp_modes;
627}
628
629/* Various screen update functions available */
630static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
631
632#if ! TARGET_API_MAC_OSX
633
634static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */
635
636Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con )
637{
638 retrace_count++;
639
640 return 1; /* Darrell, is this right? */
641}
642
643static void DSp_SetHWError (OSStatus err, int is_agp)
644{
645 char message[1024];
646 const char *fmt, *mem;
647
648 if ( is_agp ) {
649 mem = "AGP Memory";
650 } else {
651 mem = "VRAM";
652 }
653 switch(err) {
654 case memFullErr:
655 fmt = "Hardware surface possible but not enough %s available";
656 break;
657 case cDepthErr:
658 fmt = "Hardware surface possible but invalid color depth";
659 break;
660 default:
661 fmt = "Hardware surface could not be allocated in %s - unknown error";
662 break;
663 }
664 SDL_snprintf(message, SDL_arraysize(message), fmt, mem);
665 SDL_SetError(message);
666}
667#endif // TARGET_API_MAC_OSX
668
669/* put up a dialog to verify display change */
670static int DSp_ConfirmSwitch () {
671
672 /* resource id's for dialog */
673 const int rDialog = 1002;
674 const int bCancel = 1;
675 const int bOK = 2;
676
677 DialogPtr dialog;
678 OSStatus err;
679 SInt32 response;
680 DialogItemIndex item = 0;
681 GrafPtr savePort;
682
683 GetPort (&savePort);
684
685 dialog = GetNewDialog (rDialog, NULL, (WindowPtr) -1);
686 if (dialog == NULL)
687 return (0);
688
689#if TARGET_API_MAC_CARBON
690 SetPort (GetDialogPort(dialog));
691#else
692 SetPort ((WindowPtr) dialog);
693#endif
694
695 SetDialogDefaultItem (dialog, bCancel);
696 SetDialogCancelItem (dialog, bCancel);
697
698 SetEventMask (everyEvent);
699 FlushEvents (everyEvent, 0);
700
701 /* On MacOS 8.5 or later, we can make the dialog go away after 15 seconds */
702 /* This is good since it's possible user can't even see the dialog! */
703 /* Requires linking to DialogsLib */
704 err = Gestalt(gestaltSystemVersion,&response);
705 if (err == noErr && response >= 0x00000850) {
706 SetDialogTimeout(dialog, bCancel, 15);
707 }
708
709 do {
710
711 ModalDialog ( NULL, &item );
712
713 } while ( item != bCancel && item != bOK && err != noErr);
714
715
716 DisposeDialog (dialog);
717 SetPort (savePort);
718
719 SetEventMask(everyEvent - autoKeyMask);
720 FlushEvents(everyEvent, 0);
721
722 return (item - 1);
723}
724
725static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current)
726{
727
728
729 if ( current->flags & SDL_OPENGL ) {
730 Mac_GL_Quit (this);
731 }
732
733 if (dsp_context != NULL) {
734
735 GWorldPtr front;
736 DSpContext_GetFrontBuffer (dsp_context, &front);
737
738 if (front != dsp_back_buffer)
739 DisposeGWorld (dsp_back_buffer);
740
741 if (current->hwdata)
742 SDL_free(current->hwdata);
743
744 DSpContext_SetState (dsp_context, kDSpContextState_Inactive );
745 DSpContext_Release (dsp_context);
746
747 dsp_context = NULL;
748 }
749
750 if (SDL_Window != NULL) {
751 DisposeWindow (SDL_Window);
752 SDL_Window = NULL;
753 }
754
755 current->pixels = NULL;
756 current->flags = 0;
757}
758
759static SDL_Surface *DSp_SetVideoMode(_THIS,
760 SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
761{
762
763#if !TARGET_API_MAC_OSX
764 DisplayIDType display_id;
765 Fixed freq;
766#endif
767 DSpContextAttributes attrib;
768 OSStatus err;
769 UInt32 rmask = 0, gmask = 0, bmask = 0;
770
771 int page_count;
772 int double_buf;
773 int hw_surface;
774 int use_dsp_back_buffer;
775
776 DSp_UnsetVideoMode (this, current);
777
778 if (bpp != dsp_old_depth)
779 DSp_DestroyPalette (this);
780
781 double_buf = (flags & SDL_DOUBLEBUF) != 0;
782 hw_surface = (flags & SDL_HWSURFACE) != 0;
783 use_dsp_back_buffer = !dsp_vram_available || !hw_surface ;
784
785 current->flags |= SDL_FULLSCREEN;
786
787rebuild:
788
789 if ( double_buf && use_dsp_back_buffer ) {
790 page_count = 2;
791 } else {
792 page_count = 1;
793 }
794
795 SDL_memset (&attrib, 0, sizeof (DSpContextAttributes));
796 attrib.displayWidth = width;
797 attrib.displayHeight = height;
798 attrib.displayBestDepth = bpp;
799 attrib.backBufferBestDepth = bpp;
800 attrib.displayDepthMask = kDSpDepthMask_All;
801 attrib.backBufferDepthMask = kDSpDepthMask_All;
802 attrib.colorNeeds = kDSpColorNeeds_Require;
803 attrib.colorTable = 0;
804 attrib.pageCount = page_count;
805 #if TARGET_API_MAC_OSX || UNIVERSAL_INTERFACES_VERSION == 0x0320
806
807 if ( DSpFindBestContext (&attrib, &dsp_context) != noErr ) {
808 SDL_SetError ("DrawSprocket couldn't find a context");
809 return NULL;
810 }
811
812 #else
813 if ( noErr != DMGetDisplayIDByGDevice (SDL_Display, &display_id, SDL_FALSE) ) {
814 SDL_SetError ("Display Manager couldn't associate GDevice with display_id");
815 return NULL;
816 }
817 if ( DSpFindBestContextOnDisplayID(&attrib, &dsp_context, display_id) != noErr ) {
818 SDL_SetError ("DrawSprocket couldn't find a suitable context on given display");
819 return NULL;
820 }
821
822 #endif
823 if ( DSpContext_Reserve (dsp_context, &attrib) != noErr ) {
824 SDL_SetError ("DrawSprocket couldn't get the needed resources to build the display");
825 return NULL;
826 }
827
828 if ( (err = DSpContext_SetState (dsp_context, kDSpContextState_Active)) != noErr ) {
829
830 if (err == kDSpConfirmSwitchWarning) {
831
832 if ( ! DSp_ConfirmSwitch () ) {
833
834 DSpContext_Release (dsp_context);
835 dsp_context = NULL;
836 SDL_SetError ("User cancelled display switch");
837 return NULL;
838 }
839 else
840 /* Have to reactivate context. Why? */
841 DSpContext_SetState (dsp_context, kDSpContextState_Active);
842
843 }
844 else {
845 SDL_SetError ("DrawSprocket couldn't activate the context");
846 return NULL;
847 }
848 }
849
850
851 if (bpp != dsp_old_depth) {
852
853 DSp_CreatePalette (this);
854
855 /* update format if display depth changed */
856 if (bpp == 16) {
857
858 rmask = 0x00007c00;
859 gmask = 0x000003e0;
860 bmask = 0x0000001f;
861 }
862 if ( ! SDL_ReallocFormat (current, bpp, rmask, gmask, bmask, 0 ) ) {
863
864 SDL_SetError ("Could not reallocate video format.");
865 return(NULL);
866 }
867 }
868
869 if (!double_buf) {
870
871 /* single-buffer context */
872 DSpContext_GetFrontBuffer (dsp_context, &dsp_back_buffer);
873
874 current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata));
875 if (current ->hwdata == NULL) {
876 SDL_OutOfMemory ();
877 return NULL;
878 }
879 current->hwdata->offscreen = dsp_back_buffer;
880 current->flags |= SDL_HWSURFACE;
881 this->UpdateRects = DSp_DirectUpdate;
882 }
883 else if ( use_dsp_back_buffer ) {
884
885 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer);
886
887 current->flags |= SDL_DOUBLEBUF | SDL_SWSURFACE; /* only front buffer is in VRAM */
888 this->UpdateRects = DSp_DSpUpdate;
889 }
890 else if ( DSp_NewHWSurface(this, &dsp_back_buffer, bpp, width-1, height-1) == 0 ) {
891
892 current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata));
893 if (current ->hwdata == NULL) {
894 SDL_OutOfMemory ();
895 return NULL;
896 }
897
898 SDL_memset (current->hwdata, 0, sizeof (private_hwdata));
899 current->hwdata->offscreen = dsp_back_buffer;
900 current->flags |= SDL_DOUBLEBUF | SDL_HWSURFACE;
901 this->UpdateRects = DSp_DirectUpdate; /* hardware doesn't do update rects, must be page-flipped */
902 }
903 else {
904
905 DSpContext_Release (dsp_context);
906 use_dsp_back_buffer = SDL_TRUE;
907 goto rebuild;
908 }
909
910 current->pitch = GetPortPixRowBytes(dsp_back_buffer) & 0x3FFF;
911 current->pixels = GetPixBaseAddr(GetPortPixMap(dsp_back_buffer));
912
913 current->w = width;
914 current->h = height;
915
916 #if ! TARGET_API_MAC_OSX
917
918 if (use_dsp_back_buffer) {
919
920 DSpContext_GetMonitorFrequency (dsp_context, &freq);
921 DSpContext_SetMaxFrameRate (dsp_context, freq >> 16);
922 }
923
924
925 if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) )
926 DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL);
927 #endif
928
929 if (bpp == 8)
930 current->flags |= SDL_HWPALETTE;
931
932 if (flags & SDL_OPENGL) {
933
934 Rect rect;
935 RGBColor rgb = { 0.0, 0.0, 0.0 };
936 GrafPtr save_port;
937
938 SetRect (&rect, 0, 0, width, height);
939 SDL_Window = NewCWindow(nil, &( (**SDL_Display).gdRect), "\p", SDL_TRUE, plainDBox, (WindowPtr)-1, SDL_FALSE, 0);
940
941 if (SDL_Window == NULL) {
942
943 SDL_SetError ("DSp_SetVideoMode : OpenGL window could not be created.");
944 return NULL;
945 }
946
947 /* Set window color to black to avoid white flash*/
948 GetPort (&save_port);
949#if TARGET_API_MAC_CARBON
950 SetPort (GetWindowPort(SDL_Window));
951#else
952 SetPort (SDL_Window);
953#endif
954 RGBForeColor (&rgb);
955 PaintRect (&rect);
956 SetPort (save_port);
957
958 SetPortWindowPort (SDL_Window);
959 SelectWindow (SDL_Window);
960
961 if ( Mac_GL_Init (this) < 0 ) {
962
963 SDL_SetError ("DSp_SetVideoMode : could not create OpenGL context.");
964 return NULL;
965 }
966
967 current->flags |= SDL_OPENGL;
968 }
969
970 return current;
971}
972
973#ifdef DSP_TRY_CC_AND_AA
974
975static int DSp_MakeHWMask (_THIS, SDL_Surface *surface)
976{
977 GDHandle save_device;
978 CGrafPtr save_port;
979 GWorldPtr temp;
980 RGBColor black = { 0, 0, 0 };
981 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF };
982 Rect rect;
983
984 Uint32 depth = GetPixDepth ( GetGDevPixMap (SDL_Display) );
985
986 SetRect (&rect, 0, 0, surface->w, surface->h);
987
988 if ( noErr != NewGWorld (&(surface->hwdata->mask), depth, &rect, 0, SDL_Display, 0 ) < 0 ) {
989
990 SDL_OutOfMemory ();
991 return (-1);
992 }
993
994 if ( noErr != NewGWorld (&temp, depth, &rect, 0 , SDL_Display, 0 ) ) {
995
996 SDL_OutOfMemory ();
997 return (-1);
998 }
999
1000
1001 GetGWorld (&save_port, &save_device);
1002 SetGWorld (surface->hwdata->mask, SDL_Display);
1003
1004 RGBForeColor (&white);
1005 PaintRect (&rect);
1006
1007 RGBBackColor (&(surface->hwdata->trans));
1008
1009 CopyBits ( GetPortBitMapForCopyBits(surface->hwdata->offscreen),
1010 GetPortBitMapForCopyBits(surface->hwdata->mask),
1011 &rect, &rect, transparent, NULL );
1012
1013 SetGWorld (surface->hwdata->mask, SDL_Display);
1014 SetGWorld (save_port, save_device);
1015 return (0);
1016}
1017
1018static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha)
1019{
1020 surface->hwdata->alpha.red = (alpha / 255.0) * 65535;
1021 surface->hwdata->alpha.blue = (alpha / 255.0) * 65535;
1022 surface->hwdata->alpha.green = (alpha / 255.0) * 65535;
1023
1024 surface->flags |= SDL_SRCALPHA;
1025
1026 if (surface->flags & SDL_SRCCOLORKEY) {
1027 return(DSp_MakeHWMask (this, surface));
1028 }
1029 return(0);
1030}
1031
1032static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
1033{
1034 CGrafPtr save_port;
1035 GDHandle save_device;
1036
1037 GetGWorld (&save_port, &save_device);
1038 SetGWorld (surface->hwdata->offscreen, NULL);
1039
1040 Index2Color (key, &(surface->hwdata->trans));
1041 surface->flags |= SDL_SRCCOLORKEY;
1042
1043 SetGWorld (save_port, save_device);
1044
1045 if ( surface->flags & SDL_SRCALPHA ) {
1046 return(DSp_MakeHWMask (this, surface));
1047 }
1048 return(0);
1049}
1050
1051#endif /* DSP_TRY_CC_AND_AA */
1052
1053static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height) {
1054
1055 OSStatus err;
1056 Rect bounds;
1057
1058 SetRect (&bounds, 0, 0, width, height);
1059
1060 #if useDistantHdwrMem && useLocalHdwrMem
1061 if (dsp_vram_available) {
1062 /* try VRAM */
1063 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useDistantHdwrMem | noNewDevice );
1064 if (err != noErr)
1065 DSp_SetHWError (err, SDL_FALSE);
1066 else
1067 return (0);
1068 }
1069
1070 if (dsp_agp_available) {
1071 /* try AGP */
1072 err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useLocalHdwrMem | noNewDevice );
1073
1074 if (err != noErr)
1075 DSp_SetHWError (err, SDL_TRUE);
1076 else
1077 return (0);
1078 }
1079#endif
1080
1081 return (-1);
1082}
1083
1084static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface)
1085{
1086 GWorldPtr temp;
1087
1088 if ( DSp_NewHWSurface (this, &temp, surface->format->BitsPerPixel, surface->w, surface->h) < 0 )
1089 return (-1);
1090
1091 surface->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata));
1092 if (surface->hwdata == NULL) {
1093 SDL_OutOfMemory ();
1094 return -1;
1095 }
1096
1097 SDL_memset (surface->hwdata, 0, sizeof(private_hwdata));
1098 surface->hwdata->offscreen = temp;
1099 surface->pitch = GetPixRowBytes (GetPortPixMap (temp)) & 0x3FFF;
1100 surface->pixels = GetPixBaseAddr (GetPortPixMap (temp));
1101 surface->flags |= SDL_HWSURFACE;
1102#ifdef DSP_TRY_CC_AND_AA
1103 surface->flags |= SDL_HWACCEL;
1104#endif
1105 return 0;
1106}
1107
1108static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface)
1109{
1110 if (surface->hwdata->offscreen != NULL)
1111 DisposeGWorld (surface->hwdata->offscreen);
1112 SDL_free(surface->hwdata);
1113
1114 surface->pixels = NULL;
1115}
1116
1117static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest)
1118{
1119 int accelerated;
1120
1121 /* Set initial acceleration on */
1122 src->flags |= SDL_HWACCEL;
1123
1124 /* Set the surface attributes */
1125 if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
1126 if ( ! this->info.blit_hw_A ) {
1127 src->flags &= ~SDL_HWACCEL;
1128 }
1129 }
1130 if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
1131 if ( ! this->info.blit_hw_CC ) {
1132 src->flags &= ~SDL_HWACCEL;
1133 }
1134 }
1135
1136 /* Check to see if final surface blit is accelerated */
1137 accelerated = !!(src->flags & SDL_HWACCEL);
1138 if ( accelerated ) {
1139 src->map->hw_blit = DSp_HWAccelBlit;
1140 }
1141 return(accelerated);
1142}
1143
1144static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
1145 SDL_Surface *dst, SDL_Rect *dstrect)
1146{
1147 CGrafPtr save_port;
1148 GDHandle save_device;
1149 Rect src_rect, dst_rect;
1150 RGBColor black = { 0, 0, 0 };
1151 RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF };
1152
1153#ifdef DSP_TRY_CC_AND_AA
1154 UInt32 mode;
1155#endif
1156
1157 SetRect (&src_rect, srcrect->x, srcrect->y, srcrect->x + srcrect->w, srcrect->y + srcrect->h);
1158 SetRect (&dst_rect, dstrect->x, dstrect->y, dstrect->x + dstrect->w, dstrect->y + dstrect->h);
1159
1160 GetGWorld (&save_port, &save_device);
1161 SetGWorld (dst->hwdata->offscreen, NULL);
1162
1163 RGBForeColor (&black);
1164 RGBBackColor (&white);
1165
1166#ifdef DSP_TRY_CC_AND_AA
1167
1168 if ( (src->flags & SDL_SRCCOLORKEY) &&
1169 (src->flags & SDL_SRCALPHA) ) {
1170
1171 OpColor (&(src->hwdata->alpha));
1172
1173 CopyDeepMask ( GetPortBitMapForCopyBits(src->hwdata->offscreen),
1174 GetPortBitMapForCopyBits(src->hwdata->mask),
1175 GetPortBitMapForCopyBits(dst->hwdata->offscreen),
1176 &src_rect, &src_rect, &dst_rect,
1177 blend,
1178 NULL );
1179 }
1180 else {
1181
1182 if ( src->flags & SDL_SRCCOLORKEY) {
1183 RGBBackColor (&(src->hwdata->trans) );
1184 mode = transparent;
1185 }
1186 else if (src->flags & SDL_SRCALPHA) {
1187
1188 OpColor (&(src->hwdata->alpha));
1189 mode = blend;
1190 }
1191 else {
1192
1193 mode = srcCopy;
1194 }
1195
1196 CopyBits ( GetPortBitMapForCopyBits(src->hwdata->offscreen),
1197 GetPortBitMapForCopyBits(dst->hwdata->offscreen),
1198 &src_rect, &dst_rect, mode, NULL );
1199 }
1200#else
1201
1202 CopyBits ( &(((GrafPtr)(src->hwdata->offscreen))->portBits),
1203 &(((GrafPtr)(dst->hwdata->offscreen))->portBits),
1204 &src_rect, &dst_rect, srcCopy, NULL );
1205
1206#endif /* DSP_TRY_CC_AND_AA */
1207
1208 SetGWorld (save_port, save_device);
1209
1210 return(0);
1211}
1212
1213static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color)
1214{
1215 CGrafPtr save_port;
1216 GDHandle save_device;
1217 Rect fill_rect;
1218 RGBColor rgb;
1219
1220 SetRect (&fill_rect, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
1221
1222 GetGWorld (&save_port, &save_device);
1223 SetGWorld (dst->hwdata->offscreen, NULL);
1224
1225 Index2Color (color, &rgb);
1226
1227 RGBForeColor (&rgb);
1228 PaintRect (&fill_rect);
1229
1230 SetGWorld (save_port, save_device);
1231
1232 return(0);
1233}
1234
1235static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface)
1236{
1237 if ( (surface->flags & SDL_HWSURFACE) ) {
1238 CGrafPtr dsp_front_buffer, save_port;
1239 Rect rect;
1240
1241 #if ! TARGET_API_MAC_OSX
1242 unsigned int old_count;
1243 #endif
1244
1245 /* pseudo page flipping for VRAM back buffer*/
1246 DSpContext_GetFrontBuffer (dsp_context, &dsp_front_buffer);
1247 SetRect (&rect, 0, 0, surface->w-1, surface->h-1);
1248
1249 GetPort ((GrafPtr *)&save_port);
1250 SetPort ((GrafPtr)dsp_front_buffer);
1251
1252 /* wait for retrace */
1253 /* I have tried doing the swap in interrupt routine (VBL Proc) to do */
1254 /* it asynchronously, but apparently CopyBits isn't interrupt safe */
1255
1256 #if ! TARGET_API_MAC_OSX
1257 #ifndef DSP_NO_SYNC_VBL
1258 old_count = retrace_count;
1259 while (old_count == retrace_count)
1260 ;
1261 #endif
1262 #endif
1263
1264 CopyBits ( GetPortBitMapForCopyBits(dsp_back_buffer),
1265 GetPortBitMapForCopyBits(dsp_front_buffer),
1266 &rect, &rect, srcCopy, NULL );
1267
1268 SetPort ((GrafPtr)save_port);
1269
1270 } else {
1271 /* not really page flipping at all: DSp just blits the dirty rectangles from DSp_UpdateRects */
1272 Boolean busy_flag;
1273 DSpContext_SwapBuffers (dsp_context, NULL, &busy_flag); /* this waits for VBL */
1274 DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer);
1275 surface->pixels = GetPixBaseAddr( GetPortPixMap(dsp_back_buffer) );
1276 }
1277 return(0);
1278}
1279
1280static int DSp_LockHWSurface(_THIS, SDL_Surface *surface)
1281{
1282 if ( LockPixels (GetGWorldPixMap (surface->hwdata->offscreen)) )
1283 return 0;
1284 else
1285 return -1;
1286}
1287
1288static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface)
1289{
1290 UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen));
1291}
1292
1293static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects)
1294{
1295 return;
1296}
1297
1298static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects)
1299{
1300#if ! TARGET_API_MAC_OSX /* Unsupported DSp in here */
1301 int i;
1302 Rect rect;
1303
1304 for (i = 0; i < numrects; i++) {
1305
1306 rect.top = sdl_rects[i].y;
1307 rect.left = sdl_rects[i].x;
1308 rect.bottom = sdl_rects[i].h + sdl_rects[i].y;
1309 rect.right = sdl_rects[i].w + sdl_rects[i].x;
1310
1311 DSpContext_InvalBackBufferRect (dsp_context, &rect);
1312 }
1313#endif
1314}
1315
1316static int DSp_CreatePalette(_THIS) {
1317
1318
1319 /* Create our palette */
1320 SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8);
1321 if ( SDL_CTab == nil ) {
1322 SDL_OutOfMemory();
1323 return(-1);
1324 }
1325 (**SDL_CTab).ctSeed = GetCTSeed();
1326 (**SDL_CTab).ctFlags = 0;
1327 (**SDL_CTab).ctSize = 255;
1328 CTabChanged(SDL_CTab);
1329 SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0);
1330
1331 return 0;
1332}
1333
1334static int DSp_DestroyPalette(_THIS) {
1335
1336 /* Free palette and restore original one */
1337 if ( SDL_CTab != nil ) {
1338 DisposeHandle((Handle)SDL_CTab);
1339 SDL_CTab = nil;
1340 }
1341 if ( SDL_CPal != nil ) {
1342 DisposePalette(SDL_CPal);
1343 SDL_CPal = nil;
1344 }
1345 RestoreDeviceClut(SDL_Display);
1346
1347 return (0);
1348}
1349
1350static int DSp_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1351{
1352 CTabHandle cTab;
1353
1354 int i;
1355
1356 cTab = SDL_CTab;
1357
1358 /* Verify the range of colors */
1359 if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) {
1360 return(0);
1361 }
1362
1363 /* Set the screen palette and update the display */
1364 for(i = 0; i < ncolors; i++) {
1365 int j = firstcolor + i;
1366 (**cTab).ctTable[j].value = j;
1367 (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r;
1368 (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g;
1369 (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b;
1370 }
1371
1372 SetGDevice(SDL_Display);
1373 SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable);
1374
1375 return(1);
1376}
1377
1378void DSp_VideoQuit(_THIS)
1379{
1380 int i;
1381
1382 /* Free current video mode */
1383 DSp_UnsetVideoMode(this, this->screen);
1384
1385 /* Free Palette and restore original */
1386 DSp_DestroyPalette (this);
1387
1388#if SDL_MACCLASSIC_GAMMA_SUPPORT
1389 Mac_QuitGamma(this);
1390#endif
1391
1392 /* Free list of video modes */
1393 if ( SDL_modelist != NULL ) {
1394 for ( i=0; SDL_modelist[i]; i++ ) {
1395 SDL_free(SDL_modelist[i]);
1396 }
1397 SDL_free(SDL_modelist);
1398 SDL_modelist = NULL;
1399 }
1400
1401 /* Unload DrawSprocket */
1402 DSpShutdown ();
1403}
1404
1405#if SDL_VIDEO_OPENGL
1406
1407/* swap buffers with v-sync */
1408static void DSp_GL_SwapBuffers (_THIS) {
1409
1410 #ifndef DSP_NO_SYNC_OPENGL
1411
1412 unsigned int old_count;
1413
1414 old_count = retrace_count;
1415 while (old_count == retrace_count)
1416 ;
1417 #endif
1418
1419 aglSwapBuffers (glContext);
1420}
1421
1422#endif