blob: d29b625734ccb9b1119349bf3a7c6e542e7e2af7 [file] [log] [blame]
/******************************************************************************
@file Shell/PVRShell.cpp
@copyright Copyright (c) Imagination Technologies Limited.
@brief Makes programming for 3D APIs easier by wrapping surface
initialization, Texture allocation and other functions for use by a demo.
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include "PVRShell.h"
#include "PVRShellOS.h"
#include "PVRShellAPI.h"
#include "PVRShellImpl.h"
/*! This file simply defines a version string. It can be commented out. */
#include "sdkver.h"
#ifndef PVRSDK_VERSION
#define PVRSDK_VERSION "n.nn.nn.nnnn"
#endif
/*! Define to automatically stop the app after x frames. If negative, run forever. */
#ifndef PVRSHELL_QUIT_AFTER_FRAME
#define PVRSHELL_QUIT_AFTER_FRAME -1
#endif
/*! Define to automatically stop the app after x amount of seconds. If negative, run forever. */
#ifndef PVRSHELL_QUIT_AFTER_TIME
#define PVRSHELL_QUIT_AFTER_TIME -1
#endif
/*! Define for the screen shot file name. */
#define PVRSHELL_SCREENSHOT_NAME "PVRShell"
#if defined(_WIN32)
#define snprintf _snprintf
#endif
// No Doxygen for CPP files, due to documentation duplication
/// @cond NO_DOXYGEN
// Define DISABLE_SWIPE_MAPPING to disable the PVRShell's simple mapping of swipes to key commands.
//#define DISABLE_SWIPE_MAPPING 1
/*****************************************************************************
** Prototypes
*****************************************************************************/
static bool StringCopy(char *&pszStr, const char * const pszSrc);
/****************************************************************************
** Class: PVRShell
****************************************************************************/
/*!***********************************************************************
@brief Constructor
*************************************************************************/
PVRShell::PVRShell()
{
m_pShellInit = NULL;
m_pShellData = new PVRShellData;
m_pShellData->nShellPosX=0;
m_pShellData->nShellPosY=0;
m_pShellData->bFullScreen = false; // note this may be overridden by some OS versions of PVRShell
m_pShellData->nAASamples= 0;
m_pShellData->nColorBPP = 0;
m_pShellData->nDepthBPP = 0;
m_pShellData->nDieAfterFrames = PVRSHELL_QUIT_AFTER_FRAME;
m_pShellData->fDieAfterTime = PVRSHELL_QUIT_AFTER_TIME;
m_pShellData->bNeedPbuffer = false;
m_pShellData->bNeedPixmap = false;
m_pShellData->bNeedPixmapDisableCopy = false;
m_pShellData->bNeedZbuffer = true;
m_pShellData->bLockableBackBuffer = false;
m_pShellData->bSoftwareRender = false;
m_pShellData->bNeedStencilBuffer = false;
m_pShellData->bNeedAlphaFormatPre = false;
m_pShellData->bUsingPowerSaving = true;
m_pShellData->bOutputInfo = false;
m_pShellData->bNoShellSwapBuffer = false;
m_pShellData->pszAppName = 0;
m_pShellData->pszExitMessage = 0;
m_pShellData->nSwapInterval = 1;
m_pShellData->nInitRepeats = 0;
m_pShellData->nCaptureFrameStart = -1;
m_pShellData->nCaptureFrameStop = -1;
m_pShellData->nCaptureFrameScale = 1;
m_pShellData->nPriority = 2;
m_pShellData->bForceFrameTime = false;
m_pShellData->nFrameTime = 33;
// Internal Data
m_pShellData->bShellPosWasDefault = true;
m_pShellData->nShellCurFrameNum = 0;
#ifdef PVRSHELL_FPS_OUTPUT
m_pShellData->bOutputFPS = false;
#endif
m_pShellData->bDiscardFrameColor=false;
m_pShellData->bDiscardFrameDepth=true;
m_pShellData->bDiscardFrameStencil=true;
}
/*!***********************************************************************
@brief Destructor
*************************************************************************/
PVRShell::~PVRShell()
{
delete m_pShellData;
m_pShellData = NULL;
}
// Allow user to set preferences from within InitApplication
/*!***********************************************************************
@brief This function is used to pass preferences to the PVRShell.
If used, this function must be called from InitApplication().
@param[in] prefName Name of preference to set to value
@param[in] value Value
@return true for success
*************************************************************************/
bool PVRShell::PVRShellSet(const prefNameBoolEnum prefName, const bool value)
{
switch(prefName)
{
case prefFullScreen:
m_pShellData->bFullScreen = value;
return true;
case prefPBufferContext:
m_pShellData->bNeedPbuffer = value;
return true;
case prefPixmapContext:
m_pShellData->bNeedPixmap = value;
return true;
case prefPixmapDisableCopy:
m_pShellData->bNeedPixmapDisableCopy = value;
return true;
case prefZbufferContext:
m_pShellData->bNeedZbuffer = value;
return true;
case prefLockableBackBuffer:
m_pShellData->bLockableBackBuffer = value;
return true;
case prefSoftwareRendering:
m_pShellData->bSoftwareRender = value;
return true;
case prefStencilBufferContext:
m_pShellData->bNeedStencilBuffer = value;
return true;
case prefAlphaFormatPre:
m_pShellData->bNeedAlphaFormatPre = value;
return true;
case prefPowerSaving:
m_pShellData->bUsingPowerSaving = value;
return true;
case prefOutputInfo:
m_pShellData->bOutputInfo = value;
return true;
case prefNoShellSwapBuffer:
m_pShellData->bNoShellSwapBuffer = value;
return true;
case prefForceFrameTime:
m_pShellData->bForceFrameTime = value;
return true;
#ifdef PVRSHELL_FPS_OUTPUT
case prefOutputFPS:
m_pShellData->bOutputFPS = value;
return true;
#endif
case prefDiscardColor:
m_pShellData->bDiscardFrameColor = value;
return true;
case prefDiscardDepth:
m_pShellData->bDiscardFrameDepth = value;
return true;
case prefDiscardStencil:
m_pShellData->bDiscardFrameStencil = value;
return true;
default:
return m_pShellInit->OsSet(prefName, value);
}
}
/*!***********************************************************************
@brief This function is used to get parameters from the PVRShell.
It can be called from anywhere in the program.
@param[in] prefName Name of preference to set to value
@return The requested value.
*************************************************************************/
bool PVRShell::PVRShellGet(const prefNameBoolEnum prefName) const
{
switch(prefName)
{
case prefFullScreen: return m_pShellData->bFullScreen;
case prefIsRotated: return (m_pShellData->nShellDimY > m_pShellData->nShellDimX);
case prefPBufferContext: return m_pShellData->bNeedPbuffer;
case prefPixmapContext: return m_pShellData->bNeedPixmap;
case prefPixmapDisableCopy: return m_pShellData->bNeedPixmapDisableCopy;
case prefZbufferContext: return m_pShellData->bNeedZbuffer;
case prefLockableBackBuffer: return m_pShellData->bLockableBackBuffer;
case prefSoftwareRendering: return m_pShellData->bSoftwareRender;
case prefNoShellSwapBuffer: return m_pShellData->bNoShellSwapBuffer;
case prefStencilBufferContext: return m_pShellData->bNeedStencilBuffer;
case prefAlphaFormatPre: return m_pShellData->bNeedAlphaFormatPre;
case prefPowerSaving: return m_pShellData->bUsingPowerSaving;
case prefOutputInfo: return m_pShellData->bOutputInfo;
case prefForceFrameTime: return m_pShellData->bForceFrameTime;
#ifdef PVRSHELL_FPS_OUTPUT
case prefOutputFPS: return m_pShellData->bOutputFPS;
#endif
case prefDiscardColor: return m_pShellData->bDiscardFrameColor;
case prefDiscardDepth: return m_pShellData->bDiscardFrameDepth;
case prefDiscardStencil: return m_pShellData->bDiscardFrameStencil;
default: return false;
}
}
/*!***********************************************************************
@brief This function is used to pass preferences to the PVRShell.
If used, this function must be called from InitApplication().
@param[in] prefName Name of preference to set to value
@param[in] value Value
@return true for success
*************************************************************************/
bool PVRShell::PVRShellSet(const prefNameFloatEnum prefName, const float value)
{
switch(prefName)
{
case prefQuitAfterTime:
m_pShellData->fDieAfterTime = value;
return true;
default:
break;
}
return false;
}
/*!***********************************************************************
@brief This function is used to get parameters from the PVRShell.
It can be called from anywhere in the program.
@param[in] prefName Name of preference to set to value
@return The requested value.
*************************************************************************/
float PVRShell::PVRShellGet(const prefNameFloatEnum prefName) const
{
switch(prefName)
{
case prefQuitAfterTime: return m_pShellData->fDieAfterTime;
default: return -1;
}
}
/*!***********************************************************************
@brief This function is used to pass preferences to the PVRShell.
If used, this function must be called from InitApplication().
@param[in] prefName Name of preference to set to value
@param[in] value Value
@return true for success
*************************************************************************/
bool PVRShell::PVRShellSet(const prefNameIntEnum prefName, const int value)
{
switch(prefName)
{
case prefWidth:
if(value > 0)
{
m_pShellData->nShellDimX = value;
return true;
}
return false;
case prefHeight:
if(value > 0)
{
m_pShellData->nShellDimY = value;
return true;
}
return false;
case prefPositionX:
m_pShellData->bShellPosWasDefault = false;
m_pShellData->nShellPosX = value;
return true;
case prefPositionY:
m_pShellData->bShellPosWasDefault = false;
m_pShellData->nShellPosY = value;
return true;
case prefQuitAfterFrame:
m_pShellData->nDieAfterFrames = value;
return true;
case prefInitRepeats:
m_pShellData->nInitRepeats = value;
return true;
case prefAASamples:
if(value >= 0)
{
m_pShellData->nAASamples = value;
return true;
}
return false;
case prefColorBPP:
if(value >= 0)
{
m_pShellData->nColorBPP = value;
return true;
}
return false;
case prefDepthBPP:
if(value >= 0)
{
m_pShellData->nDepthBPP = value;
return true;
}
return false;
case prefRotateKeys:
{
switch((PVRShellKeyRotate)value)
{
case PVRShellKeyRotateNone:
m_pShellInit->m_eKeyMapUP = PVRShellKeyNameUP;
m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameLEFT;
m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameDOWN;
m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameRIGHT;
break;
case PVRShellKeyRotate90:
m_pShellInit->m_eKeyMapUP = PVRShellKeyNameLEFT;
m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameDOWN;
m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameRIGHT;
m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameUP;
break;
case PVRShellKeyRotate180:
m_pShellInit->m_eKeyMapUP = PVRShellKeyNameDOWN;
m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameRIGHT;
m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameUP;
m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameLEFT;
break;
case PVRShellKeyRotate270:
m_pShellInit->m_eKeyMapUP = PVRShellKeyNameRIGHT;
m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameUP;
m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameLEFT;
m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameDOWN;
break;
default:
return false;
}
}
return true;
case prefCaptureFrameStart:
m_pShellData->nCaptureFrameStart = value;
return true;
case prefCaptureFrameStop:
m_pShellData->nCaptureFrameStop = value;
return true;
case prefCaptureFrameScale:
m_pShellData->nCaptureFrameScale = value;
return true;
case prefFrameTimeValue:
m_pShellData->nFrameTime = value;
return true;
default:
{
if(m_pShellInit->ApiSet(prefName, value))
return true;
return m_pShellInit->OsSet(prefName, value);
}
}
}
/*!***********************************************************************
@brief This function is used to get parameters from the PVRShell.
It can be called from anywhere in the program.
@param[in] prefName Name of preference to set to value
@return The requested value.
*************************************************************************/
int PVRShell::PVRShellGet(const prefNameIntEnum prefName) const
{
switch(prefName)
{
case prefWidth: return m_pShellData->nShellDimX;
case prefHeight: return m_pShellData->nShellDimY;
case prefPositionX: return m_pShellData->nShellPosX;
case prefPositionY: return m_pShellData->nShellPosY;
case prefQuitAfterFrame: return m_pShellData->nDieAfterFrames;
case prefSwapInterval: return m_pShellData->nSwapInterval;
case prefInitRepeats: return m_pShellData->nInitRepeats;
case prefAASamples: return m_pShellData->nAASamples;
case prefCommandLineOptNum: return m_pShellInit->m_CommandLine.m_nOptLen;
case prefColorBPP: return m_pShellData->nColorBPP;
case prefDepthBPP: return m_pShellData->nDepthBPP;
case prefCaptureFrameStart: return m_pShellData->nCaptureFrameStart;
case prefCaptureFrameStop: return m_pShellData->nCaptureFrameStop;
case prefCaptureFrameScale: return m_pShellData->nCaptureFrameScale;
case prefFrameTimeValue: return m_pShellData->nFrameTime;
case prefPriority: return m_pShellData->nPriority;
default:
{
int n;
if(m_pShellInit->ApiGet(prefName, &n))
return n;
if(m_pShellInit->OsGet(prefName, &n))
return n;
return -1;
}
}
}
/*!***********************************************************************
@brief This function is used to pass preferences to the PVRShell.
If used, this function must be called from InitApplication().
@param[in] prefName Name of preference to set to value
@param[in] value Value
@return true for success
*************************************************************************/
bool PVRShell::PVRShellSet(const prefNamePtrEnum prefName, const void * const ptrValue)
{
PVRSHELL_UNREFERENCED_PARAMETER(prefName);
PVRSHELL_UNREFERENCED_PARAMETER(ptrValue);
return false;
}
/*!***********************************************************************
@brief This function is used to get parameters from the PVRShell.
It can be called from anywhere in the program.
@param[in] prefName Name of preference to set to value
@return The requested value.
*************************************************************************/
void *PVRShell::PVRShellGet(const prefNamePtrEnum prefName) const
{
switch(prefName)
{
case prefNativeWindowType: return m_pShellInit->OsGetNativeWindowType();
case prefPointerLocation:
if (m_pShellInit->m_bTouching)
return m_pShellInit->m_vec2PointerLocation;
break;
default:
{
void *p;
if(m_pShellInit->ApiGet(prefName, &p))
return p;
if(m_pShellInit->OsGet(prefName, &p))
return p;
}
}
return NULL;
}
/*!***********************************************************************
@brief This function is used to pass preferences to the PVRShell.
If used, this function must be called from InitApplication().
@param[in] prefName Name of preference to set to value
@param[in] value Value
@return true for success
*************************************************************************/
bool PVRShell::PVRShellSet(const prefNameConstPtrEnum prefName, const void * const ptrValue)
{
switch(prefName)
{
case prefAppName:
StringCopy(m_pShellData->pszAppName, (char*)ptrValue);
return true;
case prefExitMessage:
StringCopy(m_pShellData->pszExitMessage, (char*)ptrValue);
PVRShellOutputDebug("Exit message has been set to: \"%s\".\n", ptrValue);
return true;
default:
break;
}
return false;
}
/*!***********************************************************************
@brief This function is used to get parameters from the PVRShell.
It can be called from anywhere in the program.
@param[in] prefName Name of preference to set to value
@return The requested value.
*************************************************************************/
const void *PVRShell::PVRShellGet(const prefNameConstPtrEnum prefName) const
{
switch(prefName)
{
case prefAppName:
return m_pShellData->pszAppName;
case prefExitMessage:
return m_pShellData->pszExitMessage;
case prefReadPath:
return m_pShellInit->GetReadPath();
case prefWritePath:
return m_pShellInit->GetWritePath();
case prefCommandLine:
return m_pShellInit->m_CommandLine.m_psOrig;
case prefCommandLineOpts:
return m_pShellInit->m_CommandLine.m_pOpt;
case prefVersion:
return PVRSDK_VERSION;
default:
return 0;
}
}
/*!***********************************************************************
@brief It will be stored as 24-bit per pixel, 8-bit per chanel RGB.
The memory should be freed with free() when no longer needed.
@param[in] Width size of image to capture (relative to 0,0)
@param[in] Height size of image to capture (relative to 0,0)
@param[out] pLines receives a pointer to an area of memory containing the screen buffer.
@return true for success
*************************************************************************/
bool PVRShell::PVRShellScreenCaptureBuffer(const int Width, const int Height, unsigned char **pLines)
{
/* Allocate memory for line */
*pLines=(unsigned char *)calloc(Width*Height*3, sizeof(unsigned char));
if (!(*pLines)) return false;
return m_pShellInit->ApiScreenCaptureBuffer(Width, Height, *pLines);
}
/*!***********************************************************************
@brief Writes out the image data to a BMP file with basename fname.
@details The file written will be fname suffixed with a number to make the file unique.
For example, if fname is "abc", this function will attempt
to save to "abc0000.bmp"; if that file already exists, it
will try "abc0001.bmp", repeating until a new filename is
found. The final filename used is returned in ofname.
@param[in] fname base of file to save screen to
@param[in] Width size of image to capture (relative to 0,0)
@param[in] Height size of image to capture (relative to 0,0)
@param[in] pLines image data to write out (24bpp, 8-bit per channel RGB)
@param[in] ui32PixelReplicate expand pixels through replication (1 = no scale)
@param[out] ofname If non-NULL, receives the filename actually used
@return true for success
*************************************************************************/
int PVRShell::PVRShellScreenSave(
const char * const fname,
const int Width,
const int Height,
const unsigned char * const pLines,
const unsigned int ui32PixelReplicate,
char * const ofname)
{
char *pszFileName;
/*
Choose a filename
*/
{
FILE *file = 0;
const char *pszWritePath;
int nScreenshotCount;
pszWritePath = (const char*)PVRShellGet(prefWritePath);
size_t nFileNameSize = strlen(pszWritePath) + 200;
pszFileName = (char*)malloc(nFileNameSize);
/* Look for the first file name that doesn't already exist */
for(nScreenshotCount = 0; nScreenshotCount < 10000; ++nScreenshotCount)
{
snprintf(pszFileName, nFileNameSize, "%s%s%04d.bmp", pszWritePath, fname, nScreenshotCount);
file = fopen(pszFileName,"r");
if(!file)
break;
fclose(file);
}
/* If all files already exist, replace the first one */
if (nScreenshotCount==10000)
{
snprintf(pszFileName, nFileNameSize, "%s%s0000.bmp", pszWritePath, fname);
PVRShellOutputDebug("PVRShell: *WARNING* : Overwriting %s\n", pszFileName);
}
if(ofname) // requested the output file name
{
strcpy(ofname, pszFileName);
}
}
const int err = PVRShellWriteBMPFile(pszFileName, Width, Height, pLines, ui32PixelReplicate);
FREE(pszFileName);
if (err)
{
return 10*err+1;
}
else
{
// No problem occurred
return 0;
}
}
/*!***********************************************************************
@brief Swaps the bytes in pBytes from little to big endian (or vice versa)
@param[in] pBytes The bytes to swap
@param[in] i32ByteNo The number of bytes to swap
*************************************************************************/
inline void PVRShellByteSwap(unsigned char* pBytes, int i32ByteNo)
{
int i = 0, j = i32ByteNo - 1;
while(i < j)
{
unsigned char cTmp = pBytes[i];
pBytes[i] = pBytes[j];
pBytes[j] = cTmp;
++i;
--j;
}
}
/*!***********************************************************************
@brief Writes out the image data to a BMP file with name fname.
@param[in] pszFilename file to save screen to
@param[in] ui32Width the width of the data
@param[in] ui32Height the height of the data
@param[in] pImageData image data to write out (24bpp, 8-bit per channel RGB)
@return 0 on success
*************************************************************************/
int PVRShell::PVRShellWriteBMPFile(
const char * const pszFilename,
const unsigned int ui32Width,
const unsigned int ui32Height,
const void * const pImageData,
const unsigned int ui32PixelReplicate)
{
#define ByteSwap(x) PVRShellByteSwap((unsigned char*) &x, sizeof(x))
const int i32BMPHeaderSize = 14; /* The size of a BMP header */
const int i32BMPInfoSize = 40; /* The size of a BMP info header */
int Result = 1;
FILE* fpDumpfile = 0;
fpDumpfile = fopen(pszFilename, "wb");
if (fpDumpfile != 0)
{
const short int word = 0x0001;
const char * const byte = (char*) &word;
bool bLittleEndian = byte[0] ? true : false;
unsigned int i32OutBytesPerLine = ui32Width * 3 * ui32PixelReplicate;
unsigned int i32OutAlign = 0;
// round up to a dword boundary
if(i32OutBytesPerLine & 3)
{
i32OutBytesPerLine |= 3;
++i32OutBytesPerLine;
i32OutAlign = i32OutBytesPerLine - ui32Width * 3 * ui32PixelReplicate;
}
unsigned char *pData = (unsigned char*) pImageData;
{
int ui32RealSize = i32OutBytesPerLine * ui32Height * ui32PixelReplicate;
// BMP Header
unsigned short bfType = 0x4D42;
unsigned int bfSize = i32BMPHeaderSize + i32BMPInfoSize + ui32RealSize;
unsigned short bfReserved1 = 0;
unsigned short bfReserved2 = 0;
unsigned int bfOffBits = i32BMPHeaderSize + i32BMPInfoSize;
// BMP Info Header
unsigned int biSize = i32BMPInfoSize;
unsigned int biWidth = ui32Width * ui32PixelReplicate;
unsigned int biHeight = ui32Height * ui32PixelReplicate;
unsigned short biPlanes = 1;
unsigned short biBitCount = 24;
unsigned int biCompression = 0L;
unsigned int biSizeImage = ui32RealSize;
unsigned int biXPelsPerMeter = 0;
unsigned int biYPelsPerMeter = 0;
unsigned int biClrUsed = 0;
unsigned int biClrImportant = 0;
if(!bLittleEndian)
{
for(unsigned int i = 0; i < ui32Width * ui32Height; ++i)
PVRShellByteSwap(pData + (3 * i), 3);
ByteSwap(bfType);
ByteSwap(bfSize);
ByteSwap(bfOffBits);
ByteSwap(biSize);
ByteSwap(biWidth);
ByteSwap(biHeight);
ByteSwap(biPlanes);
ByteSwap(biBitCount);
ByteSwap(biCompression);
ByteSwap(biSizeImage);
}
// Write Header.
fwrite(&bfType , 1, sizeof(bfType) , fpDumpfile);
fwrite(&bfSize , 1, sizeof(bfSize) , fpDumpfile);
fwrite(&bfReserved1 , 1, sizeof(bfReserved1), fpDumpfile);
fwrite(&bfReserved2 , 1, sizeof(bfReserved2), fpDumpfile);
fwrite(&bfOffBits , 1, sizeof(bfOffBits) , fpDumpfile);
// Write info header.
fwrite(&biSize , 1, sizeof(biSize) , fpDumpfile);
fwrite(&biWidth , 1, sizeof(biWidth) , fpDumpfile);
fwrite(&biHeight , 1, sizeof(biHeight) , fpDumpfile);
fwrite(&biPlanes , 1, sizeof(biPlanes) , fpDumpfile);
fwrite(&biBitCount , 1, sizeof(biBitCount) , fpDumpfile);
fwrite(&biCompression , 1, sizeof(biCompression) , fpDumpfile);
fwrite(&biSizeImage , 1, sizeof(biSizeImage) , fpDumpfile);
fwrite(&biXPelsPerMeter , 1, sizeof(biXPelsPerMeter), fpDumpfile);
fwrite(&biYPelsPerMeter , 1, sizeof(biYPelsPerMeter), fpDumpfile);
fwrite(&biClrUsed , 1, sizeof(biClrUsed) , fpDumpfile);
fwrite(&biClrImportant , 1, sizeof(biClrImportant) , fpDumpfile);
}
// Write image.
for(unsigned int nY = 0; nY < ui32Height; ++nY)
{
const unsigned char * pRow = &pData[3 * ui32Width * nY];
for(unsigned int nRepY = 0; nRepY < ui32PixelReplicate; ++nRepY)
{
for(unsigned int nX = 0; nX < ui32Width; ++nX)
{
const unsigned char * pPixel = &pRow[3 * nX];
for(unsigned int nRepX = 0; nRepX < ui32PixelReplicate; ++nRepX)
{
fwrite(pPixel, 1, 3, fpDumpfile);
}
}
fwrite("\0\0\0\0", i32OutAlign, 1, fpDumpfile);
}
}
// Last but not least close the file.
fclose(fpDumpfile);
Result = 0;
}
else
{
PVRShellOutputDebug("PVRShell: Failed to open \"%s\" for writing screen dump.\n", pszFilename);
}
return Result;
}
/*!***********************************************************************
@brief The number itself should be considered meaningless; an
application should use this function to determine how much
time has passed between two points (e.g. between each
frame).
@return A value which increments once per millisecond.
*************************************************************************/
unsigned long PVRShell::PVRShellGetTime()
{
if(m_pShellData->bForceFrameTime)
{
// Return a "time" value based on the current frame number
return (unsigned long) m_pShellData->nShellCurFrameNum * m_pShellData->nFrameTime;
}
else
{
// Read timer from a platform dependant function
return m_pShellInit->OsGetTime();
}
}
/*!***********************************************************************
@brief Check if a key was pressed. The keys on various devices
are mapped to the PVRShell-supported keys (listed in @a PVRShellKeyName) in
a platform-dependent manner, since most platforms have different input
devices. Check the <a href="modules.html">Modules page</a> for your OS
for details on how the enum values map to your device's key code input.
@param[in] key Code of the key to test
@return true if key was pressed
*************************************************************************/
bool PVRShell::PVRShellIsKeyPressed(const PVRShellKeyName key)
{
if(!m_pShellInit)
return false;
return m_pShellInit->DoIsKeyPressed(key);
}
// class PVRShellCommandLine
/*!***********************************************************************
@brief Constructor
*************************************************************************/
PVRShellCommandLine::PVRShellCommandLine()
{
memset(this, 0, sizeof(*this));
}
/*!***********************************************************************
@brief Destructor
*************************************************************************/
PVRShellCommandLine::~PVRShellCommandLine()
{
delete [] m_psOrig;
delete [] m_psSplit;
FREE(m_pOpt);
}
/*!***********************************************************************
@brief Set command-line options to pStr
@param[in] pStr Input string
*************************************************************************/
void PVRShellCommandLine::Set(const char *pStr)
{
delete [] m_psOrig;
m_psOrig = 0;
if(pStr)
{
size_t len = strlen(pStr)+1;
m_psOrig = new char[len];
strcpy(m_psOrig, pStr);
}
}
/*!***********************************************************************
@brief Prepend command-line options to m_psOrig
@param[in] pStr Input string
*************************************************************************/
void PVRShellCommandLine::Prefix(const char *pStr)
{
if(!m_psOrig)
Set(pStr);
else if(!pStr)
return;
else
{
char *pstmp = m_psOrig;
size_t lenA = strlen(pStr);
size_t TotalLen = lenA + 1 + strlen(m_psOrig);
m_psOrig = new char[TotalLen + 1];
strcpy(m_psOrig, pStr);
m_psOrig[lenA] = ' ';
strcpy(m_psOrig + lenA + 1, pstmp);
m_psOrig[TotalLen] = '\0';
delete[] pstmp;
}
}
/*!***********************************************************************
@brief Prepend command-line options to m_psOrig from a file
@param[in] pFileName Input string
*************************************************************************/
bool PVRShellCommandLine::PrefixFromFile(const char *pFileName)
{
char* nl;
FILE *pFile = fopen(pFileName, "rb");
if(pFile)
{
// Get the file size
fseek(pFile, 0, SEEK_END);
long m_Size = ftell(pFile) + 2;
fseek(pFile, 0, SEEK_SET);
char *pFullFile = new char[m_Size];
if(pFullFile)
{
size_t offset = 0;
while(fgets(pFullFile + offset, (int) (m_Size - offset), pFile))
{
offset = strlen(pFullFile);
// Replace new lines with spaces
nl = strrchr(pFullFile, '\r');
if(nl) *nl = ' ';
nl = strrchr(pFullFile, '\n');
if(nl) *nl = ' ';
}
pFullFile[offset] = '\0';
Prefix(pFullFile);
delete[] pFullFile;
fclose(pFile);
return true;
}
fclose(pFile);
}
return false;
}
/*!***********************************************************************
@brief Parse m_psOrig for command-line options and store them in m_pOpt
*************************************************************************/
void PVRShellCommandLine::Parse()
{
size_t len;
int nIn, nOut;
bool bInQuotes;
SCmdLineOpt opt;
if(!m_psOrig)
return;
// Delete/free up any options we may have parsed recently
delete [] m_psSplit;
FREE(m_pOpt);
// Take a copy to be edited
len = strlen(m_psOrig) + 1;
m_psSplit = new char[len];
// Break the command line into options
bInQuotes = false;
opt.pArg = NULL;
opt.pVal = NULL;
nIn = -1;
nOut = 0;
do
{
++nIn;
if(m_psOrig[nIn] == '"')
{
bInQuotes = !bInQuotes;
}
else
{
if(bInQuotes && m_psOrig[nIn] != 0)
{
if(!opt.pArg)
opt.pArg = &m_psSplit[nOut];
m_psSplit[nOut++] = m_psOrig[nIn];
}
else
{
switch(m_psOrig[nIn])
{
case '=':
m_psSplit[nOut++] = 0;
opt.pVal = &m_psSplit[nOut];
break;
case ' ':
case '\t':
case '\0':
m_psSplit[nOut++] = 0;
if(opt.pArg || opt.pVal)
{
// Increase list length if necessary
if(m_nOptLen == m_nOptMax)
m_nOptMax = m_nOptMax * 2 + 1;
SCmdLineOpt* pTmp = (SCmdLineOpt*)realloc(m_pOpt, m_nOptMax * sizeof(*m_pOpt));
if(!pTmp)
{
FREE(m_pOpt);
return;
}
m_pOpt = pTmp;
// Add option to list
m_pOpt[m_nOptLen++] = opt;
opt.pArg = NULL;
opt.pVal = NULL;
}
break;
default:
if(!opt.pArg)
opt.pArg = &m_psSplit[nOut];
m_psSplit[nOut++] = m_psOrig[nIn];
break;
}
}
}
} while(m_psOrig[nIn]);
}
/*!***********************************************************************
@brief Apply the command-line options to shell
@param[in] shell
*************************************************************************/
void PVRShellCommandLine::Apply(PVRShell &shell)
{
int i;
const char *arg, *val;
for(i = 0; i < m_nOptLen; ++i)
{
arg = m_pOpt[i].pArg;
val = m_pOpt[i].pVal;
if(!arg)
continue;
if(val)
{
if(_stricmp(arg, "-width") == 0)
{
shell.PVRShellSet(prefWidth, atoi(val));
}
else if(_stricmp(arg, "-height") == 0)
{
shell.PVRShellSet(prefHeight, atoi(val));
}
else if(_stricmp(arg, "-aasamples") == 0)
{
shell.PVRShellSet(prefAASamples, atoi(val));
}
else if(_stricmp(arg, "-fullscreen") == 0)
{
shell.PVRShellSet(prefFullScreen, (atoi(val) != 0));
}
else if(_stricmp(arg, "-sw") == 0)
{
shell.PVRShellSet(prefSoftwareRendering, (atoi(val) != 0));
}
else if(_stricmp(arg, "-quitafterframe") == 0 || _stricmp(arg, "-qaf") == 0)
{
shell.PVRShellSet(prefQuitAfterFrame, atoi(val));
}
else if(_stricmp(arg, "-quitaftertime") == 0 || _stricmp(arg, "-qat") == 0)
{
shell.PVRShellSet(prefQuitAfterTime, (float)atof(val));
}
else if(_stricmp(arg, "-posx") == 0)
{
shell.PVRShellSet(prefPositionX, atoi(val));
}
else if(_stricmp(arg, "-posy") == 0)
{
shell.PVRShellSet(prefPositionY, atoi(val));
}
else if(_stricmp(arg, "-vsync") == 0)
{
shell.PVRShellSet(prefSwapInterval, atoi(val));
}
else if(_stricmp(arg, "-powersaving") == 0 || _stricmp(arg, "-ps") == 0)
{
shell.PVRShellSet(prefPowerSaving, (atoi(val) != 0));
}
else if(_stricmp(arg, "-colourbpp") == 0 || _stricmp(arg, "-colorbpp") == 0 ||_stricmp(arg, "-cbpp") == 0)
{
shell.PVRShellSet(prefColorBPP, atoi(val));
}
else if(_stricmp(arg, "-depthbpp") == 0 || _stricmp(arg, "-dbpp") == 0)
{
shell.PVRShellSet(prefDepthBPP, atoi(val));
}
else if(_stricmp(arg, "-rotatekeys") == 0)
{
shell.PVRShellSet(prefRotateKeys, atoi(val));
}
else if(_stricmp(arg, "-c") == 0)
{
const char* pDash = strchr(val, '-');
shell.PVRShellSet(prefCaptureFrameStart, atoi(val));
if(!pDash)
shell.PVRShellSet(prefCaptureFrameStop, atoi(val));
else
shell.PVRShellSet(prefCaptureFrameStop, atoi(pDash + 1));
}
else if(_stricmp(arg, "-screenshotscale") == 0)
{
shell.PVRShellSet(prefCaptureFrameScale, atoi(val));
}
else if(_stricmp(arg, "-priority") == 0)
{
shell.PVRShellSet(prefPriority, atoi(val));
}
else if(_stricmp(arg, "-config") == 0)
{
shell.PVRShellSet(prefRequestedConfig, atoi(val));
}
else if(_stricmp(arg, "-display") == 0)
{
shell.PVRShellSet(prefNativeDisplay, atoi(val));
}
else if(_stricmp(arg, "-forceframetime") == 0 || _stricmp(arg, "-fft") == 0)
{
shell.PVRShellSet(prefForceFrameTime, true);
shell.PVRShellSet(prefFrameTimeValue, atoi(val));
}
else if(_stricmp(arg, "-discardframeall") == 0)
{
shell.PVRShellSet(prefDiscardColor, (atoi(val) != 0));
shell.PVRShellSet(prefDiscardDepth, (atoi(val) != 0));
shell.PVRShellSet(prefDiscardStencil, (atoi(val) != 0));
}
else if(_stricmp(arg, "-discardframecolor") == 0 || _stricmp(arg, "-discardframecolour") == 0)
{
shell.PVRShellSet(prefDiscardColor, (atoi(val) != 0));
}
else if(_stricmp(arg, "-discardframedepth") == 0)
{
shell.PVRShellSet(prefDiscardDepth, (atoi(val) != 0));
}
else if(_stricmp(arg, "-discardframestencil") == 0)
{
shell.PVRShellSet(prefDiscardStencil, (atoi(val) != 0));
}
}
else
{
if(_stricmp(arg, "-version") == 0)
{
shell.PVRShellOutputDebug("Version: \"%s\"\n", shell.PVRShellGet(prefVersion));
}
#ifdef PVRSHELL_FPS_OUTPUT
else if(_stricmp(arg, "-fps") == 0)
{
shell.PVRShellSet(prefOutputFPS, true);
}
#endif
else if(_stricmp(arg, "-info") == 0)
{
shell.PVRShellSet(prefOutputInfo, true);
}
else if(_stricmp(arg, "-forceframetime") == 0 || _stricmp(arg, "-fft") == 0)
{
shell.PVRShellSet(prefForceFrameTime, true);
}
}
}
}
// @Class PVRShellInit
/*!***********************************************************************
@brief Constructor
*************************************************************************/
PVRShellInit::PVRShellInit()
{
memset(this, 0, sizeof(*this));
}
/*!***********************************************************************
@brief Destructor
*************************************************************************/
PVRShellInit::~PVRShellInit()
{
Deinit();
delete [] m_pReadPath;
m_pReadPath = NULL;
delete [] m_pWritePath;
m_pWritePath = NULL;
}
/*!***********************************************************************
@brief PVRShell deinitialisation.
@param[in] Shell
*************************************************************************/
void PVRShellInit::Deinit()
{
if(m_pShell)
{
// Is the App currently running?
if(m_eState > ePVRShellInitApp && m_eState < ePVRShellExit)
{
// If so force it to go through the exit procedure
if(m_eState < ePVRShellReleaseView)
m_eState = ePVRShellReleaseView;
// Class the App as done
gShellDone = true;
// Run through the exiting states
while(Run()){};
}
delete m_pShell;
m_pShell = 0;
}
}
/*!***********************************************************************
@brief PVRShell Initialisation.
@Function Init
@param[in] Shell
@return True on success and false on failure
*************************************************************************/
bool PVRShellInit::Init()
{
Deinit();
m_pShell = NewDemo();
if(!m_pShell)
return false;
m_pShell->m_pShellInit = this;
// set default direction key mappings
m_eKeyMapDOWN = PVRShellKeyNameDOWN;
m_eKeyMapLEFT = PVRShellKeyNameLEFT;
m_eKeyMapUP = PVRShellKeyNameUP;
m_eKeyMapRIGHT = PVRShellKeyNameRIGHT;
nLastKeyPressed = PVRShellKeyNameNull;
OsInit();
gShellDone = false;
m_eState = ePVRShellInitApp;
return true;
}
/*!***********************************************************************
@brief Receives the command-line from the application.
@param[in] str A string containing the command-line
*************************************************************************/
void PVRShellInit::CommandLine(const char *str)
{
m_CommandLine.Set(str);
}
/*!***********************************************************************
@brief Receives the command-line from the application.
@param[in] argc Number of strings in argv
@param[in] argv An array of strings
*************************************************************************/
void PVRShellInit::CommandLine(int argc, char **argv)
{
size_t tot, len;
char *buf;
int i;
tot = 0;
for(i = 0; i < argc; ++i)
tot += strlen(argv[i]);
if(!tot)
{
CommandLine((char*) "");
return;
}
// Add room for spaces and the \0
tot += argc;
buf = new char[tot];
tot = 0;
for(i = 0; i < argc; ++i)
{
len = strlen(argv[i]);
strncpy(&buf[tot], argv[i], len);
tot += len;
buf[tot++] = ' ';
}
buf[tot-1] = 0;
CommandLine(buf);
delete [] buf;
}
/*!***********************************************************************
@brief Return 'true' if the specific key has been pressed.
@param[in] key The key we're querying for
*************************************************************************/
bool PVRShellInit::DoIsKeyPressed(const PVRShellKeyName key)
{
if(key == nLastKeyPressed)
{
nLastKeyPressed = PVRShellKeyNameNull;
return true;
}
else
{
return false;
}
}
/*!***********************************************************************
@brief Used by the OS-specific code to tell the Shell that a key has been pressed.
@param[in] nKey The key that has been pressed
*************************************************************************/
void PVRShellInit::KeyPressed(PVRShellKeyName nKey)
{
nLastKeyPressed = nKey;
}
/*!***********************************************************************
@brief Used by the OS-specific code to tell the Shell that a touch has began at a location.
@param[in] vec2Location The position of a click/touch on the screen when it first touches
*************************************************************************/
void PVRShellInit::TouchBegan(const float vec2Location[2])
{
m_bTouching = true;
m_vec2PointerLocationStart[0] = m_vec2PointerLocation[0] = vec2Location[0];
m_vec2PointerLocationStart[1] = m_vec2PointerLocation[1] = vec2Location[1];
}
/*!***********************************************************************
@brief Used by the OS-specific code to tell the Shell that a touch has began at a location.
@param[in] vec2Location The position of the pointer/touch pressed on the screen
*************************************************************************/
void PVRShellInit::TouchMoved(const float vec2Location[2])
{
if(m_bTouching)
{
m_vec2PointerLocation[0] = vec2Location[0];
m_vec2PointerLocation[1] = vec2Location[1];
}
}
/*!***********************************************************************
@brief Used by the OS-specific code to tell the Shell that the current touch has ended at a location.
@param[in] vec2Location The position of the pointer/touch on the screen when it is released
*************************************************************************/
void PVRShellInit::TouchEnded(const float vec2Location[2])
{
if(m_bTouching)
{
m_bTouching = false;
m_vec2PointerLocationEnd[0] = m_vec2PointerLocation[0] = vec2Location[0];
m_vec2PointerLocationEnd[1] = m_vec2PointerLocation[1] = vec2Location[1];
#if !defined(DISABLE_SWIPE_MAPPING)
float fX = m_vec2PointerLocationEnd[0] - m_vec2PointerLocationStart[0];
float fY = m_vec2PointerLocationEnd[1] - m_vec2PointerLocationStart[1];
float fTmp = fX * fX + fY * fY;
if(fTmp > 0.005f)
{
fTmp = 1.0f / sqrt(fTmp);
fY *= fTmp;
float fAngle = acos(fY);
const float pi = 3.1415f;
const float pi_half = pi * 0.5f;
const float error = 0.25f;
if(fAngle < error)
KeyPressed(m_eKeyMapDOWN);
else if(fAngle > (pi - error))
KeyPressed(m_eKeyMapUP);
else if(fAngle > (pi_half - error) && fAngle < (pi_half + error))
KeyPressed((fX < 0) ? m_eKeyMapLEFT : m_eKeyMapRIGHT);
}
else if(fTmp < 0.09f)
{
if (m_vec2PointerLocationEnd[0] <= 0.3f) // Left half of the screen
KeyPressed(PVRShellKeyNameACTION1);
else if (m_vec2PointerLocationEnd[0] >= 0.7f) // Right half of the screen
KeyPressed(PVRShellKeyNameACTION2);
}
#endif
}
}
/*!***********************************************************************
@brief Used by the OS-specific code to tell the Shell where to read external files from
@return A path the application is capable of reading from
*************************************************************************/
const char* PVRShellInit::GetReadPath() const
{
return m_pReadPath;
}
/*!***********************************************************************
@brief Used by the OS-specific code to tell the Shell where to write to
@return A path the applications is capable of writing to
*************************************************************************/
const char* PVRShellInit::GetWritePath() const
{
return m_pWritePath;
}
/*!****************************************************************************
@brief Sets the default app name (to be displayed by the OS)
@param[in] str The application name
*******************************************************************************/
void PVRShellInit::SetAppName(const char * const str)
{
const char *pName = strrchr(str, PVRSHELL_DIR_SYM);
if(pName)
{
++pName;
}
else
{
pName = str;
}
m_pShell->PVRShellSet(prefAppName, pName);
}
/*!***********************************************************************
@brief Set the path to where the application expects to read from.
@param[in] str The read path
*************************************************************************/
void PVRShellInit::SetReadPath(const char * const str)
{
m_pReadPath = new char[strlen(str)+1];
if(m_pReadPath)
{
strcpy(m_pReadPath, str);
char* lastSlash = strrchr(m_pReadPath, PVRSHELL_DIR_SYM);
if(lastSlash)
lastSlash[1] = 0;
}
}
/*!***********************************************************************
@brief Set the path to where the application expects to write to.
@param[in] str The write path
*************************************************************************/
void PVRShellInit::SetWritePath(const char * const str)
{
m_pWritePath = new char[strlen(str)+1];
if(m_pWritePath)
{
strcpy(m_pWritePath, str);
char* lastSlash = strrchr(m_pWritePath, PVRSHELL_DIR_SYM);
if(lastSlash)
lastSlash[1] = 0;
}
}
#ifdef PVRSHELL_FPS_OUTPUT
/*****************************************************************************
@fn FpsUpdate
@brief Calculates a value for frames-per-second (FPS).
@details This is only compiled in to the application if PVRSHELL_FPS_OUTPUT is defined.
*****************************************************************************/
void PVRShellInit::FpsUpdate()
{
unsigned int ui32TimeDelta, ui32Time;
ui32Time = m_pShell->PVRShellGetTime();
++m_i32FpsFrameCnt;
ui32TimeDelta = ui32Time - m_i32FpsTimePrev;
if(ui32TimeDelta >= 1000)
{
float fFPS = 1000.0f * (float) m_i32FpsFrameCnt / (float) ui32TimeDelta;
m_pShell->PVRShellOutputDebug("PVRShell: frame %d, FPS %.1f.\n",
m_pShell->m_pShellData->nShellCurFrameNum, fFPS);
m_i32FpsFrameCnt = 0;
m_i32FpsTimePrev = ui32Time;
}
}
#endif
/*****************************************************************************
@brief Main message loop / render loop
@return false when the app should quit
*****************************************************************************/
bool PVRShellInit::Run()
{
static unsigned long StartTime = 0;
switch(m_eState)
{
case ePVRShellInitApp:
{
// Make sure the shell isn't done
gShellDone = false;
// Prepend command-line options from PVRShellCL.txt
const char * const pCL = "PVRShellCL.txt";
const char *pPath = (const char*) m_pShell->PVRShellGet(prefReadPath);
size_t nSize = strlen(pPath) + strlen(pCL) + 1;
char *pString = new char[nSize];
if(pString)
{
snprintf(pString, nSize, "%s%s", pPath, pCL);
if(!m_CommandLine.PrefixFromFile(pString))
{
delete[] pString;
pPath = (const char*) m_pShell->PVRShellGet(prefWritePath);
nSize = strlen(pPath) + strlen(pCL) + 1;
pString = new char[nSize];
snprintf(pString, nSize, "%s%s", pPath, pCL);
if(m_CommandLine.PrefixFromFile(pString))
m_pShell->PVRShellOutputDebug("Loaded command-line options from %s.\n", pString);
}
else
m_pShell->PVRShellOutputDebug("Loaded command-line options from %s.\n", pString);
delete[] pString;
}
// Parse the command-line
m_CommandLine.Parse();
#if defined(_DEBUG)
m_pShell->PVRShellOutputDebug("PVRShell command line: %d/%d\n", m_CommandLine.m_nOptLen, m_CommandLine.m_nOptMax);
for(int i = 0; i < m_CommandLine.m_nOptLen; ++i)
{
m_pShell->PVRShellOutputDebug("CL %d: \"%s\"\t= \"%s\".\n", i,
m_CommandLine.m_pOpt[i].pArg ? m_CommandLine.m_pOpt[i].pArg : "",
m_CommandLine.m_pOpt[i].pVal ? m_CommandLine.m_pOpt[i].pVal : "");
}
#endif
// Call InitApplication
if(!m_pShell->InitApplication())
{
m_eState = ePVRShellExit;
return true;
}
m_eState = ePVRShellInitInstance;
return true;
}
case ePVRShellInitInstance:
{
m_CommandLine.Apply(*m_pShell);
// Output non-api specific data if required
OutputInfo();
// Perform OS initialisation
if(!OsInitOS())
{
m_pShell->PVRShellOutputDebug("InitOS failed!\n");
m_eState = ePVRShellQuitApp;
return true;
}
// Initialize the 3D API
if(!OsDoInitAPI())
{
m_pShell->PVRShellOutputDebug("InitAPI failed!\n");
m_eState = ePVRShellReleaseOS;
gShellDone = true;
return true;
}
// Output api specific data if required
OutputAPIInfo();
// Initialise the app
if(!m_pShell->InitView())
{
m_pShell->PVRShellOutputDebug("InitView failed!\n");
m_eState = ePVRShellReleaseAPI;
gShellDone = true;
return true;
}
if(StartTime==0)
{
StartTime = OsGetTime();
}
m_eState = ePVRShellRender;
return true;
}
case ePVRShellRender:
{
// Main message loop:
if(!m_pShell->RenderScene())
break;
ApiRenderComplete();
OsRenderComplete();
#ifdef PVRSHELL_FPS_OUTPUT
if(m_pShell->m_pShellData->bOutputFPS)
FpsUpdate();
#endif
int nCurrentFrame = m_pShell->m_pShellData->nShellCurFrameNum;
if(DoIsKeyPressed(PVRShellKeyNameScreenshot) || (nCurrentFrame >= m_pShell->m_pShellData->nCaptureFrameStart && nCurrentFrame <= m_pShell->m_pShellData->nCaptureFrameStop))
{
unsigned char *pBuf;
const int nWidth = m_pShell->PVRShellGet(prefWidth);
const int nHeight = m_pShell->PVRShellGet(prefHeight);
if(m_pShell->PVRShellScreenCaptureBuffer(nWidth, nHeight, &pBuf))
{
if(m_pShell->PVRShellScreenSave(PVRSHELL_SCREENSHOT_NAME, nWidth, nHeight, pBuf, m_pShell->m_pShellData->nCaptureFrameScale) != 0)
{
m_pShell->PVRShellSet(prefExitMessage, "Screen-shot save failed.\n");
}
}
else
{
m_pShell->PVRShellSet(prefExitMessage, "Screen capture failed.\n");
}
FREE(pBuf);
}
if(DoIsKeyPressed(PVRShellKeyNameQUIT))
gShellDone = true;
if(gShellDone)
break;
/* Quit if maximum number of allowed frames is reached */
if((m_pShell->m_pShellData->nDieAfterFrames>=0) && (nCurrentFrame >= m_pShell->m_pShellData->nDieAfterFrames))
break;
/* Quit if maximum time is reached */
if((m_pShell->m_pShellData->fDieAfterTime>=0.0f) && (((OsGetTime()-StartTime)*0.001f) >= m_pShell->m_pShellData->fDieAfterTime))
break;
m_pShell->m_pShellData->nShellCurFrameNum++;
return true;
}
case ePVRShellReleaseView:
m_pShell->ReleaseView();
case ePVRShellReleaseAPI:
OsDoReleaseAPI();
case ePVRShellReleaseOS:
OsReleaseOS();
if(!gShellDone && m_pShell->m_pShellData->nInitRepeats)
{
--m_pShell->m_pShellData->nInitRepeats;
m_eState = ePVRShellInitInstance;
return true;
}
m_eState = ePVRShellQuitApp;
return true;
case ePVRShellQuitApp:
// Final app tidy-up
m_pShell->QuitApplication();
m_eState = ePVRShellExit;
case ePVRShellExit:
OsExit();
StringCopy(m_pShell->m_pShellData->pszAppName, 0);
StringCopy(m_pShell->m_pShellData->pszExitMessage, 0);
return false;
}
m_eState = (EPVRShellState)(m_eState + 1);
return true;
}
/*!***********************************************************************
@brief When prefOutputInfo is set to true this function outputs
various pieces of non-API dependent information via
PVRShellOutputDebug.
*************************************************************************/
void PVRShellInit::OutputInfo()
{
if(m_pShell->PVRShellGet(prefOutputInfo))
{
m_pShell->PVRShellOutputDebug("\n");
m_pShell->PVRShellOutputDebug("App name: %s\n" , m_pShell->PVRShellGet(prefAppName));
m_pShell->PVRShellOutputDebug("SDK version: %s\n" , m_pShell->PVRShellGet(prefVersion));
m_pShell->PVRShellOutputDebug("\n");
m_pShell->PVRShellOutputDebug("Read path: %s\n" , m_pShell->PVRShellGet(prefReadPath));
m_pShell->PVRShellOutputDebug("Write path: %s\n" , m_pShell->PVRShellGet(prefWritePath));
m_pShell->PVRShellOutputDebug("\n");
m_pShell->PVRShellOutputDebug("Command-line: %s\n" , m_pShell->PVRShellGet(prefCommandLine));
m_pShell->PVRShellOutputDebug("\n");
m_pShell->PVRShellOutputDebug("Power saving: %s\n" , m_pShell->PVRShellGet(prefPowerSaving) ? "On" : "Off");
m_pShell->PVRShellOutputDebug("AA Samples requested: %i\n", m_pShell->PVRShellGet(prefAASamples));
m_pShell->PVRShellOutputDebug("Fullscreen: %s\n", m_pShell->PVRShellGet(prefFullScreen) ? "Yes" : "No");
m_pShell->PVRShellOutputDebug("PBuffer requested: %s\n", m_pShell->PVRShellGet(prefPBufferContext) ? "Yes" : "No");
m_pShell->PVRShellOutputDebug("ZBuffer requested: %s\n", m_pShell->PVRShellGet(prefZbufferContext) ? "Yes" : "No");
m_pShell->PVRShellOutputDebug("Stencil buffer requested: %s\n", m_pShell->PVRShellGet(prefStencilBufferContext) ? "Yes" : "No");
if(m_pShell->PVRShellGet(prefColorBPP) > 0)
m_pShell->PVRShellOutputDebug("Colour buffer size requested: %i\n", m_pShell->PVRShellGet(prefColorBPP));
if(m_pShell->PVRShellGet(prefDepthBPP) > 0)
m_pShell->PVRShellOutputDebug("Depth buffer size requested: %i\n", m_pShell->PVRShellGet(prefDepthBPP));
m_pShell->PVRShellOutputDebug("Software rendering requested: %s\n", m_pShell->PVRShellGet(prefSoftwareRendering) ? "Yes" : "No");
m_pShell->PVRShellOutputDebug("Swap Interval requested: %i\n", m_pShell->PVRShellGet(prefSwapInterval));
if(m_pShell->PVRShellGet(prefInitRepeats) > 0)
m_pShell->PVRShellOutputDebug("No of Init repeats: %i\n", m_pShell->PVRShellGet(prefInitRepeats));
if(m_pShell->PVRShellGet(prefQuitAfterFrame) != -1)
m_pShell->PVRShellOutputDebug("Quit after frame: %i\n", m_pShell->PVRShellGet(prefQuitAfterFrame));
if(m_pShell->PVRShellGet(prefQuitAfterTime) != -1.0f)
m_pShell->PVRShellOutputDebug("Quit after time: %f\n", m_pShell->PVRShellGet(prefQuitAfterTime));
}
}
/****************************************************************************
** Local code
****************************************************************************/
/*!***********************************************************************
@brief This function copies pszSrc into pszStr.
@param[out] pszStr The string to copy pszSrc into
@param[in] pszSrc The source string to copy
*************************************************************************/
static bool StringCopy(char *&pszStr, const char * const pszSrc)
{
size_t len;
FREE(pszStr);
if(!pszSrc)
return true;
len = strlen(pszSrc)+1;
pszStr = (char*)malloc(len);
if(!pszStr)
return false;
strcpy(pszStr, pszSrc);
return true;
}
/// @endcond
//NO_DOXYGEN
/*****************************************************************************
End of file (PVRShell.cpp)
*****************************************************************************/