1 /*---------------------------------------------------------------------------*
2 
3   Copyright (C) 2010-2011 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 // gx2Misc.h
14 //
15 // Declares misc function prototypes for gx2 library.
16 
17 #ifndef _CAFE_GX2_MISC_H_
18 #define _CAFE_GX2_MISC_H_
19 
20 #if !(defined _WIN32 || defined _WIN64)
21 #include <cafe/mem.h>
22 #endif
23 
24 #ifdef __cplusplus
25 extern "C"
26 {
27 #endif // __cplusplus
28 
29 /// @addtogroup GX2UTComponentGroup
30 /// @{
31 
32 // -----------------
33 // Types that are used in multiple areas
34 
35 /// \brief Used to define a component (swap/routing) selection set
36 ///
37 /// Use the macros in \ref GX2UTComponentGroup to create or decode a selection.
38 /// There are also predefined variables to use for common selections.
39 ///
40 typedef u32 GX2CompSel;
41 
42 /// \brief Macro to get X_R component from a component selection set
43 ///
44 #define GX2_GET_COMPONENT_X_R(v)  (((v)>>24)&0xff)
45 
46 /// \brief Macro to get Y_G component from a component selection set
47 ///
48 #define GX2_GET_COMPONENT_Y_G(v)  (((v)>>16)&0xff)
49 
50 /// \brief Macro to get Z_B component from a component selection set
51 ///
52 #define GX2_GET_COMPONENT_Z_B(v)  (((v)>> 8)&0xff)
53 
54 /// \brief Macro to get W_A component from a component selection set
55 ///
56 #define GX2_GET_COMPONENT_W_A(v)  (((v)>> 0)&0xff)
57 
58 /// \brief Macro to assemble a component selection set from individual components
59 ///
60 #define GX2_GET_COMP_SEL(x,y,z,w) ((((x)&0xff)<<24)|(((y)&0xff)<<16)|(((z)&0xff)<<8)|((w)&0xff))
61 
62 /// \brief Predefined component select (0,0,0,1) or (0,0,0,1)
63 #define GX2_COMP_SEL_NONE GX2_GET_COMP_SEL(GX2_COMPONENT_C_0,GX2_COMPONENT_C_0,GX2_COMPONENT_C_0,GX2_COMPONENT_C_1)
64 
65 /// \brief Predefined component select (X,0,0,1) or (R,0,0,1)
66 #define GX2_COMP_SEL_X001 GX2_GET_COMP_SEL(GX2_COMPONENT_X_R,GX2_COMPONENT_C_0,GX2_COMPONENT_C_0,GX2_COMPONENT_C_1)
67 
68 /// \brief Predefined component select (X,Y,0,1) or (R,G,0,1)
69 #define GX2_COMP_SEL_XY01 GX2_GET_COMP_SEL(GX2_COMPONENT_X_R,GX2_COMPONENT_Y_G,GX2_COMPONENT_C_0,GX2_COMPONENT_C_1)
70 
71 /// \brief Predefined component select (X,Y,Z,1) or (R,G,B,1)
72 #define GX2_COMP_SEL_XYZ1 GX2_GET_COMP_SEL(GX2_COMPONENT_X_R,GX2_COMPONENT_Y_G,GX2_COMPONENT_Z_B,GX2_COMPONENT_C_1)
73 
74 /// \brief Predefined component select (X,Y,Z,W) or (R,G,B,A)
75 #define GX2_COMP_SEL_XYZW GX2_GET_COMP_SEL(GX2_COMPONENT_X_R,GX2_COMPONENT_Y_G,GX2_COMPONENT_Z_B,GX2_COMPONENT_W_A)
76 
77 /// \brief Predefined component select (X,X,X,X) or (R,R,R,R)
78 #define GX2_COMP_SEL_XXXX GX2_GET_COMP_SEL(GX2_COMPONENT_X_R,GX2_COMPONENT_X_R,GX2_COMPONENT_X_R,GX2_COMPONENT_X_R)
79 
80 /// \brief Predefined component select (Y,Y,Y,Y) or (G,G,G,G)
81 #define GX2_COMP_SEL_YYYY GX2_GET_COMP_SEL(GX2_COMPONENT_Y_G,GX2_COMPONENT_Y_G,GX2_COMPONENT_Y_G,GX2_COMPONENT_Y_G)
82 
83 /// \brief Predefined component select (Z,Z,Z,Z) or (B,B,B,B)
84 #define GX2_COMP_SEL_ZZZZ GX2_GET_COMP_SEL(GX2_COMPONENT_Z_B,GX2_COMPONENT_Z_B,GX2_COMPONENT_Z_B,GX2_COMPONENT_Z_B)
85 
86 /// \brief Predefined component select (W,W,W,W) or (A,A,A,A)
87 #define GX2_COMP_SEL_WWWW GX2_GET_COMP_SEL(GX2_COMPONENT_W_A,GX2_COMPONENT_W_A,GX2_COMPONENT_W_A,GX2_COMPONENT_W_A)
88 
89 /// \brief Predefined component select (W,Z,Y,X) or (A,B,G,R)
90 #define GX2_COMP_SEL_WZYX GX2_GET_COMP_SEL(GX2_COMPONENT_W_A,GX2_COMPONENT_Z_B,GX2_COMPONENT_Y_G,GX2_COMPONENT_X_R)
91 
92 /// \brief Predefined component select (W,X,Y,Z) or (A,R,G,B)
93 #define GX2_COMP_SEL_WXYZ GX2_GET_COMP_SEL(GX2_COMPONENT_W_A,GX2_COMPONENT_X_R,GX2_COMPONENT_Y_G,GX2_COMPONENT_Z_B);
94 
95 /// @}
96 /// @addtogroup GX2UTHelperGroup
97 /// @{
98 
99 // -----------------
100 // Utility #defines
101 
102 /// \brief Swap byte order in a 32-bit int.
103 ///
104 #define GX2_SWAP_8_IN_32(x) \
105     ( (((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000) )
106 
107 /// \brief Swap byte order in a 16-bit int.
108 ///
109 /// Note: x must already be cast to a 16-bit int-type.
110 ///
111 #define GX2_SWAP_8_IN_16(x) \
112     ( ((x) >> 8) | ((x) << 8) )
113 
114 /// \brief Swap 16-bit word order in a 32-bit int.
115 ///
116 /// Note: x must already be cast to a 32-bit int-type.
117 ///
118 #define GX2_SWAP_16_IN_32(x) \
119     ( ((x) >> 16) | ((x) << 16) )
120 
121 /// \brief Swap byte order in a 64-bit int.
122 ///
123 /// \note 0xffull is a 64-bit constant = 0xff
124 #define GX2_SWAP_8_IN_64(x) \
125     ((((x)>>56)&(0xffull<< 0))|(((x)>>40)&(0xffull<< 8))|(((x)>>24)&(0xffull<<16))|(((x)>> 8)&(0xffull<<24))| \
126      (((x)<< 8)&(0xffull<<32))|(((x)<<24)&(0xffull<<40))|(((x)<<40)&(0xffull<<48))|(((x)<<56)&(0xffull<<56)))
127 
128 /// \brief Utility function to copy and endian-swap a given range of bytes.
129 /// It performs a 8-in-32 swap while copying u32 units from source to dest.
130 /// For best results, you should also call DCZeroRange() on the dest first
131 /// (this can only be done when the range is 32-byte aligned in location and
132 /// size, though).
133 ///
134 /// \param dst     Start of the given dest buffer range to copy and swap
135 /// \param src     Start of the given src buffer range
136 /// \param byteLen Length of the given range specified in bytes. Must be a multiple of 4.
137 ///
138 /// \donotcall \threadsafe \enddonotcall
139 ///
GX2CopyEndianSwap(void * dst,const void * src,u32 byteLen)140 GX2_INLINE void GX2CopyEndianSwap(void *dst, const void *src, u32 byteLen)
141 {
142     ASSERT((byteLen % sizeof(u32))==0);
143 #if !(defined _WIN32 || defined _WIN64)
144     u32 i;
145     u32 *csrc = (u32 *) src;
146     __bytereversed u32 *cdst = (__bytereversed u32 *) dst;
147     for(i=0; i<(byteLen>>2); i++) cdst[i] = csrc[i];
148 #else
149     {
150         u32* csrc = (u32*)src;
151         u32* cdst = (u32*)dst;
152         u32 i;
153         for (i=0; i<byteLen>>2; i++)
154         {
155             cdst[i] = GX2_SWAP_8_IN_32(csrc[i]);
156         }
157     }
158 #endif
159 }
160 
161 /// \brief Utility function to endian-swap a given range of bytes. 8-in-32 swap is done in-place.
162 ///
163 /// \note Length is given in bytes to mirror other APIs that operate on ranges.
164 /// \param ptr     Start of the given range to swap
165 /// \param byteLen Length of the given range specified in bytes. Must be a multiple of 4.
166 ///
167 /// \donotcall \threadsafe \enddonotcall
168 ///
GX2EndianSwap(void * ptr,u32 byteLen)169 GX2_INLINE void GX2EndianSwap(void *ptr, u32 byteLen)
170 {
171     ASSERT((byteLen % sizeof(u32))==0);
172 #if !(defined _WIN32 || defined _WIN64)
173     u32 i;
174     u32 *src = (u32 *) ptr;
175     __bytereversed u32 *dst = (__bytereversed u32 *) ptr;
176     for(i=0; i<(byteLen>>2); i++) dst[i] = src[i];
177 #else
178     {
179         u32* src = (u32*)ptr;
180         u32 i;
181         for (i=0; i<byteLen>>2; i++)
182         {
183             src[i] = GX2_SWAP_8_IN_32(src[i]);
184         }
185     }
186 #endif
187 }
188 
189 /// \brief Utility function to round a value up to a multiple of a power of 2 size
190 ///
191 /// \note This function only works if size is a power of 2
192 ///
193 /// \param value    the input value to be rounded up
194 /// \param size     a power of 2 multiple to round value up to
195 /// \return         value rounded up to a multiple of size
196 ///
197 /// \donotcall \threadsafe \devonly \enddonotcall
198 ///
GX2RoundUp(u32 value,u32 size)199 GX2_INLINE u32 GX2RoundUp(u32 value, u32 size)
200 {
201     // assert if the size is not a power of 2
202     ASSERT((size & (size - 1)) == 0);
203     return ((value + (size - 1)) & ~(size - 1));
204 }
205 
206 /// @}
207 /// @addtogroup GX2ManagementMemGroup
208 /// @{
209 
210 /// \brief Type used for default GX2 memory allocator
211 typedef void* (*GX2DefaultAllocateFunc)(u32 userArg, u32 byteCount, u32 alignment);
212 
213 /// \brief Type used for default GX2 memory free function
214 typedef void (*GX2DefaultFreeFunc)(u32 userArg, void* pMem);
215 
216 /// \brief Set default functions to use for memory allocation/freeing.
217 ///
218 /// These will be used by GX2R regular & debug features as well as by the debug PM4 capture
219 /// unless other allocators are specifically set using other APIs.  These functions can also
220 /// be easily used by the perf APIs by passing in \ref GX2MEMDefaultAllocator.
221 ///
222 /// If not set by the user, these will just call MEMAllocFromDefaultHeap/MEMFreeToDefaultHeap.
223 ///
224 /// \param pfnAlloc pointer to allocator function
225 /// \param pfnFree  pointer to free function
226 ///
227 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
228 ///
229 void GX2API GX2SetDefaultAllocator(GX2DefaultAllocateFunc pfnAlloc, GX2DefaultFreeFunc pfnFree);
230 
231 /// \brief Get default functions to use for memory allocation/freeing.
232 /// \param ppfnAlloc pointer to get pointer to allocator function
233 /// \param ppfnFree  pointer to get pointer to free function
234 ///
235 /// \donotcall \threadsafe \devonly \enddonotcall
236 ///
237 void GX2API GX2GetDefaultAllocator(GX2DefaultAllocateFunc *ppfnAlloc, GX2DefaultFreeFunc *ppfnFree);
238 
239 #if !(defined _WIN32 || defined _WIN64)
240 /// \brief A pre-defined allocator that will call the default GX2 allocator/free functions
241 /// that are set up using \ref GX2SetDefaultAllocator.
242 extern MEMAllocator GX2MEMDefaultAllocator;
243 #endif
244 
245 #ifdef _DEBUG
246 /// \brief Tell GX2 about graphics memory allocation.
247 ///
248 /// While not required, calling this function when allocating GPU-accessed
249 /// graphics data may help the GPU debugger PM4 frame capture feature
250 /// work properly or more efficiently.
251 ///
252 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
253 ///
254 void GX2API GX2NotifyMemAlloc(void* addr, u32 size, u32 align);
255 
256 /// \brief Tell GX2 about graphics memory free.
257 ///
258 /// While not required, calling this function when freeing GPU-accessed
259 /// graphics data may help the GPU debugger PM4 frame capture feature
260 /// work properly or more efficiently.
261 ///
262 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
263 ///
264 void GX2API GX2NotifyMemFree(void* addr);
265 #else
GX2NotifyMemAlloc(const void * addr,u32 size,u32 align)266 GX2_INLINE void GX2NotifyMemAlloc(const void* addr, u32 size, u32 align){
267     addr=addr;
268     size=size;
269     align=align;
270 }
GX2NotifyMemFree(const void * addr)271 GX2_INLINE void GX2NotifyMemFree(const void* addr){
272     addr=addr;
273 }
274 #endif
275 
276 /// \brief Invalidate GPU input caches or flush GPU output caches/pipelines.
277 ///
278 /// This function invalidates GPU input caches or flushes GPU output caches.
279 /// For CPU ranges, it calls DCFlushRange() (ie, it flushes the data cache).
280 ///
281 /// Every memory range to be read by the GPU must be flushed or
282 /// invalidated from the CPU cache before use.  For display lists,
283 /// you should call GX2Invalidate() on the memory *before* writing
284 /// to it with GX2 commands.  For any vertex, texture, shader, or
285 /// uniform buffer data written by the CPU, you should call
286 /// GX2Invalidate() *after* writing it.
287 ///
288 /// For rendering to textures, this function must be called twice:
289 /// - Once to flush the color buffer (or depth buffer) write pipe
290 /// - Once to invalidate the texture read cache
291 ///
292 /// \note For GPU input cache flushes, you may specify a range of 0x0 - 0xffffffff.
293 /// This can make resource management easier for the CPU, though it may
294 /// cause some unnecessary invalidation.
295 /// \note For GPU output cache flushes, you may specify a range of 0x0 - 0xffffffff.
296 ///  This can make resource management easier for the CPU, though it may cause some
297 ///  unnecessary invalidation.  In addition, the GPU has optimizations to avoid
298 ///  unnecessary stalling when it is given ranges that match the ones it knows about.
299 ///
300 /// \param invType  Flags indicating which invalidations/flushes to perform
301 /// \param ptr      start of cached data area
302 /// \param size     size of cached data area in bytes
303 ///
304 /// \donotcall \gx2_typical \enddonotcall
305 ///
306 /// \writesgpu
307 /// \writesgpu{if the invType contains any GPU invalidation bit}
308 ///
309 void GX2API GX2Invalidate( GX2InvalidateType invType, void *ptr, u32 size );
310 
311 /// @}
312 /// @addtogroup GX2DebugGroup
313 /// @{
314 
315 // -----------------
316 // Debugging Helpers
317 
318 /// \brief Enable or disable debug drawing modes
319 ///
320 /// - "Flush per draw" makes sure that each draw command is submitted to the
321 /// hardware as soon as possible.
322 /// - "Done per flush" waits for each submit (of any type) to complete before
323 /// continuing.
324 ///
325 /// \note This function only operates in debug builds of GX2.  In non-debug
326 /// builds, the function still exists, but does not do anything.
327 ///
328 /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall
329 ///
330 void GX2API GX2SetDebugMode(GX2DebugMode dm);
331 
332 /// \brief Determines the maximum amount of time to wait for the GPU to
333 /// perform certain actions before regarding it as hung.
334 ///
335 /// This value affects functions such as \ref GX2WaitTimeStamp and
336 /// \ref GX2WaitForVsync. When GX2 thinks the GPU might be hung,
337 /// it can report the state of some GPU registers and determine which
338 /// GPU blocks are busy.
339 ///
340 /// This API can change the timeout value for debugging purposes.  Note
341 /// that you should avoid setting the timeout to less than 17 msec, or
342 /// some functions will most likely timeout on you.  The default timeout
343 /// is given by \ref GX2_DEFAULT_GPU_TIMEOUT_IN_MILLISEC.
344 ///
345 /// \param millisec amount of time before GX2 considers GPU to be hung
346 ///
347 /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall
348 ///
349 void GX2API GX2SetGPUTimeout(u32 millisec);
350 
351 /// \brief Returns the value set by \ref GX2SetGPUTimeout
352 ///
353 /// \donotcall \fgonly \threadsafe \devonly \enddonotcall
354 ///
355 u32 GX2API GX2GetGPUTimeout(void);
356 
357 /// \brief Determines the maximum number of interrupts allowed during
358 /// a single frame time (1/60 of a second) before a warning is issued.
359 ///
360 /// In debug builds only, a warning is printed out if this limit is
361 /// exceeded.  This is to help alert the user of unexpected processing
362 /// that can interfere with normal operations.  The default limit is
363 /// given by \ref GX2_DEFAULT_INTERRUPT_COUNT_LIMIT.
364 ///
365 /// \param limit The interrupt count limit during each 1/60 sec frame.
366 ///
367 /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall
368 ///
369 void GX2API GX2SetInterruptCountLimit(u32 limit);
370 
371 /// \brief Helper function to see current GPU status.
372 ///
373 /// \warning This should not be used in production code.
374 ///
375 /// \donotcall \gx2_typical \enddonotcall
376 ///
377 void GX2API GX2PrintGPUStatus(void);
378 
379 /// \brief Function used to set GX2Log-related settings.
380 ///
381 /// \donotcall \threadsafe \devonly \enddonotcall
382 ///
383 void GX2API GX2LogSetMisc(GX2LogAttrib attrib, u32 value);
384 
385 
386 /// @}
387 /// @addtogroup GX2DebugCaptureGroup
388 /// @{
389 
390 /// \brief Function to write a user string to the PM4 capture
391 /// \param userTagType      A semantic tag written with the string for tool use
392 /// \param formatString     printf-style arguments, written to the captured command buffer
393 ///
394 /// \donotcall \gx2_typical \enddonotcall
395 ///
396 /// \writesgpu
397 /// \alwayswritesgpu
398 ///
399 void GX2API GX2DebugTagUserString(GX2DebugTagUserStringType userTagType, const char* formatString, ...);
400 
401 /// \brief Use this version of \ref GX2DebugTagUserString if you want to forward a varargs wrapper
402 /// \param userTagType      A semantic tag written with the string for tool use
403 /// \param formatString     printf-style arguments, written to the captured command buffer
404 /// \param args             Extract from varargs "..." using C standard library va_start()/va_end()
405 ///
406 /// \donotcall \gx2_typical \enddonotcall
407 ///
408 /// \writesgpu
409 /// \alwayswritesgpu
410 ///
411 void GX2API GX2DebugTagUserStringVA(GX2DebugTagUserStringType userTagType, const char* formatString, va_list args);
412 
413 /// \brief Initialize the capture system.
414 ///
415 /// Initialize the capture system. The remote Capture button in the Spark GPU debugger
416 /// will be enabled after this call.
417 ///
418 /// \note You must link with gx2spark.a to use this function.
419 ///
420 /// \param initAttribs  Reserved for future use.
421 ///
422 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \notcallback \devonly \enddonotcall
423 ///
424 void GX2DebugCaptureInit(u32 *initAttribs);
425 
426 /// \brief Captures the PM4 command sequence and associated buffers to a capture file
427 ///        for analysis with pm4parse tool or Spark GPU debugger.
428 ///
429 /// The capture will start at the next \ref GX2SwapScanBuffers and will end at
430 /// the subsequent occurrence of that function.
431 ///
432 /// \note This is the officially supported API for debug captures.
433 ///
434 /// \param filename Name of the .4mp output file in data/save/common
435 ///
436 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
437 ///
438 void GX2API GX2DebugCaptureFrame(const char* filename);
439 
440 /// \brief Similar to \ref GX2DebugCaptureFrame, but handles multiple frames.
441 ///
442 /// \note This function is deprecated.  Please use \ref GX2DebugCaptureFrame instead.
443 ///
444 /// \param filename Name of the .4mp output file in data/save
445 /// \param numFrames Number of frames to capture
446 ///
447 /// \donotcall \fgonly \notthreadsafe \notinterrupt \notexception \devonly \enddonotcall
448 ///
449 void GX2API GX2DebugCaptureFrames(const char* filename, u32 numFrames);
450 
451 /// \brief Start capturing the PM4 command sequence and associated buffers to a capture file.
452 ///
453 /// \note This API is for advanced usage.  Capturing more or less than a full single frame
454 ///       may present debugger support issues not present otherwise (we may not support such
455 ///       usage).  It should be fine for viewing with pm4parse, however.
456 ///
457 /// \param filename     Name of the .4mp output file in data/save/common
458 /// \param optionFlags  See \ref GX2DebugCaptureOptions
459 ///
460 /// \donotcall \nomulticore \gx2_dl \enddonotcall
461 ///
462 /// \writesgpu
463 /// \writesgpu{if \ref GX2_DEBUG_CAPTURE_NO_FLUSH is not set.}
464 ///
465 void GX2API GX2DebugCaptureStart(const char* filename, GX2DebugCaptureOptions optionFlags);
466 
467 /// \brief Stops a PM4 capture.
468 ///
469 /// \note This API is for advanced usage.  Capturing more or less than a full single frame
470 ///       may present debugger support issues not present otherwise (we may not support such
471 ///       usage).  It should be fine for viewing with pm4parse, however.
472 ///
473 /// \param optionFlags  See \ref GX2DebugCaptureOptions
474 ///
475 /// \donotcall \nomulticore \gx2_dl \enddonotcall
476 ///
477 /// \writesgpu
478 /// \writesgpu{if \ref GX2_DEBUG_CAPTURE_NO_FLUSH is not set.}
479 ///
480 void GX2API GX2DebugCaptureEnd(GX2DebugCaptureOptions optionFlags);
481 
482 /// @}
483 /// @addtogroup GX2UTHelperGroup
484 /// @{
485 
486 /// \brief Compile-time assert
487 #define GX2_STATIC_ASSERT(e, message)   typedef int static_assert_failed_##message[!(e) ? -1 : 1]
488 
489 /// \brief Set the bits in *pFlags
490 ///
491 /// \donotcall \threadsafe \enddonotcall
492 ///
GX2SetBitFlags(u32 * pFlags,u32 bits)493 GX2_INLINE void GX2SetBitFlags(u32* pFlags, u32 bits)                 { *pFlags |= bits; }
494 
495 /// \brief Clear the bits in *pFlags
496 ///
497 /// \donotcall \threadsafe \enddonotcall
498 ///
GX2ClearBitFlags(u32 * pFlags,u32 bits)499 GX2_INLINE void GX2ClearBitFlags(u32* pFlags, u32 bits)               { *pFlags &= ~bits; }
500 
501 /// \brief Mask the bits in *pFlags
502 ///
503 /// \donotcall \threadsafe \enddonotcall
504 ///
GX2MaskBitFlags(u32 * pFlags,u32 mask)505 GX2_INLINE void GX2MaskBitFlags(u32* pFlags, u32 mask)                { *pFlags &= mask; }
506 
507 /// \brief Replace the bits in mask with bits
508 ///
509 /// \donotcall \threadsafe \enddonotcall
510 ///
GX2ReplaceBitFlags(u32 * pFlags,u32 mask,u32 bits)511 GX2_INLINE void GX2ReplaceBitFlags(u32* pFlags, u32 mask, u32 bits)   { *pFlags &= ~mask; *pFlags |= (bits & mask); }
512 
513 /// \brief Returns GX2_TRUE if any of the bits are set
514 ///
515 /// \donotcall \threadsafe \enddonotcall
516 ///
GX2TestBitFlagsAny(u32 flags,u32 bits)517 GX2_INLINE GX2Boolean GX2TestBitFlagsAny(u32 flags, u32 bits)         { return (GX2Boolean)((flags & bits) != 0); }
518 
519 /// \brief Returns GX2_TRUE if all of the bits are set
520 ///
521 /// \donotcall \threadsafe \enddonotcall
522 ///
GX2TestBitFlagsAll(u32 flags,u32 bits)523 GX2_INLINE GX2Boolean GX2TestBitFlagsAll(u32 flags, u32 bits)         { return (GX2Boolean)((flags & bits) == bits); }
524 
525 /// \brief Returns the min of a and b
526 ///
527 /// \donotcall \threadsafe \enddonotcall
528 ///
GX2Min(u32 a,u32 b)529 GX2_INLINE u32  GX2Min(u32 a, u32 b)                                  { return (a < b) ? a : b; }
530 
531 /// \brief Returns the max of a and b
532 ///
533 /// \donotcall \threadsafe \enddonotcall
534 ///
GX2Max(u32 a,u32 b)535 GX2_INLINE u32  GX2Max(u32 a, u32 b)                                  { return (a > b) ? a : b; }
536 
537 /// \brief Utility function, returns GX2_TRUE if the pointer meets the given alignment
538 ///
539 /// \donotcall \threadsafe \enddonotcall
540 ///
GX2IsAligned(const void * p,u32 alignment)541 GX2_INLINE GX2Boolean GX2IsAligned(const void *p, u32 alignment)
542 {
543     return (GX2Boolean)((u32)p == GX2RoundUp((u32)p, alignment));
544 }
545 
546 
547 /// \brief Returns true if the specified format supports the fast fixed-function box MSAA resolve.
548 ///
549 /// \donotcall \threadsafe \enddonotcall
550 ///
GX2IsResolveSupported(GX2SurfaceFormat format)551 GX2_INLINE GX2Boolean GX2IsResolveSupported(GX2SurfaceFormat format)
552 {
553     switch(format)
554     {
555         //Only the following formats support fixed function (box-filter) MSAA resolve
556         case GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT:
557 
558         case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT:
559         case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM:
560         case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM:
561         case GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT:
562 
563         case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM:
564         case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB:
565         case GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM:
566         case GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM:
567         case GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM:
568         case GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT:
569         case GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT:
570         case GX2_SURFACE_FORMAT_TC_R16_G16_UNORM:
571         case GX2_SURFACE_FORMAT_TC_R16_G16_SNORM:
572         case GX2_SURFACE_FORMAT_TCD_R32_FLOAT:
573 
574         case GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM:
575         case GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM:
576         case GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM:
577         case GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM:
578         case GX2_SURFACE_FORMAT_TC_R8_G8_UNORM:
579         case GX2_SURFACE_FORMAT_TC_R8_G8_SNORM:
580         case GX2_SURFACE_FORMAT_TC_R16_FLOAT:
581         case GX2_SURFACE_FORMAT_TCD_R16_UNORM:
582         case GX2_SURFACE_FORMAT_TC_R16_SNORM:
583 
584         case GX2_SURFACE_FORMAT_TC_R8_UNORM:
585         case GX2_SURFACE_FORMAT_TC_R8_SNORM:
586         case GX2_SURFACE_FORMAT_T_R4_G4_UNORM:
587             return GX2_TRUE;
588     }
589 
590     return GX2_FALSE;
591 }
592 
593 /// @}
594 /// @addtogroup GX2ManagementContextStateGroup
595 /// @{
596 
597 /// \brief Context state data size in bytes.
598 ///
599 #define GX2_CONTEXT_STATE_DATA_SIZE 41216
600 
601 /// \brief Context state
602 ///
603 /// Context state
604 typedef struct _GX2ContextState {
605     u32 data[GX2_CONTEXT_STATE_DATA_SIZE/sizeof(u32)];
606 } GX2ContextState;
607 
608 ///  \brief Call other GX2 commands to set up the default render state. See \ref GX2SetDefaultStateSect.
609 ///
610 /// \donotcall \gx2_typical \enddonotcall
611 ///
612 /// \clobberstate
613 ///
614 /// \writesgpu
615 /// \alwayswritesgpu
616 ///
617 void GX2API GX2SetDefaultState(void);
618 
619 /// \brief Initialize the given context state memory with the default state and set it in use.
620 ///
621 /// \note When profiling is disabled GX2 will not override any state based on the profile mode or
622 ///       toss stage that was setup during initialization.
623 ///
624 /// \note This function will normally create an internal display list as an optimization to speed
625 ///       up calls to GX2SetupContextState.  Since it must call GX2BeginDisplayList in order to
626 ///       create the internal display list, this means you cannot call this function while
627 ///       making a display list.
628 ///
629 /// \param pState          pointer to a GX2ContextState buffer.
630 /// \param enableProfiling enable HW profiling for this context state.
631 ///
632 /// \donotcall \gx2_typical \enddonotcall
633 ///
634 /// \enablesstateshadow
635 /// \clobberstate
636 ///
637 /// \writesgpu
638 /// \alwayswritesgpu
639 ///
640 void GX2API GX2SetupContextStateEx(GX2ContextState* pState, GX2Boolean enableProfiling);
641 
642 /// \brief Initialize the given context state memory with the default state and set it in use.
643 ///
644 /// \note HW Profiling will be enabled for the context state
645 ///
646 /// \param pState  pointer to a GX2ContextState buffer.
647 ///
648 /// \donotcall \gx2_typical \enddonotcall
649 ///
650 /// \enablesstateshadow if pState is non-NULL.
651 /// \disablesstateshadow if pState is NULL.
652 /// \clobberstate
653 ///
654 /// \writesgpu
655 /// \alwayswritesgpu
656 ///
GX2SetupContextState(GX2ContextState * pState)657 GX2_INLINE void GX2SetupContextState(GX2ContextState* pState)
658 {
659     GX2SetupContextStateEx(pState, GX2_ENABLE);
660 }
661 
662 /// \brief Loads the given context state and makes it current for future changes.
663 ///
664 /// \note If pState is NULL the previous context state is preserved
665 /// and future state changes will not be saved to memory.
666 /// (Ie, this disables state shadowing.)
667 ///
668 /// \note Normally this function will just call or copy an internal display list that
669 ///       contains all the necessary load commands.  A call is used unless we are in
670 ///       the process of creating a display list, in which case a copy is done instead.
671 ///
672 /// \note This function invokes a full pipeline flush; it takes approx. 23 usecs.
673 ///
674 /// \param pState  pointer to an already-initialized GX2ContextState buffer, or NULL.
675 ///
676 /// \donotcall \gx2_typical \enddonotcall
677 ///
678 /// \clobberstate
679 /// \enablesstateshadow State shadowing is enabled if pState is non-NULL.
680 /// \disablesstateshadow State shadowing is disabled if pState is NULL.
681 /// \notincompute
682 ///
683 /// \writesgpu
684 /// \alwayswritesgpu
685 ///
686 void GX2API GX2SetContextState(const GX2ContextState* pState);
687 
688 /// \brief Returns the pointer and size for the internal display list found in a GX2ContextState.
689 ///
690 /// \note To improve the performance of GX2SetContextState, when you call GX2SetupContextState,
691 /// we create an internal display list that performs all the necessary register loads.
692 /// Then, when you call GX2SetContextState, we either make a call to that display list (if
693 /// you are currently writing to a command buffer), or we copy that display list (if you
694 /// are currently writing to a display list).  The latter is done to avoid having too many
695 /// nested display list calls.  However, if you know you will not exceed the nesting level,
696 /// you can call the display list directly by getting its parameters with this API.
697 ///
698 /// \param pState         pointer to an already-initialized GX2ContextState buffer.
699 /// \param ppDisplayList  pointer to receive the display list pointer.
700 /// \param pByteSize      pointer to receive the display list size.
701 ///
702 /// \donotcall \threadsafe \devonly \enddonotcall
703 ///
704 void GX2API GX2GetContextStateDisplayList(const GX2ContextState *pState, void **ppDisplayList, u32 *pByteSize);
705 
706 /// \brief Patches a sequence of display list commands that were created using
707 /// offline display list compilation.
708 ///
709 /// \param pDisplayList     Pointer to the start of the display list to patch
710 /// \param type             Type GX2 entry that needs to be patched
711 /// \param offset           Offset in u32s from the start of the display list
712 /// \param gx2ObjectPointer Pointer to the GX2 object that generated the patch
713 ///                         entry.
714 ///
715 /// See \ref gshCompileOfflineGX2Sect for more details.
716 ///
717 /// \warning After all display list entries have been patched, the user must
718 ///          flush the CPU memory from the cache using \ref GX2Invalidate.
719 ///
720 /// \donotcall \threadsafe \devonly \enddonotcall
721 ///
722 void GX2API GX2PatchDisplayList(void *pDisplayList, GX2PatchType type, u32 offset, void *gx2ObjectPointer);
723 /// @}
724 
725 #ifdef __cplusplus
726 }
727 #endif // __cplusplus
728 
729 #endif // _CAFE_GX2_MISC_H_
730