Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
DrawSprocketTest.c
/* |
File: DrawSprocketTest.c |
Description: Simple implementation of DrawSprcoket functions for testing |
Author: cjd |
Copyright: © Copyright 1999 Apple Computer, Inc. All rights reserved. |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
("Apple") in consideration of your agreement to the following terms, and your |
use, installation, modification or redistribution of this Apple software |
constitutes acceptance of these terms. If you do not agree with these terms, |
please do not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject |
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs |
copyrights in this original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or without |
modifications, in source and/or binary forms; provided that if you redistribute |
the Apple Software in its entirety and without modifications, you must retain |
this notice and the following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks or logos of |
Apple Computer, Inc. may be used to endorse or promote products derived from the |
Apple Software without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any patent rights that |
may be infringed by your derivative works or by other works in which the Apple |
Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Change History (most recent first): |
<SP33> 2/3/99 cjd Adding DSpGetVersion test |
<SP32> 1/26/99 cjd Removing code from GSp, overlays, scaling |
<SP31> 10/19/98 cjd Updating so that it is buildable by MPW |
*/ |
//¥ ------------------------------ Includes |
#include <CodeFragments.h> |
#include <Dialogs.h> |
#include <Displays.h> |
#include <DrawSprocket.h> |
#include <Events.h> |
#include <Fonts.h> |
#include <MacMemory.h> |
#include <MacWindows.h> |
#include <Menus.h> |
#include <Quickdraw.h> |
#include <Resources.h> |
#include <TextEdit.h> |
#include <Timer.h> |
#if defined (__MWERKS__) |
//#include <Math Routines.h> |
#endif |
#include <stdio.h> |
#include <string.h> |
#include <stdlib.h> |
#include <math.h> |
#if defined (__MWERKS__) |
#include <sioux.h> |
#else |
#include <SIOW.h> |
#endif |
//¥ ------------------------------ Private Definitions |
#define kRectSize 16 |
#define kDisplayWidth 640 |
#define kDisplayHeight 480 |
#define kDisplayDepth 8 |
//¥ ------------------------------ Private Types |
//¥ ------------------------------ Private Variables |
static Boolean gVBLSync = true; |
static char gTextBuffer[512]; |
//¥ ------------------------------ Private Functions |
void main(void); |
static void ErrorMessage(char *inMessage, OSStatus inError); |
static void DumpContextAttributes(DSpContextAttributes *inAttributes); |
static void MyInitAttributes(DSpContextAttributes *inAttributes); |
static void TestDrawSprocket(void); |
static void TestContextIteration(void); |
static void TestContextSearchingAuto(void); |
static void TestContextSearchingManual(void); |
static void TestContextBuffering(Boolean inUseUnderlay, Boolean inUseSingleBuffer); |
static void TestContextCLUT(void); |
static void TestUserSelectContext(void); |
static void TestFlatContexts(void); |
static void TestGetVersion(void); |
//¥ ------------------------------ Public Variables |
#pragma mark ##### support routines ##### |
//¥ -------------------- main |
void |
main(void) |
{ |
OSStatus theError; |
#if defined (__MWERKS__) |
/* tell SIOUX to shut up */ |
SIOUXSettings.autocloseonquit = true; |
SIOUXSettings.asktosaveonclose = false; |
#endif |
/* startup DrawSprocket */ |
theError = DSpStartup(); |
if (theError) |
{ |
ErrorMessage("DSpStartup()", theError); |
return; |
} |
/* main test menu */ |
TestDrawSprocket(); |
/* shutdown draw sprocket */ |
theError = DSpShutdown(); |
if (theError) |
ErrorMessage("DSpShutdown()", theError); |
} |
//¥ -------------------- ErrorMessage |
void |
ErrorMessage( |
char *inMessage, |
OSStatus inError |
) |
{ |
UInt32 theIndex; |
static char *theErrorTexts[] = |
{ |
"Unknown Error", |
"kDSpNotInitializedErr", |
"kDSpSystemSWTooOldErr", |
"kDSpInvalidContextErr", |
"kDSpInvalidAttributesErr", |
"kDSpContextAlreadyReservedErr", |
"kDSpContextNotReservedErr", |
"kDSpContextNotFoundErr", |
"kDSpFrameRateNotReadyErr", |
"kDSpConfirmSwitchWarning", |
"kDSpInternalErr" |
}; |
/* convert the error code into an array index */ |
if (inError <= kDSpNotInitializedErr && inError >= kDSpInternalErr) |
theIndex = kDSpNotInitializedErr - inError + 1; |
else |
theIndex = 0; |
/* print the message */ |
printf("# Error %d (%s) encountered: %s\n", inError, theErrorTexts[theIndex], inMessage); |
} |
//¥ -------------------- DumpContextAttributes |
void |
DumpContextAttributes(DSpContextAttributes *inAttributes) |
{ |
printf("\t frequency : "); |
if (inAttributes->frequency) |
printf("%dhz\n", inAttributes->frequency>>16); |
else |
printf("(unknown)\n"); |
printf("\t displayWidth : %d\n", inAttributes->displayWidth); |
printf("\t displayHeight : %d\n", inAttributes->displayHeight); |
printf("\t colorNeeds : "); |
switch (inAttributes->colorNeeds) |
{ |
case kDSpColorNeeds_DontCare: |
printf("kDSpColorNeeds_DontCare\n"); |
break; |
case kDSpColorNeeds_Request: |
printf("kDSpColorNeeds_Request\n"); |
break; |
case kDSpColorNeeds_Require: |
printf("kDSpColorNeeds_Require\n"); |
break; |
default: |
printf(" %d (Unknown)\n", inAttributes->colorNeeds); |
break; |
} |
printf("\t colorTable : 0x%X\n", inAttributes->colorTable); |
printf("\t contextOptions : \n"); |
if (inAttributes->contextOptions & kDSpContextOption_PageFlip) |
printf("\t kDSpContextOption_PageFlip\n"); |
if (0 == inAttributes->contextOptions) |
printf("\t (no options set)\n"); |
printf("\t backBufferDepthMask : 0x%X\n", inAttributes->backBufferDepthMask); |
printf("\t displayDepthMask : 0x%X\n", inAttributes->displayDepthMask); |
printf("\t backBufferBestDepth : %d\n", inAttributes->backBufferBestDepth); |
printf("\t displayBestDepth : %d\n", inAttributes->displayBestDepth); |
printf("\t pageCount : %d\n", inAttributes->pageCount); |
printf("\t gameMustConfirmSwitch : "); |
if (inAttributes->gameMustConfirmSwitch) |
printf("TRUE\n"); |
else |
printf("FALSE\n"); |
} |
//¥ -------------------- MyInitAttributes |
void |
MyInitAttributes(DSpContextAttributes *inAttributes) |
{ |
if (nil == inAttributes) |
DebugStr("\pStimpy! You Idiot!"); |
inAttributes->frequency = 0; |
inAttributes->displayWidth = 0; |
inAttributes->displayHeight = 0; |
inAttributes->reserved1 = 0; |
inAttributes->reserved2 = 0; |
inAttributes->colorNeeds = 0; |
inAttributes->colorTable = nil; |
inAttributes->contextOptions = 0; |
inAttributes->backBufferDepthMask = 0; |
inAttributes->displayDepthMask = 0; |
inAttributes->backBufferBestDepth = 0; |
inAttributes->displayBestDepth = 0; |
inAttributes->pageCount = 0; |
inAttributes->gameMustConfirmSwitch = false; |
inAttributes->reserved3[0] = 0; |
inAttributes->reserved3[1] = 0; |
inAttributes->reserved3[2] = 0; |
inAttributes->reserved3[3] = 0; |
} |
#pragma mark ##### test routines ##### |
//¥ -------------------- TestDrawSprocket |
void |
TestDrawSprocket(void) |
{ |
Boolean theDoneFlag = false; |
while (false == theDoneFlag) |
{ |
UInt32 theChoice; |
printf("\n\n############################################################\n"); |
printf("DrawSprocket test application.\n"); |
printf("Please select from the following tests:\n"); |
printf("\t 1. Exit\n"); |
printf("\t 2. Get Version\n"); |
printf("\t 4. Display/context iteration\n"); |
printf("\t 5. Context searching (auto selection of w/h/d/d)\n"); |
printf("\t 6. Context searching (you specify w/h/d/d)\n"); |
printf("\t 7. Multiple-buffering/page flipping (640x480x8)\n"); |
printf("\t 8. CLUT operations\n"); |
printf("\t 9. DSpUserSelectContext\n"); |
printf("\t10. Underlays\n"); |
printf("\t14. Single Buffering\n"); |
if (gVBLSync) |
printf("\t15. Disable VBL Sync\n"); |
else |
printf("\t15. Enable VBL Sync\n"); |
printf("\t16. Test context flattening\n"); |
printf("\n\tSelection: "); |
gets(gTextBuffer); |
theChoice = atoi(gTextBuffer); |
switch (theChoice) |
{ |
case 1: //¥ Exit |
theDoneFlag = true; |
break; |
case 2: //¥ Get version |
TestGetVersion(); |
break; |
case 4: //¥ Context iteration |
TestContextIteration(); |
break; |
case 5: //¥ Auto context searching |
TestContextSearchingAuto(); |
break; |
case 6: //¥ Manual context searching |
TestContextSearchingManual(); |
break; |
case 7: //¥ Buffering |
TestContextBuffering(false, false); |
break; |
case 8: //¥ CLUT |
TestContextCLUT(); |
break; |
case 9: //¥ User select context |
TestUserSelectContext(); |
break; |
case 10: //¥ Underlay |
TestContextBuffering(true, false); |
break; |
case 14: //¥ Single buffer |
TestContextBuffering(false, true); |
break; |
case 15: //¥ Toggle sync |
gVBLSync ^= 1; |
break; |
case 16: //¥ Context flattening |
TestFlatContexts(); |
break; |
default: //¥ Unknown |
printf("\nhuh?\n"); |
break; |
} |
printf("\nThank you, please drive through.\n"); |
} |
} |
//¥ -------------------- TestContextInteration |
void |
TestContextIteration(void) |
{ |
GDHandle theGDevice; |
OSStatus theError; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing Display/Context Iteration ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
/* |
** Walk the list of display devices in the system. DrawSprocket is |
** centered around the DisplayIDType, which is used by the Display |
** Manager. The GDevice records are going to be in flux with future |
** versions of the system software, so it is best to make the change |
** now and make your software DisplayManager-centric. |
*/ |
theGDevice = DMGetFirstScreenDevice(false); |
while (theGDevice) |
{ |
DisplayIDType theDisplayID; |
DSpContextReference theContext; |
UInt32 theContextIndex = 0; |
/* get the display ID */ |
theError = DMGetDisplayIDByGDevice(theGDevice, &theDisplayID, false); |
if (theError) |
{ |
ErrorMessage("DMGetDisplayIDByGDevice", theError); |
return; |
} |
/* walk the list of contexts for this display */ |
theError = DSpGetFirstContext(theDisplayID, &theContext); |
while (noErr == theError) |
{ |
DSpContextAttributes theAttributes; |
/* obtain the context attributes */ |
theError = DSpContext_GetAttributes(theContext, &theAttributes); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetAttributes", theError); |
return; |
} |
/* display the attributes structure */ |
printf("Display %d, Context %d capabilities:\n", theDisplayID, theContextIndex++); |
DumpContextAttributes(&theAttributes); |
/* |
** get the next context. when a kDSpContextNotFoundErr code |
** is returned we have hit the end of the context list. if |
** a different error code is returned, something went wrong. |
*/ |
theError = DSpGetNextContext(theContext, &theContext); |
if (theError && (kDSpContextNotFoundErr != theError)) |
{ |
ErrorMessage("DSpGetNextContext", theError); |
return; |
} |
} |
/* next device */ |
theGDevice = DMGetNextScreenDevice(theGDevice, false); |
} |
} |
//¥ -------------------- TestContextSearchingAuto |
void |
TestContextSearchingAuto(void) |
{ |
DSpContextAttributes theDesiredAttributes; |
DSpContextReference theContext; |
OSStatus theError; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing Display/Context Searching ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
/* |
** Find a 640x480x8 mode |
** |
** First, init the attributes so that there will be no garbage in any |
** of the fields (and which will cause DS to return an error). This |
** is especially important for fields that DS can't check, such as |
** the colorTable. If the colorTable is bogus when a call to reserve |
** a context is made, then it will try to use the bogus color table |
** (causing unpleasant visits to the debugger). |
** |
** When using DSpFindBestContext(), the attributes are interpreted as |
** *REQUIREMENTS*, unlike when you call DSpContext_Reserve(), when |
** they are interpreted as *REQUESTS*. If I specify a contextOption |
** of kDSpContextOption_PageFlip here, only contexts with the ability |
** to page flip will be considered in the search, however if I specify |
** the same option when reserving the context, and page flipping is not |
** available, then DS will use software double/triple buffering. This |
** is so to make it easy for the game to always request that DS use |
** page flipping if it is there (at reservation time), but still continue |
** if it is not. Conversely, the game can search for only contexts |
** that meet a specific criteria, and know that any matches found will |
** meet those specifications. |
*/ |
MyInitAttributes(&theDesiredAttributes); |
theDesiredAttributes.displayWidth = 640; |
theDesiredAttributes.displayHeight = 480; |
theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; |
theDesiredAttributes.backBufferDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.displayDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.backBufferBestDepth = kDisplayDepth; |
theDesiredAttributes.displayBestDepth = kDisplayDepth; |
theDesiredAttributes.pageCount = 2; |
theError = DSpFindBestContext(&theDesiredAttributes, &theContext); |
if (theError && kDSpContextNotFoundErr != theError) |
{ |
ErrorMessage("DSpFindBestContext 640x480x8", theError); |
return; |
} |
if (kDSpContextNotFoundErr == theError) |
{ |
printf("# Unable to find a matching context for the following attributes:\n"); |
DumpContextAttributes(&theDesiredAttributes); |
return; |
} |
else |
{ |
DSpContextAttributes theActualAttributes; |
DisplayIDType theDisplayID; |
/* get the actual attributes for the context */ |
theError = DSpContext_GetAttributes(theContext, &theActualAttributes); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetAttributes", theError); |
return; |
} |
/* get the display id for the context */ |
theError = DSpContext_GetDisplayID(theContext, &theDisplayID); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetDisplayID", theError); |
return; |
} |
/* tell the user about the results */ |
printf("Best matching Context for the following attributes...\n"); |
DumpContextAttributes(&theDesiredAttributes); |
printf("...is the context on display id %d with these attributes:\n", theDisplayID); |
DumpContextAttributes(&theActualAttributes); |
} |
} |
//¥ -------------------- TestContextSearchingManual |
void |
TestContextSearchingManual(void) |
{ |
DSpContextAttributes theDesiredAttributes; |
DSpContextReference theContext; |
OSStatus theError; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing Display/Context Searching ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
/* get the context attributes */ |
MyInitAttributes(&theDesiredAttributes); |
theDesiredAttributes.pageCount = 2; |
printf("enter the display width: "); |
gets(gTextBuffer); |
theDesiredAttributes.displayWidth = atoi(gTextBuffer); |
if (0 == theDesiredAttributes.displayWidth) |
{ |
printf("bogus value!\n"); |
return; |
} |
printf("enter the display height: "); |
gets(gTextBuffer); |
theDesiredAttributes.displayHeight = atoi(gTextBuffer); |
if (0 == theDesiredAttributes.displayHeight) |
{ |
printf("bogus value!\n"); |
return; |
} |
printf("enter the back buffer best depth: "); |
gets(gTextBuffer); |
theDesiredAttributes.backBufferBestDepth = atoi(gTextBuffer); |
if (0 == theDesiredAttributes.backBufferBestDepth) |
{ |
printf("bogus value!\n"); |
return; |
} |
printf("enter the display best depth: "); |
gets(gTextBuffer); |
theDesiredAttributes.displayBestDepth = atoi(gTextBuffer); |
if (0 == theDesiredAttributes.displayBestDepth) |
{ |
printf("bogus value!\n"); |
return; |
} |
theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; |
theDesiredAttributes.backBufferDepthMask = theDesiredAttributes.backBufferBestDepth; |
theDesiredAttributes.displayDepthMask = theDesiredAttributes.displayBestDepth; |
/* find the context */ |
theError = DSpFindBestContext(&theDesiredAttributes, &theContext); |
if (theError && kDSpContextNotFoundErr != theError) |
{ |
ErrorMessage("DSpFindBestContext (Manual)", theError); |
return; |
} |
if (kDSpContextNotFoundErr == theError) |
{ |
printf("# Unable to find a matching context for the following attributes:\n"); |
DumpContextAttributes(&theDesiredAttributes); |
return; |
} |
else |
{ |
DSpContextAttributes theActualAttributes; |
DisplayIDType theDisplayID; |
/* get the actual attributes for the context */ |
theError = DSpContext_GetAttributes(theContext, &theActualAttributes); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetAttributes", theError); |
return; |
} |
/* get the display id for the context */ |
theError = DSpContext_GetDisplayID(theContext, &theDisplayID); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetDisplayID", theError); |
return; |
} |
/* tell the user about the results */ |
printf("Best matching Context for the following attributes...\n"); |
DumpContextAttributes(&theDesiredAttributes); |
printf("...is the context on display id %d with these attributes:\n", theDisplayID); |
DumpContextAttributes(&theActualAttributes); |
} |
} |
//¥ -------------------- TestContextBuffering |
void |
TestContextBuffering( |
Boolean inUseUnderlay, |
Boolean inUseSingleBuffer |
) |
{ |
DSpContextAttributes theDesiredAttributes; |
DSpContextReference theContext; |
OSStatus theError; |
DSpAltBufferReference theUnderlay; |
UInt32 theDisplayWidth, theDisplayHeight; |
CGrafPtr theAltBufferPort; |
GDHandle theAltBufferGDevice, theOldGDevice; |
GrafPtr theOldPort; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing Buffering ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
/* find the context */ |
MyInitAttributes(&theDesiredAttributes); |
theDesiredAttributes.displayWidth = kDisplayWidth; |
theDesiredAttributes.displayHeight = kDisplayHeight; |
theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; |
theDesiredAttributes.backBufferDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.displayDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.backBufferBestDepth = kDisplayDepth; |
theDesiredAttributes.displayBestDepth = kDisplayDepth; |
theDesiredAttributes.pageCount = 2; |
if (inUseSingleBuffer) |
theDesiredAttributes.pageCount = 1; |
theError = DSpFindBestContext(&theDesiredAttributes, &theContext); |
if (theError && kDSpContextNotFoundErr != theError) |
{ |
ErrorMessage("DSpFindBestContext", theError); |
return; |
} |
if (kDSpContextNotFoundErr == theError) |
{ |
printf("# Unable to find a matching context for the following attributes:\n"); |
DumpContextAttributes(&theDesiredAttributes); |
return; |
} |
theDisplayWidth = kDisplayWidth; |
theDisplayHeight = kDisplayHeight; |
/* |
** Here is where I need to OR in the value to use page flipping. If |
** I had used the value when calling DSpFindBestContext() then it would |
** have only considered displays that have page flipping hardware, but |
** I want to run with software buffering too. |
*/ |
theDesiredAttributes.contextOptions |= kDSpContextOption_PageFlip; |
/* |
** If page flipping isn't available, then software buffering will |
** be used. DS can use double or triple buffering depending on the |
** state of the kDSpContextOption_TripleBuffer option bit. |
** |
** If you only want double buffering, perhaps because of memory |
** constraints then you should turn off the option bit. |
** |
** If you leave the bit on and there is hardware page flipping |
** available (and you haven't turned off that option bit), but |
** there are only 2 video pages (not three) then DS will consider |
** page flipping to be more important of an option than triple |
** buffering and will drop you down to 2 VRAM pages (leaving you |
** still page flipping). |
** |
*/ |
//¥ theDesiredAttributes.contextOptions &= ~kDSpContextOption_TripleBuffer; |
//¥ set vbl sync |
if (false == gVBLSync) |
theDesiredAttributes.contextOptions |= kDSpContextOption_DontSyncVBL; |
//¥ reset page count |
theDesiredAttributes.pageCount = 2; |
if (inUseSingleBuffer) |
theDesiredAttributes.pageCount = 1; |
/* reserve the context */ |
theError = DSpContext_Reserve(theContext, &theDesiredAttributes); |
if (theError) |
{ |
ErrorMessage("DSpContext_Reserve", theError); |
return; |
} |
/* |
** If you are in a debug cycle, you may want to enable debugging mode |
** in DrawSprocket so that a fade out, followed by a break in the |
** debugger, won't leave you with nothing to see. |
** |
** You can also create a folder in same folder as your game, and name |
** it "DSpSetDebugMode", this will also cause DSp to enter debug mode. |
** This method is handy if you don't want to rebuild your game with |
** the call just to debug it. |
*/ |
//¥ DSpSetDebugMode(true); |
/* |
** fade out all displays to black, you must have at least one reserved |
** context to do this or you will get an error. A game should always |
** fade to black before activating a context because if the activation |
** causes a resolution change the user will see a very ugly twitch in |
** the display. |
*/ |
theError = DSpContext_FadeGammaOut(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaOut", theError); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(theContext); |
return; |
} |
/* put the context into the active state */ |
theError = DSpContext_SetState(theContext, kDSpContextState_Active); |
if (theError) |
{ |
ErrorMessage("DSpContext_SetState", theError); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(theContext); |
return; |
} |
/* fade back in */ |
theError = DSpContext_FadeGammaIn(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaIn", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* |
** allocate an alt buffer that will be used for the underlay. An |
** underlay is useful in games that have a need to restore from a |
** static background. |
*/ |
theError = DSpAltBuffer_New(theContext, false, 0, &theUnderlay); |
if (theError) |
{ |
DSpContext_Release(theContext); |
ErrorMessage("DSpAltBuffer_New (underlay)", theError); |
return; |
} |
theError = DSpContext_SetUnderlayAltBuffer(theContext, theUnderlay); |
if (theError) |
{ |
DSpContext_Release(theContext); |
ErrorMessage("DSpContext_SetUnderlayAltBuffer", theError); |
return; |
} |
//¥ do the double buffering |
{ |
UInt32 theColorIndex, theXPos, theYPos; |
Rect theRect; |
GetPort(&theOldPort); |
theOldGDevice = GetGDevice(); |
/* set the alt buffer to be the current port */ |
theError = DSpAltBuffer_GetCGrafPtr(theUnderlay, kDSpBufferKind_Normal, &theAltBufferPort, &theAltBufferGDevice); |
if (theError) |
{ |
ErrorMessage("DSpAltBuffer_GetCGrafPtr (underlay)", theError); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(theContext); |
return; |
} |
/* |
** if you want to use QuickDraw or any other toolbox rendering |
** code, you must setup the GDevice as well as the port when |
** working with AltBuffers! |
*/ |
SetPort((GrafPtr)theAltBufferPort); |
SetGDevice(theAltBufferGDevice); |
/* |
** fill the underlay buffer with a pattern or clear it |
*/ |
if (inUseUnderlay) |
{ |
/* |
** draw a pattern into the underlay buffer. this pattern will be |
** restored every time I get the back buffer |
*/ |
theColorIndex = 0; |
for (theYPos = 0; theYPos < theDesiredAttributes.displayHeight; theYPos += kRectSize) |
{ |
for(theXPos = 0; theXPos < theDesiredAttributes.displayWidth; theXPos += kRectSize) |
{ |
SetRect(&theRect, 0, 0, kRectSize, kRectSize); |
OffsetRect(&theRect, theXPos, theYPos); |
theAltBufferPort->fgColor = theColorIndex % 255; |
PaintRect(&theRect); |
theColorIndex++; |
} |
} |
} |
else |
{ |
ForeColor(blackColor); |
BackColor(whiteColor); |
SetRect(&theRect, 0, 0, theDesiredAttributes.displayWidth, theDesiredAttributes.displayHeight); |
EraseRect(&theRect); |
} |
SetPort(theOldPort); |
SetGDevice(theOldGDevice); |
} |
/* |
** this test slides a black vertical bar left and right on the |
** display, producing an image where any tearing is amplified. |
*/ |
{ |
RGBColor theColor, theTextColor; |
Rect theRectangleRect, theRect; |
UInt32 theStartTick, theMaxTick, theCurrentTick; |
UInt32 theCount, theRectangleDelta; |
UInt32 theWidth, theXPos, theYPos; |
CGrafPtr theBackBuffer; |
UInt32 theXSquares, theYSquares; |
theXSquares = theDesiredAttributes.displayWidth / kRectSize; |
theYSquares = theDesiredAttributes.displayHeight / kRectSize; |
theColor.red = 0; |
theColor.green = 0; |
theColor.blue = 0; |
theTextColor.red = 0xFFFF; |
theTextColor.green = 0xFFFF; |
theTextColor.blue = 0xFFFF; |
/* rectangle will be 1/8 the display width, and all of the height */ |
SetRect(&theRectangleRect, 0, 0, theDesiredAttributes.displayWidth >> 3, |
theDesiredAttributes.displayHeight); |
theStartTick = theCurrentTick = TickCount(); |
theMaxTick = theStartTick + (15 * 60); |
theCount = 0; |
theRectangleDelta = 3; |
while (theCurrentTick < theMaxTick) |
{ |
/* |
** every so often change the color of one of the squares |
** in the underlay |
*/ |
if ((theCurrentTick % 10) == 0) |
{ |
RGBColor theNewColor; |
UInt32 theX, theY; |
Rect theRect; |
SetPort((GrafPtr)theAltBufferPort); |
SetGDevice(theAltBufferGDevice); |
theNewColor.red = Random(); |
theNewColor.green = Random(); |
theNewColor.blue = Random(); |
theX = Random() % theXSquares; |
theY = Random() % theYSquares; |
theRect.left = theX * kRectSize; |
theRect.right = theRect.left + kRectSize; |
theRect.top = theY * kRectSize; |
theRect.bottom = theRect.top + kRectSize; |
RGBForeColor(&theNewColor); |
PaintRect(&theRect); |
DSpAltBuffer_InvalRect(theUnderlay, &theRect); |
} |
/* get the back buffer */ |
theError = DSpContext_GetBackBuffer(theContext, kDSpBufferKind_Normal, &theBackBuffer); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetBackBuffer", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* set the back buffer to be the current port */ |
SetPort((GrafPtr)theBackBuffer); |
/* fill the display with a sliding vertical rectangle */ |
RGBForeColor(&theColor); |
PaintRect(&theRectangleRect); |
/* inval the new rect position */ |
theError = DSpContext_InvalBackBufferRect(theContext, &theRectangleRect); |
if ((theRectangleRect.right + theRectangleDelta) > theDesiredAttributes.displayWidth) |
theRectangleDelta = -theRectangleDelta; |
if ((theRectangleRect.left + theRectangleDelta) < 0) |
theRectangleDelta = -theRectangleDelta; |
theRectangleRect.left += theRectangleDelta; |
theRectangleRect.right += theRectangleDelta; |
// draw a frame counter |
sprintf((char *)&gTextBuffer[1], |
"This is frame %d (%d ticks remaining, %.1f fps)", |
theCount + 1, theMaxTick - theCurrentTick, |
(float)(theCount / ((theCurrentTick - theStartTick) / 60.0))); |
gTextBuffer[0] = strlen((char *)&gTextBuffer[1]); |
theWidth = StringWidth((ConstStr255Param)gTextBuffer); |
theXPos = (theDisplayWidth >> 1) - (theWidth >> 1); |
theYPos = theDisplayHeight - 20; |
theTextColor.red = 0; |
theTextColor.green = 0; |
theTextColor.blue = 0; |
RGBForeColor(&theTextColor); |
SetRect(&theRect, theXPos - 10, theYPos - 20, theXPos + theWidth + 10, theYPos + 10); |
PaintRect(&theRect); |
theError = DSpContext_InvalBackBufferRect(theContext, &theRect); |
theTextColor.red = 0; |
theTextColor.green = 0xFFFF; |
theTextColor.blue = 0xFFFF; |
RGBForeColor(&theTextColor); |
FrameRect(&theRect); |
MoveTo(theXPos, theYPos); |
DrawString((ConstStr255Param)gTextBuffer); |
// swap the buffers |
theError = DSpContext_SwapBuffers(theContext, nil, 0); |
if (theError) |
{ |
ErrorMessage("DSpContext_SwapBuffers", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* increase frame counter */ |
theCount++; |
theCurrentTick = TickCount(); |
} |
} |
/* |
**************************************************************************** |
** cleanup |
**************************************************************************** |
*/ |
if (inUseUnderlay) |
{ |
SetPort(theOldPort); |
SetGDevice(theOldGDevice); |
} |
/* fade to black */ |
theError = DSpContext_FadeGammaOut(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaIn", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* remove the underlay & release it */ |
DSpContext_SetUnderlayAltBuffer(theContext, nil); |
DSpAltBuffer_Dispose(theUnderlay); |
theUnderlay = nil; |
/* put the context into the inactive state */ |
theError = DSpContext_SetState(theContext, kDSpContextState_Inactive); |
if (theError) |
{ |
ErrorMessage("DSpContext_SetState", theError); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(theContext); |
return; |
} |
/* fade back in */ |
theError = DSpContext_FadeGammaIn(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaIn", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* release the context */ |
theError = DSpContext_Release(theContext); |
if (theError) |
{ |
ErrorMessage("DSpContext_Release", theError); |
return; |
} |
} |
//¥ -------------------- TextContextCLUT |
void |
TestContextCLUT(void) |
{ |
DSpContextAttributes theDesiredAttributes; |
DSpContextReference theContext; |
OSStatus theError; |
RGBColor theBlankingColor; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing CLUT ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
/* find the context */ |
MyInitAttributes(&theDesiredAttributes); |
theDesiredAttributes.displayWidth = kDisplayWidth; |
theDesiredAttributes.displayHeight = kDisplayHeight; |
theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; |
theDesiredAttributes.backBufferDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.displayDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.backBufferBestDepth = kDisplayDepth; |
theDesiredAttributes.displayBestDepth = kDisplayDepth; |
theDesiredAttributes.pageCount = 2; |
theError = DSpFindBestContext(&theDesiredAttributes, &theContext); |
if (theError && kDSpContextNotFoundErr != theError) |
{ |
ErrorMessage("DSpFindBestContext", theError); |
return; |
} |
if (kDSpContextNotFoundErr == theError) |
{ |
printf("# Unable to find a matching context for the following attributes:\n"); |
DumpContextAttributes(&theDesiredAttributes); |
return; |
} |
/* reserve the context */ |
theError = DSpContext_Reserve(theContext, &theDesiredAttributes); |
if (theError) |
{ |
ErrorMessage("DSpContext_Reserve", theError); |
return; |
} |
/* set the blanking color to white, just for the heck of it */ |
theBlankingColor.red = 0xFFFFF; |
theBlankingColor.green = 0xFFFFF; |
theBlankingColor.blue = 0xFFFFF; |
theError = DSpSetBlankingColor(&theBlankingColor); |
if (theError) |
{ |
ErrorMessage("DSpSetBlankingColor", theError); |
return; |
} |
/* fade out all displays to black */ |
theError = DSpContext_FadeGammaOut(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaOut", theError); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(theContext); |
return; |
} |
/* put the context into the active state */ |
theError = DSpContext_SetState(theContext, kDSpContextState_Active); |
if (theError) |
{ |
ErrorMessage("DSpContext_SetState", theError); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(theContext); |
return; |
} |
/* fade back in */ |
theError = DSpContext_FadeGammaIn(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaIn", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* |
**************************************************************************** |
** do the CLUT testing |
**************************************************************************** |
*/ |
/* draw a pattern into the back buffer and cycle it */ |
{ |
UInt32 thePosition, theColorIndex, theXPos, theYPos; |
CGrafPtr theBackBuffer; |
ColorSpec theOriginalColors[256]; |
/* get the back buffer */ |
theError = DSpContext_GetBackBuffer(theContext, kDSpBufferKind_Normal, &theBackBuffer); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetBackBuffer", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* set the back buffer to be the current port */ |
SetPort((GrafPtr)theBackBuffer); |
/* draw a pattern into the back buffer */ |
theColorIndex = 0; |
for(theYPos = 0; theYPos < theDesiredAttributes.displayHeight; theYPos += kRectSize) |
{ |
for(theXPos = 0; theXPos < theDesiredAttributes.displayWidth; theXPos += kRectSize) |
{ |
Rect theRect; |
SetRect(&theRect, 0, 0, kRectSize, kRectSize); |
OffsetRect(&theRect, theXPos, theYPos); |
theBackBuffer->fgColor = theColorIndex % 255; |
PaintRect(&theRect); |
theColorIndex++; |
} |
} |
/* bring the back buffer to the front */ |
theError = DSpContext_SwapBuffers(theContext, nil, 0); |
if (theError) |
{ |
ErrorMessage("DSpContext_SwapBuffers", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* |
** get the original color table |
** |
** unfortunately, these probably aren't the real colors, since |
** the way that gamma works on the Mac is to remap the indexed |
** color table to new colors. In other words, these colors are |
** gamma corrected versions of the ones that were originally set. |
** |
*/ |
theError = DSpContext_GetCLUTEntries(theContext, theOriginalColors, 0, 255); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetCLUTEntries", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* cycle the colors */ |
while (! Button()) |
{ |
ColorSpec theSpec[256], theTempSpec; |
/* rotate them */ |
theTempSpec = theOriginalColors[0]; |
for(theColorIndex = 0; theColorIndex < 255; theColorIndex++) |
theSpec[theColorIndex].rgb = theOriginalColors[(theColorIndex + thePosition) % 255].rgb; |
theSpec[255].rgb = theTempSpec.rgb; |
thePosition++; |
if (thePosition > 255) |
thePosition = 0; |
/* set the entries */ |
theError = DSpContext_SetCLUTEntries(theContext, theSpec, 0, 255); |
if (theError) |
{ |
ErrorMessage("DSpContext_SetCLUTEntries", theError); |
DSpContext_Release(theContext); |
return; |
} |
} |
} |
/* |
**************************************************************************** |
** cleanup |
**************************************************************************** |
*/ |
/* fade to black */ |
theError = DSpContext_FadeGammaOut(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaIn", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* put the context into the inactive state */ |
theError = DSpContext_SetState(theContext, kDSpContextState_Inactive); |
if (theError) |
{ |
ErrorMessage("DSpContext_SetState", theError); |
DSpContext_FadeGammaIn(nil, nil); |
DSpContext_Release(theContext); |
return; |
} |
/* fade back in */ |
theError = DSpContext_FadeGammaIn(nil, nil); |
if (theError) |
{ |
ErrorMessage("DSpContext_FadeGammaIn", theError); |
DSpContext_Release(theContext); |
return; |
} |
/* release the context */ |
theError = DSpContext_Release(theContext); |
if (theError) |
{ |
ErrorMessage("DSpContext_Release", theError); |
return; |
} |
} |
//¥ -------------------- TestUserSelectContext |
void |
TestUserSelectContext(void) |
{ |
DSpContextAttributes theDesiredAttributes; |
DSpContextAttributes theActualAttributes; |
DSpContextReference theContext; |
OSStatus theError; |
Boolean theShowDialogFlag; |
DisplayIDType theDisplayID; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing CLUT ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
/* find the context */ |
MyInitAttributes(&theDesiredAttributes); |
theDesiredAttributes.displayWidth = kDisplayWidth; |
theDesiredAttributes.displayHeight = kDisplayHeight; |
theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; |
theDesiredAttributes.backBufferDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.displayDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.backBufferBestDepth = kDisplayDepth; |
theDesiredAttributes.displayBestDepth = kDisplayDepth; |
theDesiredAttributes.pageCount = 2; |
/* |
** see if there are enough choices available for the user to |
** choose from, this can be used if I needed to determine |
** whether or not to enable a menu item, etc. |
*/ |
theError = DSpCanUserSelectContext(&theDesiredAttributes, &theShowDialogFlag); |
if (theError) |
{ |
ErrorMessage("DSpCanUserSelectContext", theError); |
return; |
} |
if (false == theShowDialogFlag) |
{ |
printf("There are not enough choices to warrant asking the user.\n"); |
return; |
} |
/* |
** put up the choice dialog, I don't care about what display it |
** appears on, nor do I care to know about update events |
*/ |
theError = DSpUserSelectContext(&theDesiredAttributes, 0, nil, &theContext); |
if (theError) |
{ |
/* |
** since we know that there were possible matches available (because |
** we called DSpCanUserSelectContext), we know that a context-not-found |
** error means that the user canceled the dialog |
*/ |
if (kDSpContextNotFoundErr == theError) |
printf("The user canceled the dialog.\n"); |
else |
ErrorMessage("DSpUserSelectContext", theError); |
return; |
} |
/* tell the user about the results */ |
printf("User-Selected Context for the following attributes...\n"); |
DumpContextAttributes(&theDesiredAttributes); |
theError = DSpContext_GetDisplayID(theContext, &theDisplayID); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetDisplayID", theError); |
return; |
} |
theError = DSpContext_GetAttributes(theContext, &theActualAttributes); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetAttributes", theError); |
return; |
} |
printf("...is the context on display id %d with these attributes:\n", theDisplayID); |
DumpContextAttributes(&theActualAttributes); |
} |
//¥ -------------------- TestFlatContexts |
void |
TestFlatContexts(void) |
{ |
DSpContextAttributes theDesiredAttributes; |
DSpContextReference theContext, theRestoredContext; |
OSStatus theError; |
UInt32 theFlatContextSize; |
Ptr theFlatContextBuffer = nil; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing Flat Contexts ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
/* find the context */ |
MyInitAttributes(&theDesiredAttributes); |
theDesiredAttributes.displayWidth = kDisplayWidth; |
theDesiredAttributes.displayHeight = kDisplayHeight; |
theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; |
theDesiredAttributes.backBufferDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.displayDepthMask = kDSpDepthMask_8; |
theDesiredAttributes.backBufferBestDepth = kDisplayDepth; |
theDesiredAttributes.displayBestDepth = kDisplayDepth; |
theDesiredAttributes.pageCount = 2; |
theError = DSpFindBestContext(&theDesiredAttributes, &theContext); |
if (theError && kDSpContextNotFoundErr != theError) |
{ |
ErrorMessage("DSpFindBestContext", theError); |
return; |
} |
if (kDSpContextNotFoundErr == theError) |
{ |
printf("# Unable to find a matching context for the following attributes:\n"); |
DumpContextAttributes(&theDesiredAttributes); |
return; |
} |
/* get the flattened size & allocate space for it */ |
theError = DSpContext_GetFlattenedSize(theContext, &theFlatContextSize); |
if (theError) |
{ |
ErrorMessage("DSpContext_GetFlattenedSize", theError); |
return; |
} |
theFlatContextBuffer = NewPtr(theFlatContextSize); |
if (nil == theFlatContextBuffer) |
{ |
ErrorMessage("not enough memory to allocate flat context", 0); |
return; |
} |
/* flatten the context */ |
theError = DSpContext_Flatten(theContext, theFlatContextBuffer); |
if (theError) |
ErrorMessage("DSpContext_Flatten", theError); |
/* restore the context from the flattened version */ |
if (noErr == theError) |
{ |
theError = DSpContext_Restore(theFlatContextBuffer, &theRestoredContext); |
if (theError) |
ErrorMessage("DSpContext_Flatten", theError); |
/* same context? */ |
if (theRestoredContext == theContext) |
printf("restored context successfully\n"); |
else |
printf("Error: restored context didn't match!\n"); |
} |
/* cleanup */ |
DisposePtr(theFlatContextBuffer); |
} |
//¥ -------------------- TestGetVersion |
static void |
TestGetVersion(void) |
{ |
NumVersion theVersion; |
char buffer[128]; |
printf("\n\n"); |
printf("############################################################\n"); |
printf("### Testing DSpGetVersion ###\n"); |
printf("############################################################\n"); |
printf("\n\n"); |
if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpGetVersion) |
{ |
printf("Error: DSpGetVersion not present. Your DrawSprocket is too old."); |
return; |
} |
theVersion = DSpGetVersion(); |
sprintf(buffer, "DrawSprocket v%d.%d.%d", |
theVersion.majorRev, |
theVersion.minorAndBugRev >> 4, |
theVersion.minorAndBugRev & 0x0F); |
switch (theVersion.stage) |
{ |
case 0x20: |
sprintf(buffer, "%s development %d\n\n", buffer, theVersion.nonRelRev); |
break; |
case 0x40: |
sprintf(buffer, "%s alpha %d\n\n", buffer, theVersion.nonRelRev); |
break; |
case 0x60: |
sprintf(buffer, "%s beta %d\n\n", buffer, theVersion.nonRelRev); |
break; |
case 0x80: |
sprintf(buffer, "%s final %d\n\n", buffer, theVersion.nonRelRev); |
break; |
} |
printf(buffer); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14