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