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