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 // demoGfx.h
14 //
15 // -----------------------------------------------------------------------------
16
17 #ifndef __DEMO_GFX_H__
18 #define __DEMO_GFX_H__
19
20 #include <cafe/demo.h>
21 #include <cafe/demo/demoGfxTypes.h>
22 #include <cafe/demo/demoGfxShader.h>
23 #include <cafe/gx2ut.h>
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 /// @addtogroup demoRender
30 /// @{
31
32 /// \brief The maximum length allowed for the asset directory passed with DEMO_ASSETS_DIR
33 #define MAX_ASSET_DIR_LEN 1000
34
35 /// \brief The maximum total length allowed for the asset's path in DEMOGfxLoadAssetFile
36 #define MAX_ASSET_DIR_FULL_LEN 2000
37
38 /// \brief Default color buffer for DEMOGfx (global)
39 extern GX2ColorBuffer DEMOColorBuffer;
40
41 /// \brief Default depth buffer for DEMOGfx (global)
42 extern GX2DepthBuffer DEMODepthBuffer;
43
44 /// \brief Default context state ptr for DEMOGfx (global)
45 extern GX2ContextState *DEMOContextState;
46
47 /// \brief Structure used to define an instance of DEMOGfx
48 typedef struct
49 {
50 /// \brief Context state ptr for DEMOGfx (instance)
51 GX2ContextState *contextState;
52
53 } DEMOGfxInstance;
54
55 /// \brief Memory allocator that allocates MEM1 for graphics
56 ///
57 /// This function calls \ref GX2NotifyMemAlloc which enables
58 /// various (future) debugging features.
59 void *DEMOGfxAllocMEM1(u32 size, u32 align);
60
61 /// \brief Memory allocator that allocates from the foreground bucket for graphics
62 ///
63 /// This function calls \ref GX2NotifyMemAlloc which enables
64 /// various (future) debugging features.
65 void *DEMOGfxAllocBucket(u32 size, u32 align);
66
67 /// \brief Memory allocator that allocates MEM2 for graphics
68 ///
69 /// This function calls \ref GX2NotifyMemAlloc which enables
70 /// various (future) debugging features.
71 void *DEMOGfxAllocMEM2(u32 size, u32 align);
72
73 /// \brief Free MEM1
74 ///
75 void DEMOGfxFreeMEM1(void * ptr);
76
77 /// \brief Free memory from the foreground bucket.
78 ///
79 void DEMOGfxFreeBucket(void * ptr);
80
81 /// \brief Free MEM2
82 ///
83 void DEMOGfxFreeMEM2(void * ptr);
84
85 /// \brief Initializes GX2 & AVM; sets up default render/depth/scan buffers.
86 ///
87 /// It must be called before calling any other GX2 functions.\n
88 /// The following arguments can be specified:\n
89 ///
90 /// -DEMO_WIDTH=n (set TV RT width to n) \n
91 /// -DEMO_HEIGHT=n (set TV RT height to n) \n
92 /// -DEMO_CB_FORMAT=str (set TV color buffer format to 8_8_8_8, 10_10_10_2, 2_10_10_10, 16_16_16_16F, or 32_32_32_32F) \n
93 /// -DEMO_SCAN_FORMAT=str (set TV scan-out buffer format to 8_8_8_8, 10_10_10_2, or 2_10_10_10) \n
94 /// -DEMO_DB_FORMAT=str (set TV depth buffer format to 16, 32F, 8_24, X24_8_32F) \n
95 /// -DEMO_AA_MODE=n (set TV AA mode to 0/1/2/3) \n
96 /// -DEMO_FONT_DISABLE (disables drawing of DEMOFont API)\n
97 ///
98 /// Set up defaults for all options are (1280/720/8_8_8_8/32F/no AA).\n
99 /// Unknown args are ignored, and the arg list is left unchanged.\n
100 ///
101 /// To configure the DRC, please see \ref DEMODRCInit.
102 ///
103 /// This function will call DEMOGfxMem1HeapInit(), which will allocate all available memory from the MEM1
104 /// frame heap and initialize the expanded heap used by DEMOGfxAllocMEM1().
105 ///
106 /// \param argc number of arguments
107 /// \param argv argument values
108 ///
109 /// \retval A pointer to the instance created by this function
110 DEMOGfxInstance* DEMOGfxInit(int argc, char *argv[]);
111
112 /// \brief Releases allocated buffers and shuts down GX2.
113 ///
114 void DEMOGfxShutdown(void);
115
116 /// \brief Releases foreground only resources and GX2.
117 ///
118 void DEMOGfxReleaseForeground(void);
119
120 /// \brief Re-acquires GX2 resources and prepares for rendering.
121 ///
122 void DEMOGfxAcquiredForeground(void);
123
124 /// \brief Get demo graphics running state
125 ///
126 /// \retval TRUE if \ref DEMOGfxInit() has been called; false otherwise.
127 BOOL DEMOGfxIsRunning(void);
128
129 /// Set demo gfx context to current.
130 /// Need to call this API before Drawing with demo gfx context created in DEMOGfxInit.
131 void DEMOGfxSetContextState(void);
132
133 /// \brief Currently, this function waits for the previously rendered frame to appear.
134 /// Functionality may change in the future.
135 ///
136 void DEMOGfxBeforeRender(void);
137
138 /// \brief Swaps the video (scan) buffers, requests new frame to be displayed.
139 /// Note that it does not wait for the new frame to appear.
140 ///
141 void DEMOGfxDoneRender(void);
142
143 /// \brief Wrapper for GX2DrawDone that works in the background and if
144 /// DEMOGfx has not been initialized.
145 ///
146 void DEMOGfxDrawDone(void);
147
148 /// \brief Synchronize rendering with video display/swap in a specific way
149 ///
150 /// This is a very important function that every app should include in some fashion.
151 /// It prevents the CPU and GPU from running too far ahead of the video display.
152 /// This function shows an example of how to specify a precise amount of
153 /// latency with respect to when video swap occurs.
154 ///
155 /// \param depth Number of frames rendering may run ahead of display
156 /// \param percent Additional fraction of a frame to wait after specified swap
157 /// (expressed as an integer 0...100 percent of the swap interval time)
158 void DEMOGfxWaitForSwap(u32 depth, u32 percent);
159
160 /// \brief Returns a string with the name of a given GX2 attrib format.
161 ///
162 const char *DEMOGfxGetAttribFormatName(GX2AttribFormat format);
163
164 /// \brief Returns a string with the name of a given GX2 surface format.
165 ///
166 const char *DEMOGfxGetSurfaceFormatName(GX2SurfaceFormat format);
167
168 /// \brief A helper function to reset render targets to DEMO buffers.
169 ///
DEMOGfxSetDefaultRenderTarget(void)170 GX2_INLINE void DEMOGfxSetDefaultRenderTarget(void) {
171 GX2UTDebugTagIndent("DEMOGfxSetDefaultRenderTarget()");
172 GX2SetColorBuffer(&DEMOColorBuffer, GX2_RENDER_TARGET_0);
173 GX2SetDepthBuffer(&DEMODepthBuffer);
174 GX2UTDebugTagUndent();
175 }
176
177 /// \brief Setting up special color buffer (e.g) multi-layered frame buffer
178 ///
179 /// \param colorBuffer Ptr to color buffer structure to initialize.
180 /// \param dim Desired dim for color buffer.
181 /// \param width Desired width for color buffer.
182 /// \param height Desired height for color buffer.
183 /// \param depth Desired depth for color buffer.
184 /// \param format Desired surface format for color buffer.
185 /// \param aa Desired AA mode for color buffer.
186 ///
DEMOGfxInitColorBufferEx(GX2ColorBuffer * colorBuffer,GX2SurfaceDim dim,u32 width,u32 height,u32 depth,GX2SurfaceFormat format,GX2AAMode aa)187 GX2_INLINE void DEMOGfxInitColorBufferEx(GX2ColorBuffer *colorBuffer,
188 GX2SurfaceDim dim,
189 u32 width, u32 height, u32 depth,
190 GX2SurfaceFormat format, GX2AAMode aa)
191 {
192 GX2UTDebugTagIndent("DEMOGfxInitColorBufferEx()");
193 GX2_CHECK_ENUM_RANGE(dim, GX2_SURFACE_DIM)
194 GX2_CHECK_ENUM_RANGE(format, GX2_SURFACE_FORMAT)
195 GX2_CHECK_ENUM_RANGE(aa, GX2_AA_MODE)
196
197 colorBuffer->surface.dim = dim;
198 colorBuffer->surface.width = width;
199 colorBuffer->surface.height = height;
200 colorBuffer->surface.depth = depth;
201 colorBuffer->surface.numMips = 1; // 1 means base level only
202 colorBuffer->surface.format = format;
203 colorBuffer->surface.aa = aa;
204 colorBuffer->surface.use = GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE;
205 colorBuffer->surface.tileMode = GX2_TILE_MODE_DEFAULT;
206 colorBuffer->surface.swizzle = 0;
207 colorBuffer->viewMip = 0;
208 colorBuffer->viewFirstSlice = 0;
209 colorBuffer->viewNumSlices = depth;
210 GX2CalcSurfaceSizeAndAlignment(&colorBuffer->surface);
211 GX2InitColorBufferRegs(colorBuffer);
212 GX2UTDebugTagUndent();
213 }
214
215 /// \brief Setting up special depth buffer (e.g) multi-layered frame buffer
216 ///
217 /// \param depthBuffer Ptr to depth buffer structure to initialize.
218 /// \param dim Desired dim for depth buffer.
219 /// \param width Desired width for depth buffer.
220 /// \param height Desired height for depth buffer.
221 /// \param depth Desired depth for depth buffer.
222 /// \param format Desired surface format for depth buffer.
223 /// \param aa Desired AA mode for depth buffer.
224 ///
DEMOGfxInitDepthBufferEx(GX2DepthBuffer * depthBuffer,GX2SurfaceDim dim,u32 width,u32 height,u32 depth,GX2SurfaceFormat format,GX2AAMode aa)225 GX2_INLINE void DEMOGfxInitDepthBufferEx(GX2DepthBuffer *depthBuffer,
226 GX2SurfaceDim dim,
227 u32 width, u32 height, u32 depth,
228 GX2SurfaceFormat format, GX2AAMode aa)
229 {
230 GX2UTDebugTagIndent("DEMOGfxInitDepthBufferEx()");
231 GX2_CHECK_ENUM_RANGE(dim, GX2_SURFACE_DIM)
232 GX2_CHECK_ENUM_RANGE(format, GX2_SURFACE_FORMAT)
233 GX2_CHECK_ENUM_RANGE(aa, GX2_AA_MODE)
234
235 depthBuffer->surface.dim = dim;
236 depthBuffer->surface.width = width;
237 depthBuffer->surface.height = height;
238 depthBuffer->surface.depth = depth;
239 depthBuffer->surface.numMips = 1; // 1 means base level only
240 depthBuffer->surface.format = format;
241 depthBuffer->surface.aa = aa;
242 depthBuffer->surface.use = ((format==GX2_SURFACE_FORMAT_D_D24_S8_UNORM) || (format==GX2_SURFACE_FORMAT_D_D24_S8_FLOAT)) ? GX2_SURFACE_USE_DEPTH_BUFFER : GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE;
243 depthBuffer->surface.tileMode = GX2_TILE_MODE_DEFAULT;
244 depthBuffer->surface.swizzle = 0;
245 depthBuffer->viewMip = 0;
246 depthBuffer->viewFirstSlice = 0;
247 depthBuffer->viewNumSlices = depth;
248 depthBuffer->clearDepth = 1.0f;
249 depthBuffer->clearStencil = 0;
250 GX2CalcSurfaceSizeAndAlignment(&depthBuffer->surface);
251 GX2InitDepthBufferRegs(depthBuffer);
252 GX2UTDebugTagUndent();
253 }
254
255 /// \brief Initializes the expanded heap for MEM1
256 ///
257 /// This function will allocate all available memory from the MEM1 frame heap and
258 /// initialize the expanded heap used by \ref DEMOGfxAllocMEM1.
259 /// This is normally called by \ref DEMOGfxInit.
260 /// A real game shouldn't use the expanded heap to manage MEM1, but for demos it should be fine.
261 ///
262 void DEMOGfxMem1HeapInit(void);
263
264 /// \brief Destroys the expanded heap for MEM1
265 ///
266 /// This function will destroy the expanded heap used by DEMOGfxAllocMEM1().
267 /// This is normally called by \ref DEMOGfxShutdown.
268 ///
269 void DEMOGfxMem1HeapDestroy(void);
270
271 /// \brief Initializes the expanded heap for the foreground bucket
272 ///
273 /// This function will initialize the expanded heap used by DEMOGfxAllocBucket().
274 /// This is normally called by \ref DEMOGfxInit.
275 ///
276 void DEMOGfxBucketHeapInit(void);
277
278 /// \brief Destroys the expanded heap for the foreground bucket
279 ///
280 /// This function will destroy the expanded heap used by DEMOGfxAllocBucket().
281 /// This is normally called by \ref DEMOGfxShutdown.
282 ///
283 void DEMOGfxBucketHeapDestroy(void);
284
285 /// \brief Creates a new instance of DEMOGfx
286 ///
287 /// This will create a new instance, in addition to setting the instance.
288 /// This is called by \ref DEMOGfxInit.
289 ///
290 DEMOGfxInstance* DEMOGfxAddInstance(void);
291
292 /// \brief Deletes an instance of DEMOGfx
293 ///
294 /// This is called by \ref DEMOGfxShutdown.
295 ///
296 /// \param instance The instance to be deleted
297 ///
298 void DEMOGfxDeleteInstance(DEMOGfxInstance *instance);
299
300 /// \brief Sets the instance of DEMOGfx
301 ///
302 /// \param instance The instance to use
303 ///
304 void DEMOGfxSetInstance(DEMOGfxInstance *instance);
305
306 /// \brief Gets the instance of DEMOGfx
307 DEMOGfxInstance* DEMOGfxGetInstance(void);
308
309 /// \brief Reads an asset from the asset directory into an automatically created and allocated buffer.
310 ///
311 /// File is automatically closed after it's read from.
312 /// Call \ref DEMOFree to free this buffer.
313 ///
314 /// This function is a wrapper for \ref DEMOFSSimpleRead.
315 ///
316 /// \param path File string name to read (full path is \<asset_dir>\<path>)
317 /// \param len Length of file returned here
318 ///
319 void* DEMOGfxLoadAssetFile(const char* path, u32* len);
320
321 /// \brief Open an asset file for reading.
322 ///
323 /// Opens a file for reading.
324 ///
325 /// This function is a wrapper for \ref DEMOFSOpenFile.
326 ///
327 /// \param path Pointer to file name to open
328 /// \param info Pointer to file information to use
329 ///
330 /// \retval DEMO_FS_RESULT_OK if it is ok.
331 /// \retval DEMO_FS_RESULT_PERMISSION if it is not permitted to open current file.
332 /// \retval DEMO_FS_RESULT_CORRUPTION if a file is corrupted.
333 /// \retval DEMO_FS_FATAL_ERROR if a fatal error occurs during a read, the function returns.
334 s32 DEMOGfxOpenAssetFile(const char* path, DEMOFSFileInfo* info);
335
336 /// \brief Gets the size of the opened asset file.
337 ///
338 /// Gets the size of a file opened with \ref DEMOGfxOpenAssetFile.
339 ///
340 /// This function is a wrapper for \ref DEMOFSGetLength.
341 ///
342 /// \param fileInfo File information of the file
343 /// \param length The file size. As a return value, this size may not always be a multiple of 32. For this reason, when preparing buffers for reading files, this value must be rounded up to a multiple of 32
344 ///
345 /// \retval DEMO_FS_RESULT_OK if it is successed.
346 /// \retval DEMO_FS_RESULT_FATAL_ERROR if a fatal error occurs during a read, the function returns.
347 s32 DEMOGfxGetAssetFileLength(const DEMOFSFileInfo* fileInfo, u32* length);
348
349 /// \brief Synchronously reads from the opened asset file.
350 ///
351 /// Synchronously reads data from a file. First opens the file with the DEMOGfxOpenAssetFile function.
352 ///
353 /// This function is a wrapper for \ref DEMOFSRead.
354 ///
355 /// \param fileInfo File information of the file.
356 /// \param addr Buffer address. Must be \c PPC_IO_BUFFER_ALIGN byte aligned.
357 /// \param length Number of bytes to read. Must be a multiple of 32.
358 /// \param offset File position to start reading from. Must be a multiple of 4.
359 ///
360 /// \retval DEMO_FS_RESULT_OK if it is ok.
361 /// \retval DEMO_FS_RESULT_ACCESS if it is no right to access file.
362 /// \retval DEMO_FS_RESULT_CORRUPTION if a file is corrupted.
363 /// \retval DEMO_FS_FATAL_ERROR if a fatal error occurs during a read, the function returns.
364 s32 DEMOGfxReadAssetFile(DEMOFSFileInfo* fileInfo, void* addr, s32 length, s32 offset);
365
366 /// \brief Closes the asset file.
367 ///
368 /// Closes the specified file.
369 /// if the FS library is not expecting a call (for example, during transfer) to the DEMOGfxCloseAssetFile function, the call to the function takes time.
370 /// Ensure that this situation doesn't occur.
371 /// (Namely, when calling DEMOGfxCloseAssetFile, make sure the transfer is complete.)
372 ///
373 /// This function is a wrapper for \ref DEMOFSCloseFile.
374 ///
375 /// \param fileInfo File information for the file to close.
376 ///
377 /// \retval DEMO_FS_RESULT_OK if it is ok.
378 /// \retval DEMO_FS_RESULT_CORRUPTION if a file is corrupted.
379 /// \retval DEMO_FS_FATAL_ERROR if a fatal error occurs during a read, the function returns.
380 s32 DEMOGfxCloseAssetFile(DEMOFSFileInfo* fileInfo);
381
382 /// \brief Reads an asset from the asset directory into an automatically created and allocated buffer.
383 ///
384 /// This buffer is aligned with alignSize.
385 /// File is automatically closed after it's read from.
386 /// Call \ref DEMOFree to free this buffer.
387 ///
388 /// This function is a wrapper for \ref DEMOFSSimpleReadAlign.
389 ///
390 /// \param path File string name to read (full path is \<asset_dir\>\<path\>)
391 /// \param len Length of file returned here
392 /// \param alignSize The alignment to use
393 ///
394 void* DEMOGfxLoadAssetFileAlign(const char* path, u32* len, u32 alignSize);
395
396 /// \brief Scans directory for all the assets in it.
397 ///
398 /// This returns a list of the names of all the files in a directory. Subdirectories
399 /// are automatically excluded. Pathnames are returned, suitable for passing directly
400 /// to \ref DEMOGfxOpenAssetFile or \ref DEMOGfxLoadAssetFile.
401 ///
402 /// This function is a wrapper for \ref DEMOFSSimpleScanDir.
403 ///
404 /// \param path Directory name
405 /// \param pFileCount Number of files in the directory
406 /// \param maxFiles Maximum number of file names to return from this function
407 /// \param ppFileNames Returned array of names of files. The base array must be specified
408 /// by the caller. (e.g char *ppFileNames[maxFiles]; )
409 /// Each non null string is allocated using \ref DEMOAlloc in this routine.
410 /// Call \ref DEMOFree in caller to free them.
411 /// \return DEMO_FS_RESULT_OK on success, or error value.
412 s32 DEMOGfxScanAssetDir(const char *path, u32 *pFileCount, u32 maxFiles, char** ppFileNames);
413
414 /// \brief Determines whether a file exists
415 ///
416 /// This function can be used prior to \ref DEMOGfxLoadAssetFile to error out without
417 /// asserting if the file does not exist.
418 ///
419 /// This function is a wrapper for \ref DEMOFSFileExists.
420 ///
421 /// \param path Pointer to the name of the file
422 ///
423 /// \retval TRUE if the file exists.
424 /// \retval FALSE if the file does not exist.
425 BOOL DEMOGfxFileExists(const char* path);
426
427 /// \brief Structure used to manage GPU Tasks
428 typedef struct _DEMOGfxGPUTask
429 {
430 void *pDLPatchLoc; /// pointer to the nop patch space within the dl epilogue
431 u64 timeVal; /// our key, used for lookups
432 struct _DEMOGfxGPUTask *next; /// simple linked list
433
434 } DEMOGfxGPUTask;
435
436 /// \brief Memory location used by GPU Task Management
437 extern u32 gDemoGfxGPUFence;
438
439 /// \brief Timestamp used by GPU Task Management
440 extern u64 *gpDemoGfxGPUTs;
441
442 /// \brief Bit used to differentiate GPUTask TimeStamps, set for End TimeStamp
443 #define DEMO_GPU_TASK_END_TS (1ull << 63ull)
444
445 /// \brief Given a display list, writes the DEMOGfxGPUTask prologue
446 ///
447 /// \retval NULL if GPU Task Creation fails
448 /// \retval Address of new GPU Task if successful
449 ///
450 DEMOGfxGPUTask* DEMOGfxBeginGPUTask();
451
452 /// \brief Given a display list, writes the DEMOGfxGPUTask epilogue
453 ///
454 void DEMOGfxEndGPUTask();
455
456 /// \brief Insert a call to a new GPU Task in the epilogue of the task currently
457 /// being executed by the GPU
458 ///
459 /// \param pDisplayList Display list to be executed
460 /// \param byteSize Size of the display list
461 ///
462 void DEMOGfxInsertGPUTask(void *pDisplayList, u32 byteSize);
463
464 /// \brief Frees one GPUTaskHandle, used to prune DEMO's list of GPU Tasks
465 ///
466 /// \param pTask GPU Task to be freed
467 ///
468 void DEMOGfxFreeGPUTask(DEMOGfxGPUTask *pTask);
469
470 /// \brief Frees entire GPUTaskHandle list, used to clobber DEMO's list of GPU Tasks
471 ///
472 void DEMOGfxFreeGPUTasks(void);
473
474
475 /// @} // demoGfx
476
477 #ifdef __cplusplus
478 }
479 #endif
480
481 #endif /// __DEMO_GFX_H__
482