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