1 /*---------------------------------------------------------------------------*
2
3 Copyright (C) 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 /// DEMODRC.c
14 ///
15 /// This is DRC system code for the DEMO library.
16 ///
17 ////===========================================================================
18
19 #include <cafe/demo.h>
20 #include <cafe/gx2.h>
21 #include <cafe/procui.h>
22 #include <cafe/camera/camera.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 #define _DEMO_NUM_DRC 2
28
29 GX2ColorBuffer DEMODRCColorBuffer;
30 GX2DepthBuffer DEMODRCDepthBuffer;
31 void *DEMODRCScanBufferPtr;
32
33 // DEMO Gfx Context State
34 GX2ContextState *DEMODRCContextState;
35
36 static BOOL gDemoDRCRunningFlag = FALSE;
37 static BOOL gDemoDRCOutputEnabled = FALSE;
38
39 extern BOOL gDemoGfxInForeground;
40
41 // State set at init time that needs to be used to reacquire foreground.
42 static GX2DRCMode gDemoDRCRenderMode;
43 static GX2SurfaceFormat gDemoDRCScanOutCBFormat;
44 static u32 gDemoDRCScanSize;
45
46 // Other preserved items
47 static u32 gDemoDRCRenderWidth;
48 static u32 gDemoDRCRenderHeight;
49
50 // Instance
51 static DEMODRCInstance* gDemoDRCCurInstance = NULL;
52
DEMODRCCallbackAcquiredForeground(void * unused)53 static u32 DEMODRCCallbackAcquiredForeground(void* unused)
54 {
55 DEMODRCAcquiredForeground();
56
57 // No issues
58 return 0;
59 }
60
DEMODRCCallbackReleaseForeground(void * unused)61 static u32 DEMODRCCallbackReleaseForeground(void* unused)
62 {
63 DEMODRCReleaseForeground();
64
65 // No issues
66 return 0;
67 }
68
DEMODRCInit(int argc,char * argv[])69 DEMODRCInstance* DEMODRCInit(int argc, char *argv[])
70 {
71 void *ptr;
72
73 u32 scanSize;
74 GX2Boolean scaleNeeded;
75
76 u32 i;
77 char *p;
78 u32 renderWidth = 854;
79 u32 renderHeight = 480;
80 // Default to SRGB for gamma
81 GX2SurfaceFormat renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
82 GX2SurfaceFormat scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
83 GX2SurfaceFormat renderDBFormat = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
84 GX2AAMode renderAAMode = GX2_AA_MODE_1X;
85 GX2DRCMode renderMode = GX2_DRC_SINGLE;
86
87 #define SKIP_NON_DIGIT(c) ((c)!=0&&((c)<'0'||(c)>'9'))
88
89 // Analyze arguments
90 // Note that all arguments might be in a single string!
91 for (i = 0; i < argc; ++i)
92 {
93 p = strstr(argv[i], "DEMO_DRC_WIDTH");
94 if (p != 0){
95 renderWidth = (u32)atoi(p+14+SKIP_NON_DIGIT(p[14]));
96 }
97 p = strstr(argv[i], "DEMO_DRC_HEIGHT");
98 if (p != 0){
99 renderHeight = (u32)atoi(p+15+SKIP_NON_DIGIT(p[15]));
100 }
101 p = strstr(argv[i], "DEMO_DRC_CB_FORMAT");
102 if (p != 0){
103 p = p+18+SKIP_NON_DIGIT(p[18]);
104 if(strncmp(p, "10_10_10_2", 10) == 0){
105 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM;
106 } else if(strncmp(p, "2_10_10_10", 10) == 0){
107 renderCBFormat = GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM;
108 } else if(strncmp(p, "8_8_8_8_SRGB", 12) == 0){
109 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
110 } else if(strncmp(p, "8_8_8_8", 7) == 0){
111 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM;
112 } else if(strncmp(p, "16_16_16_16F", 12) == 0){
113 renderCBFormat = GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT;
114 } else if(strncmp(p, "32_32_32_32F", 12) == 0){
115 renderCBFormat = GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT;
116 } else {
117 DEMOPrintf("Unrecognized CB format: %s\n",p);
118 }
119 }
120 p = strstr(argv[i], "DEMO_DRC_SCAN_FORMAT");
121 if (p != 0){
122 p = p+20+SKIP_NON_DIGIT(p[20]);
123 if(strncmp(p, "10_10_10_2", 10) == 0){
124 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM;
125 }else if(strncmp(p, "2_10_10_10", 10) == 0){
126 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM;
127 }else if(strncmp(p, "8_8_8_8_SRGB", 12) == 0){
128 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
129 }else if(strncmp(p, "8_8_8_8", 7) == 0){
130 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM;
131 } else {
132 DEMOPrintf("Unrecognized SCAN format: %s\n",p);
133 }
134 }
135 p = strstr(argv[i], "DEMO_DRC_DB_FORMAT");
136 if (p != 0){
137 p = p+18+SKIP_NON_DIGIT(p[18]);
138 if(strncmp(p, "16", 2) == 0){
139 renderDBFormat = GX2_SURFACE_FORMAT_TCD_R16_UNORM;
140 }else if(strncmp(p, "8_24F", 5) == 0){
141 renderDBFormat = GX2_SURFACE_FORMAT_D_D24_S8_FLOAT;
142 }else if(strncmp(p, "8_24", 4) == 0){
143 renderDBFormat = GX2_SURFACE_FORMAT_D_D24_S8_UNORM;
144 }else if(strncmp(p, "X24_8_32F", 9) == 0){
145 renderDBFormat = GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24;
146 }else if(strncmp(p, "32F", 3) == 0){
147 renderDBFormat = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
148 } else {
149 DEMOPrintf("Unrecognized DB format: %s\n",p);
150 }
151 }
152 p = strstr(argv[i], "DEMO_DRC_AA_MODE");
153 if (p != 0){
154 renderAAMode = (GX2AAMode)atoi(p+16+SKIP_NON_DIGIT(p[16]));
155 GX2_CHECK_ENUM_RANGE(renderAAMode, GX2_AA_MODE)
156 }
157 p = strstr(argv[i], "DEMO_DRC_MODE");
158 if (p != 0){
159 renderMode = (GX2DRCMode)atoi(p+13);
160 GX2_CHECK_ENUM_RANGE(renderMode, GX2_DRC)
161 }
162 }
163
164 char *aaStr[4]={ "1X", "2X", "4X", "8X" };
165 char *modeStr[4]={ "none", "Single", "Double", "Single 30Hz"};
166
167 DEMOPrintf("DEMO: Rendering DRC:%dx%d CB:%s DB:%s ScanCB:%s AA:%s Mode:%s\n",
168 renderWidth, renderHeight,
169 &DEMOGfxGetSurfaceFormatName(renderCBFormat)[19],
170 &DEMOGfxGetSurfaceFormatName(renderDBFormat)[19],
171 &DEMOGfxGetSurfaceFormatName(scanOutCBFormat)[19],
172 aaStr[renderAAMode], modeStr[renderMode]);
173
174 // Setup Scan Buffers
175 GX2CalcDRCSize(renderMode, scanOutCBFormat,
176 GX2_BUFFERING_DOUBLE, &scanSize, &scaleNeeded);
177
178 // For Cafe, should put scan buffers in the foreground bucket
179 DEMODRCScanBufferPtr = DEMOGfxAllocBucket(scanSize, GX2_SCAN_BUFFER_ALIGNMENT);
180 DEMOCheck(DEMODRCScanBufferPtr!=NULL, "DRC Scan buffer alloc failed");
181 GX2Invalidate(GX2_INVALIDATE_CPU, DEMODRCScanBufferPtr, scanSize);
182
183 GX2SetDRCBuffer(DEMODRCScanBufferPtr, scanSize, renderMode,
184 scanOutCBFormat, GX2_BUFFERING_DOUBLE);
185
186 // Setup render buffer
187 GX2InitColorBuffer(&DEMODRCColorBuffer,
188 renderWidth, renderHeight,
189 renderCBFormat,
190 renderAAMode);
191
192 ptr = DEMOGfxAllocMEM1(DEMODRCColorBuffer.surface.imageSize,
193 DEMODRCColorBuffer.surface.alignment);
194 DEMOCheck(ptr!=NULL, "DRC Color buffer alloc failed");
195 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODRCColorBuffer.surface.imageSize);
196
197 GX2InitColorBufferPtr(&DEMODRCColorBuffer, ptr);
198
199 // Setup aux buffer
200 if (DEMODRCColorBuffer.surface.aa != GX2_AA_MODE_1X) {
201 u32 size, align;
202 GX2CalcColorBufferAuxInfo(&DEMODRCColorBuffer, &size, &align);
203 ptr = DEMOGfxAllocMEM1(size, align);
204 DEMOCheck(ptr!=NULL, "DRC Color aux buffer alloc failed");
205 GX2InitColorBufferAuxPtr(&DEMODRCColorBuffer, ptr);
206 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
207 // Aux buffer must be cleared manually to this value once:
208 GX2UTSetupColorAuxBuffer(&DEMODRCColorBuffer);
209 }
210
211 // Setup Depth Buffer
212 GX2InitDepthBuffer(&DEMODRCDepthBuffer,
213 renderWidth, renderHeight,
214 renderDBFormat,
215 renderAAMode);
216 ptr = DEMOGfxAllocMEM1(DEMODRCDepthBuffer.surface.imageSize,
217 DEMODRCDepthBuffer.surface.alignment);
218 DEMOCheck(ptr!=NULL, "DRC Depth buffer alloc failed");
219 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODRCDepthBuffer.surface.imageSize);
220 GX2InitDepthBufferPtr(&DEMODRCDepthBuffer, ptr);
221
222 // Setup Hi-Z buffer
223 if (1) { // Allow testing with & without Hi-Z
224 u32 size, align;
225 GX2CalcDepthBufferHiZInfo(&DEMODRCDepthBuffer, &size, &align);
226 ptr = DEMOGfxAllocMEM1(size, align);
227 DEMOCheck(ptr!=NULL, "DRC Depth Hi-Z buffer alloc failed");
228 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
229 GX2InitDepthBufferHiZPtr(&DEMODRCDepthBuffer, ptr);
230 }
231
232 // Register a callback upon foreground acquire and release
233 ProcUIRegisterCallback(PROCUI_MESSAGE_ACQUIRE, DEMODRCCallbackAcquiredForeground, NULL, 200);
234 ProcUIRegisterCallback(PROCUI_MESSAGE_RELEASE, DEMODRCCallbackReleaseForeground, NULL, 200);
235
236 // Save state for DEMODRCAcquireForeground
237 gDemoDRCRenderMode = renderMode;
238 gDemoDRCScanOutCBFormat = scanOutCBFormat;
239 gDemoDRCScanSize = scanSize;
240
241 // Save state for instancing
242 gDemoDRCRenderWidth = renderWidth;
243 gDemoDRCRenderHeight = renderHeight;
244
245 // Create a new instance (including the context state)
246 gDemoDRCCurInstance = NULL;
247 DEMODRCAddInstance();
248
249 // Indicate that graphics has been started
250 gDemoDRCRunningFlag = TRUE;
251
252 return gDemoDRCCurInstance;
253 }
254
DEMODRCShutdown()255 void DEMODRCShutdown()
256 {
257 // Delete the instances
258 DEMODRCDeleteInstance(gDemoDRCCurInstance);
259
260 gDemoDRCOutputEnabled = FALSE;
261
262 // Disable video outputs if this process is in the foreground.
263 if (gDemoGfxInForeground && OS_SHUTDOWN_RESTART != OSGetShutdownReason())
264 {
265 GX2SetDRCEnable(GX2_FALSE);
266 }
267
268 // Free allocated buffers
269 DEMOGfxFreeBucket(DEMODRCScanBufferPtr);
270 if (DEMODRCDepthBuffer.hiZPtr) {
271 DEMOGfxFreeMEM1(DEMODRCDepthBuffer.hiZPtr);
272 DEMODRCDepthBuffer.hiZPtr = NULL;
273 }
274 DEMOGfxFreeMEM1(DEMODRCDepthBuffer.surface.imagePtr);
275 if (DEMODRCColorBuffer.auxPtr) {
276 DEMOGfxFreeMEM1(DEMODRCColorBuffer.auxPtr);
277 DEMODRCColorBuffer.auxPtr = NULL;
278 }
279 DEMOGfxFreeMEM1(DEMODRCColorBuffer.surface.imagePtr);
280
281 gDemoDRCRunningFlag = FALSE;
282 }
283
DEMODRCReleaseForeground()284 void DEMODRCReleaseForeground()
285 {
286 if (DEMODRCDepthBuffer.hiZPtr) {
287 DEMOGfxFreeMEM1(DEMODRCDepthBuffer.hiZPtr);
288 DEMODRCDepthBuffer.hiZPtr = NULL;
289 }
290 DEMOGfxFreeMEM1(DEMODRCDepthBuffer.surface.imagePtr);
291 if (DEMODRCColorBuffer.auxPtr) {
292 DEMOGfxFreeMEM1(DEMODRCColorBuffer.auxPtr);
293 DEMODRCColorBuffer.auxPtr = NULL;
294 }
295 DEMOGfxFreeMEM1(DEMODRCColorBuffer.surface.imagePtr);
296
297 DEMOGfxFreeBucket(DEMODRCScanBufferPtr);
298
299 gDemoDRCOutputEnabled = FALSE;
300 }
301
DEMODRCAcquiredForeground()302 void DEMODRCAcquiredForeground()
303 {
304 void * ptr;
305
306 // For Cafe, should put scan buffers in the foreground bucket
307 DEMODRCScanBufferPtr = DEMOGfxAllocBucket(gDemoDRCScanSize, GX2_SCAN_BUFFER_ALIGNMENT);
308 GX2Invalidate(GX2_INVALIDATE_CPU, DEMODRCScanBufferPtr, gDemoDRCScanSize);
309
310 GX2SetDRCBuffer(DEMODRCScanBufferPtr, gDemoDRCScanSize, gDemoDRCRenderMode,
311 gDemoDRCScanOutCBFormat, GX2_BUFFERING_DOUBLE);
312
313 // Re-allocate color buffer
314 ptr = DEMOGfxAllocMEM1(DEMODRCColorBuffer.surface.imageSize,
315 DEMODRCColorBuffer.surface.alignment);
316 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODRCColorBuffer.surface.imageSize);
317
318 GX2InitColorBufferPtr(&DEMODRCColorBuffer, ptr);
319
320 // Setup aux buffer
321 if (DEMODRCColorBuffer.surface.aa != GX2_AA_MODE_1X) {
322 u32 size, align;
323 GX2CalcColorBufferAuxInfo(&DEMODRCColorBuffer, &size, &align);
324 ptr = DEMOGfxAllocMEM1(size, align);
325 GX2InitColorBufferAuxPtr(&DEMODRCColorBuffer, ptr);
326 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
327 // Aux buffer must be cleared manually to this value once:
328 GX2UTSetupColorAuxBuffer(&DEMODRCColorBuffer);
329 }
330
331 // Re-allocate depth buffer
332 ptr = DEMOGfxAllocMEM1(DEMODRCDepthBuffer.surface.imageSize,
333 DEMODRCDepthBuffer.surface.alignment);
334 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODRCDepthBuffer.surface.imageSize);
335 GX2InitDepthBufferPtr(&DEMODRCDepthBuffer, ptr);
336
337 // Setup Hi-Z buffer
338 if (1) { // Allow testing with & without Hi-Z
339 u32 size, align;
340 GX2CalcDepthBufferHiZInfo(&DEMODRCDepthBuffer, &size, &align);
341 ptr = DEMOGfxAllocMEM1(size, align);
342 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
343 GX2InitDepthBufferHiZPtr(&DEMODRCDepthBuffer, ptr);
344 }
345
346 GX2SetContextState(DEMODRCContextState);
347
348 // Force the next call to DEMODRCDoneRender to enable DRC output.
349 gDemoDRCOutputEnabled = FALSE;
350 }
351
DEMODRCIsRunning()352 BOOL DEMODRCIsRunning()
353 {
354 return gDemoDRCRunningFlag;
355 }
356
DEMODRCGetStatus()357 GX2DRCMode DEMODRCGetStatus()
358 {
359 return GX2GetSystemDRCMode();
360 }
361
DEMODRCSetContextState(void)362 void DEMODRCSetContextState(void)
363 {
364 GX2SetContextState(DEMODRCContextState);
365 }
366
DEMODRCBeforeRender(void)367 void DEMODRCBeforeRender(void)
368 {
369 // Set DRC Context
370 GX2SetContextState(DEMODRCContextState);
371 }
372
DEMODRCDoneRender(void)373 void DEMODRCDoneRender(void)
374 {
375 // Copy Color Buffer to DRC SCAN Buffer
376 GX2CopyColorBufferToScanBuffer(&DEMODRCColorBuffer, GX2_SCAN_TARGET_DRC_FIRST);
377
378 // Restore Demo context state after copy
379 DEMOGfxSetContextState();
380
381 // Enable video output after first frame rendered
382 if (gDemoDRCOutputEnabled == FALSE) {
383 GX2SetDRCEnable(GX2_TRUE);
384 gDemoDRCOutputEnabled = TRUE;
385 }
386 }
387
388
DEMODRCAddInstance(void)389 DEMODRCInstance* DEMODRCAddInstance(void)
390 {
391 // Setup Context State buffer
392 DEMODRCContextState = DEMOGfxAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
393 DEMOCheck(DEMODRCContextState != NULL, "DRC Context state buffer alloc failed");
394 // GX2SetupContextState will invalidate CPU cache for us
395 GX2SetupContextState(DEMODRCContextState);
396
397 // Setup render/depth buffers to be used now
398 GX2SetColorBuffer(&DEMODRCColorBuffer, GX2_RENDER_TARGET_0);
399 GX2SetDepthBuffer(&DEMODRCDepthBuffer);
400
401 // Misc graphics setup
402 GX2SetViewport(0, 0, (f32)gDemoDRCRenderWidth, (f32)gDemoDRCRenderHeight, 0.0f, 1.0f);
403 GX2SetScissor(0, 0, gDemoDRCRenderWidth, gDemoDRCRenderHeight);
404 GX2SetDRCScale(gDemoDRCRenderWidth, gDemoDRCRenderHeight);
405
406 /////////////////////////////////////////////////////////////////////////////
407 // Create the new instance
408 gDemoDRCCurInstance = DEMOAlloc(sizeof(DEMODRCInstance));
409 gDemoDRCCurInstance->contextState = DEMODRCContextState;
410
411 return gDemoDRCCurInstance;
412 }
413
DEMODRCDeleteInstance(DEMODRCInstance * instance)414 void DEMODRCDeleteInstance(DEMODRCInstance *instance)
415 {
416 DEMOGfxFreeMEM2(instance->contextState);
417 DEMOFree(instance);
418
419 // Edge case: delete current
420 if (gDemoDRCCurInstance == instance) {
421 gDemoDRCCurInstance = NULL;
422 DEMODRCContextState = NULL;
423 }
424 }
425
426
DEMODRCSetInstance(DEMODRCInstance * instance)427 void DEMODRCSetInstance(DEMODRCInstance *instance)
428 {
429 gDemoDRCCurInstance = instance;
430
431 DEMODRCContextState = instance->contextState;
432 GX2SetContextState(DEMODRCContextState);
433 }
434
DEMODRCGetInstance(void)435 DEMODRCInstance* DEMODRCGetInstance(void)
436 {
437 return gDemoDRCCurInstance;
438 }
439