1 /****************************************************************************** 2 3 @file Shell/PVRShell.cpp 4 @copyright Copyright (c) Imagination Technologies Limited. 5 @brief Makes programming for 3D APIs easier by wrapping surface 6 initialization, Texture allocation and other functions for use by a demo. 7 8 ******************************************************************************/ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <stdarg.h> 14 #include <math.h> 15 16 #include "PVRShell.h" 17 #include "PVRShellOS.h" 18 #include "PVRShellAPI.h" 19 #include "PVRShellImpl.h" 20 21 /*! This file simply defines a version string. It can be commented out. */ 22 #include "sdkver.h" 23 #ifndef PVRSDK_VERSION 24 #define PVRSDK_VERSION "n.nn.nn.nnnn" 25 #endif 26 27 /*! Define to automatically stop the app after x frames. If negative, run forever. */ 28 #ifndef PVRSHELL_QUIT_AFTER_FRAME 29 #define PVRSHELL_QUIT_AFTER_FRAME -1 30 #endif 31 32 /*! Define to automatically stop the app after x amount of seconds. If negative, run forever. */ 33 #ifndef PVRSHELL_QUIT_AFTER_TIME 34 #define PVRSHELL_QUIT_AFTER_TIME -1 35 #endif 36 37 /*! Define for the screen shot file name. */ 38 #define PVRSHELL_SCREENSHOT_NAME "PVRShell" 39 40 #if defined(_WIN32) 41 #define snprintf _snprintf 42 #endif 43 44 // No Doxygen for CPP files, due to documentation duplication 45 /// @cond NO_DOXYGEN 46 47 // Define DISABLE_SWIPE_MAPPING to disable the PVRShell's simple mapping of swipes to key commands. 48 //#define DISABLE_SWIPE_MAPPING 1 49 /***************************************************************************** 50 ** Prototypes 51 *****************************************************************************/ 52 static bool StringCopy(char *&pszStr, const char * const pszSrc); 53 54 /**************************************************************************** 55 ** Class: PVRShell 56 ****************************************************************************/ 57 58 /*!*********************************************************************** 59 @brief Constructor 60 *************************************************************************/ 61 PVRShell::PVRShell() 62 { 63 m_pShellInit = NULL; 64 m_pShellData = new PVRShellData; 65 66 m_pShellData->nShellPosX=0; 67 m_pShellData->nShellPosY=0; 68 69 m_pShellData->bFullScreen = false; // note this may be overridden by some OS versions of PVRShell 70 71 m_pShellData->nAASamples= 0; 72 m_pShellData->nColorBPP = 0; 73 m_pShellData->nDepthBPP = 0; 74 75 m_pShellData->nDieAfterFrames = PVRSHELL_QUIT_AFTER_FRAME; 76 m_pShellData->fDieAfterTime = PVRSHELL_QUIT_AFTER_TIME; 77 78 m_pShellData->bNeedPbuffer = false; 79 m_pShellData->bNeedPixmap = false; 80 m_pShellData->bNeedPixmapDisableCopy = false; 81 m_pShellData->bNeedZbuffer = true; 82 m_pShellData->bLockableBackBuffer = false; 83 m_pShellData->bSoftwareRender = false; 84 m_pShellData->bNeedStencilBuffer = false; 85 86 m_pShellData->bNeedAlphaFormatPre = false; 87 m_pShellData->bUsingPowerSaving = true; 88 m_pShellData->bOutputInfo = false; 89 m_pShellData->bNoShellSwapBuffer = false; 90 91 m_pShellData->pszAppName = 0; 92 m_pShellData->pszExitMessage = 0; 93 94 m_pShellData->nSwapInterval = 1; 95 m_pShellData->nInitRepeats = 0; 96 97 m_pShellData->nCaptureFrameStart = -1; 98 m_pShellData->nCaptureFrameStop = -1; 99 m_pShellData->nCaptureFrameScale = 1; 100 101 m_pShellData->nPriority = 2; 102 103 m_pShellData->bForceFrameTime = false; 104 m_pShellData->nFrameTime = 33; 105 106 // Internal Data 107 m_pShellData->bShellPosWasDefault = true; 108 m_pShellData->nShellCurFrameNum = 0; 109 #ifdef PVRSHELL_FPS_OUTPUT 110 m_pShellData->bOutputFPS = false; 111 #endif 112 m_pShellData->bDiscardFrameColor=false; 113 m_pShellData->bDiscardFrameDepth=true; 114 m_pShellData->bDiscardFrameStencil=true; 115 } 116 117 /*!*********************************************************************** 118 @brief Destructor 119 *************************************************************************/ 120 PVRShell::~PVRShell() 121 { 122 delete m_pShellData; 123 m_pShellData = NULL; 124 } 125 126 // Allow user to set preferences from within InitApplication 127 128 /*!*********************************************************************** 129 @brief This function is used to pass preferences to the PVRShell. 130 If used, this function must be called from InitApplication(). 131 @param[in] prefName Name of preference to set to value 132 @param[in] value Value 133 @return true for success 134 *************************************************************************/ 135 136 bool PVRShell::PVRShellSet(const prefNameBoolEnum prefName, const bool value) 137 { 138 switch(prefName) 139 { 140 case prefFullScreen: 141 m_pShellData->bFullScreen = value; 142 return true; 143 144 case prefPBufferContext: 145 m_pShellData->bNeedPbuffer = value; 146 return true; 147 148 case prefPixmapContext: 149 m_pShellData->bNeedPixmap = value; 150 return true; 151 152 case prefPixmapDisableCopy: 153 m_pShellData->bNeedPixmapDisableCopy = value; 154 return true; 155 156 case prefZbufferContext: 157 m_pShellData->bNeedZbuffer = value; 158 return true; 159 160 case prefLockableBackBuffer: 161 m_pShellData->bLockableBackBuffer = value; 162 return true; 163 164 case prefSoftwareRendering: 165 m_pShellData->bSoftwareRender = value; 166 return true; 167 168 case prefStencilBufferContext: 169 m_pShellData->bNeedStencilBuffer = value; 170 return true; 171 172 case prefAlphaFormatPre: 173 m_pShellData->bNeedAlphaFormatPre = value; 174 return true; 175 176 case prefPowerSaving: 177 m_pShellData->bUsingPowerSaving = value; 178 return true; 179 180 case prefOutputInfo: 181 m_pShellData->bOutputInfo = value; 182 return true; 183 184 case prefNoShellSwapBuffer: 185 m_pShellData->bNoShellSwapBuffer = value; 186 return true; 187 188 case prefForceFrameTime: 189 m_pShellData->bForceFrameTime = value; 190 return true; 191 192 #ifdef PVRSHELL_FPS_OUTPUT 193 case prefOutputFPS: 194 m_pShellData->bOutputFPS = value; 195 return true; 196 #endif 197 198 case prefDiscardColor: 199 m_pShellData->bDiscardFrameColor = value; 200 return true; 201 case prefDiscardDepth: 202 m_pShellData->bDiscardFrameDepth = value; 203 return true; 204 case prefDiscardStencil: 205 m_pShellData->bDiscardFrameStencil = value; 206 return true; 207 default: 208 return m_pShellInit->OsSet(prefName, value); 209 } 210 } 211 212 /*!*********************************************************************** 213 @brief This function is used to get parameters from the PVRShell. 214 It can be called from anywhere in the program. 215 @param[in] prefName Name of preference to set to value 216 @return The requested value. 217 *************************************************************************/ 218 219 bool PVRShell::PVRShellGet(const prefNameBoolEnum prefName) const 220 { 221 switch(prefName) 222 { 223 case prefFullScreen: return m_pShellData->bFullScreen; 224 case prefIsRotated: return (m_pShellData->nShellDimY > m_pShellData->nShellDimX); 225 case prefPBufferContext: return m_pShellData->bNeedPbuffer; 226 case prefPixmapContext: return m_pShellData->bNeedPixmap; 227 case prefPixmapDisableCopy: return m_pShellData->bNeedPixmapDisableCopy; 228 case prefZbufferContext: return m_pShellData->bNeedZbuffer; 229 case prefLockableBackBuffer: return m_pShellData->bLockableBackBuffer; 230 case prefSoftwareRendering: return m_pShellData->bSoftwareRender; 231 case prefNoShellSwapBuffer: return m_pShellData->bNoShellSwapBuffer; 232 case prefStencilBufferContext: return m_pShellData->bNeedStencilBuffer; 233 case prefAlphaFormatPre: return m_pShellData->bNeedAlphaFormatPre; 234 case prefPowerSaving: return m_pShellData->bUsingPowerSaving; 235 case prefOutputInfo: return m_pShellData->bOutputInfo; 236 case prefForceFrameTime: return m_pShellData->bForceFrameTime; 237 #ifdef PVRSHELL_FPS_OUTPUT 238 case prefOutputFPS: return m_pShellData->bOutputFPS; 239 #endif 240 case prefDiscardColor: return m_pShellData->bDiscardFrameColor; 241 case prefDiscardDepth: return m_pShellData->bDiscardFrameDepth; 242 case prefDiscardStencil: return m_pShellData->bDiscardFrameStencil; 243 default: return false; 244 } 245 } 246 247 /*!*********************************************************************** 248 @brief This function is used to pass preferences to the PVRShell. 249 If used, this function must be called from InitApplication(). 250 @param[in] prefName Name of preference to set to value 251 @param[in] value Value 252 @return true for success 253 *************************************************************************/ 254 255 bool PVRShell::PVRShellSet(const prefNameFloatEnum prefName, const float value) 256 { 257 switch(prefName) 258 { 259 case prefQuitAfterTime: 260 m_pShellData->fDieAfterTime = value; 261 return true; 262 263 default: 264 break; 265 } 266 return false; 267 } 268 269 /*!*********************************************************************** 270 @brief This function is used to get parameters from the PVRShell. 271 It can be called from anywhere in the program. 272 @param[in] prefName Name of preference to set to value 273 @return The requested value. 274 *************************************************************************/ 275 float PVRShell::PVRShellGet(const prefNameFloatEnum prefName) const 276 { 277 switch(prefName) 278 { 279 case prefQuitAfterTime: return m_pShellData->fDieAfterTime; 280 default: return -1; 281 } 282 } 283 284 /*!*********************************************************************** 285 @brief This function is used to pass preferences to the PVRShell. 286 If used, this function must be called from InitApplication(). 287 @param[in] prefName Name of preference to set to value 288 @param[in] value Value 289 @return true for success 290 *************************************************************************/ 291 bool PVRShell::PVRShellSet(const prefNameIntEnum prefName, const int value) 292 { 293 switch(prefName) 294 { 295 case prefWidth: 296 if(value > 0) 297 { 298 m_pShellData->nShellDimX = value; 299 return true; 300 } 301 return false; 302 303 case prefHeight: 304 if(value > 0) 305 { 306 m_pShellData->nShellDimY = value; 307 return true; 308 } 309 return false; 310 311 case prefPositionX: 312 m_pShellData->bShellPosWasDefault = false; 313 m_pShellData->nShellPosX = value; 314 return true; 315 316 case prefPositionY: 317 m_pShellData->bShellPosWasDefault = false; 318 m_pShellData->nShellPosY = value; 319 return true; 320 321 case prefQuitAfterFrame: 322 m_pShellData->nDieAfterFrames = value; 323 return true; 324 325 case prefInitRepeats: 326 m_pShellData->nInitRepeats = value; 327 return true; 328 329 case prefAASamples: 330 if(value >= 0) 331 { 332 m_pShellData->nAASamples = value; 333 return true; 334 } 335 return false; 336 337 case prefColorBPP: 338 if(value >= 0) 339 { 340 m_pShellData->nColorBPP = value; 341 return true; 342 } 343 return false; 344 345 case prefDepthBPP: 346 if(value >= 0) 347 { 348 m_pShellData->nDepthBPP = value; 349 return true; 350 } 351 return false; 352 353 case prefRotateKeys: 354 { 355 switch((PVRShellKeyRotate)value) 356 { 357 case PVRShellKeyRotateNone: 358 m_pShellInit->m_eKeyMapUP = PVRShellKeyNameUP; 359 m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameLEFT; 360 m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameDOWN; 361 m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameRIGHT; 362 break; 363 case PVRShellKeyRotate90: 364 m_pShellInit->m_eKeyMapUP = PVRShellKeyNameLEFT; 365 m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameDOWN; 366 m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameRIGHT; 367 m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameUP; 368 break; 369 case PVRShellKeyRotate180: 370 m_pShellInit->m_eKeyMapUP = PVRShellKeyNameDOWN; 371 m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameRIGHT; 372 m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameUP; 373 m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameLEFT; 374 break; 375 case PVRShellKeyRotate270: 376 m_pShellInit->m_eKeyMapUP = PVRShellKeyNameRIGHT; 377 m_pShellInit->m_eKeyMapLEFT = PVRShellKeyNameUP; 378 m_pShellInit->m_eKeyMapDOWN = PVRShellKeyNameLEFT; 379 m_pShellInit->m_eKeyMapRIGHT = PVRShellKeyNameDOWN; 380 break; 381 default: 382 return false; 383 } 384 } 385 return true; 386 case prefCaptureFrameStart: 387 m_pShellData->nCaptureFrameStart = value; 388 return true; 389 case prefCaptureFrameStop: 390 m_pShellData->nCaptureFrameStop = value; 391 return true; 392 case prefCaptureFrameScale: 393 m_pShellData->nCaptureFrameScale = value; 394 return true; 395 case prefFrameTimeValue: 396 m_pShellData->nFrameTime = value; 397 return true; 398 default: 399 { 400 if(m_pShellInit->ApiSet(prefName, value)) 401 return true; 402 403 return m_pShellInit->OsSet(prefName, value); 404 } 405 } 406 } 407 408 /*!*********************************************************************** 409 @brief This function is used to get parameters from the PVRShell. 410 It can be called from anywhere in the program. 411 @param[in] prefName Name of preference to set to value 412 @return The requested value. 413 *************************************************************************/ 414 int PVRShell::PVRShellGet(const prefNameIntEnum prefName) const 415 { 416 switch(prefName) 417 { 418 case prefWidth: return m_pShellData->nShellDimX; 419 case prefHeight: return m_pShellData->nShellDimY; 420 case prefPositionX: return m_pShellData->nShellPosX; 421 case prefPositionY: return m_pShellData->nShellPosY; 422 case prefQuitAfterFrame: return m_pShellData->nDieAfterFrames; 423 case prefSwapInterval: return m_pShellData->nSwapInterval; 424 case prefInitRepeats: return m_pShellData->nInitRepeats; 425 case prefAASamples: return m_pShellData->nAASamples; 426 case prefCommandLineOptNum: return m_pShellInit->m_CommandLine.m_nOptLen; 427 case prefColorBPP: return m_pShellData->nColorBPP; 428 case prefDepthBPP: return m_pShellData->nDepthBPP; 429 case prefCaptureFrameStart: return m_pShellData->nCaptureFrameStart; 430 case prefCaptureFrameStop: return m_pShellData->nCaptureFrameStop; 431 case prefCaptureFrameScale: return m_pShellData->nCaptureFrameScale; 432 case prefFrameTimeValue: return m_pShellData->nFrameTime; 433 case prefPriority: return m_pShellData->nPriority; 434 default: 435 { 436 int n; 437 438 if(m_pShellInit->ApiGet(prefName, &n)) 439 return n; 440 if(m_pShellInit->OsGet(prefName, &n)) 441 return n; 442 return -1; 443 } 444 } 445 } 446 447 /*!*********************************************************************** 448 @brief This function is used to pass preferences to the PVRShell. 449 If used, this function must be called from InitApplication(). 450 @param[in] prefName Name of preference to set to value 451 @param[in] value Value 452 @return true for success 453 *************************************************************************/ 454 bool PVRShell::PVRShellSet(const prefNamePtrEnum prefName, const void * const ptrValue) 455 { 456 PVRSHELL_UNREFERENCED_PARAMETER(prefName); 457 PVRSHELL_UNREFERENCED_PARAMETER(ptrValue); 458 return false; 459 } 460 461 /*!*********************************************************************** 462 @brief This function is used to get parameters from the PVRShell. 463 It can be called from anywhere in the program. 464 @param[in] prefName Name of preference to set to value 465 @return The requested value. 466 *************************************************************************/ 467 void *PVRShell::PVRShellGet(const prefNamePtrEnum prefName) const 468 { 469 switch(prefName) 470 { 471 case prefNativeWindowType: return m_pShellInit->OsGetNativeWindowType(); 472 case prefPointerLocation: 473 if (m_pShellInit->m_bTouching) 474 return m_pShellInit->m_vec2PointerLocation; 475 break; 476 default: 477 { 478 void *p; 479 480 if(m_pShellInit->ApiGet(prefName, &p)) 481 return p; 482 if(m_pShellInit->OsGet(prefName, &p)) 483 return p; 484 } 485 } 486 return NULL; 487 } 488 489 /*!*********************************************************************** 490 @brief This function is used to pass preferences to the PVRShell. 491 If used, this function must be called from InitApplication(). 492 @param[in] prefName Name of preference to set to value 493 @param[in] value Value 494 @return true for success 495 *************************************************************************/ 496 bool PVRShell::PVRShellSet(const prefNameConstPtrEnum prefName, const void * const ptrValue) 497 { 498 switch(prefName) 499 { 500 case prefAppName: 501 StringCopy(m_pShellData->pszAppName, (char*)ptrValue); 502 return true; 503 case prefExitMessage: 504 StringCopy(m_pShellData->pszExitMessage, (char*)ptrValue); 505 PVRShellOutputDebug("Exit message has been set to: \"%s\".\n", ptrValue); 506 return true; 507 default: 508 break; 509 } 510 return false; 511 } 512 513 /*!*********************************************************************** 514 @brief This function is used to get parameters from the PVRShell. 515 It can be called from anywhere in the program. 516 @param[in] prefName Name of preference to set to value 517 @return The requested value. 518 *************************************************************************/ 519 const void *PVRShell::PVRShellGet(const prefNameConstPtrEnum prefName) const 520 { 521 switch(prefName) 522 { 523 case prefAppName: 524 return m_pShellData->pszAppName; 525 case prefExitMessage: 526 return m_pShellData->pszExitMessage; 527 case prefReadPath: 528 return m_pShellInit->GetReadPath(); 529 case prefWritePath: 530 return m_pShellInit->GetWritePath(); 531 case prefCommandLine: 532 return m_pShellInit->m_CommandLine.m_psOrig; 533 case prefCommandLineOpts: 534 return m_pShellInit->m_CommandLine.m_pOpt; 535 case prefVersion: 536 return PVRSDK_VERSION; 537 default: 538 return 0; 539 } 540 } 541 542 /*!*********************************************************************** 543 @brief It will be stored as 24-bit per pixel, 8-bit per chanel RGB. 544 The memory should be freed with free() when no longer needed. 545 @param[in] Width size of image to capture (relative to 0,0) 546 @param[in] Height size of image to capture (relative to 0,0) 547 @param[out] pLines receives a pointer to an area of memory containing the screen buffer. 548 @return true for success 549 *************************************************************************/ 550 bool PVRShell::PVRShellScreenCaptureBuffer(const int Width, const int Height, unsigned char **pLines) 551 { 552 /* Allocate memory for line */ 553 *pLines=(unsigned char *)calloc(Width*Height*3, sizeof(unsigned char)); 554 if (!(*pLines)) return false; 555 556 return m_pShellInit->ApiScreenCaptureBuffer(Width, Height, *pLines); 557 } 558 559 /*!*********************************************************************** 560 @brief Writes out the image data to a BMP file with basename fname. 561 @details The file written will be fname suffixed with a number to make the file unique. 562 For example, if fname is "abc", this function will attempt 563 to save to "abc0000.bmp"; if that file already exists, it 564 will try "abc0001.bmp", repeating until a new filename is 565 found. The final filename used is returned in ofname. 566 @param[in] fname base of file to save screen to 567 @param[in] Width size of image to capture (relative to 0,0) 568 @param[in] Height size of image to capture (relative to 0,0) 569 @param[in] pLines image data to write out (24bpp, 8-bit per channel RGB) 570 @param[in] ui32PixelReplicate expand pixels through replication (1 = no scale) 571 @param[out] ofname If non-NULL, receives the filename actually used 572 @return true for success 573 *************************************************************************/ 574 int PVRShell::PVRShellScreenSave( 575 const char * const fname, 576 const int Width, 577 const int Height, 578 const unsigned char * const pLines, 579 const unsigned int ui32PixelReplicate, 580 char * const ofname) 581 { 582 char *pszFileName; 583 584 /* 585 Choose a filename 586 */ 587 { 588 FILE *file = 0; 589 const char *pszWritePath; 590 int nScreenshotCount; 591 592 pszWritePath = (const char*)PVRShellGet(prefWritePath); 593 594 size_t nFileNameSize = strlen(pszWritePath) + 200; 595 pszFileName = (char*)malloc(nFileNameSize); 596 597 /* Look for the first file name that doesn't already exist */ 598 for(nScreenshotCount = 0; nScreenshotCount < 10000; ++nScreenshotCount) 599 { 600 snprintf(pszFileName, nFileNameSize, "%s%s%04d.bmp", pszWritePath, fname, nScreenshotCount); 601 602 file = fopen(pszFileName,"r"); 603 if(!file) 604 break; 605 fclose(file); 606 } 607 608 /* If all files already exist, replace the first one */ 609 if (nScreenshotCount==10000) 610 { 611 snprintf(pszFileName, nFileNameSize, "%s%s0000.bmp", pszWritePath, fname); 612 PVRShellOutputDebug("PVRShell: *WARNING* : Overwriting %s\n", pszFileName); 613 } 614 615 if(ofname) // requested the output file name 616 { 617 strcpy(ofname, pszFileName); 618 } 619 } 620 621 const int err = PVRShellWriteBMPFile(pszFileName, Width, Height, pLines, ui32PixelReplicate); 622 FREE(pszFileName); 623 if (err) 624 { 625 return 10*err+1; 626 } 627 else 628 { 629 // No problem occurred 630 return 0; 631 } 632 } 633 634 /*!*********************************************************************** 635 @brief Swaps the bytes in pBytes from little to big endian (or vice versa) 636 @param[in] pBytes The bytes to swap 637 @param[in] i32ByteNo The number of bytes to swap 638 *************************************************************************/ 639 inline void PVRShellByteSwap(unsigned char* pBytes, int i32ByteNo) 640 { 641 int i = 0, j = i32ByteNo - 1; 642 643 while(i < j) 644 { 645 unsigned char cTmp = pBytes[i]; 646 pBytes[i] = pBytes[j]; 647 pBytes[j] = cTmp; 648 649 ++i; 650 --j; 651 } 652 } 653 654 /*!*********************************************************************** 655 @brief Writes out the image data to a BMP file with name fname. 656 @param[in] pszFilename file to save screen to 657 @param[in] ui32Width the width of the data 658 @param[in] ui32Height the height of the data 659 @param[in] pImageData image data to write out (24bpp, 8-bit per channel RGB) 660 @return 0 on success 661 *************************************************************************/ 662 int PVRShell::PVRShellWriteBMPFile( 663 const char * const pszFilename, 664 const unsigned int ui32Width, 665 const unsigned int ui32Height, 666 const void * const pImageData, 667 const unsigned int ui32PixelReplicate) 668 { 669 #define ByteSwap(x) PVRShellByteSwap((unsigned char*) &x, sizeof(x)) 670 671 const int i32BMPHeaderSize = 14; /* The size of a BMP header */ 672 const int i32BMPInfoSize = 40; /* The size of a BMP info header */ 673 int Result = 1; 674 FILE* fpDumpfile = 0; 675 676 fpDumpfile = fopen(pszFilename, "wb"); 677 678 if (fpDumpfile != 0) 679 { 680 const short int word = 0x0001; 681 const char * const byte = (char*) &word; 682 bool bLittleEndian = byte[0] ? true : false; 683 684 unsigned int i32OutBytesPerLine = ui32Width * 3 * ui32PixelReplicate; 685 unsigned int i32OutAlign = 0; 686 687 // round up to a dword boundary 688 if(i32OutBytesPerLine & 3) 689 { 690 i32OutBytesPerLine |= 3; 691 ++i32OutBytesPerLine; 692 i32OutAlign = i32OutBytesPerLine - ui32Width * 3 * ui32PixelReplicate; 693 } 694 695 unsigned char *pData = (unsigned char*) pImageData; 696 697 { 698 int ui32RealSize = i32OutBytesPerLine * ui32Height * ui32PixelReplicate; 699 700 // BMP Header 701 unsigned short bfType = 0x4D42; 702 unsigned int bfSize = i32BMPHeaderSize + i32BMPInfoSize + ui32RealSize; 703 unsigned short bfReserved1 = 0; 704 unsigned short bfReserved2 = 0; 705 unsigned int bfOffBits = i32BMPHeaderSize + i32BMPInfoSize; 706 707 // BMP Info Header 708 unsigned int biSize = i32BMPInfoSize; 709 unsigned int biWidth = ui32Width * ui32PixelReplicate; 710 unsigned int biHeight = ui32Height * ui32PixelReplicate; 711 unsigned short biPlanes = 1; 712 unsigned short biBitCount = 24; 713 unsigned int biCompression = 0L; 714 unsigned int biSizeImage = ui32RealSize; 715 unsigned int biXPelsPerMeter = 0; 716 unsigned int biYPelsPerMeter = 0; 717 unsigned int biClrUsed = 0; 718 unsigned int biClrImportant = 0; 719 720 if(!bLittleEndian) 721 { 722 for(unsigned int i = 0; i < ui32Width * ui32Height; ++i) 723 PVRShellByteSwap(pData + (3 * i), 3); 724 725 ByteSwap(bfType); 726 ByteSwap(bfSize); 727 ByteSwap(bfOffBits); 728 ByteSwap(biSize); 729 ByteSwap(biWidth); 730 ByteSwap(biHeight); 731 ByteSwap(biPlanes); 732 ByteSwap(biBitCount); 733 ByteSwap(biCompression); 734 ByteSwap(biSizeImage); 735 } 736 737 // Write Header. 738 fwrite(&bfType , 1, sizeof(bfType) , fpDumpfile); 739 fwrite(&bfSize , 1, sizeof(bfSize) , fpDumpfile); 740 fwrite(&bfReserved1 , 1, sizeof(bfReserved1), fpDumpfile); 741 fwrite(&bfReserved2 , 1, sizeof(bfReserved2), fpDumpfile); 742 fwrite(&bfOffBits , 1, sizeof(bfOffBits) , fpDumpfile); 743 744 // Write info header. 745 fwrite(&biSize , 1, sizeof(biSize) , fpDumpfile); 746 fwrite(&biWidth , 1, sizeof(biWidth) , fpDumpfile); 747 fwrite(&biHeight , 1, sizeof(biHeight) , fpDumpfile); 748 fwrite(&biPlanes , 1, sizeof(biPlanes) , fpDumpfile); 749 fwrite(&biBitCount , 1, sizeof(biBitCount) , fpDumpfile); 750 fwrite(&biCompression , 1, sizeof(biCompression) , fpDumpfile); 751 fwrite(&biSizeImage , 1, sizeof(biSizeImage) , fpDumpfile); 752 fwrite(&biXPelsPerMeter , 1, sizeof(biXPelsPerMeter), fpDumpfile); 753 fwrite(&biYPelsPerMeter , 1, sizeof(biYPelsPerMeter), fpDumpfile); 754 fwrite(&biClrUsed , 1, sizeof(biClrUsed) , fpDumpfile); 755 fwrite(&biClrImportant , 1, sizeof(biClrImportant) , fpDumpfile); 756 } 757 758 // Write image. 759 for(unsigned int nY = 0; nY < ui32Height; ++nY) 760 { 761 const unsigned char * pRow = &pData[3 * ui32Width * nY]; 762 for(unsigned int nRepY = 0; nRepY < ui32PixelReplicate; ++nRepY) 763 { 764 for(unsigned int nX = 0; nX < ui32Width; ++nX) 765 { 766 const unsigned char * pPixel = &pRow[3 * nX]; 767 for(unsigned int nRepX = 0; nRepX < ui32PixelReplicate; ++nRepX) 768 { 769 fwrite(pPixel, 1, 3, fpDumpfile); 770 } 771 } 772 773 fwrite("\0\0\0\0", i32OutAlign, 1, fpDumpfile); 774 } 775 } 776 777 // Last but not least close the file. 778 fclose(fpDumpfile); 779 780 Result = 0; 781 } 782 else 783 { 784 PVRShellOutputDebug("PVRShell: Failed to open \"%s\" for writing screen dump.\n", pszFilename); 785 } 786 787 return Result; 788 } 789 790 /*!*********************************************************************** 791 @brief The number itself should be considered meaningless; an 792 application should use this function to determine how much 793 time has passed between two points (e.g. between each 794 frame). 795 @return A value which increments once per millisecond. 796 *************************************************************************/ 797 unsigned long PVRShell::PVRShellGetTime() 798 { 799 if(m_pShellData->bForceFrameTime) 800 { 801 // Return a "time" value based on the current frame number 802 return (unsigned long) m_pShellData->nShellCurFrameNum * m_pShellData->nFrameTime; 803 } 804 else 805 { 806 // Read timer from a platform dependant function 807 return m_pShellInit->OsGetTime(); 808 } 809 } 810 811 /*!*********************************************************************** 812 @brief Check if a key was pressed. The keys on various devices 813 are mapped to the PVRShell-supported keys (listed in @a PVRShellKeyName) in 814 a platform-dependent manner, since most platforms have different input 815 devices. Check the <a href="modules.html">Modules page</a> for your OS 816 for details on how the enum values map to your device's key code input. 817 @param[in] key Code of the key to test 818 @return true if key was pressed 819 *************************************************************************/ 820 bool PVRShell::PVRShellIsKeyPressed(const PVRShellKeyName key) 821 { 822 if(!m_pShellInit) 823 return false; 824 825 return m_pShellInit->DoIsKeyPressed(key); 826 } 827 828 // class PVRShellCommandLine 829 830 /*!*********************************************************************** 831 @brief Constructor 832 *************************************************************************/ 833 PVRShellCommandLine::PVRShellCommandLine() 834 { 835 memset(this, 0, sizeof(*this)); 836 } 837 838 /*!*********************************************************************** 839 @brief Destructor 840 *************************************************************************/ 841 PVRShellCommandLine::~PVRShellCommandLine() 842 { 843 delete [] m_psOrig; 844 delete [] m_psSplit; 845 FREE(m_pOpt); 846 } 847 848 /*!*********************************************************************** 849 @brief Set command-line options to pStr 850 @param[in] pStr Input string 851 *************************************************************************/ 852 void PVRShellCommandLine::Set(const char *pStr) 853 { 854 delete [] m_psOrig; 855 m_psOrig = 0; 856 857 if(pStr) 858 { 859 size_t len = strlen(pStr)+1; 860 m_psOrig = new char[len]; 861 strcpy(m_psOrig, pStr); 862 } 863 } 864 865 /*!*********************************************************************** 866 @brief Prepend command-line options to m_psOrig 867 @param[in] pStr Input string 868 *************************************************************************/ 869 void PVRShellCommandLine::Prefix(const char *pStr) 870 { 871 if(!m_psOrig) 872 Set(pStr); 873 else if(!pStr) 874 return; 875 else 876 { 877 char *pstmp = m_psOrig; 878 size_t lenA = strlen(pStr); 879 size_t TotalLen = lenA + 1 + strlen(m_psOrig); 880 881 m_psOrig = new char[TotalLen + 1]; 882 883 strcpy(m_psOrig, pStr); 884 m_psOrig[lenA] = ' '; 885 strcpy(m_psOrig + lenA + 1, pstmp); 886 m_psOrig[TotalLen] = '\0'; 887 888 delete[] pstmp; 889 } 890 } 891 892 /*!*********************************************************************** 893 @brief Prepend command-line options to m_psOrig from a file 894 @param[in] pFileName Input string 895 *************************************************************************/ 896 bool PVRShellCommandLine::PrefixFromFile(const char *pFileName) 897 { 898 char* nl; 899 FILE *pFile = fopen(pFileName, "rb"); 900 901 if(pFile) 902 { 903 // Get the file size 904 fseek(pFile, 0, SEEK_END); 905 long m_Size = ftell(pFile) + 2; 906 fseek(pFile, 0, SEEK_SET); 907 908 char *pFullFile = new char[m_Size]; 909 910 if(pFullFile) 911 { 912 size_t offset = 0; 913 while(fgets(pFullFile + offset, (int) (m_Size - offset), pFile)) 914 { 915 offset = strlen(pFullFile); 916 917 // Replace new lines with spaces 918 nl = strrchr(pFullFile, '\r'); 919 if(nl) *nl = ' '; 920 921 nl = strrchr(pFullFile, '\n'); 922 if(nl) *nl = ' '; 923 } 924 925 pFullFile[offset] = '\0'; 926 Prefix(pFullFile); 927 928 delete[] pFullFile; 929 fclose(pFile); 930 return true; 931 } 932 933 fclose(pFile); 934 } 935 936 return false; 937 } 938 939 /*!*********************************************************************** 940 @brief Parse m_psOrig for command-line options and store them in m_pOpt 941 *************************************************************************/ 942 void PVRShellCommandLine::Parse() 943 { 944 size_t len; 945 int nIn, nOut; 946 bool bInQuotes; 947 SCmdLineOpt opt; 948 949 if(!m_psOrig) 950 return; 951 952 // Delete/free up any options we may have parsed recently 953 delete [] m_psSplit; 954 FREE(m_pOpt); 955 956 // Take a copy to be edited 957 len = strlen(m_psOrig) + 1; 958 m_psSplit = new char[len]; 959 960 // Break the command line into options 961 bInQuotes = false; 962 opt.pArg = NULL; 963 opt.pVal = NULL; 964 nIn = -1; 965 nOut = 0; 966 967 do 968 { 969 ++nIn; 970 if(m_psOrig[nIn] == '"') 971 { 972 bInQuotes = !bInQuotes; 973 } 974 else 975 { 976 if(bInQuotes && m_psOrig[nIn] != 0) 977 { 978 if(!opt.pArg) 979 opt.pArg = &m_psSplit[nOut]; 980 981 m_psSplit[nOut++] = m_psOrig[nIn]; 982 } 983 else 984 { 985 switch(m_psOrig[nIn]) 986 { 987 case '=': 988 m_psSplit[nOut++] = 0; 989 opt.pVal = &m_psSplit[nOut]; 990 break; 991 992 case ' ': 993 case '\t': 994 case '\0': 995 m_psSplit[nOut++] = 0; 996 if(opt.pArg || opt.pVal) 997 { 998 // Increase list length if necessary 999 if(m_nOptLen == m_nOptMax) 1000 m_nOptMax = m_nOptMax * 2 + 1; 1001 SCmdLineOpt* pTmp = (SCmdLineOpt*)realloc(m_pOpt, m_nOptMax * sizeof(*m_pOpt)); 1002 if(!pTmp) 1003 { 1004 FREE(m_pOpt); 1005 return; 1006 } 1007 1008 m_pOpt = pTmp; 1009 1010 // Add option to list 1011 m_pOpt[m_nOptLen++] = opt; 1012 opt.pArg = NULL; 1013 opt.pVal = NULL; 1014 } 1015 break; 1016 1017 default: 1018 if(!opt.pArg) 1019 opt.pArg = &m_psSplit[nOut]; 1020 1021 m_psSplit[nOut++] = m_psOrig[nIn]; 1022 break; 1023 } 1024 } 1025 } 1026 } while(m_psOrig[nIn]); 1027 } 1028 1029 /*!*********************************************************************** 1030 @brief Apply the command-line options to shell 1031 @param[in] shell 1032 *************************************************************************/ 1033 void PVRShellCommandLine::Apply(PVRShell &shell) 1034 { 1035 int i; 1036 const char *arg, *val; 1037 1038 for(i = 0; i < m_nOptLen; ++i) 1039 { 1040 arg = m_pOpt[i].pArg; 1041 val = m_pOpt[i].pVal; 1042 1043 if(!arg) 1044 continue; 1045 1046 if(val) 1047 { 1048 if(_stricmp(arg, "-width") == 0) 1049 { 1050 shell.PVRShellSet(prefWidth, atoi(val)); 1051 } 1052 else if(_stricmp(arg, "-height") == 0) 1053 { 1054 shell.PVRShellSet(prefHeight, atoi(val)); 1055 } 1056 else if(_stricmp(arg, "-aasamples") == 0) 1057 { 1058 shell.PVRShellSet(prefAASamples, atoi(val)); 1059 } 1060 else if(_stricmp(arg, "-fullscreen") == 0) 1061 { 1062 shell.PVRShellSet(prefFullScreen, (atoi(val) != 0)); 1063 } 1064 else if(_stricmp(arg, "-sw") == 0) 1065 { 1066 shell.PVRShellSet(prefSoftwareRendering, (atoi(val) != 0)); 1067 } 1068 else if(_stricmp(arg, "-quitafterframe") == 0 || _stricmp(arg, "-qaf") == 0) 1069 { 1070 shell.PVRShellSet(prefQuitAfterFrame, atoi(val)); 1071 } 1072 else if(_stricmp(arg, "-quitaftertime") == 0 || _stricmp(arg, "-qat") == 0) 1073 { 1074 shell.PVRShellSet(prefQuitAfterTime, (float)atof(val)); 1075 } 1076 else if(_stricmp(arg, "-posx") == 0) 1077 { 1078 shell.PVRShellSet(prefPositionX, atoi(val)); 1079 } 1080 else if(_stricmp(arg, "-posy") == 0) 1081 { 1082 shell.PVRShellSet(prefPositionY, atoi(val)); 1083 } 1084 else if(_stricmp(arg, "-vsync") == 0) 1085 { 1086 shell.PVRShellSet(prefSwapInterval, atoi(val)); 1087 } 1088 else if(_stricmp(arg, "-powersaving") == 0 || _stricmp(arg, "-ps") == 0) 1089 { 1090 shell.PVRShellSet(prefPowerSaving, (atoi(val) != 0)); 1091 } 1092 else if(_stricmp(arg, "-colourbpp") == 0 || _stricmp(arg, "-colorbpp") == 0 ||_stricmp(arg, "-cbpp") == 0) 1093 { 1094 shell.PVRShellSet(prefColorBPP, atoi(val)); 1095 } 1096 else if(_stricmp(arg, "-depthbpp") == 0 || _stricmp(arg, "-dbpp") == 0) 1097 { 1098 shell.PVRShellSet(prefDepthBPP, atoi(val)); 1099 } 1100 else if(_stricmp(arg, "-rotatekeys") == 0) 1101 { 1102 shell.PVRShellSet(prefRotateKeys, atoi(val)); 1103 } 1104 else if(_stricmp(arg, "-c") == 0) 1105 { 1106 const char* pDash = strchr(val, '-'); 1107 1108 shell.PVRShellSet(prefCaptureFrameStart, atoi(val)); 1109 1110 if(!pDash) 1111 shell.PVRShellSet(prefCaptureFrameStop, atoi(val)); 1112 else 1113 shell.PVRShellSet(prefCaptureFrameStop, atoi(pDash + 1)); 1114 } 1115 else if(_stricmp(arg, "-screenshotscale") == 0) 1116 { 1117 shell.PVRShellSet(prefCaptureFrameScale, atoi(val)); 1118 } 1119 else if(_stricmp(arg, "-priority") == 0) 1120 { 1121 shell.PVRShellSet(prefPriority, atoi(val)); 1122 } 1123 else if(_stricmp(arg, "-config") == 0) 1124 { 1125 shell.PVRShellSet(prefRequestedConfig, atoi(val)); 1126 } 1127 else if(_stricmp(arg, "-display") == 0) 1128 { 1129 shell.PVRShellSet(prefNativeDisplay, atoi(val)); 1130 } 1131 else if(_stricmp(arg, "-forceframetime") == 0 || _stricmp(arg, "-fft") == 0) 1132 { 1133 shell.PVRShellSet(prefForceFrameTime, true); 1134 shell.PVRShellSet(prefFrameTimeValue, atoi(val)); 1135 } 1136 else if(_stricmp(arg, "-discardframeall") == 0) 1137 { 1138 shell.PVRShellSet(prefDiscardColor, (atoi(val) != 0)); 1139 shell.PVRShellSet(prefDiscardDepth, (atoi(val) != 0)); 1140 shell.PVRShellSet(prefDiscardStencil, (atoi(val) != 0)); 1141 } 1142 else if(_stricmp(arg, "-discardframecolor") == 0 || _stricmp(arg, "-discardframecolour") == 0) 1143 { 1144 shell.PVRShellSet(prefDiscardColor, (atoi(val) != 0)); 1145 } 1146 else if(_stricmp(arg, "-discardframedepth") == 0) 1147 { 1148 shell.PVRShellSet(prefDiscardDepth, (atoi(val) != 0)); 1149 } 1150 else if(_stricmp(arg, "-discardframestencil") == 0) 1151 { 1152 shell.PVRShellSet(prefDiscardStencil, (atoi(val) != 0)); 1153 } 1154 } 1155 else 1156 { 1157 if(_stricmp(arg, "-version") == 0) 1158 { 1159 shell.PVRShellOutputDebug("Version: \"%s\"\n", shell.PVRShellGet(prefVersion)); 1160 } 1161 #ifdef PVRSHELL_FPS_OUTPUT 1162 else if(_stricmp(arg, "-fps") == 0) 1163 { 1164 shell.PVRShellSet(prefOutputFPS, true); 1165 } 1166 #endif 1167 else if(_stricmp(arg, "-info") == 0) 1168 { 1169 shell.PVRShellSet(prefOutputInfo, true); 1170 } 1171 else if(_stricmp(arg, "-forceframetime") == 0 || _stricmp(arg, "-fft") == 0) 1172 { 1173 shell.PVRShellSet(prefForceFrameTime, true); 1174 } 1175 } 1176 } 1177 } 1178 1179 // @Class PVRShellInit 1180 1181 /*!*********************************************************************** 1182 @brief Constructor 1183 *************************************************************************/ 1184 PVRShellInit::PVRShellInit() 1185 { 1186 memset(this, 0, sizeof(*this)); 1187 } 1188 1189 /*!*********************************************************************** 1190 @brief Destructor 1191 *************************************************************************/ 1192 PVRShellInit::~PVRShellInit() 1193 { 1194 Deinit(); 1195 1196 delete [] m_pReadPath; 1197 m_pReadPath = NULL; 1198 1199 delete [] m_pWritePath; 1200 m_pWritePath = NULL; 1201 } 1202 1203 /*!*********************************************************************** 1204 @brief PVRShell deinitialisation. 1205 @param[in] Shell 1206 *************************************************************************/ 1207 void PVRShellInit::Deinit() 1208 { 1209 if(m_pShell) 1210 { 1211 // Is the App currently running? 1212 if(m_eState > ePVRShellInitApp && m_eState < ePVRShellExit) 1213 { 1214 // If so force it to go through the exit procedure 1215 if(m_eState < ePVRShellReleaseView) 1216 m_eState = ePVRShellReleaseView; 1217 1218 // Class the App as done 1219 gShellDone = true; 1220 1221 // Run through the exiting states 1222 while(Run()){}; 1223 } 1224 1225 delete m_pShell; 1226 m_pShell = 0; 1227 } 1228 } 1229 1230 /*!*********************************************************************** 1231 @brief PVRShell Initialisation. 1232 @Function Init 1233 @param[in] Shell 1234 @return True on success and false on failure 1235 *************************************************************************/ 1236 bool PVRShellInit::Init() 1237 { 1238 Deinit(); 1239 1240 m_pShell = NewDemo(); 1241 1242 if(!m_pShell) 1243 return false; 1244 1245 m_pShell->m_pShellInit = this; 1246 1247 // set default direction key mappings 1248 m_eKeyMapDOWN = PVRShellKeyNameDOWN; 1249 m_eKeyMapLEFT = PVRShellKeyNameLEFT; 1250 m_eKeyMapUP = PVRShellKeyNameUP; 1251 m_eKeyMapRIGHT = PVRShellKeyNameRIGHT; 1252 nLastKeyPressed = PVRShellKeyNameNull; 1253 1254 OsInit(); 1255 1256 gShellDone = false; 1257 m_eState = ePVRShellInitApp; 1258 return true; 1259 } 1260 1261 /*!*********************************************************************** 1262 @brief Receives the command-line from the application. 1263 @param[in] str A string containing the command-line 1264 *************************************************************************/ 1265 void PVRShellInit::CommandLine(const char *str) 1266 { 1267 m_CommandLine.Set(str); 1268 } 1269 1270 /*!*********************************************************************** 1271 @brief Receives the command-line from the application. 1272 @param[in] argc Number of strings in argv 1273 @param[in] argv An array of strings 1274 *************************************************************************/ 1275 void PVRShellInit::CommandLine(int argc, char **argv) 1276 { 1277 size_t tot, len; 1278 char *buf; 1279 int i; 1280 1281 tot = 0; 1282 for(i = 0; i < argc; ++i) 1283 tot += strlen(argv[i]); 1284 1285 if(!tot) 1286 { 1287 CommandLine((char*) ""); 1288 return; 1289 } 1290 1291 // Add room for spaces and the \0 1292 tot += argc; 1293 1294 buf = new char[tot]; 1295 tot = 0; 1296 for(i = 0; i < argc; ++i) 1297 { 1298 len = strlen(argv[i]); 1299 strncpy(&buf[tot], argv[i], len); 1300 tot += len; 1301 buf[tot++] = ' '; 1302 } 1303 buf[tot-1] = 0; 1304 1305 CommandLine(buf); 1306 1307 delete [] buf; 1308 } 1309 1310 /*!*********************************************************************** 1311 @brief Return 'true' if the specific key has been pressed. 1312 @param[in] key The key we're querying for 1313 *************************************************************************/ 1314 bool PVRShellInit::DoIsKeyPressed(const PVRShellKeyName key) 1315 { 1316 if(key == nLastKeyPressed) 1317 { 1318 nLastKeyPressed = PVRShellKeyNameNull; 1319 return true; 1320 } 1321 else 1322 { 1323 return false; 1324 } 1325 } 1326 1327 /*!*********************************************************************** 1328 @brief Used by the OS-specific code to tell the Shell that a key has been pressed. 1329 @param[in] nKey The key that has been pressed 1330 *************************************************************************/ 1331 void PVRShellInit::KeyPressed(PVRShellKeyName nKey) 1332 { 1333 nLastKeyPressed = nKey; 1334 } 1335 1336 /*!*********************************************************************** 1337 @brief Used by the OS-specific code to tell the Shell that a touch has began at a location. 1338 @param[in] vec2Location The position of a click/touch on the screen when it first touches 1339 *************************************************************************/ 1340 void PVRShellInit::TouchBegan(const float vec2Location[2]) 1341 { 1342 m_bTouching = true; 1343 m_vec2PointerLocationStart[0] = m_vec2PointerLocation[0] = vec2Location[0]; 1344 m_vec2PointerLocationStart[1] = m_vec2PointerLocation[1] = vec2Location[1]; 1345 } 1346 1347 /*!*********************************************************************** 1348 @brief Used by the OS-specific code to tell the Shell that a touch has began at a location. 1349 @param[in] vec2Location The position of the pointer/touch pressed on the screen 1350 *************************************************************************/ 1351 void PVRShellInit::TouchMoved(const float vec2Location[2]) 1352 { 1353 if(m_bTouching) 1354 { 1355 m_vec2PointerLocation[0] = vec2Location[0]; 1356 m_vec2PointerLocation[1] = vec2Location[1]; 1357 } 1358 } 1359 1360 /*!*********************************************************************** 1361 @brief Used by the OS-specific code to tell the Shell that the current touch has ended at a location. 1362 @param[in] vec2Location The position of the pointer/touch on the screen when it is released 1363 *************************************************************************/ 1364 void PVRShellInit::TouchEnded(const float vec2Location[2]) 1365 { 1366 if(m_bTouching) 1367 { 1368 m_bTouching = false; 1369 m_vec2PointerLocationEnd[0] = m_vec2PointerLocation[0] = vec2Location[0]; 1370 m_vec2PointerLocationEnd[1] = m_vec2PointerLocation[1] = vec2Location[1]; 1371 1372 #if !defined(DISABLE_SWIPE_MAPPING) 1373 float fX = m_vec2PointerLocationEnd[0] - m_vec2PointerLocationStart[0]; 1374 float fY = m_vec2PointerLocationEnd[1] - m_vec2PointerLocationStart[1]; 1375 float fTmp = fX * fX + fY * fY; 1376 1377 if(fTmp > 0.005f) 1378 { 1379 fTmp = 1.0f / sqrt(fTmp); 1380 fY *= fTmp; 1381 float fAngle = acos(fY); 1382 1383 const float pi = 3.1415f; 1384 const float pi_half = pi * 0.5f; 1385 const float error = 0.25f; 1386 1387 if(fAngle < error) 1388 KeyPressed(m_eKeyMapDOWN); 1389 else if(fAngle > (pi - error)) 1390 KeyPressed(m_eKeyMapUP); 1391 else if(fAngle > (pi_half - error) && fAngle < (pi_half + error)) 1392 KeyPressed((fX < 0) ? m_eKeyMapLEFT : m_eKeyMapRIGHT); 1393 } 1394 else if(fTmp < 0.09f) 1395 { 1396 if (m_vec2PointerLocationEnd[0] <= 0.3f) // Left half of the screen 1397 KeyPressed(PVRShellKeyNameACTION1); 1398 else if (m_vec2PointerLocationEnd[0] >= 0.7f) // Right half of the screen 1399 KeyPressed(PVRShellKeyNameACTION2); 1400 } 1401 #endif 1402 } 1403 } 1404 1405 /*!*********************************************************************** 1406 @brief Used by the OS-specific code to tell the Shell where to read external files from 1407 @return A path the application is capable of reading from 1408 *************************************************************************/ 1409 const char* PVRShellInit::GetReadPath() const 1410 { 1411 return m_pReadPath; 1412 } 1413 1414 /*!*********************************************************************** 1415 @brief Used by the OS-specific code to tell the Shell where to write to 1416 @return A path the applications is capable of writing to 1417 *************************************************************************/ 1418 const char* PVRShellInit::GetWritePath() const 1419 { 1420 return m_pWritePath; 1421 } 1422 1423 /*!**************************************************************************** 1424 @brief Sets the default app name (to be displayed by the OS) 1425 @param[in] str The application name 1426 *******************************************************************************/ 1427 void PVRShellInit::SetAppName(const char * const str) 1428 { 1429 const char *pName = strrchr(str, PVRSHELL_DIR_SYM); 1430 1431 if(pName) 1432 { 1433 ++pName; 1434 } 1435 else 1436 { 1437 pName = str; 1438 } 1439 m_pShell->PVRShellSet(prefAppName, pName); 1440 } 1441 1442 /*!*********************************************************************** 1443 @brief Set the path to where the application expects to read from. 1444 @param[in] str The read path 1445 *************************************************************************/ 1446 void PVRShellInit::SetReadPath(const char * const str) 1447 { 1448 m_pReadPath = new char[strlen(str)+1]; 1449 1450 if(m_pReadPath) 1451 { 1452 strcpy(m_pReadPath, str); 1453 char* lastSlash = strrchr(m_pReadPath, PVRSHELL_DIR_SYM); 1454 1455 if(lastSlash) 1456 lastSlash[1] = 0; 1457 } 1458 } 1459 1460 /*!*********************************************************************** 1461 @brief Set the path to where the application expects to write to. 1462 @param[in] str The write path 1463 *************************************************************************/ 1464 void PVRShellInit::SetWritePath(const char * const str) 1465 { 1466 m_pWritePath = new char[strlen(str)+1]; 1467 1468 if(m_pWritePath) 1469 { 1470 strcpy(m_pWritePath, str); 1471 char* lastSlash = strrchr(m_pWritePath, PVRSHELL_DIR_SYM); 1472 1473 if(lastSlash) 1474 lastSlash[1] = 0; 1475 } 1476 } 1477 1478 #ifdef PVRSHELL_FPS_OUTPUT 1479 /***************************************************************************** 1480 @fn FpsUpdate 1481 @brief Calculates a value for frames-per-second (FPS). 1482 @details This is only compiled in to the application if PVRSHELL_FPS_OUTPUT is defined. 1483 *****************************************************************************/ 1484 void PVRShellInit::FpsUpdate() 1485 { 1486 unsigned int ui32TimeDelta, ui32Time; 1487 1488 ui32Time = m_pShell->PVRShellGetTime(); 1489 ++m_i32FpsFrameCnt; 1490 ui32TimeDelta = ui32Time - m_i32FpsTimePrev; 1491 1492 if(ui32TimeDelta >= 1000) 1493 { 1494 float fFPS = 1000.0f * (float) m_i32FpsFrameCnt / (float) ui32TimeDelta; 1495 1496 m_pShell->PVRShellOutputDebug("PVRShell: frame %d, FPS %.1f.\n", 1497 m_pShell->m_pShellData->nShellCurFrameNum, fFPS); 1498 1499 m_i32FpsFrameCnt = 0; 1500 m_i32FpsTimePrev = ui32Time; 1501 } 1502 } 1503 #endif 1504 1505 /***************************************************************************** 1506 @brief Main message loop / render loop 1507 @return false when the app should quit 1508 *****************************************************************************/ 1509 bool PVRShellInit::Run() 1510 { 1511 static unsigned long StartTime = 0; 1512 1513 switch(m_eState) 1514 { 1515 case ePVRShellInitApp: 1516 { 1517 // Make sure the shell isn't done 1518 gShellDone = false; 1519 1520 // Prepend command-line options from PVRShellCL.txt 1521 const char * const pCL = "PVRShellCL.txt"; 1522 const char *pPath = (const char*) m_pShell->PVRShellGet(prefReadPath); 1523 size_t nSize = strlen(pPath) + strlen(pCL) + 1; 1524 char *pString = new char[nSize]; 1525 1526 if(pString) 1527 { 1528 snprintf(pString, nSize, "%s%s", pPath, pCL); 1529 1530 if(!m_CommandLine.PrefixFromFile(pString)) 1531 { 1532 delete[] pString; 1533 pPath = (const char*) m_pShell->PVRShellGet(prefWritePath); 1534 nSize = strlen(pPath) + strlen(pCL) + 1; 1535 pString = new char[nSize]; 1536 1537 snprintf(pString, nSize, "%s%s", pPath, pCL); 1538 1539 if(m_CommandLine.PrefixFromFile(pString)) 1540 m_pShell->PVRShellOutputDebug("Loaded command-line options from %s.\n", pString); 1541 } 1542 else 1543 m_pShell->PVRShellOutputDebug("Loaded command-line options from %s.\n", pString); 1544 1545 delete[] pString; 1546 } 1547 1548 // Parse the command-line 1549 m_CommandLine.Parse(); 1550 1551 #if defined(_DEBUG) 1552 m_pShell->PVRShellOutputDebug("PVRShell command line: %d/%d\n", m_CommandLine.m_nOptLen, m_CommandLine.m_nOptMax); 1553 for(int i = 0; i < m_CommandLine.m_nOptLen; ++i) 1554 { 1555 m_pShell->PVRShellOutputDebug("CL %d: \"%s\"\t= \"%s\".\n", i, 1556 m_CommandLine.m_pOpt[i].pArg ? m_CommandLine.m_pOpt[i].pArg : "", 1557 m_CommandLine.m_pOpt[i].pVal ? m_CommandLine.m_pOpt[i].pVal : ""); 1558 } 1559 #endif 1560 // Call InitApplication 1561 if(!m_pShell->InitApplication()) 1562 { 1563 m_eState = ePVRShellExit; 1564 return true; 1565 } 1566 1567 m_eState = ePVRShellInitInstance; 1568 return true; 1569 } 1570 case ePVRShellInitInstance: 1571 { 1572 m_CommandLine.Apply(*m_pShell); 1573 1574 // Output non-api specific data if required 1575 OutputInfo(); 1576 1577 // Perform OS initialisation 1578 if(!OsInitOS()) 1579 { 1580 m_pShell->PVRShellOutputDebug("InitOS failed!\n"); 1581 m_eState = ePVRShellQuitApp; 1582 return true; 1583 } 1584 1585 // Initialize the 3D API 1586 if(!OsDoInitAPI()) 1587 { 1588 m_pShell->PVRShellOutputDebug("InitAPI failed!\n"); 1589 m_eState = ePVRShellReleaseOS; 1590 gShellDone = true; 1591 return true; 1592 } 1593 1594 // Output api specific data if required 1595 OutputAPIInfo(); 1596 1597 // Initialise the app 1598 if(!m_pShell->InitView()) 1599 { 1600 m_pShell->PVRShellOutputDebug("InitView failed!\n"); 1601 m_eState = ePVRShellReleaseAPI; 1602 gShellDone = true; 1603 return true; 1604 } 1605 1606 if(StartTime==0) 1607 { 1608 StartTime = OsGetTime(); 1609 } 1610 1611 m_eState = ePVRShellRender; 1612 return true; 1613 } 1614 case ePVRShellRender: 1615 { 1616 // Main message loop: 1617 if(!m_pShell->RenderScene()) 1618 break; 1619 1620 ApiRenderComplete(); 1621 OsRenderComplete(); 1622 1623 #ifdef PVRSHELL_FPS_OUTPUT 1624 if(m_pShell->m_pShellData->bOutputFPS) 1625 FpsUpdate(); 1626 #endif 1627 int nCurrentFrame = m_pShell->m_pShellData->nShellCurFrameNum; 1628 1629 if(DoIsKeyPressed(PVRShellKeyNameScreenshot) || (nCurrentFrame >= m_pShell->m_pShellData->nCaptureFrameStart && nCurrentFrame <= m_pShell->m_pShellData->nCaptureFrameStop)) 1630 { 1631 unsigned char *pBuf; 1632 const int nWidth = m_pShell->PVRShellGet(prefWidth); 1633 const int nHeight = m_pShell->PVRShellGet(prefHeight); 1634 if(m_pShell->PVRShellScreenCaptureBuffer(nWidth, nHeight, &pBuf)) 1635 { 1636 if(m_pShell->PVRShellScreenSave(PVRSHELL_SCREENSHOT_NAME, nWidth, nHeight, pBuf, m_pShell->m_pShellData->nCaptureFrameScale) != 0) 1637 { 1638 m_pShell->PVRShellSet(prefExitMessage, "Screen-shot save failed.\n"); 1639 } 1640 } 1641 else 1642 { 1643 m_pShell->PVRShellSet(prefExitMessage, "Screen capture failed.\n"); 1644 } 1645 FREE(pBuf); 1646 } 1647 1648 if(DoIsKeyPressed(PVRShellKeyNameQUIT)) 1649 gShellDone = true; 1650 1651 if(gShellDone) 1652 break; 1653 1654 /* Quit if maximum number of allowed frames is reached */ 1655 if((m_pShell->m_pShellData->nDieAfterFrames>=0) && (nCurrentFrame >= m_pShell->m_pShellData->nDieAfterFrames)) 1656 break; 1657 1658 /* Quit if maximum time is reached */ 1659 if((m_pShell->m_pShellData->fDieAfterTime>=0.0f) && (((OsGetTime()-StartTime)*0.001f) >= m_pShell->m_pShellData->fDieAfterTime)) 1660 break; 1661 1662 m_pShell->m_pShellData->nShellCurFrameNum++; 1663 return true; 1664 } 1665 1666 case ePVRShellReleaseView: 1667 m_pShell->ReleaseView(); 1668 1669 case ePVRShellReleaseAPI: 1670 OsDoReleaseAPI(); 1671 1672 case ePVRShellReleaseOS: 1673 OsReleaseOS(); 1674 1675 if(!gShellDone && m_pShell->m_pShellData->nInitRepeats) 1676 { 1677 --m_pShell->m_pShellData->nInitRepeats; 1678 m_eState = ePVRShellInitInstance; 1679 return true; 1680 } 1681 1682 m_eState = ePVRShellQuitApp; 1683 return true; 1684 1685 case ePVRShellQuitApp: 1686 // Final app tidy-up 1687 m_pShell->QuitApplication(); 1688 m_eState = ePVRShellExit; 1689 1690 case ePVRShellExit: 1691 OsExit(); 1692 StringCopy(m_pShell->m_pShellData->pszAppName, 0); 1693 StringCopy(m_pShell->m_pShellData->pszExitMessage, 0); 1694 return false; 1695 } 1696 1697 m_eState = (EPVRShellState)(m_eState + 1); 1698 return true; 1699 } 1700 1701 /*!*********************************************************************** 1702 @brief When prefOutputInfo is set to true this function outputs 1703 various pieces of non-API dependent information via 1704 PVRShellOutputDebug. 1705 *************************************************************************/ 1706 void PVRShellInit::OutputInfo() 1707 { 1708 if(m_pShell->PVRShellGet(prefOutputInfo)) 1709 { 1710 m_pShell->PVRShellOutputDebug("\n"); 1711 m_pShell->PVRShellOutputDebug("App name: %s\n" , m_pShell->PVRShellGet(prefAppName)); 1712 m_pShell->PVRShellOutputDebug("SDK version: %s\n" , m_pShell->PVRShellGet(prefVersion)); 1713 m_pShell->PVRShellOutputDebug("\n"); 1714 m_pShell->PVRShellOutputDebug("Read path: %s\n" , m_pShell->PVRShellGet(prefReadPath)); 1715 m_pShell->PVRShellOutputDebug("Write path: %s\n" , m_pShell->PVRShellGet(prefWritePath)); 1716 m_pShell->PVRShellOutputDebug("\n"); 1717 m_pShell->PVRShellOutputDebug("Command-line: %s\n" , m_pShell->PVRShellGet(prefCommandLine)); 1718 m_pShell->PVRShellOutputDebug("\n"); 1719 m_pShell->PVRShellOutputDebug("Power saving: %s\n" , m_pShell->PVRShellGet(prefPowerSaving) ? "On" : "Off"); 1720 m_pShell->PVRShellOutputDebug("AA Samples requested: %i\n", m_pShell->PVRShellGet(prefAASamples)); 1721 m_pShell->PVRShellOutputDebug("Fullscreen: %s\n", m_pShell->PVRShellGet(prefFullScreen) ? "Yes" : "No"); 1722 m_pShell->PVRShellOutputDebug("PBuffer requested: %s\n", m_pShell->PVRShellGet(prefPBufferContext) ? "Yes" : "No"); 1723 m_pShell->PVRShellOutputDebug("ZBuffer requested: %s\n", m_pShell->PVRShellGet(prefZbufferContext) ? "Yes" : "No"); 1724 m_pShell->PVRShellOutputDebug("Stencil buffer requested: %s\n", m_pShell->PVRShellGet(prefStencilBufferContext) ? "Yes" : "No"); 1725 1726 if(m_pShell->PVRShellGet(prefColorBPP) > 0) 1727 m_pShell->PVRShellOutputDebug("Colour buffer size requested: %i\n", m_pShell->PVRShellGet(prefColorBPP)); 1728 if(m_pShell->PVRShellGet(prefDepthBPP) > 0) 1729 m_pShell->PVRShellOutputDebug("Depth buffer size requested: %i\n", m_pShell->PVRShellGet(prefDepthBPP)); 1730 1731 m_pShell->PVRShellOutputDebug("Software rendering requested: %s\n", m_pShell->PVRShellGet(prefSoftwareRendering) ? "Yes" : "No"); 1732 m_pShell->PVRShellOutputDebug("Swap Interval requested: %i\n", m_pShell->PVRShellGet(prefSwapInterval)); 1733 1734 if(m_pShell->PVRShellGet(prefInitRepeats) > 0) 1735 m_pShell->PVRShellOutputDebug("No of Init repeats: %i\n", m_pShell->PVRShellGet(prefInitRepeats)); 1736 1737 if(m_pShell->PVRShellGet(prefQuitAfterFrame) != -1) 1738 m_pShell->PVRShellOutputDebug("Quit after frame: %i\n", m_pShell->PVRShellGet(prefQuitAfterFrame)); 1739 1740 if(m_pShell->PVRShellGet(prefQuitAfterTime) != -1.0f) 1741 m_pShell->PVRShellOutputDebug("Quit after time: %f\n", m_pShell->PVRShellGet(prefQuitAfterTime)); 1742 } 1743 } 1744 1745 /**************************************************************************** 1746 ** Local code 1747 ****************************************************************************/ 1748 /*!*********************************************************************** 1749 @brief This function copies pszSrc into pszStr. 1750 @param[out] pszStr The string to copy pszSrc into 1751 @param[in] pszSrc The source string to copy 1752 *************************************************************************/ 1753 static bool StringCopy(char *&pszStr, const char * const pszSrc) 1754 { 1755 size_t len; 1756 1757 FREE(pszStr); 1758 1759 if(!pszSrc) 1760 return true; 1761 1762 len = strlen(pszSrc)+1; 1763 pszStr = (char*)malloc(len); 1764 if(!pszStr) 1765 return false; 1766 1767 strcpy(pszStr, pszSrc); 1768 return true; 1769 } 1770 1771 /// @endcond 1772 //NO_DOXYGEN 1773 1774 /***************************************************************************** 1775 End of file (PVRShell.cpp) 1776 *****************************************************************************/ 1777 1778