SDL-1.2.14
[sdl_omap.git] / src / video / macdsp / SDL_dspvideo.c
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 */
153 static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat);
154 static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
155 static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
156 static int DSp_SetColors(_THIS, int firstcolor, int ncolors,
157                          SDL_Color *colors);
158 static int DSp_CreatePalette(_THIS);
159 static int DSp_DestroyPalette(_THIS);
160 static void DSp_VideoQuit(_THIS);
161
162 static int DSp_GetMainDevice (_THIS, GDHandle *device);
163 static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat);
164 static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);
165 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);
166
167 /* Hardware surface functions */
168 static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha);
169 static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
170 static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height);
171 static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface);
172 static int DSp_LockHWSurface(_THIS, SDL_Surface *surface);
173 static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface);
174 static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface);
175 static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface);
176 static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest);
177 static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
178                            SDL_Surface *dst, SDL_Rect *dstrect);
179 static 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
203 typedef 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
215 typedef private_hwdata private_swdata ; /* have same fields */
216
217 /* Macintosh toolbox driver bootstrap functions */
218
219 static 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
230 static 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
246 static 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
330 VideoBootStrap 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 */
336 static 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         }
394 done:
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
420 static 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
458 static 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
520 static 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
607 static 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 */
630 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
631
632 #if ! TARGET_API_MAC_OSX
633
634 static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */
635
636 Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con )
637 {
638         retrace_count++;
639         
640         return 1; /* Darrell, is this right? */
641 }
642
643 static 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 */
670 static 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
725 static 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
759 static 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
787 rebuild:  
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
975 static 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
1018 static 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
1032 static 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
1053 static 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
1084 static 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
1108 static 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
1117 static 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
1144 static 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
1213 static 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
1235 static 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
1280 static 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
1288 static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface)
1289 {
1290         UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen));
1291 }
1292
1293 static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects)
1294 {
1295         return;
1296 }
1297
1298 static 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
1316 static 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
1334 static 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
1350 static 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
1378 void 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 */
1408 static 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