1 /*---------------------------------------------------------------------------*
2 
3   Copyright 2010-2012 Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 ////===========================================================================
13 ///  DEMOGfx.c
14 ///
15 ///     This is graphics system code for the DEMO library.
16 ///
17 ////===========================================================================
18 
19 #include <stdio.h>
20 #include <cafe/demo.h>
21 #include <cafe/gx2.h>
22 #include <cafe/procui.h>
23 
24 // A bit like asserts, but even for NDEBUG=TRUE:
25 #define DEMOCheck(x,y) if (!(x)) { OSReport("%s\n", y); while(1) OSSleepSeconds(1); }
26 
27 GX2ColorBuffer   DEMOColorBuffer;
28 GX2DepthBuffer   DEMODepthBuffer;
29 void            *DEMOScanBufferPtr;
30 
31 // DEMO Gfx Context State
32 GX2ContextState *DEMOContextState;
33 
34 u32             *DEMOCommandBufferBasePtr;
35 #define DEMO_GFX_COMMAND_BUFFER_POOL_SIZE 1024*1024*sizeof(u32)
36 
37 static BOOL gDemoGfxRunningFlag=FALSE;
38 static BOOL gDemoGfxTVEnabled=FALSE;
39 
40 BOOL gDemoGfxInForeground=TRUE;
41 
42 static MEMHeapHandle  gDEMOMem1Heap = MEM_HEAP_INVALID_HANDLE;
43 static MEMHeapHandle  gDEMOBucketHeap = MEM_HEAP_INVALID_HANDLE;
44 
45 static char gDemoAssetsDir[MAX_ASSET_DIR_LEN];
46 
47 // State from init that needs to be preserved when reacquiring foreground.
48 static GX2TVRenderMode gDemoGfxRenderMode;
49 static GX2SurfaceFormat gDemoGfxScanOutCBFormat;
50 static u32 gDemoGfxScanSize;
51 
52 // Other preserved items
53 static u32 gDemoGfxRenderWidth;
54 static u32 gDemoGfxRenderHeight;
55 static u32 gDemoGfxSwapInterval;
56 
57 // Instance
58 static DEMOGfxInstance* gDemoGfxCurInstance = NULL;
59 
60 
DEMOGX2RAlloc(GX2RResourceFlags resourceFlags,u32 byteCount,u32 alignment)61 static void* DEMOGX2RAlloc(GX2RResourceFlags resourceFlags, u32 byteCount, u32 alignment)
62 {
63     if (GX2TestBitFlagsAny(resourceFlags, GX2R_BIND_COLOR_BUFFER | GX2R_BIND_DEPTH_BUFFER | GX2R_BIND_SCAN_BUFFER | GX2R_BIND_GS_RING | GX2R_USAGE_FORCE_MEM1) &&
64         !GX2TestBitFlagsAny(resourceFlags, GX2R_USAGE_FORCE_MEM2))
65     {
66         return DEMOGfxAllocMEM1(byteCount, alignment);
67     }
68     else
69     {
70         return DEMOGfxAllocMEM2(byteCount, alignment);
71     }
72 }
73 
74 
DEMOGX2RFree(GX2RResourceFlags resourceFlags,void * pMem)75 static void DEMOGX2RFree(GX2RResourceFlags resourceFlags, void* pMem)
76 {
77     if (GX2TestBitFlagsAny(resourceFlags, GX2R_BIND_COLOR_BUFFER | GX2R_BIND_DEPTH_BUFFER | GX2R_BIND_SCAN_BUFFER | GX2R_BIND_GS_RING | GX2R_USAGE_FORCE_MEM1) &&
78         !GX2TestBitFlagsAny(resourceFlags, GX2R_USAGE_FORCE_MEM2))
79     {
80         DEMOGfxFreeMEM1(pMem);
81     }
82     else
83     {
84         DEMOGfxFreeMEM2(pMem);
85     }
86 }
87 
88 
89 
DEMOGfxAllocMEM1(u32 size,u32 align)90 void *DEMOGfxAllocMEM1(u32 size, u32 align)
91 {
92     void *ptr;
93 
94     if (align < 4)
95     {
96         align = 4;
97     }
98 
99     // DEMOGfxMem1HeapInit() must be called first to init the heap.
100     DEMOAssert(gDEMOMem1Heap != MEM_HEAP_INVALID_HANDLE);
101 
102     // Use the expanded heap for demos.
103     ptr = MEMAllocFromExpHeapEx(gDEMOMem1Heap, size, align);
104     GX2NotifyMemAlloc(ptr, size, align);
105 
106     DEMOAssert(ptr&&"Failed MEM1 alloc");
107 
108     return ptr;
109 }
110 
DEMOGfxFreeMEM1(void * ptr)111 void DEMOGfxFreeMEM1(void * ptr)
112 {
113     if (gDemoGfxInForeground) MEMFreeToExpHeap(gDEMOMem1Heap, ptr);
114     GX2NotifyMemFree(ptr);
115 }
116 
DEMOGfxAllocBucket(u32 size,u32 align)117 void *DEMOGfxAllocBucket(u32 size, u32 align)
118 {
119     DEMOAssert(gDEMOBucketHeap != MEM_HEAP_INVALID_HANDLE);
120 
121     void * ptr = MEMAllocFromExpHeapEx(gDEMOBucketHeap, size, align);
122     GX2NotifyMemAlloc(ptr, size, align);
123 
124     DEMOAssert(ptr);
125 
126     return ptr;
127 }
128 
DEMOGfxFreeBucket(void * ptr)129 void DEMOGfxFreeBucket(void * ptr)
130 {
131     if (gDemoGfxInForeground) MEMFreeToExpHeap(gDEMOBucketHeap, ptr);
132     GX2NotifyMemFree(ptr);
133 }
134 
DEMOGfxAllocMEM2(u32 size,u32 align)135 void *DEMOGfxAllocMEM2(u32 size, u32 align)
136 {
137     void *ptr;
138 
139     if (align < 4)
140     {
141         align = 4;
142     }
143         // FINAL MEMORY MANAGEMENT MODEL
144         ptr = DEMOAllocEx(size, align);
145         GX2NotifyMemAlloc(ptr, size, align);
146 
147     DEMOAssert(ptr&&"Failed MEM2 alloc");
148 
149     return ptr;
150 }
151 
152 
DEMOGfxFreeMEM2(void * ptr)153 void DEMOGfxFreeMEM2(void * ptr)
154 {
155         // FINAL MEMORY MANAGEMENT MODEL
156     DEMOFree(ptr);
157     GX2NotifyMemFree(ptr);
158 }
159 
DEMOGfxCallbackAcquiredForeground(void * unused)160 static u32 DEMOGfxCallbackAcquiredForeground(void* unused)
161 {
162     DEMOGfxAcquiredForeground();
163 
164     // No issues
165     return 0;
166 }
167 
DEMOGfxCallbackReleaseForeground(void * unused)168 static u32 DEMOGfxCallbackReleaseForeground(void* unused)
169 {
170     DEMOGfxReleaseForeground();
171 
172     // No issues
173     return 0;
174 }
175 
DEMOGfxInit(int argc,char * argv[])176 DEMOGfxInstance* DEMOGfxInit(int argc, char *argv[])
177 {
178     void *ptr;
179 
180     u32 scanSize;
181     GX2Boolean scaleNeeded;
182 
183     u32 i;
184     char *p;
185     u32 renderWidth = 1280;
186     u32 renderHeight = 720;
187     // Default to SRGB for gamma
188     GX2SurfaceFormat renderCBFormat  = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
189     GX2SurfaceFormat scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
190     GX2SurfaceFormat renderDBFormat  = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
191     GX2AAMode renderAAMode = GX2_AA_MODE_1X;
192 	GX2Boolean renderHiZ = GX2_TRUE;
193 
194     static const u32 tvRenderModeTable[] = {
195          640,  480, GX2_TV_RENDER_480_NARROW,   // 4:3 ratio (640x480)
196          854,  480, GX2_TV_RENDER_480_WIDE,     // 16:9 ratio (854x480)
197         1280,  720, GX2_TV_RENDER_720,          // 16:9 for all the rest...
198         1920, 1080, GX2_TV_RENDER_1080,
199     };
200 #define RM_TABLE_SZ 4
201 
202     GX2TVRenderMode renderMode;
203 
204     // Init flags
205     gDemoGfxRunningFlag=FALSE;
206     gDemoGfxTVEnabled=FALSE;
207 
208     // Asset Directory
209     strcpy(gDemoAssetsDir, "assets/");
210 
211     // Alloc Gfx command buffer pool
212     DEMOCommandBufferBasePtr = (u32 *) DEMOAllocEx(
213                                        DEMO_GFX_COMMAND_BUFFER_POOL_SIZE,
214                                        GX2_DEFAULT_BUFFER_ALIGNMENT);
215     DEMOCheck(DEMOCommandBufferBasePtr, "Failed to allocate command buffer pool");
216 
217     // Passing user allocated cb buffer and command-line arguments to gx2Init
218     u32 gx2InitAttribs[] =
219     {
220         GX2_INIT_ATTRIB_CB_BASE, (u32)DEMOCommandBufferBasePtr,          // cb buffer
221         GX2_INIT_ATTRIB_CB_SIZE, (u32)DEMO_GFX_COMMAND_BUFFER_POOL_SIZE, // cb size
222         GX2_INIT_ATTRIB_ARGC,    (u32)argc,  // number of args
223         GX2_INIT_ATTRIB_ARGV,    (u32)argv,  // command-line args
224         GX2_INIT_ATTRIB_NULL                 // terminates the list
225     };
226 
227     // Initialize GX2 library
228     GX2Init(gx2InitAttribs);
229 
230     s32 gx2DebugMode=-1;
231     s32 gx2rDebugOptions=-1;
232     u32 swapInterval = 1;
233 
234 #define SKIP_NON_DIGIT(c) ((c)!=0&&((c)<'0'||(c)>'9'))
235 
236     // Analyze arguments
237     // Note that all arguments might be in a single string!
238     for (i = 0; i < argc; ++i)
239     {
240         p = strstr(argv[i], "DEMO_WIDTH");
241         if (p != 0){
242             renderWidth = (u32)atoi(p+10+SKIP_NON_DIGIT(p[10]));
243         }
244         p = strstr(argv[i], "DEMO_HEIGHT");
245         if (p != 0){
246             renderHeight = (u32)atoi(p+11+SKIP_NON_DIGIT(p[11]));
247         }
248         p = strstr(argv[i], "DEMO_CB_FORMAT");
249         if (p != 0){
250             p = p+14+SKIP_NON_DIGIT(p[14]);
251             if(strncmp(p, "10_10_10_2", 10) == 0){
252                 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM;
253             } else if(strncmp(p, "2_10_10_10", 10) == 0){
254                 renderCBFormat = GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM;
255             } else if(strncmp(p, "8_8_8_8_SRGB", 12) == 0){
256                 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
257             } else if(strncmp(p, "8_8_8_8", 7) == 0){
258                 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM;
259             } else if(strncmp(p, "16_16_16_16F", 12) == 0){
260                 renderCBFormat = GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT;
261             } else if(strncmp(p, "32_32_32_32F", 12) == 0){
262                 renderCBFormat = GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT;
263             } else if(strncmp(p, "16", 2) == 0){
264                 renderCBFormat = GX2_SURFACE_FORMAT_TCD_R16_UNORM;
265             } else if(strncmp(p, "32F", 3) == 0){
266                 renderCBFormat = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
267             } else {
268                 DEMOPrintf("Unrecognized CB format: %s\n",p);
269             }
270         }
271         p = strstr(argv[i], "DEMO_SCAN_FORMAT");
272         if (p != 0){
273             p = p+16+SKIP_NON_DIGIT(p[16]);
274             if(strncmp(p, "10_10_10_2", 10) == 0){
275                 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM;
276             }else if(strncmp(p, "2_10_10_10", 10) == 0){
277                 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM;
278             }else if(strncmp(p, "8_8_8_8_SRGB", 12) == 0){
279                 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
280             }else if(strncmp(p, "8_8_8_8", 7) == 0){
281                 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM;
282             } else {
283                 DEMOPrintf("Unrecognized SCAN format: %s\n",p);
284             }
285         }
286         p = strstr(argv[i], "DEMO_DB_FORMAT");
287         if (p != 0){
288             p = p+14+SKIP_NON_DIGIT(p[14]);
289             if(strncmp(p, "16", 2) == 0){
290                 renderDBFormat = GX2_SURFACE_FORMAT_TCD_R16_UNORM;
291             }else if(strncmp(p, "8_24F", 5) == 0){
292                 renderDBFormat = GX2_SURFACE_FORMAT_D_D24_S8_FLOAT;
293             }else if(strncmp(p, "8_24", 4) == 0){
294                 renderDBFormat = GX2_SURFACE_FORMAT_D_D24_S8_UNORM;
295             }else if(strncmp(p, "X24_8_32F", 9) == 0){
296                 renderDBFormat = GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24;
297             }else if(strncmp(p, "32F", 3) == 0){
298                 renderDBFormat = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
299             } else  {
300                 DEMOPrintf("Unrecognized DB format: %s\n",p);
301             }
302         }
303         p = strstr(argv[i], "DEMO_AA_MODE");
304         if (p != 0){
305             renderAAMode = (GX2AAMode)atoi(p+12+SKIP_NON_DIGIT(p[12]));
306             GX2_CHECK_ENUM_RANGE(renderAAMode, GX2_AA_MODE)
307         }
308         p = strstr(argv[i], "DEMO_FONT_DISABLE");
309         if (p != 0){
310             DEMOFontDrawEnable(FALSE);
311             DEMOPrintf("DEMO: DISABLE_FONT\n");
312         }
313         p = strstr(argv[i], "DEMO_HIZ_DISABLE");
314         if (p != 0){
315             DEMOPrintf("DEMO: DISABLE_HIZ\n");
316 			renderHiZ = GX2_FALSE;
317         }
318 
319         p = strstr(argv[i], "DEMO_GX2_DEBUG_MODE");
320         if (p != 0)
321         {
322             sscanf(p+strlen("DEMO_GX2_DEBUG_MODE="), "%i", &gx2DebugMode);       // allows hex notation
323         }
324 
325         p = strstr(argv[i], "DEMO_GX2R_DEBUG_OPTIONS");
326         if (p != 0)
327         {
328             sscanf(p+strlen("DEMO_GX2R_DEBUG_OPTIONS="), "%i", &gx2rDebugOptions); // allows hex notation
329         }
330 
331         p = strstr(argv[i], "DEMO_SWAP_INTERVAL");
332         if (p != 0)
333         {
334             u32 offset=strlen("DEMO_SWAP_INTERVAL");
335             swapInterval = atoi(p+offset+SKIP_NON_DIGIT(p[offset]));
336             OSReport("DEMO: swap interval=%d\n", swapInterval);
337         }
338 
339         // Modify the assets directory if DEMO_ASSETS_DIR is passed in
340         p = strstr(argv[i], "DEMO_ASSETS_DIR=");
341         if (p != 0){
342             char tempBuffer[MAX_ASSET_DIR_LEN];
343             tempBuffer[MAX_ASSET_DIR_LEN - 2] = 0;
344 
345             strncpy(tempBuffer, p+strlen("DEMO_ASSETS_DIR="), MAX_ASSET_DIR_LEN - 2);
346             // replace EOL or ',' with terminating 0
347             char* p2 = tempBuffer;
348             for( ; *p2 != '\n' && *p2 != '\r' && *p2 != ',' && *p2 != 0; p2++ ) {}
349             *p2 = 0;
350 
351             // Make sure the asset directory ends with a forward slash
352             if (*(p2 - 1) != '/')
353             {
354                 *p2 = '/';
355                 *(p2 + 1) = 0;
356             }
357 
358             strcpy(gDemoAssetsDir, tempBuffer);
359         }
360     }
361 
362     //Use a different MEM1 allocator for DEMO lib.
363     DEMOGfxMem1HeapInit();
364     DEMOGfxBucketHeapInit();
365 
366     if (gx2DebugMode!=-1)
367     {
368         DEMOPrintf("DEMO: GX2 debug mode=%#04x\n", gx2DebugMode);
369         GX2SetDebugMode((GX2DebugMode)gx2DebugMode);
370     }
371 
372 #ifdef _DEBUG
373     // If no GX2R debug options specified, default some of them in debug builds
374     if (gx2rDebugOptions==-1)
375     {
376         gx2rDebugOptions = GX2R_DEBUG_GUARD_BANDS_ENABLED | GX2R_DEBUG_LEAK_CHECK | GX2R_DEBUG_CHECK_GPU_CONTENTION;
377     }
378 #endif
379 
380     if (gx2rDebugOptions!=-1)
381     {
382         DEMOPrintf("DEMO: GX2R debug options=%#04x\n", gx2rDebugOptions);
383         GX2RSetDebugOptions((GX2RDebugOptions)gx2rDebugOptions);
384     }
385 
386     // Hook in the demo allocators for GX2R
387     GX2RSetAllocator(DEMOGX2RAlloc, DEMOGX2RFree);
388 
389     char *aaStr[4]={ "1X", "2X", "4X", "8X" };
390 
391     DEMOPrintf("DEMO: Rendering TV:%dx%d CB:%s DB:%s ScanCB:%s AA:%s\n",
392                renderWidth, renderHeight,
393                &DEMOGfxGetSurfaceFormatName(renderCBFormat)[19],
394                &DEMOGfxGetSurfaceFormatName(renderDBFormat)[19],
395                &DEMOGfxGetSurfaceFormatName(scanOutCBFormat)[19],
396                aaStr[renderAAMode]);
397 
398     // Choose an appropriate TV render mode based on desired dimensions
399     for (i = 0; i < RM_TABLE_SZ; i++) {
400         if (((tvRenderModeTable[i*3] >= renderWidth) &&
401              (tvRenderModeTable[i*3+1] >= renderHeight)) || i==(RM_TABLE_SZ-1)) {
402             renderMode = (GX2TVRenderMode) tvRenderModeTable[i*3+2];
403             break;
404         }
405     }
406 
407     // Setup Scan Buffers; this must be done before setting up TV render targets!
408     GX2CalcTVSize(renderMode, scanOutCBFormat,
409                   GX2_BUFFERING_DOUBLE, &scanSize, &scaleNeeded);
410 
411     // For Cafe, should put scan buffers in the foreground bucket
412     DEMOScanBufferPtr = DEMOGfxAllocBucket(scanSize, GX2_SCAN_BUFFER_ALIGNMENT);
413     DEMOCheck(DEMOScanBufferPtr!=NULL, "Scan buffer alloc failed");
414     GX2Invalidate(GX2_INVALIDATE_CPU, DEMOScanBufferPtr, scanSize);
415 
416     GX2SetTVBuffer(DEMOScanBufferPtr, scanSize, renderMode,
417                    scanOutCBFormat, GX2_BUFFERING_DOUBLE);
418 
419     // First, we do all the memory allocations to see what fits into MEM1.
420 
421     // Setup render buffer; designate it as "final" TV render target.
422     GX2InitColorBufferFTV(&DEMOColorBuffer,
423                           renderWidth, renderHeight,
424                           renderCBFormat,
425                           renderAAMode);
426 
427     // AA mode may have changed due to display-related issues.
428     // Please refer to the GX2 display documentation.
429     renderAAMode = DEMOColorBuffer.surface.aa;
430 
431     ptr = DEMOGfxAllocMEM1(DEMOColorBuffer.surface.imageSize,
432                            DEMOColorBuffer.surface.alignment);
433     DEMOCheck(ptr!=NULL, "Color buffer alloc failed");
434     GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMOColorBuffer.surface.imageSize);
435 
436     GX2InitColorBufferPtr(&DEMOColorBuffer, ptr);
437 
438     // Setup aux buffer
439     if (DEMOColorBuffer.surface.aa != GX2_AA_MODE_1X) {
440         u32 size, align;
441         GX2CalcColorBufferAuxInfo(&DEMOColorBuffer, &size, &align);
442         ptr = DEMOGfxAllocMEM1(size, align);
443         DEMOCheck(ptr!=NULL, "Color aux buffer alloc failed");
444         GX2InitColorBufferAuxPtr(&DEMOColorBuffer, ptr);
445         GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
446         // Aux buffer must be cleared manually to this value once:
447         GX2UTSetupColorAuxBuffer(&DEMOColorBuffer);
448     }
449 
450     // Setup Depth Buffer
451     GX2InitDepthBuffer(&DEMODepthBuffer,
452                        renderWidth, renderHeight,
453                        renderDBFormat,
454                        renderAAMode);
455     ptr = DEMOGfxAllocMEM1(DEMODepthBuffer.surface.imageSize,
456                            DEMODepthBuffer.surface.alignment);
457     DEMOCheck(ptr!=NULL, "Depth buffer alloc failed");
458     GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODepthBuffer.surface.imageSize);
459     GX2InitDepthBufferPtr(&DEMODepthBuffer, ptr);
460 
461     // Setup Hi-Z buffer
462     if (renderHiZ) {
463         u32 size, align;
464         GX2CalcDepthBufferHiZInfo(&DEMODepthBuffer, &size, &align);
465         ptr = DEMOGfxAllocMEM1(size, align);
466         DEMOCheck(ptr!=NULL, "Depth Hi-Z buffer alloc failed");
467         GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
468         GX2InitDepthBufferHiZPtr(&DEMODepthBuffer, ptr);
469     }
470 
471     // Register a callback upon foreground acquire and release
472     ProcUIRegisterCallback(PROCUI_MESSAGE_ACQUIRE, DEMOGfxCallbackAcquiredForeground, NULL, 100);
473     ProcUIRegisterCallback(PROCUI_MESSAGE_RELEASE, DEMOGfxCallbackReleaseForeground, NULL, 100);
474 
475     // Save state for DEMOGfxAcquiredForeground
476     gDemoGfxRenderMode = renderMode;
477     gDemoGfxScanOutCBFormat = scanOutCBFormat;
478     gDemoGfxScanSize = scanSize;
479 
480     // Save state for instancing
481     gDemoGfxRenderWidth = renderWidth;
482     gDemoGfxRenderHeight = renderHeight;
483     gDemoGfxSwapInterval = swapInterval;
484 
485     // Create a new instance (including the context state)
486     gDemoGfxCurInstance = NULL;
487     DEMOGfxAddInstance();
488 
489     // The main core is the one with GFX
490     DEMOSetMainCore(OSGetCoreId());
491 
492     // Indicate that graphics has been started
493     gDemoGfxRunningFlag = TRUE;
494 
495     return gDemoGfxCurInstance;
496 }
497 
DEMOGfxShutdown()498 void DEMOGfxShutdown()
499 {
500     // Delete the instances
501     DEMOGfxDeleteInstance(gDemoGfxCurInstance);
502 
503     // It is possible to exit from the background, but some API calls
504     // can only happen from the foreground. Check a flag to see if this
505     // processes is exiting from the foreground before calling APIs
506     // that deal with foreground-only resources.
507 
508     // Disable video outputs
509     if (gDemoGfxInForeground && OS_SHUTDOWN_RESTART != OSGetShutdownReason())
510     {
511         GX2SetTVEnable(GX2_FALSE);
512     }
513     gDemoGfxTVEnabled = FALSE;
514 
515     // Free allocated buffers
516     DEMOGfxFreeBucket(DEMOScanBufferPtr);
517     if (DEMODepthBuffer.hiZPtr) {
518         DEMOGfxFreeMEM1(DEMODepthBuffer.hiZPtr);
519         DEMODepthBuffer.hiZPtr = NULL;
520     }
521     DEMOGfxFreeMEM1(DEMODepthBuffer.surface.imagePtr);
522     if (DEMOColorBuffer.auxPtr) {
523         DEMOGfxFreeMEM1(DEMOColorBuffer.auxPtr);
524         DEMOColorBuffer.auxPtr = NULL;
525     }
526     DEMOGfxFreeMEM1(DEMOColorBuffer.surface.imagePtr);
527     if (gDemoGfxInForeground) DEMOFree(DEMOCommandBufferBasePtr);
528 
529     // Shutdown GX2 (which is safe to call from the background);
530     GX2Shutdown();
531 
532     // Dump any leaked resources if enabled
533     if (GX2RGetDebugOptions() & GX2R_DEBUG_LEAK_CHECK)
534     {
535         if (GX2TempGetResourceCount()>0)
536         {
537             OSReport("***DEMO: resources were not destroyed on shutdown\n");
538             GX2TempDumpResources();
539             ASSERT(FALSE && "Resources were not destroyed on shutdown");
540         }
541     }
542     // Unhook the GX2R allocator functions.
543     GX2RSetAllocator(NULL, NULL);
544 
545     // Only destroy these heaps if this process is in the foreground.
546     if (gDemoGfxInForeground)
547     {
548         DEMOGfxMem1HeapDestroy();
549         DEMOGfxBucketHeapDestroy();
550     }
551 
552     gDemoGfxRunningFlag = FALSE;
553 }
554 
DEMOGfxReleaseForeground()555 void DEMOGfxReleaseForeground()
556 {
557     // First wait for all pending draws to complete.
558     GX2DrawDone();
559 
560     // Release resources in MEM1
561     if (DEMODepthBuffer.hiZPtr) {
562         DEMOGfxFreeMEM1(DEMODepthBuffer.hiZPtr);
563         DEMODepthBuffer.hiZPtr = NULL;
564     }
565     DEMOGfxFreeMEM1(DEMODepthBuffer.surface.imagePtr);
566     if (DEMOColorBuffer.auxPtr) {
567         DEMOGfxFreeMEM1(DEMOColorBuffer.auxPtr);
568         DEMOColorBuffer.auxPtr = NULL;
569     }
570     DEMOGfxFreeMEM1(DEMOColorBuffer.surface.imagePtr);
571 
572     // Free resources from the foreground bucket
573     DEMOGfxFreeBucket(DEMOScanBufferPtr);
574 
575     // Destroy heaps that will not be available.
576     DEMOGfxMem1HeapDestroy();
577     DEMOGfxBucketHeapDestroy();
578 
579     // Mark the TV as disabled.
580     gDemoGfxTVEnabled=FALSE;
581 
582     // Set a flag to indicate that this process is in the background.
583     gDemoGfxInForeground=FALSE;
584     OSMemoryBarrier();
585 }
586 
DEMOGfxAcquiredForeground()587 void DEMOGfxAcquiredForeground()
588 {
589     void *ptr;
590 
591     // Set a flag to indicate that this process is in the foreground.
592     gDemoGfxInForeground=TRUE;
593     OSMemoryBarrier();
594 
595     // Recreate heaps that were lost.
596     DEMOGfxMem1HeapInit();
597     DEMOGfxBucketHeapInit();
598 
599     // For Cafe, should put scan buffers in the foreground bucket
600     DEMOScanBufferPtr = DEMOGfxAllocBucket(gDemoGfxScanSize, GX2_SCAN_BUFFER_ALIGNMENT);
601     GX2Invalidate(GX2_INVALIDATE_CPU, DEMOScanBufferPtr, gDemoGfxScanSize);
602 
603     GX2SetTVBuffer(DEMOScanBufferPtr, gDemoGfxScanSize, gDemoGfxRenderMode,
604                    gDemoGfxScanOutCBFormat, GX2_BUFFERING_DOUBLE);
605 
606     // Re-allocate color buffer
607     ptr = DEMOGfxAllocMEM1(DEMOColorBuffer.surface.imageSize,
608                            DEMOColorBuffer.surface.alignment);
609     GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMOColorBuffer.surface.imageSize);
610 
611     GX2InitColorBufferPtr(&DEMOColorBuffer, ptr);
612 
613     // Setup aux buffer
614     if (DEMOColorBuffer.surface.aa != GX2_AA_MODE_1X) {
615         u32 size, align;
616         GX2CalcColorBufferAuxInfo(&DEMOColorBuffer, &size, &align);
617         ptr = DEMOGfxAllocMEM1(size, align);
618         GX2InitColorBufferAuxPtr(&DEMOColorBuffer, ptr);
619         GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
620         // Aux buffer must be cleared manually to this value once:
621         GX2UTSetupColorAuxBuffer(&DEMOColorBuffer);
622     }
623 
624     // Re-allocate depth buffer
625     ptr = DEMOGfxAllocMEM1(DEMODepthBuffer.surface.imageSize,
626                            DEMODepthBuffer.surface.alignment);
627     GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODepthBuffer.surface.imageSize);
628     GX2InitDepthBufferPtr(&DEMODepthBuffer, ptr);
629 
630     // Setup Hi-Z buffer
631     if (1) { // Allow testing with & without Hi-Z
632         u32 size, align;
633         GX2CalcDepthBufferHiZInfo(&DEMODepthBuffer, &size, &align);
634         ptr = DEMOGfxAllocMEM1(size, align);
635         GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
636         GX2InitDepthBufferHiZPtr(&DEMODepthBuffer, ptr);
637     }
638 
639     GX2SetContextState(DEMOContextState);
640 
641     // Indicate that graphics has been started
642     gDemoGfxRunningFlag = TRUE;
643 }
644 
DEMOGfxIsRunning()645 BOOL DEMOGfxIsRunning()
646 {
647     return gDemoGfxRunningFlag;
648 }
649 
DEMOGfxSetContextState(void)650 void DEMOGfxSetContextState(void)
651 {
652     GX2UTDebugTagIndent("DEMOGfxSetContextState()");
653     GX2SetContextState(DEMOContextState);
654     GX2UTDebugTagUndent();
655 }
656 
DEMOGfxBeforeRender(void)657 void DEMOGfxBeforeRender(void)
658 {
659     GX2UTDebugTagIndent("DEMOGfxBeforeRender()");
660     // Allow CPU to run 1 frame ahead of GPU and display
661     //DEMOGfxWaitForSwap(1, 0);
662     //TEMP TODO: most of the demos rely on the CPU not being ahead of the GPU, until that's (maybe) going to get fixed
663     // we need to leave the swap queue depth at 0.
664     DEMOGfxWaitForSwap(0, 0);
665 
666     // Enabled when Demo Perf condition is met
667     DEMOTestCheckPerfBegin();
668     GX2UTDebugTagUndent();
669 }
670 
DEMOGfxDoneRender(void)671 void DEMOGfxDoneRender(void)
672 {
673     GX2UTDebugTagIndent("DEMOGfxDoneRender()");
674     // Enabled when Demo Perf condition is met
675     DEMOTestCheckPerfEnd();
676 
677     // This extra flush avoids a potential race condition that can occur with
678     // the GX2R Resource Tracker: the swap buffer command might finish before
679     // the time stamp of its CB is updated.  The race condition would make the
680     // resource appear still in use at the start of the next frame.  This extra
681     // flush makes sure that no GX2R resources share the same time stamp as
682     // the swap buffer CB, thus avoiding the problem.
683     GX2Flush();
684 
685     GX2SwapBuffers(&DEMOColorBuffer);
686 
687     // Restore the context state after copy
688     GX2SetContextState(DEMOContextState);
689 
690     // Do this before the flush so it's in the same CB as everything else
691     GX2UTDebugTagUndent();
692 
693     // Flush after swap, since swap goes into the FIFO
694     GX2Flush();
695 
696     // Enable video output after first frame rendered
697     if (gDemoGfxTVEnabled == FALSE) {
698         GX2SetTVEnable(GX2_TRUE);
699         gDemoGfxTVEnabled = TRUE;
700     }
701 }
702 
DEMOGfxDrawDone(void)703 void DEMOGfxDrawDone(void)
704 {
705     // Only if running and in the foreground
706     if (APP_IN_FOREGROUND && DEMOGfxIsRunning())
707         GX2DrawDone();
708 }
709 
DEMOGfxWaitForSwap(u32 depth,u32 percent)710 void DEMOGfxWaitForSwap(u32 depth, u32 percent)
711 {
712     GX2UTDebugTagIndent("DEMOGfxWaitForSwap()");
713     u32 swapCount, flipCount, waitCount=0;
714     OSTime tLastFlip, tLastVsync;
715     OSTime tNow;
716     const OSTime t60  = (OSTime)OSSecondsToTicks(1.0f/59.94f);
717     OSTime period;
718     u32    swapInt = GX2GetSwapInterval();
719 
720     if (swapInt != 0)
721     {
722         // Note: must be careful about unsigned wrap-around!
723 
724         // Wait for "depth" frames ago to post
725         while (1)
726         {
727             GX2GetSwapStatus(&swapCount, &flipCount, &tLastFlip, &tLastVsync);
728             if (flipCount+depth >= swapCount) break;
729 
730             // If we've waited over 10 seconds for a flip, consider the GPU hung
731             // and stop running.
732             if (waitCount++ > 60*GX2GetGPUTimeout()/1000) {
733                 OSReport("DEMOGfxWaitForSwap timed out. Potential GPU hang detected?\n");
734                 GX2SetMiscParam(GX2_MISC_HANG_STATE, GX2_HANG_STATE_ETC);
735                 if (GX2GetMiscParam(GX2_MISC_HANG_RESPONSE) == GX2_HANG_RESPONSE_DEBUG) {
736                     GX2PrintGPUStatus();
737                     OSDebugStrIfConnected(0);
738                     DEMOStopRunning();
739                 }
740                 break;
741             }
742 
743             // Call WaitForVsync instead of WaitForFlip due to possible
744             // race condition of flip happening right after above test.
745             // (There will always be more vsyncs, but not always more flips.)
746             GX2WaitForVsync();
747         }
748 
749         // Wait for (percent * Swap Period) milliseconds since last flip
750         period = (percent * swapInt * t60 / 100);
751         tNow = OSGetSystemTime();
752         if (period > (tNow - tLastFlip))
753         {
754             OSSleepTicks(period - (tNow - tLastFlip));
755         }
756     }
757 
758     GX2UTDebugTagUndent();
759 }
760 
DEMOGfxMem1HeapInit(void)761 void DEMOGfxMem1HeapInit(void)
762 {
763     //A real game should use the frame heap directly to save memory,
764     //but using an expanded heap makes the demos simpler.
765 
766     //For more information on MEM1 usage, go to
767     // Operating System->Cafe Core OS (COS) Overview->Basic Memory Allocation->MEM1
768     //in the MAN pages.
769     MEMHeapHandle hMEM1 = MEMGetBaseHeapHandle(MEM_ARENA_1);
770     u32 uMEM1Size = MEMGetAllocatableSizeForFrmHeapEx(hMEM1,4);
771     void* pStartOfMem1 = MEMAllocFromFrmHeapEx(hMEM1, uMEM1Size, 4);
772     gDEMOMem1Heap = MEMCreateExpHeap(pStartOfMem1, uMEM1Size);
773     DEMOAssert(gDEMOMem1Heap != MEM_HEAP_INVALID_HANDLE);
774 }
775 
DEMOGfxMem1HeapDestroy(void)776 void DEMOGfxMem1HeapDestroy(void)
777 {
778         DEMOAssert(gDEMOMem1Heap != MEM_HEAP_INVALID_HANDLE);
779 
780         //Destroy the expanded heap and reset the frame heap to restore the allocation.
781         MEMDestroyExpHeap(gDEMOMem1Heap);
782         gDEMOMem1Heap = MEM_HEAP_INVALID_HANDLE;
783         MEMHeapHandle hMEM1 = MEMGetBaseHeapHandle(MEM_ARENA_1);
784         MEMFreeToFrmHeap(hMEM1, MEM_FRMHEAP_FREE_ALL);
785 }
786 
DEMOGfxBucketHeapInit(void)787 void DEMOGfxBucketHeapInit(void)
788 {
789     //A real game should use the frame heap directly to save memory,
790     //but using an expanded heap makes the demos simpler.
791 
792     //For more information on Foreground Bucket usage, go to
793     // Operating System->Cafe Core OS (COS) Overview->Basic Memory Allocation->Foreground Bucket
794     //in the MAN pages.
795     MEMHeapHandle hMEMFg = MEMGetBaseHeapHandle(MEM_ARENA_FG);
796     u32 uMEMFgSize = MEMGetAllocatableSizeForFrmHeapEx(hMEMFg,4);
797     void* pStartOfMemFg = MEMAllocFromFrmHeapEx(hMEMFg, uMEMFgSize, 4);
798     gDEMOBucketHeap = MEMCreateExpHeap(pStartOfMemFg, uMEMFgSize);
799     DEMOAssert(gDEMOBucketHeap != MEM_HEAP_INVALID_HANDLE);
800 }
801 
DEMOGfxBucketHeapDestroy(void)802 void DEMOGfxBucketHeapDestroy(void)
803 {
804     DEMOAssert(gDEMOBucketHeap != MEM_HEAP_INVALID_HANDLE);
805 
806     //Destroy the expanded heap and reset the frame heap to restore the allocation.
807     MEMDestroyExpHeap(gDEMOBucketHeap);
808     gDEMOBucketHeap = MEM_HEAP_INVALID_HANDLE;
809     MEMHeapHandle hMEMFg = MEMGetBaseHeapHandle(MEM_ARENA_FG);
810     MEMFreeToFrmHeap(hMEMFg, MEM_FRMHEAP_FREE_ALL);
811 }
812 
813 
DEMOGfxAddInstance(void)814 DEMOGfxInstance* DEMOGfxAddInstance(void)
815 {
816     // Setup Context State buffer
817     DEMOContextState = DEMOGfxAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
818     DEMOCheck(DEMOContextState != NULL, "Context state buffer alloc failed");
819     // GX2SetupContextState will invalidate CPU cache for us
820     GX2SetupContextState(DEMOContextState);
821 
822     // Setup render/depth buffers to be used now
823     GX2SetColorBuffer(&DEMOColorBuffer, GX2_RENDER_TARGET_0);
824     GX2SetDepthBuffer(&DEMODepthBuffer);
825 
826     // Misc graphics setup
827     GX2SetViewport(0, 0, (f32)gDemoGfxRenderWidth, (f32)gDemoGfxRenderHeight, 0.0f, 1.0f);
828     GX2SetScissor(0, 0, gDemoGfxRenderWidth, gDemoGfxRenderHeight);
829 
830     // Indicate that swaps can happen as fast as every vertical interval (1/60 sec)
831     GX2SetSwapInterval(gDemoGfxSwapInterval);
832 
833     /////////////////////////////////////////////////////////////////////////////
834     // Create the new instance
835     gDemoGfxCurInstance = DEMOAlloc(sizeof(DEMOGfxInstance));
836     gDemoGfxCurInstance->contextState = DEMOContextState;
837 
838     return gDemoGfxCurInstance;
839 }
840 
DEMOGfxDeleteInstance(DEMOGfxInstance * instance)841 void DEMOGfxDeleteInstance(DEMOGfxInstance *instance)
842 {
843     DEMOGfxFreeMEM2(instance->contextState);
844     DEMOFree(instance);
845 
846     // Edge case:  delete current
847     if (gDemoGfxCurInstance == instance) {
848         gDemoGfxCurInstance = NULL;
849         DEMOContextState = NULL;
850     }
851 }
852 
853 
DEMOGfxSetInstance(DEMOGfxInstance * instance)854 void DEMOGfxSetInstance(DEMOGfxInstance *instance)
855 {
856     gDemoGfxCurInstance = instance;
857 
858     DEMOContextState = instance->contextState;
859     GX2SetContextState(DEMOContextState);
860 }
861 
DEMOGfxGetInstance(void)862 DEMOGfxInstance* DEMOGfxGetInstance(void)
863 {
864     return gDemoGfxCurInstance;
865 }
866 
DEMOGfxOpenAssetFile(const char * path,DEMOFSFileInfo * info)867 s32 DEMOGfxOpenAssetFile(const char* path, DEMOFSFileInfo* info)
868 {
869     char filename[MAX_ASSET_DIR_FULL_LEN];
870 
871     strcpy(filename, gDemoAssetsDir);
872     strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
873 
874     return DEMOFSOpenFile(filename, info);
875 }
876 
DEMOGfxGetAssetFileLength(const DEMOFSFileInfo * fileInfo,u32 * length)877 s32 DEMOGfxGetAssetFileLength(const DEMOFSFileInfo* fileInfo, u32* length)
878 {
879     return DEMOFSGetLength(fileInfo, length);
880 }
881 
DEMOGfxReadAssetFile(DEMOFSFileInfo * fileInfo,void * addr,s32 length,s32 offset)882 s32 DEMOGfxReadAssetFile(DEMOFSFileInfo* fileInfo, void* addr, s32 length, s32 offset)
883 {
884     return DEMOFSRead(fileInfo, addr, length, offset);
885 }
886 
DEMOGfxCloseAssetFile(DEMOFSFileInfo * fileInfo)887 s32 DEMOGfxCloseAssetFile(DEMOFSFileInfo* fileInfo)
888 {
889     return DEMOFSCloseFile(fileInfo);
890 }
891 
DEMOGfxLoadAssetFile(const char * path,u32 * len)892 void* DEMOGfxLoadAssetFile(const char* path, u32* len)
893 {
894     char filename[MAX_ASSET_DIR_FULL_LEN];
895 
896     strcpy(filename, gDemoAssetsDir);
897     strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
898 
899     return DEMOFSSimpleRead(filename, len);
900 }
901 
DEMOGfxLoadAssetFileAlign(const char * path,u32 * len,u32 alignSize)902 void* DEMOGfxLoadAssetFileAlign(const char* path, u32* len, u32 alignSize)
903 {
904     char filename[MAX_ASSET_DIR_FULL_LEN];
905 
906     strcpy(filename, gDemoAssetsDir);
907     strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
908 
909     return DEMOFSSimpleReadAlign(filename, len, alignSize);
910 }
911 
DEMOGfxScanAssetDir(const char * path,u32 * pFileCount,u32 maxFiles,char ** ppFileNames)912 s32 DEMOGfxScanAssetDir(const char *path, u32 *pFileCount, u32 maxFiles, char** ppFileNames)
913 {
914     char filename[MAX_ASSET_DIR_FULL_LEN];
915 
916     strcpy(filename, gDemoAssetsDir);
917     strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
918 
919     return DEMOFSScanDir(filename, path, pFileCount, maxFiles, ppFileNames);
920 }
921 
DEMOGfxGetAttribFormatName(GX2AttribFormat format)922 const char *DEMOGfxGetAttribFormatName(GX2AttribFormat format)
923 {
924     switch(format) {
925     case GX2_ATTRIB_FORMAT_8_UNORM:                   return "GX2_ATTRIB_FORMAT_8_UNORM";                   // 0x0000
926     case GX2_ATTRIB_FORMAT_8_UINT:                    return "GX2_ATTRIB_FORMAT_8_UINT";                    // 0x0100
927     case GX2_ATTRIB_FORMAT_8_SNORM:                   return "GX2_ATTRIB_FORMAT_8_SNORM";                   // 0x0200
928     case GX2_ATTRIB_FORMAT_8_SINT:                    return "GX2_ATTRIB_FORMAT_8_SINT";                    // 0x0300
929     case GX2_ATTRIB_FORMAT_8_UINT_TO_FLOAT:           return "GX2_ATTRIB_FORMAT_8_UINT_TO_FLOAT";           // 0x0800
930     case GX2_ATTRIB_FORMAT_8_SINT_TO_FLOAT:           return "GX2_ATTRIB_FORMAT_8_SINT_TO_FLOAT";           // 0x0a00
931     case GX2_ATTRIB_FORMAT_4_4_UNORM:                 return "GX2_ATTRIB_FORMAT_4_4_UNORM";                 // 0x0001
932     case GX2_ATTRIB_FORMAT_16_UNORM:                  return "GX2_ATTRIB_FORMAT_16_UNORM";                  // 0x0002
933     case GX2_ATTRIB_FORMAT_16_UINT:                   return "GX2_ATTRIB_FORMAT_16_UINT";                   // 0x0102
934     case GX2_ATTRIB_FORMAT_16_SNORM:                  return "GX2_ATTRIB_FORMAT_16_SNORM";                  // 0x0202
935     case GX2_ATTRIB_FORMAT_16_SINT:                   return "GX2_ATTRIB_FORMAT_16_SINT";                   // 0x0302
936     case GX2_ATTRIB_FORMAT_16_FLOAT:                  return "GX2_ATTRIB_FORMAT_16_FLOAT";                  // 0x0803
937     case GX2_ATTRIB_FORMAT_16_UINT_TO_FLOAT:          return "GX2_ATTRIB_FORMAT_16_UINT_TO_FLOAT";          // 0x0802
938     case GX2_ATTRIB_FORMAT_16_SINT_TO_FLOAT:          return "GX2_ATTRIB_FORMAT_16_SINT_TO_FLOAT";          // 0x0a02
939     case GX2_ATTRIB_FORMAT_8_8_UNORM:                 return "GX2_ATTRIB_FORMAT_8_8_UNORM";                 // 0x0004
940     case GX2_ATTRIB_FORMAT_8_8_UINT:                  return "GX2_ATTRIB_FORMAT_8_8_UINT";                  // 0x0104
941     case GX2_ATTRIB_FORMAT_8_8_SNORM:                 return "GX2_ATTRIB_FORMAT_8_8_SNORM";                 // 0x0204
942     case GX2_ATTRIB_FORMAT_8_8_SINT:                  return "GX2_ATTRIB_FORMAT_8_8_SINT";                  // 0x0304
943     case GX2_ATTRIB_FORMAT_8_8_UINT_TO_FLOAT:         return "GX2_ATTRIB_FORMAT_8_8_UINT_TO_FLOAT";         // 0x0804
944     case GX2_ATTRIB_FORMAT_8_8_SINT_TO_FLOAT:         return "GX2_ATTRIB_FORMAT_8_8_SINT_TO_FLOAT";         // 0x0a04
945     case GX2_ATTRIB_FORMAT_32_UINT:                   return "GX2_ATTRIB_FORMAT_32_UINT";                   // 0x0105
946     case GX2_ATTRIB_FORMAT_32_SINT:                   return "GX2_ATTRIB_FORMAT_32_SINT";                   // 0x0305
947     case GX2_ATTRIB_FORMAT_32_FLOAT:                  return "GX2_ATTRIB_FORMAT_32_FLOAT";                  // 0x0806
948     case GX2_ATTRIB_FORMAT_16_16_UNORM:               return "GX2_ATTRIB_FORMAT_16_16_UNORM";               // 0x0007
949     case GX2_ATTRIB_FORMAT_16_16_UINT:                return "GX2_ATTRIB_FORMAT_16_16_UINT";                // 0x0107
950     case GX2_ATTRIB_FORMAT_16_16_SNORM:               return "GX2_ATTRIB_FORMAT_16_16_SNORM";               // 0x0207
951     case GX2_ATTRIB_FORMAT_16_16_SINT:                return "GX2_ATTRIB_FORMAT_16_16_SINT";                // 0x0307
952     case GX2_ATTRIB_FORMAT_16_16_FLOAT:               return "GX2_ATTRIB_FORMAT_16_16_FLOAT";               // 0x0808
953     case GX2_ATTRIB_FORMAT_16_16_UINT_TO_FLOAT:       return "GX2_ATTRIB_FORMAT_16_16_UINT_TO_FLOAT";       // 0x0807
954     case GX2_ATTRIB_FORMAT_16_16_SINT_TO_FLOAT:       return "GX2_ATTRIB_FORMAT_16_16_SINT_TO_FLOAT";       // 0x0a07
955     case GX2_ATTRIB_FORMAT_10_11_11_FLOAT:            return "GX2_ATTRIB_FORMAT_10_11_11_FLOAT";            // 0x0809
956     case GX2_ATTRIB_FORMAT_8_8_8_8_UNORM:             return "GX2_ATTRIB_FORMAT_8_8_8_8_UNORM";             // 0x000a
957     case GX2_ATTRIB_FORMAT_8_8_8_8_UINT:              return "GX2_ATTRIB_FORMAT_8_8_8_8_UINT";              // 0x010a
958     case GX2_ATTRIB_FORMAT_8_8_8_8_SNORM:             return "GX2_ATTRIB_FORMAT_8_8_8_8_SNORM";             // 0x020a
959     case GX2_ATTRIB_FORMAT_8_8_8_8_SINT:              return "GX2_ATTRIB_FORMAT_8_8_8_8_SINT";              // 0x030a
960     case GX2_ATTRIB_FORMAT_8_8_8_8_UINT_TO_FLOAT:     return "GX2_ATTRIB_FORMAT_8_8_8_8_UINT_TO_FLOAT";     // 0x080a
961     case GX2_ATTRIB_FORMAT_8_8_8_8_SINT_TO_FLOAT:     return "GX2_ATTRIB_FORMAT_8_8_8_8_SINT_TO_FLOAT";     // 0x0a0a
962     case GX2_ATTRIB_FORMAT_10_10_10_2_UNORM:          return "GX2_ATTRIB_FORMAT_10_10_10_2_UNORM";          // 0x000b
963     case GX2_ATTRIB_FORMAT_10_10_10_2_UINT:           return "GX2_ATTRIB_FORMAT_10_10_10_2_UINT";           // 0x010b
964     case GX2_ATTRIB_FORMAT_10_10_10_2_SNORM:          return "GX2_ATTRIB_FORMAT_10_10_10_2_SNORM";          // 0x020b
965     case GX2_ATTRIB_FORMAT_10_10_10_2_SINT:           return "GX2_ATTRIB_FORMAT_10_10_10_2_SINT";           // 0x030b
966     case GX2_ATTRIB_FORMAT_32_32_UINT:                return "GX2_ATTRIB_FORMAT_32_32_UINT";                // 0x010c
967     case GX2_ATTRIB_FORMAT_32_32_SINT:                return "GX2_ATTRIB_FORMAT_32_32_SINT";                // 0x030c
968     case GX2_ATTRIB_FORMAT_32_32_FLOAT:               return "GX2_ATTRIB_FORMAT_32_32_FLOAT";               // 0x080d
969     case GX2_ATTRIB_FORMAT_16_16_16_16_UNORM:         return "GX2_ATTRIB_FORMAT_16_16_16_16_UNORM";         // 0x000e
970     case GX2_ATTRIB_FORMAT_16_16_16_16_UINT:          return "GX2_ATTRIB_FORMAT_16_16_16_16_UINT";          // 0x010e
971     case GX2_ATTRIB_FORMAT_16_16_16_16_SNORM:         return "GX2_ATTRIB_FORMAT_16_16_16_16_SNORM";         // 0x020e
972     case GX2_ATTRIB_FORMAT_16_16_16_16_SINT:          return "GX2_ATTRIB_FORMAT_16_16_16_16_SINT";          // 0x030e
973     case GX2_ATTRIB_FORMAT_16_16_16_16_FLOAT:         return "GX2_ATTRIB_FORMAT_16_16_16_16_FLOAT";         // 0x080f
974     case GX2_ATTRIB_FORMAT_16_16_16_16_UINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_16_16_UINT_TO_FLOAT"; // 0x080e
975     case GX2_ATTRIB_FORMAT_16_16_16_16_SINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_16_16_SINT_TO_FLOAT"; // 0x0a0e
976     case GX2_ATTRIB_FORMAT_32_32_32_UINT:             return "GX2_ATTRIB_FORMAT_32_32_32_UINT";             // 0x0110
977     case GX2_ATTRIB_FORMAT_32_32_32_SINT:             return "GX2_ATTRIB_FORMAT_32_32_32_SINT";             // 0x0310
978     case GX2_ATTRIB_FORMAT_32_32_32_FLOAT:            return "GX2_ATTRIB_FORMAT_32_32_32_FLOAT";            // 0x0811
979     case GX2_ATTRIB_FORMAT_32_32_32_32_UINT:          return "GX2_ATTRIB_FORMAT_32_32_32_32_UINT";          // 0x0112
980     case GX2_ATTRIB_FORMAT_32_32_32_32_SINT:          return "GX2_ATTRIB_FORMAT_32_32_32_32_SINT";          // 0x0312
981     case GX2_ATTRIB_FORMAT_32_32_32_32_FLOAT:         return "GX2_ATTRIB_FORMAT_32_32_32_32_FLOAT";         // 0x0813
982     default:                                          return "invalid format";
983     }
984 }
985 
DEMOGfxGetSurfaceFormatName(GX2SurfaceFormat format)986 const char *DEMOGfxGetSurfaceFormatName(GX2SurfaceFormat format)
987 {
988     switch(format) {
989     case GX2_SURFACE_FORMAT_INVALID:                  return "GX2_SURFACE_FORMAT_INVALID";                  // 0x0000
990     case GX2_SURFACE_FORMAT_TC_R8_UNORM:              return "GX2_SURFACE_FORMAT_TC_R8_UNORM";              // 0x0001
991     case GX2_SURFACE_FORMAT_TC_R8_UINT:               return "GX2_SURFACE_FORMAT_TC_R8_UINT";               // 0x0101
992     case GX2_SURFACE_FORMAT_TC_R8_SNORM:              return "GX2_SURFACE_FORMAT_TC_R8_SNORM";              // 0x0201
993     case GX2_SURFACE_FORMAT_TC_R8_SINT:               return "GX2_SURFACE_FORMAT_TC_R8_SINT";               // 0x0301
994     case GX2_SURFACE_FORMAT_T_R4_G4_UNORM:            return "GX2_SURFACE_FORMAT_T_R4_G4_UNORM";            // 0x0002
995     case GX2_SURFACE_FORMAT_TCD_R16_UNORM:            return "GX2_SURFACE_FORMAT_TCD_R16_UNORM";            // 0x0005
996     case GX2_SURFACE_FORMAT_TC_R16_UINT:              return "GX2_SURFACE_FORMAT_TC_R16_UINT";              // 0x0105
997     case GX2_SURFACE_FORMAT_TC_R16_SNORM:             return "GX2_SURFACE_FORMAT_TC_R16_SNORM";             // 0x0205
998     case GX2_SURFACE_FORMAT_TC_R16_SINT:              return "GX2_SURFACE_FORMAT_TC_R16_SINT";              // 0x0305
999     case GX2_SURFACE_FORMAT_TC_R16_FLOAT:             return "GX2_SURFACE_FORMAT_TC_R16_FLOAT";             // 0x0806
1000     case GX2_SURFACE_FORMAT_TC_R8_G8_UNORM:           return "GX2_SURFACE_FORMAT_TC_R8_G8_UNORM";           // 0x0007
1001     case GX2_SURFACE_FORMAT_TC_R8_G8_UINT:            return "GX2_SURFACE_FORMAT_TC_R8_G8_UINT";            // 0x0107
1002     case GX2_SURFACE_FORMAT_TC_R8_G8_SNORM:           return "GX2_SURFACE_FORMAT_TC_R8_G8_SNORM";           // 0x0207
1003     case GX2_SURFACE_FORMAT_TC_R8_G8_SINT:            return "GX2_SURFACE_FORMAT_TC_R8_G8_SINT";            // 0x0307
1004     case GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM:       return "GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM";       // 0x0008
1005     case GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM:     return "GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM";     // 0x000a
1006     case GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM:     return "GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM";     // 0x000b
1007     case GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM:     return "GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM";     // 0x000c
1008     case GX2_SURFACE_FORMAT_TC_R32_UINT:              return "GX2_SURFACE_FORMAT_TC_R32_UINT";              // 0x010d
1009     case GX2_SURFACE_FORMAT_TC_R32_SINT:              return "GX2_SURFACE_FORMAT_TC_R32_SINT";              // 0x030d
1010     case GX2_SURFACE_FORMAT_TCD_R32_FLOAT:            return "GX2_SURFACE_FORMAT_TCD_R32_FLOAT";            // 0x080e
1011     case GX2_SURFACE_FORMAT_TC_R16_G16_UNORM:         return "GX2_SURFACE_FORMAT_TC_R16_G16_UNORM";         // 0x000f
1012     case GX2_SURFACE_FORMAT_TC_R16_G16_UINT:          return "GX2_SURFACE_FORMAT_TC_R16_G16_UINT";          // 0x010f
1013     case GX2_SURFACE_FORMAT_TC_R16_G16_SNORM:         return "GX2_SURFACE_FORMAT_TC_R16_G16_SNORM";         // 0x020f
1014     case GX2_SURFACE_FORMAT_TC_R16_G16_SINT:          return "GX2_SURFACE_FORMAT_TC_R16_G16_SINT";          // 0x030f
1015     case GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT:         return "GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT";         // 0x0810
1016     case GX2_SURFACE_FORMAT_D_D24_S8_UNORM:           return "GX2_SURFACE_FORMAT_D_D24_S8_UNORM";           // 0x0011
1017 //    case GX2_SURFACE_FORMAT_T_R24_UNORM_X8:           return "GX2_SURFACE_FORMAT_T_R24_UNORM_X8";           // 0x0011
1018     case GX2_SURFACE_FORMAT_T_X24_G8_UINT:            return "GX2_SURFACE_FORMAT_T_X24_G8_UINT";            // 0x0111
1019     case GX2_SURFACE_FORMAT_D_D24_S8_FLOAT:           return "GX2_SURFACE_FORMAT_D_D24_S8_FLOAT";           // 0x0811
1020     case GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT:     return "GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT";     // 0x0816
1021     case GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM: return "GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM"; // 0x0019
1022     case GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT:   return "GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT";   // 0x0119
1023     case GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM:  return "GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM";  // 0x0219
1024     case GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT:   return "GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT";   // 0x0319
1025     case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM:    return "GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM";    // 0x001a
1026     case GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT:      return "GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT";      // 0x011a
1027     case GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM:     return "GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM";     // 0x021a
1028     case GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT:      return "GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT";      // 0x031a
1029     case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB:     return "GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB";     // 0x041a
1030     case GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM: return "GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM"; // 0x001b
1031     case GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT:   return "GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT";   // 0x011b
1032     case GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24:  return "GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24";  // 0x081c
1033 //    case GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24:       return "GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24";       // 0x081c
1034     case GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24:        return "GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24";        // 0x011c
1035     case GX2_SURFACE_FORMAT_TC_R32_G32_UINT:          return "GX2_SURFACE_FORMAT_TC_R32_G32_UINT";          // 0x011d
1036     case GX2_SURFACE_FORMAT_TC_R32_G32_SINT:          return "GX2_SURFACE_FORMAT_TC_R32_G32_SINT";          // 0x031d
1037     case GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT:         return "GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT";         // 0x081e
1038     case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM"; // 0x001f
1039     case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT:  return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT";  // 0x011f
1040     case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM"; // 0x021f
1041     case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT:  return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT";  // 0x031f
1042     case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT"; // 0x0820
1043     case GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT:  return "GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT";  // 0x0122
1044     case GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT:  return "GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT";  // 0x0322
1045     case GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT: return "GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT"; // 0x0823
1046     case GX2_SURFACE_FORMAT_T_BC1_UNORM:              return "GX2_SURFACE_FORMAT_T_BC1_UNORM";              // 0x0031
1047     case GX2_SURFACE_FORMAT_T_BC1_SRGB:               return "GX2_SURFACE_FORMAT_T_BC1_SRGB";               // 0x0431
1048     case GX2_SURFACE_FORMAT_T_BC2_UNORM:              return "GX2_SURFACE_FORMAT_T_BC2_UNORM";              // 0x0032
1049     case GX2_SURFACE_FORMAT_T_BC2_SRGB:               return "GX2_SURFACE_FORMAT_T_BC2_SRGB";               // 0x0432
1050     case GX2_SURFACE_FORMAT_T_BC3_UNORM:              return "GX2_SURFACE_FORMAT_T_BC3_UNORM";              // 0x0033
1051     case GX2_SURFACE_FORMAT_T_BC3_SRGB:               return "GX2_SURFACE_FORMAT_T_BC3_SRGB";               // 0x0433
1052     case GX2_SURFACE_FORMAT_T_BC4_UNORM:              return "GX2_SURFACE_FORMAT_T_BC4_UNORM";              // 0x0034
1053     case GX2_SURFACE_FORMAT_T_BC4_SNORM:              return "GX2_SURFACE_FORMAT_T_BC4_SNORM";              // 0x0234
1054     case GX2_SURFACE_FORMAT_T_BC5_UNORM:              return "GX2_SURFACE_FORMAT_T_BC5_UNORM";              // 0x0035
1055     case GX2_SURFACE_FORMAT_T_BC5_SNORM:              return "GX2_SURFACE_FORMAT_T_BC5_SNORM";              // 0x0235
1056     case GX2_SURFACE_FORMAT_T_NV12_UNORM:             return "GX2_SURFACE_FORMAT_T_NV12_UNORM";             // 0x0081
1057     default:                                          return "invalid format";
1058     }
1059 }
1060 
1061 
1062 
1063