Descent3/ddgr_mac/macOSSurface.cpp
2024-04-16 12:56:40 -06:00

865 lines
28 KiB
C++
Raw Blame History

/*
* $Logfile: /Descent3/main/ddgr_mac/macOSSurface.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003/08/26 03:56:53 $
* $Author: kevinb $
*
* macintosh implementation of ddgr_surfaces
*
* $Log: macOSSurface.cpp,v $
* Revision 1.1.1.1 2003/08/26 03:56:53 kevinb
* initial 1.5 import
*
*
* 10 5/21/97 5:09 PM Jeremy
* made a quick hack to convert the contents of the frame buffer from
* 5-6-5 format to 1-5-5-5 format pixel data right before the video flip.
* use the #define USE_COLOR_CONVERSION_HACK to turn this on or off (see
* flipVideo for details)
*
* 9 5/20/97 11:38 PM Jeremy
* temporarily removed the mprintf's in os_surf_clear
*
* 8 5/19/97 7:08 PM Jeremy
* removed extra gamma fade in of monitor when closing down video
*
* 7 5/17/97 6:50 PM Jeremy
* implemented clearing function
*
* 6 5/15/97 1:47 AM Jeremy
* changed mprintf's to be standard (with newline at end), also fixed a
* potential bug where a variable was declared twice in a function (blit)
* but in different scopes
*
* 5 5/13/97 11:15 AM Jeremy
* removed bug in initialization code (was checking an extra variable
* m_initted instead of m_video_initted)
*
* 4 5/11/97 8:00 PM Jeremy
* implemented ddgr_os_surf_GetAspectRatio
*
* 3 5/9/97 7:13 PM Jeremy
* implemented blitting (still need to implement clearing)
*
* 2 4/15/97 7:01 PM Jeremy
* initial implementation of fullscreen (via DrawSprocket) os_surfaces.
* right now only initialization and closing of surfaces/video is
* implemented. still need to implement surface
* creation/deletion/blitting.
*
* 1 4/9/97 7:16 PM Jeremy
* initial check in
*
* $NoKeywords: $
*/
//#define check
// ---------------------------------------------------------------------------
// Macintosh Headers
// ---------------------------------------------------------------------------
#include <DrawSprocket.h>
#include <QuickDraw.h>
// ---------------------------------------------------------------------------
// Descent3 Headers
// ---------------------------------------------------------------------------
#include "pserror.h"
#include "gr.h"
#include "ddgr_mac.h"
#include "macOSSurface.h"
// ---------------------------------------------------------------------------
// Local File Types
// ---------------------------------------------------------------------------
// The FullScreenData class is intended to encapsulate the
// data necessary for interacting with DrawSprocket
// and some utility functions for dealing with full screen info
// into one structure
class CFullScreenDataObj {
public:
CFullScreenDataObj(void);
~CFullScreenDataObj(void);
bool m_video_initted;
DSpContextAttributes m_screen_attr;
DSpContextReference m_context;
DSpAltBufferReference m_underlay;
GDHandle m_save_gdevice;
GrafPtr m_save_port;
};
// This is the data type of the object pointed to in the surfaces obj ptr
// for os_surfaces
class CMacOffscreenDataObj {
public:
CMacOffscreenDataObj(void) { m_GWorld = nil; }
GWorldPtr m_GWorld;
};
// The Error class is used for passing error information around
// It is internal to this file
class CMacOSSurfErr {
public:
CMacOSSurfErr(char *inErrStr, OSErr inMacErr, ddgr_error inDDGRErr) {
m_ErrStr = inErrStr;
m_MacErr = inMacErr;
m_DDGRErr = inDDGRErr;
}
char *m_ErrStr;
OSErr m_MacErr;
ddgr_error m_DDGRErr;
};
// ---------------------------------------------------------------------------
// File Level Globals
// ---------------------------------------------------------------------------
static CFullScreenDataObj gFullScreenData;
// ------------------------------------------------------------
// Implementation of the CFullScreenDataObj class
// It is intended that an instance of this object class
// be around for the whole game if full screen mode is used.
// ------------------------------------------------------------
CFullScreenDataObj::CFullScreenDataObj(void) {
// Initialize the data members
m_video_initted = false;
memset(&m_screen_attr, 0, sizeof(m_screen_attr));
m_context = nil;
m_underlay = nil;
m_save_gdevice = nil;
m_save_port = nil;
}
CFullScreenDataObj::~CFullScreenDataObj(void) {
// Release the contexts if they were allocated?
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_InitVideo
ddgr_error ddgr_os_surf_InitVideo(ddgr_surface *sf) {
ddgr_error err = DDGRERR_SUCCESS;
OSErr macErr = noErr;
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_VIDEOSCREEN);
ASSERT(!Mac_DDGR_Lib.IsWindowed());
mprintf((0, "Initializing video.\n"));
bool userCanSelect = false;
// <20> Initialize the desired screen attributes structure
gFullScreenData.m_screen_attr.displayWidth = sf->w;
gFullScreenData.m_screen_attr.displayHeight = sf->h;
gFullScreenData.m_screen_attr.colorNeeds = kDSpColorNeeds_Require;
gFullScreenData.m_screen_attr.backBufferDepthMask = sf->bpp;
gFullScreenData.m_screen_attr.displayDepthMask = sf->bpp;
gFullScreenData.m_screen_attr.backBufferBestDepth = sf->bpp;
gFullScreenData.m_screen_attr.displayBestDepth = sf->bpp;
gFullScreenData.m_screen_attr.pageCount = (sf->flags & SURFFLAG_BACKBUFFER) ? 2 : 1;
try {
// <20> Check whether multiple monitors are available
macErr = DSpCanUserSelectContext(&(gFullScreenData.m_screen_attr), &userCanSelect);
if (macErr)
throw(CMacOSSurfErr("Error checking if user could select from different monitors.", macErr, DDGRERR_DRIVERINIT));
if (userCanSelect) {
// <20> Allow user to select a monitor from those available
macErr = DSpUserSelectContext(&(gFullScreenData.m_screen_attr), 0, nil, &(gFullScreenData.m_context));
if (macErr)
throw(CMacOSSurfErr("Error while allowing user to choose a monitor.", macErr, DDGRERR_DRIVERINIT));
} else {
// <20> Autoselect the best monitor/context
macErr = DSpFindBestContext(&(gFullScreenData.m_screen_attr), &(gFullScreenData.m_context));
if (macErr)
throw(CMacOSSurfErr("Error while autoselecting a monitor.", macErr, DDGRERR_DRIVERINIT));
}
// <20> Request hardware pageflipping if it is available when reserving the context
gFullScreenData.m_screen_attr.contextOptions |= kDSpContextOption_PageFlip;
// <20> Reserve the context (take over the monitor)
macErr = DSpContext_Reserve(gFullScreenData.m_context, &(gFullScreenData.m_screen_attr));
if (macErr)
throw(CMacOSSurfErr("Error while reserving the draw sprocket context.", macErr, DDGRERR_DRIVERINIT));
// <20> Fade out the monitor while resolution switching
macErr = DSpContext_FadeGammaOut(gFullScreenData.m_context, NULL);
if (macErr)
throw(CMacOSSurfErr("Error while fading out monitor.", macErr, DDGRERR_DRIVERINIT));
// <20> Activate the context (do the resolution/depth switch)
macErr = DSpContext_SetState(gFullScreenData.m_context, kDSpContextState_Active);
if (macErr)
throw(CMacOSSurfErr("Error while activating context", macErr, DDGRERR_DRIVERINIT));
// <20> Fade the monitor back in at the new resolution/depth
macErr = DSpContext_FadeGammaIn(gFullScreenData.m_context, NULL);
if (macErr)
throw(CMacOSSurfErr("Error while fading in monitor ", macErr, DDGRERR_DRIVERINIT));
//<2F> All's well!
gFullScreenData.m_video_initted = true;
} catch (CMacOSSurfErr theCaughtError) {
mprintf((0, theCaughtError.m_ErrStr));
mprintf((0, "DSp MacOS Error: %d\n", theCaughtError.m_MacErr));
if (gFullScreenData.m_context) {
//<2F> The monitor might be faded out so fade it back in and release the context
DSpContext_FadeGammaIn(gFullScreenData.m_context, NULL);
DSpContext_Release(gFullScreenData.m_context);
gFullScreenData.m_context = nil;
}
err = theCaughtError.m_DDGRErr;
}
return err;
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_CloseVideo
// will kill all objects created in os_surf_InitVideo
void ddgr_os_surf_CloseVideo(ddgr_surface *sf) {
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_VIDEOSCREEN);
ASSERT(sf->locks == 0);
ASSERT(!Mac_DDGR_Lib.IsWindowed());
OSErr macErr = noErr;
mprintf((0, "Closing video.\n"));
try {
// <20> Fade out the monitor while resolution switching
macErr = DSpContext_FadeGammaOut(gFullScreenData.m_context, NULL);
if (macErr)
throw(CMacOSSurfErr("Error while fading out monitor.", macErr, DDGRERR_DRIVERINIT));
// <20> Deactivate the context (undo the resolution/depth switch)
macErr = DSpContext_SetState(gFullScreenData.m_context, kDSpContextState_Inactive);
if (macErr)
throw(CMacOSSurfErr("Error while de-activating context", macErr, DDGRERR_DRIVERINIT));
} catch (CMacOSSurfErr theCaughtError) {
mprintf((0, "Error while closing video!\n"));
mprintf((0, theCaughtError.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "---> DSp MacOS Error: %d\n", theCaughtError.m_MacErr));
}
if (gFullScreenData.m_context) {
//<2F> The monitor might be faded out so fade it back in and release the context
DSpContext_FadeGammaIn(gFullScreenData.m_context, NULL);
DSpContext_Release(gFullScreenData.m_context);
gFullScreenData.m_context = nil;
}
//<2F> Video is deinitialized!
gFullScreenData.m_video_initted = false;
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_FlipVideo
// if this surface supports page flipping, will page flip. Otherwise, we
// flag an error.
// This allows the use of the (costly) color conversion to get 5-6-5 ---> 1-5-5-5
// but it only works when you are redrawing every pixel on the screen because
// it steps through the frame buffer and converts each pixel
#define USE_COLOR_CONVERSION_HACK
ddgr_error ddgr_os_surf_FlipVideo(ddgr_surface *sf) {
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_VIDEOSCREEN);
ASSERT(sf->locks == 0);
ASSERT(!Mac_DDGR_Lib.IsWindowed());
// mprintf((0, "Clearing OS Surface!\n"));
ddgr_error err = DDGRERR_SUCCESS;
CGrafPtr macBackBufferPtr = NULL;
PixMapHandle dstPixMapH = NULL;
CGrafPtr savePort = NULL;
GDHandle saveGDevice = NULL;
OSErr macErr = noErr;
GetGWorld(&savePort, &saveGDevice);
try {
if (!(sf->flags & SURFFLAG_BACKBUFFER)) {
throw(CMacOSSurfErr("Tried to swap surface with no backbuffer.\n", noErr, DDGRERR_FAIL));
}
#ifdef USE_COLOR_CONVERSION_HACK
macErr = DSpContext_GetBackBuffer(gFullScreenData.m_context, kDSpBufferKind_Normal, &macBackBufferPtr);
if (macErr || !macBackBufferPtr) {
throw(CMacOSSurfErr("Could not obtain full screen surface backbuffer ptr!", macErr, DDGRERR_FAIL));
}
dstPixMapH = macBackBufferPtr->portPixMap;
SetGWorld(macBackBufferPtr, nil);
if (!dstPixMapH) {
throw(CMacOSSurfErr("Could not obtain full screen pixmaps for clearing os surface", macErr, DDGRERR_FAIL));
}
bool lockSuccess = false;
lockSuccess = LockPixels(dstPixMapH);
if (!lockSuccess) {
throw(CMacOSSurfErr("Error: Could not lock destination pixels for flipping!", 0, DDGRERR_FAIL));
}
PixMapPtr macPixMapPtr = *dstPixMapH;
// For now assume, 16 bpp
ASSERT(sf->bpp == BPP_16);
//!! Do the Conversion
int i = 0;
int numRows = macPixMapPtr->bounds.bottom - macPixMapPtr->bounds.top;
int numCols = macPixMapPtr->bounds.right - macPixMapPtr->bounds.left;
int numTimes = numRows * numCols;
ushort oldColor = 0;
ushort newColor = 0;
ushort r = 0;
ushort g = 0;
ushort b = 0;
ushort *base = (ushort *)macPixMapPtr->baseAddr;
for (i = 0; i < numTimes; i++) {
oldColor = base[i];
r = (oldColor & 0xF800) >> 11;
g = (oldColor & 0x07E0) >> 6;
b = (oldColor & 0x001F);
newColor = 0;
newColor |= (r << 10);
newColor |= (g << 5);
newColor |= b;
base[i] = newColor;
}
UnlockPixels(dstPixMapH);
#endif // USE_COLOR_CONVERSION_HACK
// swap the buffers
macErr = DSpContext_SwapBuffers(gFullScreenData.m_context, NULL, 0);
if (macErr) {
throw(CMacOSSurfErr("DSpContext_SwapBuffers returned error: %d\n", macErr, DDGRERR_FAIL));
}
} catch (CMacOSSurfErr errObj) {
mprintf((0, errObj.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "MacOS Error: %d\n", errObj.m_MacErr));
err = errObj.m_DDGRErr;
}
SetGWorld(savePort, saveGDevice);
return err;
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_Create
// create a surface in we are in fullscreen mode
ddgr_error ddgr_os_surf_Create(ddgr_surface *sf) {
ddgr_error err = DDGRERR_SUCCESS;
OSErr macErr = noErr;
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_OFFSCREEN_OS);
mprintf((0, "Creating OS Surface!\n"));
try {
// Allocate a mac os surface data object
CMacOffscreenDataObj *surfDataObj = nil;
surfDataObj = new CMacOffscreenDataObj;
if (surfDataObj == nil) {
throw(CMacOSSurfErr("Error allocating memory for mac os surface data object!", noErr, DDGRERR_OUTOFMEMORY));
}
// Store the reference to the new data object for use later
sf->obj = surfDataObj;
// Allocate a new offscreen graphics world (cgrafptr)
GWorldPtr newOffscreen = nil;
Rect surfBoundsRect = {0, 0, 0, 0};
surfBoundsRect.top = 0;
surfBoundsRect.left = 0;
surfBoundsRect.right = surfBoundsRect.left + sf->w;
surfBoundsRect.bottom = surfBoundsRect.top + sf->h;
mprintf((0, "OS SURFACE CREATE: surface bounds rect = %d, %d, %d, %d (t,l,b,r). Is this correct?\n",
surfBoundsRect.top, surfBoundsRect.left, surfBoundsRect.right, surfBoundsRect.bottom));
macErr = NewGWorld(&newOffscreen, sf->bpp, &surfBoundsRect, nil, nil, 0);
if (macErr) {
throw(CMacOSSurfErr("Error allocating memory for mac offscreen buffer!", noErr, DDGRERR_OUTOFMEMORY));
}
// Store the new offscreen gworld for use later (blitting and such)
((CMacOffscreenDataObj *)sf->obj)->m_GWorld = newOffscreen;
// Reset unused data members
sf->locks = 0;
sf->rowsize = 0;
} catch (CMacOSSurfErr errObj) {
mprintf((0, errObj.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "MacOS Error: %d\n", errObj.m_MacErr));
err = errObj.m_DDGRErr;
}
return err;
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_Destroy
void ddgr_os_surf_Destroy(ddgr_surface *sf) {
OSErr macErr = noErr;
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_OFFSCREEN_OS);
ASSERT(sf->locks == 0);
mprintf((0, "Deleting OS Surface!\n"));
try {
// Get the mac os surface data object
CMacOffscreenDataObj *surfDataObj = nil;
surfDataObj = (CMacOffscreenDataObj *)sf->obj;
if (surfDataObj == nil) {
throw(CMacOSSurfErr("Error: No data object associated with offscreen surface!", 0, DDGRERR_FAIL));
}
// Free the associated new offscreen graphics world (cgrafptr)
DisposeGWorld(surfDataObj->m_GWorld);
// Clear the data member
surfDataObj->m_GWorld = nil;
// Dispose of the surface data object
delete surfDataObj;
// Clear the surface's data member
sf->obj = nil;
} catch (CMacOSSurfErr errObj) {
mprintf((0, "Could not destroy surface!\n"));
mprintf((0, errObj.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "MacOS Error: %d\n", errObj.m_MacErr));
}
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_Clear
// clears a surface based on the given rectangle in left, top, width, height
ddgr_error ddgr_os_surf_Clear(ddgr_surface *dsf, ddgr_color col, int l, int t, int w, int h) {
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(dsf != NULL);
ASSERT(dsf->type == SURFTYPE_OFFSCREEN_OS || dsf->type == SURFTYPE_VIDEOSCREEN);
ASSERT(dsf->locks == 0);
ASSERT(!Mac_DDGR_Lib.IsWindowed());
// mprintf((0, "Clearing OS Surface!\n"));
ddgr_error err = DDGRERR_SUCCESS;
CGrafPtr macBackBufferPtr = NULL;
PixMapHandle dstPixMapH = NULL;
CGrafPtr savePort = NULL;
GDHandle saveGDevice = NULL;
OSErr macErr = noErr;
GetGWorld(&savePort, &saveGDevice);
try {
if (dsf->type == SURFTYPE_OFFSCREEN_OS) {
CMacOffscreenDataObj *dataObj = nil;
dataObj = (CMacOffscreenDataObj *)dsf->obj;
if (dataObj == nil) {
throw(CMacOSSurfErr("Error: No data object associated with offscreen surface!", 0, DDGRERR_FAIL));
}
dstPixMapH = GetGWorldPixMap(dataObj->m_GWorld);
SetGWorld(dataObj->m_GWorld, nil);
} else // FullScreen
{
macErr = DSpContext_GetBackBuffer(gFullScreenData.m_context, kDSpBufferKind_Normal, &macBackBufferPtr);
if (macErr || !macBackBufferPtr) {
throw(CMacOSSurfErr("Could not obtain full screen surface backbuffer ptr!", macErr, DDGRERR_FAIL));
}
dstPixMapH = macBackBufferPtr->portPixMap;
SetGWorld(macBackBufferPtr, nil);
}
if (!dstPixMapH) {
throw(CMacOSSurfErr("Could not obtain full screen pixmaps for clearing os surface", macErr, DDGRERR_FAIL));
}
bool lockSuccess = false;
lockSuccess = LockPixels(dstPixMapH);
if (!lockSuccess) {
throw(CMacOSSurfErr("Error: Could not lock destination pixels for blit!", 0, DDGRERR_FAIL));
}
PixMapPtr macPixMapPtr = *dstPixMapH;
//!! Do the Clear
int i = 0;
int j = 0;
int bitsPerPixel = macPixMapPtr->pixelSize;
ASSERT((bitsPerPixel == BPP_DEFAULT) || (bitsPerPixel == BPP_8) || (bitsPerPixel == BPP_16) ||
(bitsPerPixel == BPP_24) || (bitsPerPixel == BPP_32));
RGBColor clearColor = {0, 0, 0};
RGBColor saveColor = {0, 0, 0};
Rect clearRect = {0, 0, 0, 0};
::GetForeColor(&saveColor);
// Set up the color
clearColor.red = GR_COLOR_RED(col);
clearColor.green = GR_COLOR_GREEN(col);
clearColor.blue = GR_COLOR_BLUE(col);
// Set up the bounding rect
clearRect.top = t;
clearRect.bottom = t + h;
clearRect.left = l;
clearRect.right = l + w;
// Do the clear
// mprintf((0, "Clearing OS Surface to ddgr_color = %d, RGB = (%d, %d, %d)\n",
// col, clearColor.red, clearColor.green, clearColor.blue));
::RGBForeColor(&clearColor);
::PaintRect(&clearRect);
::RGBForeColor(&saveColor);
UnlockPixels(dstPixMapH);
} catch (CMacOSSurfErr errObj) {
mprintf((0, errObj.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "MacOS Error: %d\n", errObj.m_MacErr));
err = errObj.m_DDGRErr;
}
SetGWorld(savePort, saveGDevice);
return err;
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_Blt
// blts a non-scaled bitmap using windowed or fullscreen modes
// note that we DONT have to handle fullscreen->windowed or vice-versa,
// since they will never coexist
ddgr_error ddgr_os_surf_Blt(ddgr_surface *dsf, int dx, int dy, ddgr_surface *ssf, int sx, int sy, int sw, int sh) {
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(dsf != NULL && ssf != NULL);
ASSERT(dsf->type == SURFTYPE_VIDEOSCREEN || dsf->type == SURFTYPE_OFFSCREEN_OS);
ASSERT(ssf->type == SURFTYPE_VIDEOSCREEN || ssf->type == SURFTYPE_OFFSCREEN_OS);
ASSERT(dsf->locks == 0);
ASSERT(ssf->locks == 0);
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ddgr_error err = DDGRERR_SUCCESS;
CGrafPtr macBackBufferPtr = NULL;
PixMapHandle dstPixMapH = NULL;
PixMapHandle srcPixMapH = NULL;
CGrafPtr savePort = NULL;
GDHandle saveGDevice = NULL;
OSErr macErr = noErr;
GetGWorld(&savePort, &saveGDevice);
try {
if (dsf->type == SURFTYPE_OFFSCREEN_OS) {
CMacOffscreenDataObj *dataObj = nil;
dataObj = (CMacOffscreenDataObj *)dsf->obj;
if (dataObj == nil) {
throw(CMacOSSurfErr("Error: No data object associated with offscreen surface!", 0, DDGRERR_FAIL));
}
dstPixMapH = GetGWorldPixMap(dataObj->m_GWorld);
SetGWorld(dataObj->m_GWorld, nil);
} else // FullScreen
{
macErr = DSpContext_GetBackBuffer(gFullScreenData.m_context, kDSpBufferKind_Normal, &macBackBufferPtr);
if (macErr || !macBackBufferPtr) {
throw(CMacOSSurfErr("Could not obtain full screen surface backbuffer ptr!", macErr, DDGRERR_FAIL));
}
dstPixMapH = macBackBufferPtr->portPixMap;
SetGWorld(macBackBufferPtr, nil);
}
if (ssf->type == SURFTYPE_OFFSCREEN_OS) {
CMacOffscreenDataObj *dataObj = nil;
dataObj = (CMacOffscreenDataObj *)ssf->obj;
if (dataObj == nil) {
throw(CMacOSSurfErr("Error: No data object associated with offscreen surface!", 0, DDGRERR_FAIL));
}
srcPixMapH = GetGWorldPixMap(dataObj->m_GWorld);
} else // FullScreen
{
macErr = DSpContext_GetBackBuffer(gFullScreenData.m_context, kDSpBufferKind_Normal, &macBackBufferPtr);
if (macErr || !macBackBufferPtr) {
throw(CMacOSSurfErr("Could not obtain full screen surface backbuffer ptr!", macErr, DDGRERR_FAIL));
}
srcPixMapH = macBackBufferPtr->portPixMap;
}
if (!srcPixMapH || !dstPixMapH) {
throw(CMacOSSurfErr("Could not obtain full screen pixmaps for blitting os surface", macErr, DDGRERR_FAIL));
}
bool lockSuccess = false;
lockSuccess = LockPixels(srcPixMapH);
if (!lockSuccess) {
throw(CMacOSSurfErr("Error: Could not lock source pixels for blit!", 0, DDGRERR_FAIL));
}
lockSuccess = LockPixels(dstPixMapH);
if (!lockSuccess) {
throw(CMacOSSurfErr("Error: Could not lock destination pixels for blit!", 0, DDGRERR_FAIL));
}
// Source and dest rectangles are the same (no scaling)
Rect srcRect = {sy, sx, sx + sw, sy + sh};
Rect dstRect = {dy, dx, dx + sw, dy + sh};
// DO THE BLIT!
CopyBits((BitMap *)(*srcPixMapH), (BitMap *)(*dstPixMapH), &srcRect, &dstRect, srcCopy, nil);
UnlockPixels(srcPixMapH);
UnlockPixels(dstPixMapH);
} catch (CMacOSSurfErr errObj) {
mprintf((0, errObj.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "MacOS Error: %d\n", errObj.m_MacErr));
err = errObj.m_DDGRErr;
}
SetGWorld(savePort, saveGDevice);
return err;
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_Lock and Unlock
// performs a lock which retrieves the data pointer and rowsize of a surface
// for direct rendering.
ddgr_error ddgr_os_surf_Lock(ddgr_surface *sf) {
ddgr_error err = DDGRERR_SUCCESS;
OSErr macErr = noErr;
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_OFFSCREEN_OS || sf->type == SURFTYPE_VIDEOSCREEN);
CGrafPtr macBackBufferPtr = NULL;
PixMapHandle macPixMapH = NULL;
try {
if (sf->type == SURFTYPE_OFFSCREEN_OS) {
CMacOffscreenDataObj *dataObj = nil;
dataObj = (CMacOffscreenDataObj *)sf->obj;
if (dataObj == nil) {
throw(CMacOSSurfErr("Error: No data object associated with offscreen surface!", 0, DDGRERR_FAIL));
}
macPixMapH = GetGWorldPixMap(dataObj->m_GWorld);
} else if (sf->type == SURFTYPE_VIDEOSCREEN) {
macErr = DSpContext_GetBackBuffer(gFullScreenData.m_context, kDSpBufferKind_Normal, &macBackBufferPtr);
if (macErr) {
throw(CMacOSSurfErr("Could not obtain full screen surface backbuffer ptr!", macErr, DDGRERR_FAIL));
}
macPixMapH = macBackBufferPtr->portPixMap;
} else {
throw(CMacOSSurfErr("Attempted to lock surface with invalid surftype!", 0, DDGRERR_FAIL));
}
Boolean lockSuccess = false;
lockSuccess = LockPixels(macPixMapH);
if (!lockSuccess) {
throw(CMacOSSurfErr("Error: Could not lock pixel data!", noErr, DDGRERR_FAIL));
}
PixMapPtr macPixMapPtr = *macPixMapH;
sf->w = macPixMapPtr->bounds.right - macPixMapPtr->bounds.left;
sf->h = macPixMapPtr->bounds.bottom - macPixMapPtr->bounds.top;
sf->bpp = macPixMapPtr->pixelSize;
sf->rowsize = (macPixMapPtr->rowBytes) & 0x7FFF;
sf->data = GetPixBaseAddr(macPixMapH);
sf->locks++;
} catch (CMacOSSurfErr errObj) {
mprintf((0, errObj.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "MacOS Error: %d\n", errObj.m_MacErr));
err = errObj.m_DDGRErr;
}
return err;
}
ddgr_error ddgr_os_surf_Unlock(ddgr_surface *sf) {
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_OFFSCREEN_OS || sf->type == SURFTYPE_VIDEOSCREEN);
ASSERT(sf->locks);
ddgr_error err = DDGRERR_SUCCESS;
OSErr macErr = noErr;
CGrafPtr macBackBufferPtr = NULL;
PixMapHandle macPixMapH = nil;
try {
if (sf->type == SURFTYPE_OFFSCREEN_OS) {
CMacOffscreenDataObj *dataObj = nil;
dataObj = (CMacOffscreenDataObj *)sf->obj;
if (dataObj == nil) {
throw(CMacOSSurfErr("Error: No data object associated with offscreen surface!", 0, DDGRERR_FAIL));
}
macPixMapH = GetGWorldPixMap(dataObj->m_GWorld);
} else if (sf->type == SURFTYPE_VIDEOSCREEN) {
macErr = DSpContext_GetBackBuffer(gFullScreenData.m_context, kDSpBufferKind_Normal, &macBackBufferPtr);
if (macErr) {
throw(CMacOSSurfErr("Could not obtain full screen surface backbuffer ptr!", macErr, DDGRERR_FAIL));
}
macPixMapH = macBackBufferPtr->portPixMap;
} else {
throw(CMacOSSurfErr("Attempted to lock surface with invalid surftype!", 0, DDGRERR_FAIL));
}
UnlockPixels(macPixMapH);
sf->data = NULL;
sf->locks--;
} catch (CMacOSSurfErr errObj) {
mprintf((0, errObj.m_ErrStr));
mprintf((0, "\n"));
mprintf((0, "MacOS Error: %d\n", errObj.m_MacErr));
err = errObj.m_DDGRErr;
}
return err;
}
// ---------------------------------------------------------------------------
// ddgr_os_surf_AttachHandle(ddgr_suface *sf, unsigned handle)
// attaches an OS handle to a surface
ddgr_error ddgr_os_surf_AttachHandle(ddgr_surface *sf, unsigned handle) {
ddgr_error err = DDGRERR_SUCCESS;
ASSERT(Mac_DDGR_Lib.IsInitted());
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(sf != NULL);
ASSERT(sf->type == SURFTYPE_OFFSCREEN_OS || sf->type == SURFTYPE_VIDEOSCREEN);
err = DDGRERR_FAIL;
mprintf((0, "Attaching handle to OS Surface is *NOT* implemented\n"));
return err;
}
//<2F>======================================================
// MacOS Full Screen Graphics routines
//<2F>======================================================
// Initialize the macintosh for full screen graphics
ddgr_error ddgr_os_surf_fullscreen_Init(ddgr_init_info *info) {
ddgr_error err = DDGRERR_SUCCESS;
OSErr macErr = noErr;
// Save the curreent macintosh port and graphics device to be restored later
GetPort(&(gFullScreenData.m_save_port));
gFullScreenData.m_save_gdevice = GetGDevice();
// Initialize DrawSprocket
macErr = DSpStartup();
if (macErr) {
mprintf((0, "Error initializing draw sprocket!: %d\n", macErr));
err = DDGRERR_DRIVERINIT;
}
return err;
}
ddgr_error ddgr_os_surf_fullscreen_Close(void) {
ddgr_error err = DDGRERR_SUCCESS;
OSErr macErr = noErr;
// Close DrawSprocket
macErr = DSpShutdown();
if (macErr) {
mprintf((0, "Error initializing draw sprocket!: %d\n", macErr));
err = DDGRERR_DRIVERINIT;
}
// Save the curreent macintosh port and graphics device to be restored later
SetPort(gFullScreenData.m_save_port);
SetGDevice(gFullScreenData.m_save_gdevice);
return err;
}
float ddgr_os_surf_GetAspectRatio(void) {
ASSERT(!Mac_DDGR_Lib.IsWindowed());
ASSERT(gFullScreenData.m_screen_attr.displayWidth != 0);
ASSERT(gFullScreenData.m_screen_attr.displayHeight != 0);
float aspect = 1.0;
aspect = (float)gFullScreenData.m_screen_attr.displayWidth / (float)gFullScreenData.m_screen_attr.displayHeight;
return aspect;
}