Home | History | Annotate | Download | only in macdsp
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 /*
     25  Written by Darrell Walisser <dwaliss1 (at) 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
   1423