SDL_dspvideo.c
资源名称:NETVIDEO.rar [点击查看]
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:40k
源码类别:
流媒体/Mpeg4/MP4
开发平台:
Visual C++
- /*
- SDL - Simple DirectMedia Layer
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 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
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Sam Lantinga
- slouken@libsdl.org
- */
- /*
- 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 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
- #ifdef SAVE_RCSID
- static char rcsid =
- "@(#) $Id: SDL_dspvideo.c,v 1.4 2002/04/22 21:38:05 wmay Exp $";
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #if TARGET_API_MAC_CARBON
- #include <Carbon.h>
- #else
- #include <LowMem.h>
- #include <Gestalt.h>
- #include <Devices.h>
- #include <DiskInit.h>
- #include <QDOffscreen.h>
- #endif
- #include "SDL_video.h"
- #include "SDL_blit.h"
- #include "SDL_error.h"
- #include "SDL_syswm.h"
- #include "SDL_sysvideo.h"
- #include "SDL_dspvideo.h"
- #include "SDL_macgl_c.h"
- #include "SDL_macwm_c.h"
- #include "SDL_macmouse_c.h"
- #include "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);
- #ifdef HAVE_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 */
- /* This check is only meaningful if you weak-link DrawSprocketLib */
- return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress);
- }
- static void DSp_DeleteDevice(SDL_VideoDevice *device)
- {
- /* -dw- taking no chances with null pointers */
- if (device) {
- if (device->hidden) {
- if (device->hidden->dspinfo)
- free(device->hidden->dspinfo);
- free(device->hidden);
- }
- free(device);
- }
- }
- static SDL_VideoDevice *DSp_CreateDevice(int devindex)
- {
- SDL_VideoDevice *device;
- /* Initialize all variables that we clean on shutdown */
- device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
- if ( device ) {
- memset(device, 0, sizeof (*device));
- device->hidden = (struct SDL_PrivateVideoData *)
- malloc((sizeof *device->hidden));
- if (device->hidden)
- memset(device->hidden, 0, sizeof ( *(device->hidden) ) );
- }
- if ( (device == NULL) || (device->hidden == NULL) ) {
- SDL_OutOfMemory();
- if ( device ) {
- if (device->hidden)
- free (device->hidden);
- free(device);
- }
- return(NULL);
- }
- /* Allocate DrawSprocket information */
- device->hidden->dspinfo = (struct DSpInfo *)malloc(
- (sizeof *device->hidden->dspinfo));
- if ( device->hidden->dspinfo == NULL ) {
- SDL_OutOfMemory();
- free(device->hidden);
- free(device);
- return(0);
- }
- 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;
- #ifdef HAVE_OPENGL
- device->GL_MakeCurrent = Mac_GL_MakeCurrent;
- device->GL_SwapBuffers = DSp_GL_SwapBuffers;
- #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)
- {
- 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;
- for ( i = 0; i < SDL_TABLESIZE(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**) 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*) malloc (sizeof (SDL_Rect));
- if (mode_list [j])
- 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);
- 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;
- }
- }
- }
- 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;
- }
- 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 = DSpGetVersion ();
- 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);
- 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);
- static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */
- #if ! TARGET_API_MAC_OSX
- Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con )
- {
- retrace_count++;
- return 1; /* Darrell, is this right? */
- }
- #endif
- 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;
- }
- sprintf(message, fmt, mem);
- SDL_SetError(message);
- }
- /* 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);
- SetPort (dialog);
- 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);
- DisposeWindow (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)
- 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)
- {
- DisplayIDType display_id;
- DSpContextAttributes attrib;
- Fixed freq;
- 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;
- }
- 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
- 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*) 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*) malloc (sizeof (private_hwdata));
- if (current ->hwdata == NULL) {
- SDL_OutOfMemory ();
- return NULL;
- }
- 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);
- SetPort (SDL_Window);
- 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 (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);
- }
- 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*) malloc (sizeof (private_hwdata));
- if (surface->hwdata == NULL) {
- SDL_OutOfMemory ();
- return -1;
- }
- 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);
- 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;
- unsigned int old_count;
- /* 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);
- /* Free list of video modes */
- if ( SDL_modelist != NULL ) {
- for ( i=0; SDL_modelist[i]; i++ ) {
- free(SDL_modelist[i]);
- }
- free(SDL_modelist);
- SDL_modelist = NULL;
- }
- /* Unload DrawSprocket */
- DSpShutdown ();
- }
- #ifdef HAVE_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