1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tex-mix-mode.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-mix-mode
15         mixture of cached / preloaded textures test
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 
24 /*---------------------------------------------------------------------------*
25    Macro definitions
26  *---------------------------------------------------------------------------*/
27 #define NUM_TEXTURES    16
28 #define NUM_REGIONS     8
29 
30 /*---------------------------------------------------------------------------*
31    Structure definitions
32  *---------------------------------------------------------------------------*/
33 // for camera
34 typedef struct
35 {
36     Vec    location;
37     Vec    up;
38     Vec    target;
39     f32    left;
40     f32    top;
41     f32    znear;
42     f32    zfar;
43 } CameraConfig;
44 
45 typedef struct
46 {
47     CameraConfig  cfg;
48     Mtx           view;
49     Mtx44         proj;
50 } MyCameraObj;
51 
52 // for texture (includes region control)
53 typedef struct
54 {
55     u32           numPreload;
56     u32           numGen0;
57     u32           numGen1;
58     GXTexObj      texObjs[NUM_TEXTURES];
59     GXTexRegion   texRegions[NUM_REGIONS];
60 } MyTexCtrlObj;
61 
62 // for entire scene control
63 typedef struct
64 {
65     MyCameraObj   cam;
66     s32           modelRot;
67     s32           duplication;
68     MyTexCtrlObj  texCtrl;
69 } MySceneCtrlObj;
70 
71 /*---------------------------------------------------------------------------*
72    Forward references
73  *---------------------------------------------------------------------------*/
74 void        main               ( void );
75 static void DrawInit           ( MySceneCtrlObj* sc );
76 static void DrawTick           ( MySceneCtrlObj* sc );
77 static void AnimTick           ( MySceneCtrlObj* sc );
78 static void DrawCube           ( MyTexCtrlObj* tco );
79 static void LoadOneTexture     ( MyTexCtrlObj* tco );
80 static void InitTexNumGen      ( MyTexCtrlObj* tco );
81 static void ConfigureTmemMap   ( MyTexCtrlObj* tco );
82 static void SetCamera          ( MyCameraObj* cam );
83 static void StatusMessage      ( u32 numPreload );
84 static void PrintIntro         ( void );
85 static GXTexRegion*
86             MyTexRegionCallback( const GXTexObj* texObj, GXTexMapID mapID );
87 
88 /*---------------------------------------------------------------------------*
89    Model Data
90  *---------------------------------------------------------------------------*/
91 static s16 CubeVertices[3*8] ATTRIBUTE_ALIGN(32) =
92 {
93     -32, -32,  32, // 0
94      32, -32,  32, // 1
95      32,  32,  32, // 2
96     -32,  32,  32, // 3
97     -32, -32, -32, // 4
98      32, -32, -32, // 5
99      32,  32, -32, // 6
100     -32,  32, -32  // 7
101 };
102 
103 static s16 CubeTexCoords[2*4] ATTRIBUTE_ALIGN(32) =
104 {
105       0,   0,
106       1,   0,
107       1,   1,
108       0,   1
109 };
110 
111 static u8 CubeFaces[6][4] =
112 {
113     { 3, 2, 1, 0 },
114     { 4, 5, 6, 7 },
115     { 4, 7, 3, 0 },
116     { 5, 4, 0, 1 },
117     { 6, 5, 1, 2 },
118     { 7, 6, 2, 3 }
119 };
120 
121 /*---------------------------------------------------------------------------*
122    Camera configuration
123  *---------------------------------------------------------------------------*/
124 static CameraConfig DefaultCamera =
125 {
126     { 0.0F, 0.0F, 500.0F }, // location
127     { 0.0F, 1.0F,   0.0F }, // up
128     { 0.0F, 0.0F,   0.0F }, // target
129     -320.0F, // left
130     240.0F,  // top
131     50.0F,   // near
132     2000.0F  // far
133 };
134 
135 /*---------------------------------------------------------------------------*
136    Global variables
137  *---------------------------------------------------------------------------*/
138 static MySceneCtrlObj   SceneCtrl;          // scene control parameters
139 static TPLPalettePtr    MyTplObj = NULL;    // texture palette
140 
141 /*---------------------------------------------------------------------------*
142    Application main loop
143  *---------------------------------------------------------------------------*/
main(void)144 void main ( void )
145 {
146     DEMOInit(NULL);  // Init the OS, game pad, graphics and video.
147 
148     DrawInit(&SceneCtrl); // Initialize vertex formats, array pointers
149                           // and default scene settings.
150 
151     PrintIntro();    // Print demo directions
152 
153     StatusMessage(SceneCtrl.texCtrl.numPreload);
154     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
155     {
156 		DEMOBeforeRender();
157         DrawTick(&SceneCtrl);    // Draw the model.
158         DEMODoneRender();
159         DEMOPadRead();           // Read controller
160         AnimTick(&SceneCtrl);    // Do animation
161     }
162 
163     OSHalt("End of demo");
164 }
165 
166 /*---------------------------------------------------------------------------*
167    Functions
168  *---------------------------------------------------------------------------*/
169 /*---------------------------------------------------------------------------*
170     Name:           DrawInit
171 
172     Description:    Initializes the vertex attribute format and sets up
173                     the array pointer for the indexed data.
174                     This function also initializes scene control parameters.
175 
176     Arguments:      sc : pointer to the structure of scene control parameters
177 
178     Returns:        none
179  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)180 static void DrawInit( MySceneCtrlObj* sc )
181 {
182     TPLDescriptorPtr  tdp;
183     GXBool            mipMapFlag;
184     u32               i;
185 
186     // Vertex Attribute
187     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
188     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0);
189 
190     // Array pointers
191     GXSetArray(GX_VA_POS,  CubeVertices, 3 * sizeof(s16));
192     GXSetArray(GX_VA_TEX0, CubeTexCoords, 2 * sizeof(s16));
193 
194     // Texture coords
195     GXSetNumTexGens(1);
196     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
197 
198     // Color channels
199     GXSetNumChans(0);
200 
201     // Use user-defined tex region Callback
202     GXSetTexRegionCallback(MyTexRegionCallback);
203 
204     // Load TPL file and initialize texture objects
205     TPLGetPalette(&MyTplObj, "gxTests/tex-07.tpl");
206     for ( i = 0 ; i < NUM_TEXTURES ; ++i )
207     {
208         tdp = TPLGet(MyTplObj, i);
209         mipMapFlag =
210             (GXBool)(( tdp->textureHeader->minLOD == tdp->textureHeader->maxLOD ) ?
211                      GX_FALSE : GX_TRUE);
212 
213         GXInitTexObj(
214             &sc->texCtrl.texObjs[i],
215             tdp->textureHeader->data,
216             tdp->textureHeader->width,
217             tdp->textureHeader->height,
218             (GXTexFmt)tdp->textureHeader->format,
219             tdp->textureHeader->wrapS, // s
220             tdp->textureHeader->wrapT, // t
221             mipMapFlag ); // Mipmap
222 
223         GXInitTexObjLOD(
224             &sc->texCtrl.texObjs[i],
225             tdp->textureHeader->minFilter,
226             tdp->textureHeader->magFilter,
227             tdp->textureHeader->minLOD,
228             tdp->textureHeader->maxLOD,
229             tdp->textureHeader->LODBias,
230             GX_FALSE,
231             tdp->textureHeader->edgeLODEnable,
232             GX_ANISO_1 );
233     }
234 
235 
236     // Default scene control parameter settings
237 
238     // camera
239     sc->cam.cfg = DefaultCamera;
240     SetCamera(&sc->cam);   // never changes in this test
241 
242     // number of preload textures
243     sc->texCtrl.numPreload = 0;
244 
245     // number of drawing duplications
246     sc->duplication = 1;
247 
248     // model rotation parameter
249     sc->modelRot = 0;
250 }
251 
252 /*---------------------------------------------------------------------------*
253     Name:           DrawTick
254 
255     Description:    Draw the model by using given scene parameters
256 
257     Arguments:      sc : pointer to the structure of scene control parameters
258 
259     Returns:        none
260  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)261 static void DrawTick( MySceneCtrlObj* sc )
262 {
263     Mtx  mt, mv, mr;
264     s32  x, y, z;
265 
266     // configure tmem map
267     ConfigureTmemMap(&sc->texCtrl);
268 
269     // use texture in Tev
270     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
271     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
272 
273     // common rotation matrix
274     MTXRotDeg(mv, 'y', sc->modelRot);
275     MTXRotDeg(mr, 'x', sc->modelRot * 2);
276     MTXConcat(mv, mr, mr);
277 
278     // initialize tex number generator
279     InitTexNumGen(&sc->texCtrl);
280 
281     for ( z = sc->duplication ; z > 0 ; --z )
282     {
283         // display 8x6 cubes
284         for ( y = 0 ; y < 6 ; ++y )
285         {
286             for ( x = 0 ; x < 8 ; ++x )
287             {
288                 // Set modelview matrix
289                 MTXTrans( mt,
290                           (f32)(x * 80 + z * 5 - 280),
291                           (f32)(y * 80 + z * 5 - 200),
292                           (f32)(z * -100) );
293                 MTXConcat(sc->cam.view, mt, mv);
294                 MTXConcat(mv, mr, mv);
295                 GXLoadPosMtxImm(mv, GX_PNMTX0);
296 
297                 // Draw a textured cube
298                 DrawCube(&sc->texCtrl);
299 
300             } // x
301         } // y
302     } // z
303 
304 }
305 
306 /*---------------------------------------------------------------------------*
307     Name:           AnimTick
308 
309     Description:    Changes scene parameters according to the pad status.
310 
311     Arguments:      sc : pointer to the structure of scene control parameters
312 
313     Returns:        none
314  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)315 static void AnimTick( MySceneCtrlObj* sc )
316 {
317     u16 down = DEMOPadGetButtonDown(0);
318 
319 
320     // Model rotation parameter
321     sc->modelRot = ( sc->modelRot + 1 ) % 360;
322 
323 
324     // Change number of preloaded textures
325     if ( ( down & PAD_TRIGGER_L ) && sc->texCtrl.numPreload > 0 )
326     {
327         sc->texCtrl.numPreload -= 1;
328         StatusMessage(sc->texCtrl.numPreload);
329     }
330 
331     if ( ( down & PAD_TRIGGER_R ) && sc->texCtrl.numPreload < NUM_REGIONS - 1 )
332     {
333         sc->texCtrl.numPreload += 1;
334         StatusMessage(sc->texCtrl.numPreload);
335     }
336 
337     // Change number of drawing duplications
338     if ( ( down & PAD_BUTTON_Y ) && sc->duplication > 1 )
339     {
340         sc->duplication -= 1;
341         OSReport("Drawing %d layers\n", sc->duplication);
342     }
343 
344     if ( ( down & PAD_BUTTON_X ) && sc->duplication < 8 )
345     {
346         sc->duplication += 1;
347         OSReport("Drawing %d layers\n", sc->duplication);
348     }
349 }
350 
351 /*---------------------------------------------------------------------------*
352     Name:           DrawCube
353 
354     Description:    Draw a textured cube. Each face can have different texture
355                     which is automatically set by LoadOneTexture function.
356 
357     Arguments:      tco : texture control object which includes
358                           texture map set mapped on faces
359 
360     Returns:        none
361  *---------------------------------------------------------------------------*/
DrawCube(MyTexCtrlObj * tco)362 static void DrawCube( MyTexCtrlObj* tco )
363 {
364     u8   i, j;
365 
366     // set vertex descriptor
367     GXClearVtxDesc();
368     GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
369     GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
370 
371     // draw the box
372     for ( i = 0 ; i < 6 ; ++i )
373     {
374         LoadOneTexture(tco);
375 
376         // Draw a face
377         GXBegin(GX_QUADS, GX_VTXFMT0, 4);
378             for ( j = 0 ; j < 4 ; ++j )
379             {
380                 GXPosition1x8(CubeFaces[i][j]);
381                 GXTexCoord1x8(j);
382             }
383         GXEnd();
384     }
385 }
386 
387 /*---------------------------------------------------------------------------*
388     Name:           LoadOneTexture
389 
390     Description:    Load an appropriate texture (which number is
391                     generated automatically)
392                     If the texture is preloaded, this function calls
393                     GXLoadTexObjPreLoaded and use preloaded region.
394 
395     Arguments:      tco : texture control object which includes
396                           texture map set to be mapped on
397 
398     Returns:        none
399  *---------------------------------------------------------------------------*/
LoadOneTexture(MyTexCtrlObj * tco)400 static void LoadOneTexture( MyTexCtrlObj* tco )
401 {
402     u32 texNo;
403 
404     // Generate an appropriate number
405     texNo = tco->numGen0;
406     if ( ++(tco->numGen0) > tco->numGen1 )
407     {
408         tco->numGen0 = 0;
409         tco->numGen1 = ( tco->numGen1 + 1 ) % NUM_TEXTURES;
410     }
411 
412     // Load texture object
413     if ( texNo < tco->numPreload )
414     {
415         GXLoadTexObjPreLoaded(
416             &tco->texObjs[texNo],
417             (GXTexRegion*)(GXGetTexObjUserData(&tco->texObjs[texNo])),
418             GX_TEXMAP0 );
419     }
420     else
421     {
422         GXLoadTexObj(&tco->texObjs[texNo], GX_TEXMAP0);
423     }
424 }
425 
426 /*---------------------------------------------------------------------------*
427     Name:           InitTexNumGen
428 
429     Description:    Initialize parameters for generating texture number
430                     which is used in LoadOneTexture function.
431 
432     Arguments:      tco : texture control object in which parameters
433                           should be initialized
434 
435     Returns:        none
436  *---------------------------------------------------------------------------*/
InitTexNumGen(MyTexCtrlObj * tco)437 static void InitTexNumGen( MyTexCtrlObj* tco )
438 {
439     tco->numGen0 = 0;
440     tco->numGen1 = 0;
441 }
442 
443 /*---------------------------------------------------------------------------*
444     Name:           ConfigureTmemMap
445 
446     Description:    Initialize TMEM configuration. Set up cache regions
447                     and preloading regions. This function also preloads
448                     specified textures.
449                     Texture #0 - #(numPreload - 1) are preloaded.
450 
451     Arguments:      tco : a pointer to MyTexCtrlObj structure which
452                           includes number of preloaded texture, texture
453                           object array and region array.
454 
455     Returns:        none
456  *---------------------------------------------------------------------------*/
ConfigureTmemMap(MyTexCtrlObj * tco)457 static void ConfigureTmemMap( MyTexCtrlObj* tco )
458 {
459     u32  i, r;
460     u32  numPreload, numCaches;
461 
462     // Synchronization for new TMEM cache configuration
463     GXTexModeSync();
464 
465     numPreload = tco->numPreload;
466     numCaches  = NUM_REGIONS - numPreload;
467 
468     for ( i = 0 ; i < NUM_REGIONS ; ++i )
469     {
470         if ( i < numPreload )
471         {
472             // The region is used for preloading.
473             // Though this test is using only 32K region, it is possible
474             // to use any 32byte-aligned region for preloading.
475             GXInitTexPreLoadRegion(
476                 &tco->texRegions[i],
477                 0x00000 + i * 0x08000,  // tmem_even
478                 0x08000,                // size_even
479                 0x80000 + i * 0x08000,  // tmem_odd
480                 0x08000 );              // size_odd
481 
482             // Preload texture (tex No.i uses region No.i respectively)
483             GXPreLoadEntireTexture(&tco->texObjs[i], &tco->texRegions[i]);
484             // The userdata field keeps the pointer to region object.
485             GXInitTexObjUserData(
486                 &tco->texObjs[i],
487                 (void*)(&tco->texRegions[i]) );
488         }
489         else
490         {
491             // The region is used as a cache.
492             GXInitTexCacheRegion(
493                 &tco->texRegions[i],
494                 GX_FALSE,               // 32b mipmap
495                 0x00000 + i * 0x08000,  // tmem_even
496                 GX_TEXCACHE_32K,        // size_even
497                 0x80000 + i * 0x08000,  // tmem_odd
498                 GX_TEXCACHE_32K );      // size_odd
499         }
500     }
501 
502     // Decide which cache region should be used beforehand.
503     for ( i = numPreload ; i < NUM_TEXTURES ; ++i )
504     {
505         // Get appropriate cache region number.
506         r = numPreload + ( i % numCaches );
507         // The userdata field keeps the pointer to region object directly.
508         GXInitTexObjUserData(
509             &tco->texObjs[i],
510             (void*)(&tco->texRegions[r]) );
511     }
512 
513     // Invalidate all new caches.
514     GXInvalidateTexAll();
515 }
516 
517 /*---------------------------------------------------------------------------*
518     Name:           MyTexRegionCallback
519 
520     Description:    User-defined Callback function for texture cache
521                     region allocation
522 
523     Arguments:      texObj : a pointer to texture object to be loaded
524                     mapID  : destination texmap ID (just same as GXLoadTexObj)
525 
526     Returns:        appropriate tex cache region for loading texture.
527  *---------------------------------------------------------------------------*/
MyTexRegionCallback(const GXTexObj * texObj,GXTexMapID mapID)528 static GXTexRegion* MyTexRegionCallback(const GXTexObj* texObj, GXTexMapID mapID)
529 {
530     #pragma unused(mapID)
531 
532     // In this test, userdata field already has a pointer
533     // to cache region to be used.
534     return (GXTexRegion*)(GXGetTexObjUserData(texObj));
535 }
536 
537 /*---------------------------------------------------------------------------*
538     Name:           SetCamera
539 
540     Description:    set view matrix and load projection matrix into hardware
541 
542     Arguments:      cam : pointer to the MyCameraObj structure
543 
544     Returns:        none
545  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)546 static void SetCamera( MyCameraObj* cam )
547 {
548     MTXLookAt(
549         cam->view,
550         &cam->cfg.location,
551         &cam->cfg.up,
552         &cam->cfg.target );
553 
554     MTXOrtho(
555         cam->proj,
556         cam->cfg.top,
557         - (cam->cfg.top),
558         cam->cfg.left,
559         - (cam->cfg.left),
560         cam->cfg.znear,
561         cam->cfg.zfar );
562     GXSetProjection(cam->proj, GX_ORTHOGRAPHIC);
563 }
564 
565 /*---------------------------------------------------------------------------*
566     Name:           StatusMessage
567 
568     Description:    Prints current status (number of preloaded textures.)
569 
570     Arguments:      numPreload : number of preloaded textures
571 
572     Returns:        none
573  *---------------------------------------------------------------------------*/
StatusMessage(u32 numPreload)574 static void StatusMessage( u32 numPreload )
575 {
576     if ( numPreload == 0 )
577     {
578         OSReport("No preloaded texture\n");
579     }
580     else if ( numPreload == 1 )
581     {
582         OSReport("0   : preloaded / 1-15 : cached\n");
583     }
584     else
585     {
586         OSReport("0-%d : preloaded / %d-15 : cached\n",
587                  numPreload-1, numPreload);
588     }
589 }
590 
591 /*---------------------------------------------------------------------------*
592     Name:           PrintIntro
593 
594     Description:    Prints the directions on how to use this demo.
595 
596     Arguments:      none
597 
598     Returns:        none
599  *---------------------------------------------------------------------------*/
PrintIntro(void)600 static void PrintIntro( void )
601 {
602     OSReport("\n\n");
603     OSReport("************************************************\n");
604     OSReport("tex-mix-mode: mixture of preloaded/cached tex test\n");
605     OSReport("************************************************\n");
606     OSReport("to quit hit the start button\n");
607     OSReport("\n");
608     OSReport("L/R Triggers : Change number of preloaded texture.\n");
609     OSReport("X/Y Buttons  : Change number of layers to be drawn.\n");
610     OSReport("************************************************\n\n");
611 }
612 
613 /*============================================================================*/
614