| /* |
| 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 |