1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tex-preload.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-preload
15         simple texture preloading test
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <math.h>
24 
25 /*---------------------------------------------------------------------------*
26    Macro definitions
27  *---------------------------------------------------------------------------*/
28 #define PI            3.1415926F
29 
30 #define NUM_TEXTURES  16
31 
32 /*---------------------------------------------------------------------------*
33    Structure definitions
34  *---------------------------------------------------------------------------*/
35 // for camera
36 typedef struct
37 {
38     Vec    location;
39     Vec    up;
40     Vec    target;
41     f32    left;
42     f32    top;
43     f32    znear;
44     f32    zfar;
45 } CameraConfig;
46 
47 typedef struct
48 {
49     CameraConfig  cfg;
50     Mtx           view;
51     Mtx44         proj;
52 } MyCameraObj;
53 
54 // for texture
55 typedef struct
56 {
57     GXTexObj      texObjs[NUM_TEXTURES];
58     GXTexRegion   texRegions[NUM_TEXTURES];
59 } MyTexCtrlObj;
60 
61 // for entire scene control
62 typedef struct
63 {
64     MyCameraObj   cam;
65     s32           modelRot;
66     MyTexCtrlObj  texCtrl;
67 } MySceneCtrlObj;
68 
69 /*---------------------------------------------------------------------------*
70    Forward references
71  *---------------------------------------------------------------------------*/
72 void        main                 ( void );
73 static void DrawInit             ( MySceneCtrlObj* sc );
74 static void DrawTick             ( MySceneCtrlObj* sc );
75 static void AnimTick             ( MySceneCtrlObj* sc );
76 static void DrawCube             ( void );
77 static void TexInit              ( MyTexCtrlObj* tco );
78 static u32  GetTexBufferSizeEven ( u16 wd, u16 ht, u32 fmt, GXBool mm, u8 max );
79 static u32  GetTexBufferSizeOdd  ( u16 wd, u16 ht, u32 fmt, GXBool mm, u8 max );
80 static void SetCamera            ( MyCameraObj* cam );
81 static void PrintIntro           ( void );
82 
83 /*---------------------------------------------------------------------------*
84    Model Data
85  *---------------------------------------------------------------------------*/
86 static s16 CubeVertices[3*8] ATTRIBUTE_ALIGN(32) =
87 {
88     -32, -32,  32, // 0
89      32, -32,  32, // 1
90      32,  32,  32, // 2
91     -32,  32,  32, // 3
92     -32, -32, -32, // 4
93      32, -32, -32, // 5
94      32,  32, -32, // 6
95     -32,  32, -32  // 7
96 };
97 
98 static s16 CubeTexCoords[2*4] ATTRIBUTE_ALIGN(32) =
99 {
100       0,   0,
101       1,   0,
102       1,   1,
103       0,   1
104 };
105 
106 static u8 CubeFaces[6][4] =
107 {
108     { 3, 2, 1, 0 },
109     { 4, 5, 6, 7 },
110     { 4, 7, 3, 0 },
111     { 5, 4, 0, 1 },
112     { 6, 5, 1, 2 },
113     { 7, 6, 2, 3 }
114 };
115 
116 /*---------------------------------------------------------------------------*
117    Camera configuration
118  *---------------------------------------------------------------------------*/
119 static CameraConfig DefaultCamera =
120 {
121     { 0.0F, 0.0F, 500.0F }, // location
122     { 0.0F, 1.0F,   0.0F }, // up
123     { 0.0F, 0.0F,   0.0F }, // target
124     -32.0F, // left
125     24.0F,  // top
126     50.0F,  // near
127     2000.0F  // far
128 };
129 
130 /*---------------------------------------------------------------------------*
131    Global variables
132  *---------------------------------------------------------------------------*/
133 static MySceneCtrlObj   SceneCtrl;          // scene control parameters
134 static TPLPalettePtr    MyTplObj = NULL;    // texture palette
135 
136 /*---------------------------------------------------------------------------*
137    Application main loop
138  *---------------------------------------------------------------------------*/
main(void)139 void main ( void )
140 {
141     DEMOInit(NULL);
142 
143     DrawInit(&SceneCtrl); // Initialize vertex formats, array pointers
144                           // and default scene settings.
145 
146     PrintIntro();    // Print demo directions
147 
148     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
149     {
150         DEMOBeforeRender();
151         DrawTick(&SceneCtrl);    // Draw the model.
152         DEMODoneRender();
153         DEMOPadRead();           // Read controller
154         AnimTick(&SceneCtrl);    // Do animation
155     }
156 
157     OSHalt("End of demo");
158 }
159 
160 /*---------------------------------------------------------------------------*
161    Functions
162  *---------------------------------------------------------------------------*/
163 /*---------------------------------------------------------------------------*
164     Name:           DrawInit
165 
166     Description:    Initializes the vertex attribute format and sets up
167                     the array pointer for the indexed data.
168                     This function also initializes scene control parameters.
169 
170     Arguments:      sc : pointer to the structure of scene control parameters
171 
172     Returns:        none
173  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)174 static void DrawInit( MySceneCtrlObj* sc )
175 {
176     // Vertex Attribute
177     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
178     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0);
179 
180     // Array pointers
181     GXSetArray(GX_VA_POS,  CubeVertices, 3 * sizeof(s16));
182     GXSetArray(GX_VA_TEX0, CubeTexCoords, 2 * sizeof(s16));
183 
184     // Initialize texture objects / regions
185     TexInit(&sc->texCtrl);
186 
187 
188     // Default scene control parameter settings
189 
190     // camera
191     sc->cam.cfg = DefaultCamera;
192     SetCamera(&sc->cam);   // never changes in this test
193 
194     // model rotation parameter
195     sc->modelRot = 0;
196 }
197 
198 /*---------------------------------------------------------------------------*
199     Name:           DrawTick
200 
201     Description:    Draw the model by using given scene parameters
202 
203     Arguments:      sc : pointer to the structure of scene control parameters
204 
205     Returns:        none
206  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)207 static void DrawTick( MySceneCtrlObj* sc )
208 {
209     s32  i, ti;
210     Mtx  mt, mv, mr;
211     f32  px, py;
212 
213     // use 2-textures
214     GXSetNumTevStages(2);
215     GXSetTevOp   (GX_TEVSTAGE0, GX_REPLACE);
216     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
217     GXSetTevOp   (GX_TEVSTAGE1, GX_DECAL);
218     GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);
219     GXSetNumTexGens(2);
220     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
221     GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
222 
223     // entire rotation matrix
224     MTXRotDeg(mv, 'x', (f32)sc->modelRot / 8.0F);
225     MTXRotDeg(mr, 'z', (f32)sc->modelRot);
226     MTXConcat(mv, mr, mr);
227 
228     // texcoord matrix
229     MTXTrans(mv, -0.5F, -0.5F, 0.0F);
230     MTXRotDeg(mt, 'z', (f32)sc->modelRot);
231     MTXConcat(mt, mv, mv);
232     MTXTrans(mt, 0.5F, 0.5F, 0.0F);
233     MTXConcat(mt, mv, mv);
234     GXLoadTexMtxImm(mv, GX_TEXMTX0, GX_MTX2x4);
235 
236     for ( i = 0 ; i < 8 ; ++i )
237     {
238         // Set modelview matrix
239         px = 220.0F * cosf(i * PI * 45 / 180);
240         py = 220.0F * sinf(i * PI * 45 / 180);
241         MTXTrans( mt, px, py, 0.0F );
242 
243         MTXConcat(sc->cam.view, mr, mv);
244         MTXConcat(mv, mt, mv);
245         GXLoadPosMtxImm(mv, GX_PNMTX0);
246 
247         // Load preloaded texture
248         ti = ( i * 2 ) % NUM_TEXTURES;
249 
250         GXLoadTexObjPreLoaded(
251             &sc->texCtrl.texObjs[ti],
252             &sc->texCtrl.texRegions[ti],
253             GX_TEXMAP0 );
254         GXLoadTexObjPreLoaded(
255             &sc->texCtrl.texObjs[ti+1],
256             &sc->texCtrl.texRegions[ti+1],
257             GX_TEXMAP1 );
258 
259         // Draw a textured cube
260         DrawCube();
261     }
262 
263 }
264 
265 /*---------------------------------------------------------------------------*
266     Name:           AnimTick
267 
268     Description:    Changes scene parameters.
269 
270     Arguments:      sc : pointer to the structure of scene control parameters
271 
272     Returns:        none
273  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)274 static void AnimTick( MySceneCtrlObj* sc )
275 {
276     // Model rotation parameter
277     if (!(DEMOPadGetButton(0) & PAD_BUTTON_A ))
278     {
279         sc->modelRot = ( sc->modelRot + 1 ) % ( 360 * 16 );
280     }
281 }
282 
283 /*---------------------------------------------------------------------------*
284     Name:           DrawCube
285 
286     Description:    Draw a textured cube.
287 
288     Arguments:      none
289 
290     Returns:        none
291  *---------------------------------------------------------------------------*/
DrawCube(void)292 static void DrawCube( void )
293 {
294     u8   i, j;
295 
296     // set vertex descriptor
297     GXClearVtxDesc();
298     GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
299     GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
300 
301     // draw the box
302     GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
303     for ( i = 0 ; i < 6 ; ++i )
304     {
305         // Draw a face
306         for ( j = 0 ; j < 4 ; ++j )
307         {
308             GXPosition1x8(CubeFaces[i][j]);
309             GXTexCoord1x8(j);
310         }
311     }
312     GXEnd();
313 }
314 
315 /*---------------------------------------------------------------------------*
316     Name:           TexInit
317 
318     Description:    Initialize texture objects and regions for preloaded
319                     texture. This function also does preloading.
320 
321     Arguments:      tco : pointer to a MyTexCtrlObj structure
322 
323     Returns:        none
324  *---------------------------------------------------------------------------*/
TexInit(MyTexCtrlObj * tco)325 static void TexInit( MyTexCtrlObj* tco )
326 {
327     TPLDescriptorPtr  tdp;
328     GXTlutObj         tlo;
329     GXBool            mipMapFlag;
330     u32               fmt;
331     u16               wd, ht;
332     u8                max;
333     u32               tmemLow, tmemHigh;
334     u32               sizeEven, sizeOdd;
335     u32               i, tlutNum;
336 
337     tmemLow  = 0x00000;
338     tmemHigh = 0x80000;
339     tlutNum  = 0;
340 
341     TPLGetPalette(&MyTplObj, "gxTests/tex-08.tpl");
342     for ( i = 0 ; i < NUM_TEXTURES ; ++i )
343     {
344         tdp = TPLGet(MyTplObj, i);
345         mipMapFlag =
346             (GXBool)(( tdp->textureHeader->minLOD == tdp->textureHeader->maxLOD ) ?
347                      GX_FALSE : GX_TRUE);
348 
349         wd  = tdp->textureHeader->width;
350         ht  = tdp->textureHeader->height;
351         fmt = tdp->textureHeader->format;
352         max = (u8)tdp->textureHeader->maxLOD;
353 
354         // Calculate region size
355         sizeEven = GetTexBufferSizeEven(wd, ht, fmt, mipMapFlag, max);
356         sizeOdd  = GetTexBufferSizeOdd(wd, ht, fmt, mipMapFlag, max);
357 
358         if (tdp->CLUTHeader)
359         {
360             // CI format
361             GXInitTexObjCI(
362                 &tco->texObjs[i],
363                 tdp->textureHeader->data,
364                 wd,
365                 ht,
366                 (GXCITexFmt)fmt,
367                 tdp->textureHeader->wrapS, // s
368                 tdp->textureHeader->wrapT, // t
369                 mipMapFlag,                // Mipmap
370                 tlutNum );
371 
372             // Load Tlut data
373             GXInitTlutObj(
374                 &tlo,
375                 tdp->CLUTHeader->data,
376                 (GXTlutFmt)tdp->CLUTHeader->format,
377                 tdp->CLUTHeader->numEntries );
378             GXLoadTlut(&tlo, tlutNum);
379 
380             // Create new region
381             GXInitTexPreLoadRegion(
382                 &tco->texRegions[i],
383                 tmemLow,             // tmem_even
384                 sizeEven,            // size_even
385                 tmemLow + sizeEven,  // tmem_odd
386                 sizeOdd );           // size_odd
387             // Both even/odd regions are placed on lower bank
388             // in the case of CI format.
389 
390             tmemLow += sizeEven + sizeOdd;
391             ++tlutNum;
392         }
393         else
394         {
395             // Non-CI format
396             GXInitTexObj(
397                 &tco->texObjs[i],
398                 tdp->textureHeader->data,
399                 wd,
400                 ht,
401                 (GXTexFmt)fmt,
402                 tdp->textureHeader->wrapS, // s
403                 tdp->textureHeader->wrapT, // t
404                 mipMapFlag );    // Mipmap
405 
406             // Create new region
407             GXInitTexPreLoadRegion(
408                 &tco->texRegions[i],
409                 tmemLow,             // tmem_even
410                 sizeEven,            // size_even
411                 tmemHigh,            // tmem_odd
412                 sizeOdd );           // size_odd
413 
414             tmemLow  += sizeEven;
415             tmemHigh += sizeOdd;
416         }
417 
418         // LOD setting
419         GXInitTexObjLOD(
420             &tco->texObjs[i],
421             tdp->textureHeader->minFilter,
422             tdp->textureHeader->magFilter,
423             tdp->textureHeader->minLOD,
424             tdp->textureHeader->maxLOD,
425             tdp->textureHeader->LODBias,
426             GX_FALSE,
427             tdp->textureHeader->edgeLODEnable,
428             GX_ANISO_1 );
429 
430         // Preload texture (texture i uses region i)
431         GXPreLoadEntireTexture(&tco->texObjs[i], &tco->texRegions[i]);
432     }
433 
434     // In general case, we also have to re-configure
435     // cache regions and region callback in order to avoid
436     // redundant usage of same TMEM space. (Default TMEM
437     // configuration prepares no area for preloading.)
438     // As for this test, such procedure is dispensable
439     // because all textures are preloaded and so GXLoadTexObj
440     // is never called.
441     // (An example of mixture usage of cached/preloaded
442     // textures is shown in tex-mix-mode.c. See it also.)
443 }
444 
445 /*---------------------------------------------------------------------------*
446     Name:           GetTexBufferSizeEven
447 
448     Description:    returns memory size for preloading region
449                     (for even LODs)
450 
451     Arguments:      wd  : texture width
452                     ht  : texture height
453                     fmt : texture format
454                     mm  : mipmap switch
455                     max : max lod value
456 
457     Returns:        required region size
458  *---------------------------------------------------------------------------*/
GetTexBufferSizeEven(u16 wd,u16 ht,u32 fmt,GXBool mm,u8 max)459 static u32 GetTexBufferSizeEven( u16 wd, u16 ht, u32 fmt, GXBool mm, u8 max )
460 {
461     u32  i;
462     u32  size;
463 
464     if ( fmt == GX_TF_RGBA8 )
465     {
466         // 32bit format (mipmap/non-mipmap)
467         size = GXGetTexBufferSize(wd, ht, fmt, mm, (u8)(max+1));
468         size /= 2;
469     }
470     else if ( mm == GX_FALSE )
471     {
472         // non-mipmap
473         size = GXGetTexBufferSize(wd, ht, fmt, GX_FALSE, 0);
474     }
475     else
476     {
477         // mipmap
478         size = 0;
479         for ( i = 0 ; i <= max ; i += 2 )
480         {
481             size += GXGetTexBufferSize(wd, ht, fmt, GX_FALSE, 1);
482             wd >>= 2;
483             ht >>= 2;
484         }
485     }
486 
487     return size;
488 }
489 
490 /*---------------------------------------------------------------------------*
491     Name:           GetTexBufferSizeOdd
492 
493     Description:    returns memory size for preloading region
494                     (for odd LODs)
495 
496     Arguments:      wd  : texture width
497                     ht  : texture height
498                     fmt : texture format
499                     mm  : mipmap switch
500                     max : max lod value
501 
502     Returns:        required region size
503  *---------------------------------------------------------------------------*/
GetTexBufferSizeOdd(u16 wd,u16 ht,u32 fmt,GXBool mm,u8 max)504 static u32 GetTexBufferSizeOdd( u16 wd, u16 ht, u32 fmt, GXBool mm, u8 max )
505 {
506     u32 size;
507 
508     size = GXGetTexBufferSize(wd, ht, fmt, mm, (u8)(max+1))
509          - GetTexBufferSizeEven(wd, ht, fmt, mm, max);
510 
511     return size;
512 }
513 
514 /*---------------------------------------------------------------------------*
515     Name:           SetCamera
516 
517     Description:    set view matrix and load projection matrix into hardware
518 
519     Arguments:      cam : pointer to the MyCameraObj structure
520 
521     Returns:        none
522  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)523 static void SetCamera( MyCameraObj* cam )
524 {
525     MTXLookAt(
526         cam->view,
527         &cam->cfg.location,
528         &cam->cfg.up,
529         &cam->cfg.target );
530 
531     MTXFrustum(
532         cam->proj,
533         cam->cfg.top,
534         - (cam->cfg.top),
535         cam->cfg.left,
536         - (cam->cfg.left),
537         cam->cfg.znear,
538         cam->cfg.zfar );
539     GXSetProjection(cam->proj, GX_PERSPECTIVE);
540 }
541 
542 /*---------------------------------------------------------------------------*
543     Name:           PrintIntro
544 
545     Description:    Prints the directions on how to use this demo.
546 
547     Arguments:      none
548 
549     Returns:        none
550  *---------------------------------------------------------------------------*/
PrintIntro(void)551 static void PrintIntro( void )
552 {
553     OSReport("\n\n");
554     OSReport("************************************************\n");
555     OSReport("tex-preload: texture preloading test\n");
556     OSReport("************************************************\n");
557     OSReport("to quit hit the start button\n");
558     OSReport("A Button : pause animation while pressed\n");
559     OSReport("\n");
560     OSReport("************************************************\n\n");
561 }
562 
563 /*============================================================================*/
564