aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/video/macdsp/SDL_dspvideo.c
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/macdsp/SDL_dspvideo.c')
-rw-r--r--distrib/sdl-1.2.15/src/video/macdsp/SDL_dspvideo.c1422
1 files changed, 1422 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/macdsp/SDL_dspvideo.c b/distrib/sdl-1.2.15/src/video/macdsp/SDL_dspvideo.c
new file mode 100644
index 0000000..aa31127
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/video/macdsp/SDL_dspvideo.c
@@ -0,0 +1,1422 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+/*
+ Written by Darrell Walisser <dwaliss1@purdue.edu>
+
+ Implementation notes ----------------------------------------------------------------------
+
+ A bit on GWorlds in VRAM from technote 1182:
+
+ There are two important things to note about GWorld's allocated in
+ VRAM. First, the base address retrieved through GetPixBaseAddr or
+ read directly from the PixMap structure can become invalid anytime
+ memory is allocated in VRAM. This can occur either by explicit
+ allocations, such as calls to NewGWorld, or by implicit ones, such as
+ those associated with the internal texture allocation of OpenGL. The
+ stored pixel images themselves will still be valid but may have been
+ moved in VRAM, thus rendering any stored base addresses invalid.
+ You should never store an image's base address for longer than is
+ necessary and especially never across calls to NewGWorld or
+ texture-creation routines.
+
+ Secondly, an offscreen pixel image allocated in VRAM can be
+ purged at system task time by the display driver. This means any
+ time your application yields time such by calling WaitNextEvent or
+ SystemTask you can lose your VRAM GWorld contents. While this
+ happens infrequently, usually associated with display resolution or
+ pixel depth changes you must code for this eventuality. This purge
+ can occur whether or not the GWorld is locked or not. A return value
+ of false from LockPixels, a NULL return value from GetPixBaseAddr
+ or NULL in the baseAddr field of the PixMap mean that the pixel
+ image has been purged. To reallocate it you can either call
+ UpdateGWorld or Dispose your current GWorld through
+ DisposeGWorld and reallocate it via NewGWorld. Either way you must
+ then rebuild the pixel image.
+
+------------------------------------------------------------------------------------
+
+ Currently, I don't account for (1). In my testing, NewGWorld never invalidated
+ other existing GWorlds in VRAM. However, I do have protection for (2).
+ Namely, I am using GetOSEvent() instead of WaitNextEvent() so that there are no
+ context switches (the app hogs the CPU). Eventually a book-keeping system should
+ be coded to take care of (1) and (2).
+
+------------------------------------------------------------------------------------
+
+ System requirements (* denotes optional):
+
+ 1. DrawSprocket 1.7.3
+ 2. *MacOS 9 or later (but *not* Mac OS X) for hardware accelerated blit / fill
+ 3. *May also require certain graphics hardware for (2). I trust that all Apple OEM
+ hardware will work. Third party accelerators may work if they have QuickDraw
+ acceleration in the drivers and the drivers have been updated for OS 9. The current
+ Voodoo 3 drivers (1.0b12) do not work.
+
+ Coding suggestions:
+
+ 1. Use SDL_UpdateRects !
+
+ If no QuickDraw acceleration is present, double-buffered surfaces will use a back buffer
+ in System memory. I recommend you use SDL_UpdateRects with double-buffered surfaces
+ for best performance on these cards, since the overhead is nearly zero for VRAM back buffer.
+
+ 2. Load most-resident surfaces first.
+
+ If you fill up VRAM or AGP memory, there is no contingency for purging to make room for the next one.
+ Therefore, you should load the surfaces you plan to use the most frequently first.
+ Sooner or later, I will code LRU replacement to help this.
+
+ TODO:
+ Some kind of posterized mode for resolutions < 640x480.
+ Window support / fullscreen toggle.
+ Figure out how much VRAM is available. Put in video->info->video_mem.
+ Track VRAM usage.
+
+ BUGS:
+ I can't create a hardware surface the same size as the screen?! How to fix?
+
+
+
+ COMPILE OPTIONS:
+
+ DSP_TRY_CC_AND_AA - Define if you want to try HWA color-key and alpha blitters
+ HW color-key blitting gives substantial improvements,
+ but hw alpha is neck-and-neck with SDL's soft bitter.
+
+ DSP_NO_SYNC_VBL - Define for HWA double-buffered surfaces: don't sync
+ pseudo-flip to monitor redraw.
+
+ DSP_NO_SYNC_OPENGL - Define for OpenGL surfaces: don't sync buffer swap. Synching buffer
+ swap may result in reduced performance, but can eliminate some
+ tearing artifacts.
+ CHANGELOG:
+ 09/17/00 Lots of little tweaks. Build modelist in reverse order so largest contexts
+ list first. Compared various methods with ROM methods and fixed rez switch
+ crashing bug in GL Tron. (Woohoo!)
+*/
+
+#define DSP_TRY_CC_AND_AA
+
+/* #define DSP_NO_SYNC_VBL */
+
+#define DSP_NO_SYNC_OPENGL
+
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <Carbon/Carbon.h>
+#include <DrawSprocket/DrawSprocket.h>
+#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
+#include <Carbon.h>
+#include <DrawSprocket.h>
+#else
+#include <LowMem.h>
+#include <Gestalt.h>
+#include <Devices.h>
+#include <DiskInit.h>
+#include <QDOffscreen.h>
+#include <DrawSprocket.h>
+#endif
+
+#include "SDL_video.h"
+#include "SDL_syswm.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_blit.h"
+#include "../SDL_pixels_c.h"
+#include "SDL_dspvideo.h"
+#include "../maccommon/SDL_macgl_c.h"
+#include "../maccommon/SDL_macwm_c.h"
+#include "../maccommon/SDL_macmouse_c.h"
+#include "../maccommon/SDL_macevents_c.h"
+
+/* Initialization/Query functions */
+static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat);
+static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
+static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
+static int DSp_SetColors(_THIS, int firstcolor, int ncolors,
+ SDL_Color *colors);
+static int DSp_CreatePalette(_THIS);
+static int DSp_DestroyPalette(_THIS);
+static void DSp_VideoQuit(_THIS);
+
+static int DSp_GetMainDevice (_THIS, GDHandle *device);
+static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat);
+static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);
+static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);
+
+/* Hardware surface functions */
+static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha);
+static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
+static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height);
+static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface);
+static int DSp_LockHWSurface(_THIS, SDL_Surface *surface);
+static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface);
+static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface);
+static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface);
+static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest);
+static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect);
+static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);
+
+#if SDL_VIDEO_OPENGL
+ static void DSp_GL_SwapBuffers (_THIS);
+#endif
+
+#if ! TARGET_API_MAC_CARBON
+
+ #define GetPortPixRowBytes(x) ( (*(x->portPixMap))->rowBytes )
+ #define GetGDevPixMap(x) ((**(x)).gdPMap)
+ #define GetPortPixMap(x) ((*(x)).portPixMap)
+
+ #define GetPixDepth(y) ((**(y)).pixelSize)
+ //#define GetPixRowBytes(y) ((**(y)).rowBytes)
+ //#define GetPixBaseAddr(y) ((**(y)).baseAddr)
+ #define GetPixCTab(y) ((**(y)).pmTable)
+ #define GetPortBitMapForCopyBits(x) (&(((GrafPtr)(x))->portBits))
+
+#else
+ #define GetPortPixRowBytes(x) (GetPixRowBytes(GetPortPixMap(x)) )
+ #define GetGDevPixMap(x) ((**(x)).gdPMap)
+
+#endif
+
+typedef struct private_hwdata {
+
+ GWorldPtr offscreen; // offscreen gworld in VRAM or AGP
+
+ #ifdef DSP_TRY_CC_AND_AA
+ GWorldPtr mask; // transparent mask
+ RGBColor alpha; // alpha color
+ RGBColor trans; // transparent color
+ #endif
+
+} private_hwdata;
+
+typedef private_hwdata private_swdata ; /* have same fields */
+
+/* Macintosh toolbox driver bootstrap functions */
+
+static int DSp_Available(void)
+{
+ /* Check for DrawSprocket */
+#if ! TARGET_API_MAC_OSX
+ /* This check is only meaningful if you weak-link DrawSprocketLib */
+ return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress);
+#else
+ return 1; // DrawSprocket.framework doesn't have it all, but it's there
+#endif
+}
+
+static void DSp_DeleteDevice(SDL_VideoDevice *device)
+{
+ /* -dw- taking no chances with null pointers */
+ if (device) {
+
+ if (device->hidden) {
+
+ if (device->hidden->dspinfo)
+ SDL_free(device->hidden->dspinfo);
+
+ SDL_free(device->hidden);
+ }
+ SDL_free(device);
+ }
+}
+
+static SDL_VideoDevice *DSp_CreateDevice(int devindex)
+{
+ SDL_VideoDevice *device;
+
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
+ if ( device ) {
+ SDL_memset(device, 0, sizeof (*device));
+ device->hidden = (struct SDL_PrivateVideoData *)
+ SDL_malloc((sizeof *device->hidden));
+ if (device->hidden)
+ SDL_memset(device->hidden, 0, sizeof ( *(device->hidden) ) );
+ }
+ if ( (device == NULL) || (device->hidden == NULL) ) {
+ SDL_OutOfMemory();
+
+ if ( device ) {
+
+ if (device->hidden)
+ SDL_free(device->hidden);
+
+ SDL_free(device);
+ }
+
+ return(NULL);
+ }
+
+ /* Allocate DrawSprocket information */
+ device->hidden->dspinfo = (struct DSpInfo *)SDL_malloc(
+ (sizeof *device->hidden->dspinfo));
+ if ( device->hidden->dspinfo == NULL ) {
+ SDL_OutOfMemory();
+ SDL_free(device->hidden);
+ SDL_free(device);
+ return(0);
+ }
+ SDL_memset(device->hidden->dspinfo, 0, (sizeof *device->hidden->dspinfo));
+
+ /* Set the function pointers */
+ device->VideoInit = DSp_VideoInit;
+ device->ListModes = DSp_ListModes;
+ device->SetVideoMode = DSp_SetVideoMode;
+ device->SetColors = DSp_SetColors;
+ device->UpdateRects = NULL;
+ device->VideoQuit = DSp_VideoQuit;
+ device->AllocHWSurface = DSp_AllocHWSurface;
+ device->CheckHWBlit = NULL;
+ device->FillHWRect = NULL;
+ device->SetHWColorKey = NULL;
+ device->SetHWAlpha = NULL;
+ device->LockHWSurface = DSp_LockHWSurface;
+ device->UnlockHWSurface = DSp_UnlockHWSurface;
+ device->FlipHWSurface = DSp_FlipHWSurface;
+ device->FreeHWSurface = DSp_FreeHWSurface;
+#if SDL_MACCLASSIC_GAMMA_SUPPORT
+ device->SetGammaRamp = Mac_SetGammaRamp;
+ device->GetGammaRamp = Mac_GetGammaRamp;
+#endif
+#if SDL_VIDEO_OPENGL
+ device->GL_MakeCurrent = Mac_GL_MakeCurrent;
+ device->GL_SwapBuffers = DSp_GL_SwapBuffers;
+ device->GL_LoadLibrary = Mac_GL_LoadLibrary;
+ device->GL_GetProcAddress = Mac_GL_GetProcAddress;
+#endif
+ device->SetCaption = NULL;
+ device->SetIcon = NULL;
+ device->IconifyWindow = NULL;
+ device->GrabInput = NULL;
+ device->GetWMInfo = NULL;
+ device->FreeWMCursor = Mac_FreeWMCursor;
+ device->CreateWMCursor = Mac_CreateWMCursor;
+ device->ShowWMCursor = Mac_ShowWMCursor;
+ device->WarpWMCursor = Mac_WarpWMCursor;
+ device->InitOSKeymap = Mac_InitOSKeymap;
+ device->PumpEvents = Mac_PumpEvents;
+
+ device->GrabInput = NULL;
+ device->CheckMouseMode = NULL;
+
+ device->free = DSp_DeleteDevice;
+
+ return device;
+}
+
+VideoBootStrap DSp_bootstrap = {
+ "DSp", "MacOS DrawSprocket",
+ DSp_Available, DSp_CreateDevice
+};
+
+/* Use DSp/Display Manager to build mode list for given screen */
+static SDL_Rect** DSp_BuildModeList (const GDHandle gDevice, int *displayWidth, int *displayHeight)
+{
+ DSpContextAttributes attributes;
+ DSpContextReference context;
+ DisplayIDType displayID;
+ SDL_Rect temp_list [16];
+ SDL_Rect **mode_list;
+ int width, height, i, j;
+
+ #if TARGET_API_MAC_OSX
+
+ displayID = 0;
+
+ #else
+ /* Ask Display Manager for integer id of screen device */
+ if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) {
+ return NULL;
+ }
+ #endif
+ /* Get the first possible DSp context on this device */
+ if ( DSpGetFirstContext (displayID, &context) != noErr ) {
+ return NULL;
+ }
+
+ if ( DSpContext_GetAttributes (context, &attributes) != noErr )
+ return NULL;
+
+ *displayWidth = attributes.displayWidth;
+ *displayHeight = attributes.displayHeight;
+
+ for ( i = 0; i < SDL_arraysize(temp_list); i++ ) {
+ width = attributes.displayWidth;
+ height = attributes.displayHeight;
+
+ temp_list [i].x = 0 | attributes.displayBestDepth;
+ temp_list [i].y = 0;
+ temp_list [i].w = width;
+ temp_list [i].h = height;
+
+ /* DSp will report many different contexts with the same width and height. */
+ /* They will differ in bit depth and refresh rate. */
+ /* We will ignore them until we reach one with a different width/height */
+ /* When there are no more contexts to look at, we will quit building the list*/
+ while ( width == attributes.displayWidth && height == attributes.displayHeight ) {
+
+ OSStatus err = DSpGetNextContext (context, &context);
+ if (err != noErr)
+ if (err == kDSpContextNotFoundErr)
+ goto done;
+ else
+ return NULL;
+
+ if ( DSpContext_GetAttributes (context, &attributes) != noErr )
+ return NULL;
+
+ temp_list [i].x |= attributes.displayBestDepth;
+ }
+ }
+done:
+ i++; /* i was not incremented before kicking out of the loop */
+
+ mode_list = (SDL_Rect**) SDL_malloc (sizeof (SDL_Rect*) * (i+1));
+ if (mode_list) {
+
+ /* -dw- new stuff: build in reverse order so largest sizes list first */
+ for (j = i-1; j >= 0; j--) {
+ mode_list [j] = (SDL_Rect*) SDL_malloc (sizeof (SDL_Rect));
+ if (mode_list [j])
+ SDL_memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect));
+ else {
+ SDL_OutOfMemory ();
+ return NULL;
+ }
+ }
+ mode_list [i] = NULL; /* append null to the end */
+ }
+ else {
+ SDL_OutOfMemory ();
+ return NULL;
+ }
+
+ return mode_list;
+}
+
+static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat)
+{
+ /*
+ VRAM GWorlds are only available on OS 9 or later.
+ Even with OS 9, some display drivers won't support it,
+ so we create a test GWorld and check for errors.
+ */
+
+ long versionSystem;
+
+ dsp_vram_available = SDL_FALSE;
+ dsp_agp_available = SDL_FALSE;
+
+ Gestalt ('sysv', &versionSystem);
+ if (0x00000860 < (versionSystem & 0x0000FFFF)) {
+
+ GWorldPtr offscreen;
+ OSStatus err;
+ Rect bounds;
+
+ SetRect (&bounds, 0, 0, 320, 240);
+
+#if useDistantHdwrMem && useLocalHdwrMem
+ err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice);
+ if (err == noErr) {
+ dsp_vram_available = SDL_TRUE;
+ DisposeGWorld (offscreen);
+ }
+
+ err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice);
+ if (err == noErr) {
+ DisposeGWorld (offscreen);
+ dsp_agp_available = SDL_TRUE;
+ }
+#endif
+ }
+}
+
+static int DSp_GetMainDevice (_THIS, GDHandle *device)
+{
+
+#if TARGET_API_MAC_OSX
+ /* DSpUserSelectContext not available on OS X */
+ *device = GetMainDevice();
+ return 0;
+#else
+
+ DSpContextAttributes attrib;
+ DSpContextReference context;
+ DisplayIDType display_id;
+ GDHandle main_device;
+ GDHandle device_list;
+
+ device_list = GetDeviceList ();
+ main_device = GetMainDevice ();
+
+ /* Quick check to avoid slower method when only one display exists */
+ if ( (**device_list).gdNextGD == NULL ) {
+ *device = main_device;
+ return 0;
+ }
+
+ SDL_memset (&attrib, 0, sizeof (DSpContextAttributes));
+
+ /* These attributes are hopefully supported on all devices...*/
+ attrib.displayWidth = 640;
+ attrib.displayHeight = 480;
+ attrib.displayBestDepth = 8;
+ attrib.backBufferBestDepth = 8;
+ attrib.displayDepthMask = kDSpDepthMask_All;
+ attrib.backBufferDepthMask = kDSpDepthMask_All;
+ attrib.colorNeeds = kDSpColorNeeds_Require;
+ attrib.pageCount = 1;
+
+ if (noErr != DMGetDisplayIDByGDevice (main_device, &display_id, SDL_FALSE)) {
+ SDL_SetError ("Display Manager couldn't associate GDevice with a Display ID");
+ return (-1);
+ }
+
+ /* Put up dialog on main display to select which display to use */
+ if (noErr != DSpUserSelectContext (&attrib, display_id, NULL, &context)) {
+ SDL_SetError ("DrawSprocket couldn't create a context");
+ return (-1);
+ }
+
+ if (noErr != DSpContext_GetDisplayID (context, &display_id)) {
+ SDL_SetError ("DrawSprocket couldn't get display ID");
+ return (-1);
+ }
+
+ if (noErr != DMGetGDeviceByDisplayID (display_id, &main_device, SDL_FALSE)) {
+ SDL_SetError ("Display Manager couldn't associate Display ID with GDevice");
+ return (-1);
+ }
+
+ *device = main_device;
+ return (0);
+#endif
+}
+
+static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat)
+{
+ NumVersion dsp_version = { 0x01, 0x00, 0x00, 0x00 };
+
+#if UNIVERSAL_INTERFACES_VERSION > 0x0320
+ dsp_version = DSpGetVersion ();
+#endif
+
+ if ( (dsp_version.majorRev == 1 && dsp_version.minorAndBugRev < 0x73) ||
+ (dsp_version.majorRev < 1) ) {
+
+ /* StandardAlert (kAlertStopAlert, "\pError!",
+ "\pI need DrawSprocket 1.7.3 or later!\n"
+ "You can find a newer version at http://www.apple.com/swupdates.",
+ NULL, NULL);
+ */
+ SDL_SetError ("DrawSprocket version is too old. Need 1.7.3 or later.");
+ return (-1);
+ }
+
+ if ( DSpStartup () != noErr ) {
+ SDL_SetError ("DrawSprocket couldn't startup");
+ return(-1);
+ }
+
+ /* Start DSpintosh events */
+ Mac_InitEvents(this);
+
+ /* Get a handle to the main monitor, or choose one on multiple monitor setups */
+ if ( DSp_GetMainDevice(this, &SDL_Display) < 0)
+ return (-1);
+
+ /* Determine pixel format */
+ vformat->BitsPerPixel = GetPixDepth ( (**SDL_Display).gdPMap );
+ dsp_old_depth = vformat->BitsPerPixel;
+
+ switch (vformat->BitsPerPixel) {
+ case 16:
+ vformat->Rmask = 0x00007c00;
+ vformat->Gmask = 0x000003e0;
+ vformat->Bmask = 0x0000001f;
+ break;
+ default:
+ break;
+ }
+
+ if ( DSp_CreatePalette (this) < 0 ) {
+ SDL_SetError ("Could not create palette");
+ return (-1);
+ }
+
+ /* Get a list of available fullscreen modes */
+ SDL_modelist = DSp_BuildModeList (SDL_Display,
+ &this->info.current_w, &this->info.current_h);
+ if (SDL_modelist == NULL) {
+ SDL_SetError ("DrawSprocket could not build a mode list");
+ return (-1);
+ }
+
+ /* Check for VRAM and AGP GWorlds for HW Blitting */
+ DSp_IsHWAvailable (this, vformat);
+
+ this->info.wm_available = 0;
+
+ if (dsp_vram_available || dsp_agp_available) {
+
+ this->info.hw_available = SDL_TRUE;
+
+ this->CheckHWBlit = DSp_CheckHWBlit;
+ this->info.blit_hw = SDL_TRUE;
+
+ this->FillHWRect = DSp_FillHWRect;
+ this->info.blit_fill = SDL_TRUE;
+
+ #ifdef DSP_TRY_CC_AND_AA
+ this->SetHWColorKey = DSp_SetHWColorKey;
+ this->info.blit_hw_CC = SDL_TRUE;
+
+ this->SetHWAlpha = DSp_SetHWAlpha;
+ this->info.blit_hw_A = SDL_TRUE;
+ #endif
+
+ }
+
+ return(0);
+}
+
+static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
+{
+ static SDL_Rect *dsp_modes[16];
+ int i = 0, j = 0;
+
+ if ( format->BitsPerPixel == 0 )
+ return ( (SDL_Rect**) NULL );
+
+ while (SDL_modelist[i] != NULL) {
+
+ if (SDL_modelist[i]->x & format->BitsPerPixel) {
+ dsp_modes[j] = SDL_modelist[i];
+ j++;
+ }
+ i++;
+ }
+
+ dsp_modes[j] = NULL;
+
+ return dsp_modes;
+}
+
+/* Various screen update functions available */
+static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
+
+#if ! TARGET_API_MAC_OSX
+
+static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */
+
+Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con )
+{
+ retrace_count++;
+
+ return 1; /* Darrell, is this right? */
+}
+
+static void DSp_SetHWError (OSStatus err, int is_agp)
+{
+ char message[1024];
+ const char *fmt, *mem;
+
+ if ( is_agp ) {
+ mem = "AGP Memory";
+ } else {
+ mem = "VRAM";
+ }
+ switch(err) {
+ case memFullErr:
+ fmt = "Hardware surface possible but not enough %s available";
+ break;
+ case cDepthErr:
+ fmt = "Hardware surface possible but invalid color depth";
+ break;
+ default:
+ fmt = "Hardware surface could not be allocated in %s - unknown error";
+ break;
+ }
+ SDL_snprintf(message, SDL_arraysize(message), fmt, mem);
+ SDL_SetError(message);
+}
+#endif // TARGET_API_MAC_OSX
+
+/* put up a dialog to verify display change */
+static int DSp_ConfirmSwitch () {
+
+ /* resource id's for dialog */
+ const int rDialog = 1002;
+ const int bCancel = 1;
+ const int bOK = 2;
+
+ DialogPtr dialog;
+ OSStatus err;
+ SInt32 response;
+ DialogItemIndex item = 0;
+ GrafPtr savePort;
+
+ GetPort (&savePort);
+
+ dialog = GetNewDialog (rDialog, NULL, (WindowPtr) -1);
+ if (dialog == NULL)
+ return (0);
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetDialogPort(dialog));
+#else
+ SetPort ((WindowPtr) dialog);
+#endif
+
+ SetDialogDefaultItem (dialog, bCancel);
+ SetDialogCancelItem (dialog, bCancel);
+
+ SetEventMask (everyEvent);
+ FlushEvents (everyEvent, 0);
+
+ /* On MacOS 8.5 or later, we can make the dialog go away after 15 seconds */
+ /* This is good since it's possible user can't even see the dialog! */
+ /* Requires linking to DialogsLib */
+ err = Gestalt(gestaltSystemVersion,&response);
+ if (err == noErr && response >= 0x00000850) {
+ SetDialogTimeout(dialog, bCancel, 15);
+ }
+
+ do {
+
+ ModalDialog ( NULL, &item );
+
+ } while ( item != bCancel && item != bOK && err != noErr);
+
+
+ DisposeDialog (dialog);
+ SetPort (savePort);
+
+ SetEventMask(everyEvent - autoKeyMask);
+ FlushEvents(everyEvent, 0);
+
+ return (item - 1);
+}
+
+static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current)
+{
+
+
+ if ( current->flags & SDL_OPENGL ) {
+ Mac_GL_Quit (this);
+ }
+
+ if (dsp_context != NULL) {
+
+ GWorldPtr front;
+ DSpContext_GetFrontBuffer (dsp_context, &front);
+
+ if (front != dsp_back_buffer)
+ DisposeGWorld (dsp_back_buffer);
+
+ if (current->hwdata)
+ SDL_free(current->hwdata);
+
+ DSpContext_SetState (dsp_context, kDSpContextState_Inactive );
+ DSpContext_Release (dsp_context);
+
+ dsp_context = NULL;
+ }
+
+ if (SDL_Window != NULL) {
+ DisposeWindow (SDL_Window);
+ SDL_Window = NULL;
+ }
+
+ current->pixels = NULL;
+ current->flags = 0;
+}
+
+static SDL_Surface *DSp_SetVideoMode(_THIS,
+ SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
+{
+
+#if !TARGET_API_MAC_OSX
+ DisplayIDType display_id;
+ Fixed freq;
+#endif
+ DSpContextAttributes attrib;
+ OSStatus err;
+ UInt32 rmask = 0, gmask = 0, bmask = 0;
+
+ int page_count;
+ int double_buf;
+ int hw_surface;
+ int use_dsp_back_buffer;
+
+ DSp_UnsetVideoMode (this, current);
+
+ if (bpp != dsp_old_depth)
+ DSp_DestroyPalette (this);
+
+ double_buf = (flags & SDL_DOUBLEBUF) != 0;
+ hw_surface = (flags & SDL_HWSURFACE) != 0;
+ use_dsp_back_buffer = !dsp_vram_available || !hw_surface ;
+
+ current->flags |= SDL_FULLSCREEN;
+
+rebuild:
+
+ if ( double_buf && use_dsp_back_buffer ) {
+ page_count = 2;
+ } else {
+ page_count = 1;
+ }
+
+ SDL_memset (&attrib, 0, sizeof (DSpContextAttributes));
+ attrib.displayWidth = width;
+ attrib.displayHeight = height;
+ attrib.displayBestDepth = bpp;
+ attrib.backBufferBestDepth = bpp;
+ attrib.displayDepthMask = kDSpDepthMask_All;
+ attrib.backBufferDepthMask = kDSpDepthMask_All;
+ attrib.colorNeeds = kDSpColorNeeds_Require;
+ attrib.colorTable = 0;
+ attrib.pageCount = page_count;
+ #if TARGET_API_MAC_OSX || UNIVERSAL_INTERFACES_VERSION == 0x0320
+
+ if ( DSpFindBestContext (&attrib, &dsp_context) != noErr ) {
+ SDL_SetError ("DrawSprocket couldn't find a context");
+ return NULL;
+ }
+
+ #else
+ if ( noErr != DMGetDisplayIDByGDevice (SDL_Display, &display_id, SDL_FALSE) ) {
+ SDL_SetError ("Display Manager couldn't associate GDevice with display_id");
+ return NULL;
+ }
+ if ( DSpFindBestContextOnDisplayID(&attrib, &dsp_context, display_id) != noErr ) {
+ SDL_SetError ("DrawSprocket couldn't find a suitable context on given display");
+ return NULL;
+ }
+
+ #endif
+ if ( DSpContext_Reserve (dsp_context, &attrib) != noErr ) {
+ SDL_SetError ("DrawSprocket couldn't get the needed resources to build the display");
+ return NULL;
+ }
+
+ if ( (err = DSpContext_SetState (dsp_context, kDSpContextState_Active)) != noErr ) {
+
+ if (err == kDSpConfirmSwitchWarning) {
+
+ if ( ! DSp_ConfirmSwitch () ) {
+
+ DSpContext_Release (dsp_context);
+ dsp_context = NULL;
+ SDL_SetError ("User cancelled display switch");
+ return NULL;
+ }
+ else
+ /* Have to reactivate context. Why? */
+ DSpContext_SetState (dsp_context, kDSpContextState_Active);
+
+ }
+ else {
+ SDL_SetError ("DrawSprocket couldn't activate the context");
+ return NULL;
+ }
+ }
+
+
+ if (bpp != dsp_old_depth) {
+
+ DSp_CreatePalette (this);
+
+ /* update format if display depth changed */
+ if (bpp == 16) {
+
+ rmask = 0x00007c00;
+ gmask = 0x000003e0;
+ bmask = 0x0000001f;
+ }
+ if ( ! SDL_ReallocFormat (current, bpp, rmask, gmask, bmask, 0 ) ) {
+
+ SDL_SetError ("Could not reallocate video format.");
+ return(NULL);
+ }
+ }
+
+ if (!double_buf) {
+
+ /* single-buffer context */
+ DSpContext_GetFrontBuffer (dsp_context, &dsp_back_buffer);
+
+ current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata));
+ if (current ->hwdata == NULL) {
+ SDL_OutOfMemory ();
+ return NULL;
+ }
+ current->hwdata->offscreen = dsp_back_buffer;
+ current->flags |= SDL_HWSURFACE;
+ this->UpdateRects = DSp_DirectUpdate;
+ }
+ else if ( use_dsp_back_buffer ) {
+
+ DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer);
+
+ current->flags |= SDL_DOUBLEBUF | SDL_SWSURFACE; /* only front buffer is in VRAM */
+ this->UpdateRects = DSp_DSpUpdate;
+ }
+ else if ( DSp_NewHWSurface(this, &dsp_back_buffer, bpp, width-1, height-1) == 0 ) {
+
+ current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata));
+ if (current ->hwdata == NULL) {
+ SDL_OutOfMemory ();
+ return NULL;
+ }
+
+ SDL_memset (current->hwdata, 0, sizeof (private_hwdata));
+ current->hwdata->offscreen = dsp_back_buffer;
+ current->flags |= SDL_DOUBLEBUF | SDL_HWSURFACE;
+ this->UpdateRects = DSp_DirectUpdate; /* hardware doesn't do update rects, must be page-flipped */
+ }
+ else {
+
+ DSpContext_Release (dsp_context);
+ use_dsp_back_buffer = SDL_TRUE;
+ goto rebuild;
+ }
+
+ current->pitch = GetPortPixRowBytes(dsp_back_buffer) & 0x3FFF;
+ current->pixels = GetPixBaseAddr(GetPortPixMap(dsp_back_buffer));
+
+ current->w = width;
+ current->h = height;
+
+ #if ! TARGET_API_MAC_OSX
+
+ if (use_dsp_back_buffer) {
+
+ DSpContext_GetMonitorFrequency (dsp_context, &freq);
+ DSpContext_SetMaxFrameRate (dsp_context, freq >> 16);
+ }
+
+
+ if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) )
+ DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL);
+ #endif
+
+ if (bpp == 8)
+ current->flags |= SDL_HWPALETTE;
+
+ if (flags & SDL_OPENGL) {
+
+ Rect rect;
+ RGBColor rgb = { 0.0, 0.0, 0.0 };
+ GrafPtr save_port;
+
+ SetRect (&rect, 0, 0, width, height);
+ SDL_Window = NewCWindow(nil, &( (**SDL_Display).gdRect), "\p", SDL_TRUE, plainDBox, (WindowPtr)-1, SDL_FALSE, 0);
+
+ if (SDL_Window == NULL) {
+
+ SDL_SetError ("DSp_SetVideoMode : OpenGL window could not be created.");
+ return NULL;
+ }
+
+ /* Set window color to black to avoid white flash*/
+ GetPort (&save_port);
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort(SDL_Window));
+#else
+ SetPort (SDL_Window);
+#endif
+ RGBForeColor (&rgb);
+ PaintRect (&rect);
+ SetPort (save_port);
+
+ SetPortWindowPort (SDL_Window);
+ SelectWindow (SDL_Window);
+
+ if ( Mac_GL_Init (this) < 0 ) {
+
+ SDL_SetError ("DSp_SetVideoMode : could not create OpenGL context.");
+ return NULL;
+ }
+
+ current->flags |= SDL_OPENGL;
+ }
+
+ return current;
+}
+
+#ifdef DSP_TRY_CC_AND_AA
+
+static int DSp_MakeHWMask (_THIS, SDL_Surface *surface)
+{
+ GDHandle save_device;
+ CGrafPtr save_port;
+ GWorldPtr temp;
+ RGBColor black = { 0, 0, 0 };
+ RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF };
+ Rect rect;
+
+ Uint32 depth = GetPixDepth ( GetGDevPixMap (SDL_Display) );
+
+ SetRect (&rect, 0, 0, surface->w, surface->h);
+
+ if ( noErr != NewGWorld (&(surface->hwdata->mask), depth, &rect, 0, SDL_Display, 0 ) < 0 ) {
+
+ SDL_OutOfMemory ();
+ return (-1);
+ }
+
+ if ( noErr != NewGWorld (&temp, depth, &rect, 0 , SDL_Display, 0 ) ) {
+
+ SDL_OutOfMemory ();
+ return (-1);
+ }
+
+
+ GetGWorld (&save_port, &save_device);
+ SetGWorld (surface->hwdata->mask, SDL_Display);
+
+ RGBForeColor (&white);
+ PaintRect (&rect);
+
+ RGBBackColor (&(surface->hwdata->trans));
+
+ CopyBits ( GetPortBitMapForCopyBits(surface->hwdata->offscreen),
+ GetPortBitMapForCopyBits(surface->hwdata->mask),
+ &rect, &rect, transparent, NULL );
+
+ SetGWorld (surface->hwdata->mask, SDL_Display);
+ SetGWorld (save_port, save_device);
+ return (0);
+}
+
+static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha)
+{
+ surface->hwdata->alpha.red = (alpha / 255.0) * 65535;
+ surface->hwdata->alpha.blue = (alpha / 255.0) * 65535;
+ surface->hwdata->alpha.green = (alpha / 255.0) * 65535;
+
+ surface->flags |= SDL_SRCALPHA;
+
+ if (surface->flags & SDL_SRCCOLORKEY) {
+ return(DSp_MakeHWMask (this, surface));
+ }
+ return(0);
+}
+
+static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
+{
+ CGrafPtr save_port;
+ GDHandle save_device;
+
+ GetGWorld (&save_port, &save_device);
+ SetGWorld (surface->hwdata->offscreen, NULL);
+
+ Index2Color (key, &(surface->hwdata->trans));
+ surface->flags |= SDL_SRCCOLORKEY;
+
+ SetGWorld (save_port, save_device);
+
+ if ( surface->flags & SDL_SRCALPHA ) {
+ return(DSp_MakeHWMask (this, surface));
+ }
+ return(0);
+}
+
+#endif /* DSP_TRY_CC_AND_AA */
+
+static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height) {
+
+ OSStatus err;
+ Rect bounds;
+
+ SetRect (&bounds, 0, 0, width, height);
+
+ #if useDistantHdwrMem && useLocalHdwrMem
+ if (dsp_vram_available) {
+ /* try VRAM */
+ err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useDistantHdwrMem | noNewDevice );
+ if (err != noErr)
+ DSp_SetHWError (err, SDL_FALSE);
+ else
+ return (0);
+ }
+
+ if (dsp_agp_available) {
+ /* try AGP */
+ err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useLocalHdwrMem | noNewDevice );
+
+ if (err != noErr)
+ DSp_SetHWError (err, SDL_TRUE);
+ else
+ return (0);
+ }
+#endif
+
+ return (-1);
+}
+
+static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface)
+{
+ GWorldPtr temp;
+
+ if ( DSp_NewHWSurface (this, &temp, surface->format->BitsPerPixel, surface->w, surface->h) < 0 )
+ return (-1);
+
+ surface->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata));
+ if (surface->hwdata == NULL) {
+ SDL_OutOfMemory ();
+ return -1;
+ }
+
+ SDL_memset (surface->hwdata, 0, sizeof(private_hwdata));
+ surface->hwdata->offscreen = temp;
+ surface->pitch = GetPixRowBytes (GetPortPixMap (temp)) & 0x3FFF;
+ surface->pixels = GetPixBaseAddr (GetPortPixMap (temp));
+ surface->flags |= SDL_HWSURFACE;
+#ifdef DSP_TRY_CC_AND_AA
+ surface->flags |= SDL_HWACCEL;
+#endif
+ return 0;
+}
+
+static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface)
+{
+ if (surface->hwdata->offscreen != NULL)
+ DisposeGWorld (surface->hwdata->offscreen);
+ SDL_free(surface->hwdata);
+
+ surface->pixels = NULL;
+}
+
+static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest)
+{
+ int accelerated;
+
+ /* Set initial acceleration on */
+ src->flags |= SDL_HWACCEL;
+
+ /* Set the surface attributes */
+ if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
+ if ( ! this->info.blit_hw_A ) {
+ src->flags &= ~SDL_HWACCEL;
+ }
+ }
+ if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
+ if ( ! this->info.blit_hw_CC ) {
+ src->flags &= ~SDL_HWACCEL;
+ }
+ }
+
+ /* Check to see if final surface blit is accelerated */
+ accelerated = !!(src->flags & SDL_HWACCEL);
+ if ( accelerated ) {
+ src->map->hw_blit = DSp_HWAccelBlit;
+ }
+ return(accelerated);
+}
+
+static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect)
+{
+ CGrafPtr save_port;
+ GDHandle save_device;
+ Rect src_rect, dst_rect;
+ RGBColor black = { 0, 0, 0 };
+ RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF };
+
+#ifdef DSP_TRY_CC_AND_AA
+ UInt32 mode;
+#endif
+
+ SetRect (&src_rect, srcrect->x, srcrect->y, srcrect->x + srcrect->w, srcrect->y + srcrect->h);
+ SetRect (&dst_rect, dstrect->x, dstrect->y, dstrect->x + dstrect->w, dstrect->y + dstrect->h);
+
+ GetGWorld (&save_port, &save_device);
+ SetGWorld (dst->hwdata->offscreen, NULL);
+
+ RGBForeColor (&black);
+ RGBBackColor (&white);
+
+#ifdef DSP_TRY_CC_AND_AA
+
+ if ( (src->flags & SDL_SRCCOLORKEY) &&
+ (src->flags & SDL_SRCALPHA) ) {
+
+ OpColor (&(src->hwdata->alpha));
+
+ CopyDeepMask ( GetPortBitMapForCopyBits(src->hwdata->offscreen),
+ GetPortBitMapForCopyBits(src->hwdata->mask),
+ GetPortBitMapForCopyBits(dst->hwdata->offscreen),
+ &src_rect, &src_rect, &dst_rect,
+ blend,
+ NULL );
+ }
+ else {
+
+ if ( src->flags & SDL_SRCCOLORKEY) {
+ RGBBackColor (&(src->hwdata->trans) );
+ mode = transparent;
+ }
+ else if (src->flags & SDL_SRCALPHA) {
+
+ OpColor (&(src->hwdata->alpha));
+ mode = blend;
+ }
+ else {
+
+ mode = srcCopy;
+ }
+
+ CopyBits ( GetPortBitMapForCopyBits(src->hwdata->offscreen),
+ GetPortBitMapForCopyBits(dst->hwdata->offscreen),
+ &src_rect, &dst_rect, mode, NULL );
+ }
+#else
+
+ CopyBits ( &(((GrafPtr)(src->hwdata->offscreen))->portBits),
+ &(((GrafPtr)(dst->hwdata->offscreen))->portBits),
+ &src_rect, &dst_rect, srcCopy, NULL );
+
+#endif /* DSP_TRY_CC_AND_AA */
+
+ SetGWorld (save_port, save_device);
+
+ return(0);
+}
+
+static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color)
+{
+ CGrafPtr save_port;
+ GDHandle save_device;
+ Rect fill_rect;
+ RGBColor rgb;
+
+ SetRect (&fill_rect, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
+
+ GetGWorld (&save_port, &save_device);
+ SetGWorld (dst->hwdata->offscreen, NULL);
+
+ Index2Color (color, &rgb);
+
+ RGBForeColor (&rgb);
+ PaintRect (&fill_rect);
+
+ SetGWorld (save_port, save_device);
+
+ return(0);
+}
+
+static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface)
+{
+ if ( (surface->flags & SDL_HWSURFACE) ) {
+ CGrafPtr dsp_front_buffer, save_port;
+ Rect rect;
+
+ #if ! TARGET_API_MAC_OSX
+ unsigned int old_count;
+ #endif
+
+ /* pseudo page flipping for VRAM back buffer*/
+ DSpContext_GetFrontBuffer (dsp_context, &dsp_front_buffer);
+ SetRect (&rect, 0, 0, surface->w-1, surface->h-1);
+
+ GetPort ((GrafPtr *)&save_port);
+ SetPort ((GrafPtr)dsp_front_buffer);
+
+ /* wait for retrace */
+ /* I have tried doing the swap in interrupt routine (VBL Proc) to do */
+ /* it asynchronously, but apparently CopyBits isn't interrupt safe */
+
+ #if ! TARGET_API_MAC_OSX
+ #ifndef DSP_NO_SYNC_VBL
+ old_count = retrace_count;
+ while (old_count == retrace_count)
+ ;
+ #endif
+ #endif
+
+ CopyBits ( GetPortBitMapForCopyBits(dsp_back_buffer),
+ GetPortBitMapForCopyBits(dsp_front_buffer),
+ &rect, &rect, srcCopy, NULL );
+
+ SetPort ((GrafPtr)save_port);
+
+ } else {
+ /* not really page flipping at all: DSp just blits the dirty rectangles from DSp_UpdateRects */
+ Boolean busy_flag;
+ DSpContext_SwapBuffers (dsp_context, NULL, &busy_flag); /* this waits for VBL */
+ DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer);
+ surface->pixels = GetPixBaseAddr( GetPortPixMap(dsp_back_buffer) );
+ }
+ return(0);
+}
+
+static int DSp_LockHWSurface(_THIS, SDL_Surface *surface)
+{
+ if ( LockPixels (GetGWorldPixMap (surface->hwdata->offscreen)) )
+ return 0;
+ else
+ return -1;
+}
+
+static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface)
+{
+ UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen));
+}
+
+static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects)
+{
+ return;
+}
+
+static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects)
+{
+#if ! TARGET_API_MAC_OSX /* Unsupported DSp in here */
+ int i;
+ Rect rect;
+
+ for (i = 0; i < numrects; i++) {
+
+ rect.top = sdl_rects[i].y;
+ rect.left = sdl_rects[i].x;
+ rect.bottom = sdl_rects[i].h + sdl_rects[i].y;
+ rect.right = sdl_rects[i].w + sdl_rects[i].x;
+
+ DSpContext_InvalBackBufferRect (dsp_context, &rect);
+ }
+#endif
+}
+
+static int DSp_CreatePalette(_THIS) {
+
+
+ /* Create our palette */
+ SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8);
+ if ( SDL_CTab == nil ) {
+ SDL_OutOfMemory();
+ return(-1);
+ }
+ (**SDL_CTab).ctSeed = GetCTSeed();
+ (**SDL_CTab).ctFlags = 0;
+ (**SDL_CTab).ctSize = 255;
+ CTabChanged(SDL_CTab);
+ SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0);
+
+ return 0;
+}
+
+static int DSp_DestroyPalette(_THIS) {
+
+ /* Free palette and restore original one */
+ if ( SDL_CTab != nil ) {
+ DisposeHandle((Handle)SDL_CTab);
+ SDL_CTab = nil;
+ }
+ if ( SDL_CPal != nil ) {
+ DisposePalette(SDL_CPal);
+ SDL_CPal = nil;
+ }
+ RestoreDeviceClut(SDL_Display);
+
+ return (0);
+}
+
+static int DSp_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
+{
+ CTabHandle cTab;
+
+ int i;
+
+ cTab = SDL_CTab;
+
+ /* Verify the range of colors */
+ if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) {
+ return(0);
+ }
+
+ /* Set the screen palette and update the display */
+ for(i = 0; i < ncolors; i++) {
+ int j = firstcolor + i;
+ (**cTab).ctTable[j].value = j;
+ (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r;
+ (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g;
+ (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b;
+ }
+
+ SetGDevice(SDL_Display);
+ SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable);
+
+ return(1);
+}
+
+void DSp_VideoQuit(_THIS)
+{
+ int i;
+
+ /* Free current video mode */
+ DSp_UnsetVideoMode(this, this->screen);
+
+ /* Free Palette and restore original */
+ DSp_DestroyPalette (this);
+
+#if SDL_MACCLASSIC_GAMMA_SUPPORT
+ Mac_QuitGamma(this);
+#endif
+
+ /* Free list of video modes */
+ if ( SDL_modelist != NULL ) {
+ for ( i=0; SDL_modelist[i]; i++ ) {
+ SDL_free(SDL_modelist[i]);
+ }
+ SDL_free(SDL_modelist);
+ SDL_modelist = NULL;
+ }
+
+ /* Unload DrawSprocket */
+ DSpShutdown ();
+}
+
+#if SDL_VIDEO_OPENGL
+
+/* swap buffers with v-sync */
+static void DSp_GL_SwapBuffers (_THIS) {
+
+ #ifndef DSP_NO_SYNC_OPENGL
+
+ unsigned int old_count;
+
+ old_count = retrace_count;
+ while (old_count == retrace_count)
+ ;
+ #endif
+
+ aglSwapBuffers (glContext);
+}
+
+#endif