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 *************************************************************************/
PVRShell()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 *************************************************************************/
~PVRShell()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
PVRShellSet(const prefNameBoolEnum prefName,const bool value)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
PVRShellGet(const prefNameBoolEnum prefName) const219 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
PVRShellSet(const prefNameFloatEnum prefName,const float value)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 *************************************************************************/
PVRShellGet(const prefNameFloatEnum prefName) const275 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 *************************************************************************/
PVRShellSet(const prefNameIntEnum prefName,const int value)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 *************************************************************************/
PVRShellGet(const prefNameIntEnum prefName) const414 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 *************************************************************************/
PVRShellSet(const prefNamePtrEnum prefName,const void * const ptrValue)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 *************************************************************************/
PVRShellGet(const prefNamePtrEnum prefName) const467 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 *************************************************************************/
PVRShellSet(const prefNameConstPtrEnum prefName,const void * const ptrValue)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 *************************************************************************/
PVRShellGet(const prefNameConstPtrEnum prefName) const519 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 *************************************************************************/
PVRShellScreenCaptureBuffer(const int Width,const int Height,unsigned char ** pLines)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 *************************************************************************/
PVRShellScreenSave(const char * const fname,const int Width,const int Height,const unsigned char * const pLines,const unsigned int ui32PixelReplicate,char * const ofname)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 *************************************************************************/
PVRShellByteSwap(unsigned char * pBytes,int i32ByteNo)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 *************************************************************************/
PVRShellWriteBMPFile(const char * const pszFilename,const unsigned int ui32Width,const unsigned int ui32Height,const void * const pImageData,const unsigned int ui32PixelReplicate)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 *************************************************************************/
PVRShellGetTime()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 *************************************************************************/
PVRShellIsKeyPressed(const PVRShellKeyName key)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 *************************************************************************/
PVRShellCommandLine()833 PVRShellCommandLine::PVRShellCommandLine()
834 {
835 memset(this, 0, sizeof(*this));
836 }
837
838 /*!***********************************************************************
839 @brief Destructor
840 *************************************************************************/
~PVRShellCommandLine()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 *************************************************************************/
Set(const char * pStr)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 *************************************************************************/
Prefix(const char * pStr)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 *************************************************************************/
PrefixFromFile(const char * pFileName)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 *************************************************************************/
Parse()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 *************************************************************************/
Apply(PVRShell & shell)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 *************************************************************************/
PVRShellInit()1184 PVRShellInit::PVRShellInit()
1185 {
1186 memset(this, 0, sizeof(*this));
1187 }
1188
1189 /*!***********************************************************************
1190 @brief Destructor
1191 *************************************************************************/
~PVRShellInit()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 *************************************************************************/
Deinit()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 *************************************************************************/
Init()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 *************************************************************************/
CommandLine(const char * str)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 *************************************************************************/
CommandLine(int argc,char ** argv)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 *************************************************************************/
DoIsKeyPressed(const PVRShellKeyName key)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 *************************************************************************/
KeyPressed(PVRShellKeyName nKey)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 *************************************************************************/
TouchBegan(const float vec2Location[2])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 *************************************************************************/
TouchMoved(const float vec2Location[2])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 *************************************************************************/
TouchEnded(const float vec2Location[2])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 *************************************************************************/
GetReadPath() const1409 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 *************************************************************************/
GetWritePath() const1418 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 *******************************************************************************/
SetAppName(const char * const str)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 *************************************************************************/
SetReadPath(const char * const str)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 *************************************************************************/
SetWritePath(const char * const str)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 *****************************************************************************/
FpsUpdate()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 *****************************************************************************/
Run()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 *************************************************************************/
OutputInfo()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 *************************************************************************/
StringCopy(char * & pszStr,const char * const pszSrc)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