src/video/macdsp/SDL_dspvideo.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. GetPortPixRowBytes
  2. GetGDevPixMap
  3. GetPortPixMap
  4. GetPixDepth
  5. GetPixCTab
  6. GetPortBitMapForCopyBits
  7. GetPortPixRowBytes
  8. GetGDevPixMap
  9. DSp_Available
  10. DSp_DeleteDevice
  11. DSp_CreateDevice
  12. DSp_BuildModeList
  13. DSp_IsHWAvailable
  14. DSp_GetMainDevice
  15. DSp_VideoInit
  16. DSp_ListModes
  17. DSp_VBLProc
  18. DSp_SetHWError
  19. DSp_ConfirmSwitch
  20. DSp_UnsetVideoMode
  21. DSp_SetVideoMode
  22. DSp_MakeHWMask
  23. DSp_SetHWAlpha
  24. DSp_SetHWColorKey
  25. DSp_NewHWSurface
  26. DSp_AllocHWSurface
  27. DSp_FreeHWSurface
  28. DSp_CheckHWBlit
  29. DSp_HWAccelBlit
  30. DSp_FillHWRect
  31. DSp_FlipHWSurface
  32. DSp_LockHWSurface
  33. DSp_UnlockHWSurface
  34. DSp_DirectUpdate
  35. DSp_DSpUpdate
  36. DSp_CreatePalette
  37. DSp_DestroyPalette
  38. DSp_SetColors
  39. DSp_VideoQuit
  40. DSp_GL_SwapBuffers

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

/* [<][>][^][v][top][bottom][index][help] */