1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tex-invalid.c
4 
5   Copyright 1998-2006 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 /*---------------------------------------------------------------------------*
14     tex-invalid
15         texture cache region invalidation test
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <string.h>
24 
25 /*---------------------------------------------------------------------------*
26    Macro definitions
27  *---------------------------------------------------------------------------*/
28 #define NUM_REGIONS     8
29 #define NUM_TEXOBJS     NUM_REGIONS
30 #define NUM_ROWS        5
31 #define NUM_TEXTURES    NUM_ROWS
32 
33 // for display position
34 #define ALI_ROW(y)      (y * 80 + 56)
35 #define ALI_COL(x)      (x * 68 + 48)
36 
37 /*---------------------------------------------------------------------------*
38    Structure definitions
39  *---------------------------------------------------------------------------*/
40 // for entire scene control
41 typedef struct
42 {
43     u32            curX;
44     u32            curY;
45     u8             invalidateSw[NUM_ROWS-2][NUM_REGIONS];
46     GXTexObj       texture[NUM_TEXOBJS];
47     u32            dataSize;
48     u8*            dataBuffer[NUM_TEXOBJS];
49     u8*            dataSource[NUM_TEXTURES];
50     u16            screenWd;
51     u16            screenHt;
52 } MySceneCtrlObj;
53 
54 /*---------------------------------------------------------------------------*
55    Forward references
56  *---------------------------------------------------------------------------*/
57 void        main               ( void );
58 static void DrawInit           ( MySceneCtrlObj* sc );
59 static void DrawTick           ( MySceneCtrlObj* sc );
60 static void AnimTick           ( MySceneCtrlObj* sc );
61 static void DrawQuad           ( void );
62 static void DrawLines          ( void );
63 static void MyDrawCaption      ( MySceneCtrlObj* sc );
64 static void MyMemCopy          ( u8* src, u8* dst, u32 size );
65 static GXTexRegion*
66             MyTexRegionCallback( const GXTexObj* texObj, GXTexMapID mapID );
67 
68 static void PrintIntro         ( void );
69 
70 
71 /*---------------------------------------------------------------------------*
72    Model Data
73  *---------------------------------------------------------------------------*/
74 static s16 QuadVertices[3*8] ATTRIBUTE_ALIGN(32) =
75 {
76       0,   0,  0, // 0
77      64,   0,  0, // 1
78      64,  64,  0, // 2
79       0,  64,  0  // 3
80 };
81 
82 static s8 QuadTexCoords[2*4] ATTRIBUTE_ALIGN(32) =
83 {
84       0,   0,
85       1,   0,
86       1,   1,
87       0,   1
88 };
89 
90 /*---------------------------------------------------------------------------*
91    String data for messages
92  *---------------------------------------------------------------------------*/
93 static char* InvSwStr[2] =
94 {
95     "-------",
96     "INVALID"
97 };
98 
99 static char* InvTexAllStr = "******* GXInvalidateTexAll *******";
100 
101 /*---------------------------------------------------------------------------*
102    Global variables
103  *---------------------------------------------------------------------------*/
104 static MySceneCtrlObj   SceneCtrl;                 // scene control parameters
105 static TPLPalettePtr    MyTplObj = NULL;           // texture palette
106 static GXTexRegion      MyTexRegions[NUM_REGIONS]; // cache regions
107 
108 /*---------------------------------------------------------------------------*
109    Application main loop
110  *---------------------------------------------------------------------------*/
main(void)111 void main ( void )
112 {
113     DEMOInit(NULL);  // Init the OS, game pad, graphics and video.
114 
115     DrawInit(&SceneCtrl); // Initialize vertex formats, array pointers
116                           // and default scene settings.
117 
118     PrintIntro();    // Print demo directions
119 
120     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
121     {
122 		DEMOBeforeRender();
123         DrawTick(&SceneCtrl);    // Draw the model.
124         DEMODoneRender();
125         DEMOPadRead();           // Read controller
126         AnimTick(&SceneCtrl);    // Do animation
127     }
128 
129     OSHalt("End of demo");
130 }
131 
132 /*---------------------------------------------------------------------------*
133    Functions
134  *---------------------------------------------------------------------------*/
135 /*---------------------------------------------------------------------------*
136     Name:           DrawInit
137 
138     Description:    Initializes the vertex attribute format and sets up
139                     the array pointer for the indexed data.
140                     This function also initializes scene control parameters.
141 
142     Arguments:      sc : pointer to the structure of scene control parameters
143 
144     Returns:        none
145  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)146 static void DrawInit( MySceneCtrlObj* sc )
147 {
148     TPLDescriptorPtr  tdp;
149     GXRenderModeObj*  rmode;
150     u32               i, j;
151 
152     // Vertex Attribute (VTXFMT0 is used by DEMOPuts library)
153     GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
154     GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA4, 0);
155     GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0);
156 
157     // Array pointers
158     GXSetArray(GX_VA_POS,  QuadVertices, 3 * sizeof(s16));
159     GXSetArray(GX_VA_TEX0, QuadTexCoords, 2 * sizeof(s8));
160 
161     // Get Screen Information defined in DEMOInit()
162     // This test is supposing height=480 (or near.)
163     rmode = DEMOGetRenderModeObj();
164     sc->screenWd = rmode->fbWidth;   // Screen Width
165     sc->screenHt = rmode->efbHeight; // Screen Height
166 
167     // TMEM configuration
168     for ( i = 0 ; i < NUM_REGIONS ; ++i )
169     {
170         // The region is used as a 32K cache.
171         GXInitTexCacheRegion(
172             &MyTexRegions[i],
173             GX_FALSE,               // 32b mipmap
174             0x00000 + i * 0x08000,  // tmem_even
175             GX_TEXCACHE_32K,        // size_even
176             0x80000 + i * 0x08000,  // tmem_odd
177             GX_TEXCACHE_32K );      // size_odd
178     }
179     // User-defined tex region Callback
180     GXSetTexRegionCallback(MyTexRegionCallback);
181 
182     // Load TPL file
183     TPLGetPalette(&MyTplObj, "gxTests/tex-07.tpl");
184 
185     // This test doesn't use tpl data directly.
186     // Just keeping pointers for image data and
187     // copies them into buffers when used.
188     for ( i = 0 ; i < NUM_TEXTURES ; ++i )
189     {
190         tdp = TPLGet(MyTplObj, i);
191         sc->dataSource[i] = (u8*)tdp->textureHeader->data;
192     }
193 
194     // Same parameter is used in every texture in tex-07.tpl.
195     tdp = TPLGet(MyTplObj, 0);
196     sc->dataSize = GXGetTexBufferSize(
197                        tdp->textureHeader->width,
198                        tdp->textureHeader->height,
199                        tdp->textureHeader->format,
200                        GX_FALSE,
201                        0 );
202 
203     // Initialize texture objects
204     for ( i = 0 ; i < NUM_TEXOBJS ; ++i )
205     {
206         sc->dataBuffer[i] = MEMAllocFromAllocator(&DemoAllocator1, sc->dataSize);
207 
208         GXInitTexObj(
209             &sc->texture[i],
210             (void*)sc->dataBuffer[i], // allocated buffer
211             tdp->textureHeader->width,
212             tdp->textureHeader->height,
213             (GXTexFmt)tdp->textureHeader->format,
214             tdp->textureHeader->wrapS, // s
215             tdp->textureHeader->wrapT, // t
216             GX_FALSE ); // Mipmap is turned off.
217 
218         // UserData field keeps ID number.
219         GXInitTexObjUserData(&sc->texture[i], (void*)i);
220     }
221 
222 
223     // Default scene control parameter settings
224 
225     // region invalidation switches
226     for ( i = 0 ; i < NUM_ROWS - 2 ; ++i )
227     {
228         for ( j = 0 ; j < NUM_REGIONS ; ++j )
229         {
230             sc->invalidateSw[i][j] = 1;
231         }
232     }
233 
234     // cursor
235     sc->curX = 0;
236     sc->curY = 0;
237 }
238 
239 /*---------------------------------------------------------------------------*
240     Name:           DrawTick
241 
242     Description:    Draw the model by using given scene parameters
243 
244     Arguments:      sc : pointer to the structure of scene control parameters
245 
246     Returns:        none
247  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)248 static void DrawTick( MySceneCtrlObj* sc )
249 {
250     Mtx  mt, mv;
251     s32  x, y;
252     u16  token;
253 
254     // set projection to match screen space coordinate system
255     DEMOSetupScrnSpc(sc->screenWd, sc->screenHt, 100.0F);
256 
257     // set up Zmode
258     GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE);
259 
260     // set up Tev for simple colored objects
261     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
262     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
263     GXSetNumChans(1);
264     GXSetNumTexGens(0);
265 
266     // draw lines
267     MTXIdentity(mv);
268     GXLoadPosMtxImm(mv, GX_PNMTX0);
269     DrawLines();
270 
271     // set up Tev for textured objects
272     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
273     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
274     GXSetNumChans(0);
275     GXSetNumTexGens(1);
276     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
277 
278     // reset token for synchronization
279     token = 0;
280     GXSetDrawSync(token);
281 
282     for ( y = 0 ; y < NUM_ROWS ; ++y )
283     {
284         // Sync is necessary because CPU modifies main
285         // memory area for textures in run-time.
286         while ( token != GXReadDrawSync() )
287         {}
288 
289         // Copy source image into each buffer
290         for ( x = 0 ; x < NUM_TEXOBJS ; ++x )
291         {
292             MyMemCopy(sc->dataSource[y], sc->dataBuffer[x], sc->dataSize);
293         }
294 
295         // Invalidate cache regions
296         if ( y == 0 || y == NUM_ROWS - 1 )
297         {
298             GXInvalidateTexAll();
299         }
300         else
301         {
302             for ( x = 0 ; x < NUM_REGIONS ; ++x )
303             {
304                 if ( sc->invalidateSw[y-1][x] )
305                 {
306                     GXInvalidateTexRegion(&MyTexRegions[x]);
307                 }
308             }
309         }
310 
311         // Draw textured quads for a row
312         for ( x = 0 ; x < NUM_TEXOBJS ; ++x )
313         {
314             // modelview matrix
315             MTXTrans(
316                 mt,
317                 (f32)ALI_COL(x),
318                 (f32)ALI_ROW(y),
319                 0.0F );
320             GXLoadPosMtxImm(mt, GX_PNMTX0);
321 
322             GXLoadTexObj(&sc->texture[x], GX_TEXMAP0);
323             DrawQuad();
324         }
325 
326         // Send the next sync token
327         GXSetDrawSync(++token);
328     }
329 
330     // Captions
331     MyDrawCaption(sc);
332 }
333 
334 /*---------------------------------------------------------------------------*
335     Name:           AnimTick
336 
337     Description:    Changes scene parameters according to the pad status.
338 
339     Arguments:      sc : pointer to the structure of scene control parameters
340 
341     Returns:        none
342  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)343 static void AnimTick( MySceneCtrlObj* sc )
344 {
345     u16  down, dirs;
346 
347     // PAD
348     down = DEMOPadGetButtonDown(0);
349     dirs = DEMOPadGetDirsNew(0);
350 
351     // move cursor
352     if ( dirs & DEMO_STICK_RIGHT )
353     {
354         sc->curX += 1;
355     }
356     if ( dirs & DEMO_STICK_LEFT )
357     {
358         sc->curX += NUM_REGIONS - 1;
359     }
360     if ( dirs & DEMO_STICK_DOWN )
361     {
362         sc->curY += 1;
363     }
364     if ( dirs & DEMO_STICK_UP )
365     {
366         sc->curY += NUM_ROWS - 3;
367     }
368     sc->curX %= NUM_REGIONS;
369     sc->curY %= NUM_ROWS - 2;
370 
371     // toggle invalidation switch
372     if ( down & PAD_BUTTON_A )
373     {
374         ++(sc->invalidateSw[sc->curY][sc->curX]);
375         sc->invalidateSw[sc->curY][sc->curX] %= 2;
376     }
377 }
378 
379 /*---------------------------------------------------------------------------*
380     Name:           DrawQuad
381 
382     Description:    Draw a textured Quad. Each face can have different texture
383                     which is specified by given texture number list.
384 
385     Arguments:      texNoList : a pointer to texture number list
386 
387     Returns:        none
388  *---------------------------------------------------------------------------*/
DrawQuad(void)389 static void DrawQuad( void )
390 {
391     u8   i;
392 
393     // set vertex descriptor
394     GXClearVtxDesc();
395     GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
396     GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
397 
398     // draw the quad
399     GXBegin(GX_QUADS, GX_VTXFMT1, 4);
400         for ( i = 0 ; i < 4 ; ++i )
401         {
402             GXPosition1x8(i);
403             GXTexCoord1x8(i);
404         }
405     GXEnd();
406 }
407 
408 /*---------------------------------------------------------------------------*
409     Name:           DrawLines
410 
411     Description:    Draw lines
412 
413     Arguments:      none
414 
415     Returns:        none
416  *---------------------------------------------------------------------------*/
DrawLines(void)417 static void DrawLines( void )
418 {
419     u8   i;
420 
421     // set vertex descriptor
422     GXClearVtxDesc();
423     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
424     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
425 
426     // draw lines
427     GXBegin(GX_LINES, GX_VTXFMT1, NUM_REGIONS * 2);
428         for ( i = 0 ; i < NUM_REGIONS ; ++i )
429         {
430             GXPosition3s16((s16)(i*72+64), 112, 0);
431             GXColor1u16(0xFFFF); // White
432             GXPosition3s16((s16)(i*72+64), 368, 0);
433             GXColor1u16(0xFFFF); // White
434         }
435     GXEnd();
436 }
437 
438 /*---------------------------------------------------------------------------*
439     Name:           MyDrawCaption
440 
441     Description:    Draw captions
442 
443     Arguments:      sc : pointer to the structure of scene control parameters
444 
445     Returns:        none
446  *---------------------------------------------------------------------------*/
MyDrawCaption(MySceneCtrlObj * sc)447 static void MyDrawCaption( MySceneCtrlObj* sc )
448 {
449     u32  i, j;
450 
451     DEMOInitCaption(DM_FT_OPQ, sc->screenWd, sc->screenHt);
452 
453     for ( i = 0 ; i < NUM_REGIONS ; ++i )
454     {
455         DEMOPrintf((s16)ALI_COL(i), (s16)(ALI_ROW(0)-16), 0, "[CACHE%d]", i);
456 
457         for ( j = 0 ; j < NUM_ROWS - 2 ; ++j )
458         {
459             DEMOPuts(
460                 (s16)(ALI_COL(i)+8),
461                 (s16)(ALI_ROW(j)+68),
462                 0,
463                 InvSwStr[sc->invalidateSw[j][i]]);
464         }
465     }
466 
467     // Cursor
468     DEMOPrintf((s16)ALI_COL(sc->curX), (s16)(ALI_ROW(sc->curY)+68), 0, "%c", 0x7F);
469 
470     // "GXInvalidateTexAll"
471     DEMOPrintf(ALI_COL(0), (s16)(ALI_ROW(3)+68), 0, "%s%s", InvTexAllStr, InvTexAllStr);
472 }
473 
474 /*---------------------------------------------------------------------------*
475     Name:           MyMemCopy
476 
477     Description:    Copy specified memory block and flush related cache.
478 
479     Arguments:      src  : start address of source data
480                     dst  : start address of destination
481                     size : data size
482 
483     Returns:        none
484  *---------------------------------------------------------------------------*/
MyMemCopy(u8 * src,u8 * dst,u32 size)485 static void MyMemCopy( u8* src, u8* dst, u32 size )
486 {
487     memcpy(dst, src, size);
488     DCFlushRange(dst, size);
489 }
490 
491 /*---------------------------------------------------------------------------*
492     Name:           MyTexRegionCallback
493 
494     Description:    Tex cache allocator using simple round algorithm
495 
496     Arguments:      texObj : a pointer to texture object to be loaded
497                     mapID  : destination texmap ID (just same as GXLoadTexObj)
498 
499     Returns:        appropriate tex cache region for loading texture.
500  *---------------------------------------------------------------------------*/
MyTexRegionCallback(const GXTexObj * texObj,GXTexMapID mapID)501 static GXTexRegion* MyTexRegionCallback(const GXTexObj* texObj, GXTexMapID mapID)
502 {
503     #pragma unused(mapID)
504 
505     u32  texID, regionNum;
506 
507     texID     = (u32)GXGetTexObjUserData(texObj);
508     regionNum = texID % NUM_REGIONS;
509 
510     return &MyTexRegions[regionNum];
511 }
512 
513 /*---------------------------------------------------------------------------*
514     Name:           PrintIntro
515 
516     Description:    Prints the directions on how to use this demo.
517 
518     Arguments:      none
519 
520     Returns:        none
521  *---------------------------------------------------------------------------*/
PrintIntro(void)522 static void PrintIntro( void )
523 {
524     OSReport("\n\n");
525     OSReport("************************************************\n");
526     OSReport("tex-invalid: tex cache region allocator test\n");
527     OSReport("************************************************\n");
528     OSReport("to quit hit the start button\n");
529     OSReport("\n");
530     OSReport("Main Stick : move the cursor\n");
531     OSReport("A button   : toggle on/off invalidation switch\n");
532     OSReport("************************************************\n\n");
533 }
534 
535 /*============================================================================*/
536