1 /*---------------------------------------------------------------------------*
2 Project: Dolphin
3 File: gd-texture-create.c
4
5 Copyright 2001 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 $Log: gd-texture-create.c,v $
14 Revision 1.2 02/20/2006 04:13:10 mitu
15 changed include path from dolphin/ to revolution/.
16
17 Revision 1.1 02/08/2006 11:19:43 mitu
18 1st version.
19
20
21 4 11/08/01 6:38p Carl
22 Added code to change TMEM configuration.
23
24 3 10/13/01 2:29a Hirose
25 Fixes due to GDSetTexCoordGen API change.
26
27 2 10/11/01 4:05p Carl
28 Added use of color-index texture and TLUT.
29
30 1 9/19/01 4:27p Carl
31 Sources for GD texture demo.
32
33 $NoKeywords: $
34 *---------------------------------------------------------------------------*/
35
36 #include <revolution/gd.h>
37 #include <revolution/mtx/GeoTypes.h>
38
39 #ifdef WIN32
40 #include <assert.h>
41 #include <stdlib.h>
42 #else
43 #include <revolution/os.h>
44 #endif
45
46 /*---------------------------------------------------------------------------*/
47
48 #ifdef WIN32
49 #define ASSERT assert
50 #define OSRoundUp32B(x) (((u32)(x) + 31) & ~31)
51 #define OSAlloc(x) ((void*)OSRoundUp32B(malloc((x)+31)))
52 #define OSFree(x) free(x)
53 #endif
54
55 /*---------------------------------------------------------------------------*
56 Forward references
57 *---------------------------------------------------------------------------*/
58
59 void CreateDLs( void );
60
61 /*---------------------------------------------------------------------------*
62 Global variables
63 *---------------------------------------------------------------------------*/
64
65 // Display lists *************************************************************
66
67 // This DL is used with the "Draw" display list.
68 // It initializes state that will be used by the Draw DL.
69
70 extern GDLObj InitDLO;
71 #define INIT_STATE_SIZE 2048 // maximum (not actual) size
72
73 // This DL draws a textured cube. It must be paired with the Init DL.
74
75 extern GDLObj DrawDLO;
76 #define DRAW_SIZE 2048 // maximum (not actual) size
77
78 // This array indicates the offsets to patch memory addresses for the
79 // primitive data arrays (positions, normals, texture coordinates)
80 // referred to in the Init DL.
81
82 extern u32 *setArrayOffsets;
83
84 // This array tells us the offsets for where to patch the memory addresses
85 // for the textures in the Draw DL.
86
87 extern u32 *texAddrOffsets;
88
89 // This array tells us the offsets for where to patch the main memory
90 // addresses for loading the TLUTs in the Init DL.
91
92 extern u32 *tlutAddrOffsets;
93
94 // This TLUT address (in TMEM) corresponds to the first 256-entry
95 // TLUT in the default GX allocation (tlut 0). Consider using the
96 // array GXTlutRegions (from GDTexture.c) if you extensively use the
97 // default GX TLUT allocation scheme.
98
99 #define TLUT0_ADDR 0xC0000
100
101 /*---------------------------------------------------------------------------*/
102
103 // This array is used to map texture cache regions in TMEM. It
104 // follows GX's default TMEM configuration. In the default configuration,
105 // texmap 0 uses the first pair of addresses in the list, texmap 1 uses the
106 // second, and so on. In this demo, we use only texmap 0 and change its
107 // mapping based on the texture we draw, making sure that each different
108 // texture uses a unique cache region. Of course, we could just as easily
109 // have used a unique texmap per texture, but for this demo we wanted to
110 // emphasize how you must pay attention to texture cache use.
111
112 u32 MyTmemRegions[8][2] = {
113 // TMEM LO, TMEM HI
114 { 0x00000, 0x80000 }, // (default assignment for texmap 0)
115 { 0x08000, 0x88000 }, // 1
116 { 0x10000, 0x90000 }, // 2
117 { 0x18000, 0x98000 }, // 3
118 { 0x20000, 0xa0000 }, // 4
119 { 0x28000, 0xa8000 }, // 5
120 { 0x30000, 0xb0000 }, // 6
121 { 0x38000, 0xb8000 } // 7
122 };
123
124 /*---------------------------------------------------------------------------*
125 Functions
126 *---------------------------------------------------------------------------*/
127
128 /*---------------------------------------------------------------------------*
129 Name: CreateDLs
130
131 Description: Creates the display lists used by the program.
132
133 Arguments: none
134
135 Returns: none
136 *---------------------------------------------------------------------------*/
CreateDLs(void)137 void CreateDLs ( void )
138 {
139 u8 *InitStateList;
140 u8 *DrawList;
141
142 //
143 // Create the init-state DL
144 //
145
146 // This display list initializes some important drawing state that will
147 // be used by the Draw DL. We will initialize the VCD/VAT, the array
148 // base pointers, the texture lookup state, and the texcoord scaling.
149
150 InitStateList = OSAlloc( INIT_STATE_SIZE );
151 ASSERT(InitStateList);
152
153 setArrayOffsets = OSAlloc( 3 * sizeof(u32) );
154 ASSERT(setArrayOffsets);
155
156 tlutAddrOffsets = OSAlloc( 1 * sizeof(u32) );
157 ASSERT(tlutAddrOffsets);
158
159 GDInitGDLObj( &InitDLO, InitStateList, INIT_STATE_SIZE );
160 GDSetCurrent( &InitDLO );
161
162 // Set the VCD and VAT
163 {
164 static GXVtxDescList vcd[] = {
165 { GX_VA_POS, GX_INDEX8 },
166 { GX_VA_NRM, GX_INDEX8 },
167 { GX_VA_TEX0, GX_INDEX8 },
168 { GX_VA_NULL, GX_NONE }, // NULL terminator is required
169 };
170 static GXVtxAttrFmtList vat[] = {
171 { GX_VA_POS, GX_POS_XYZ, GX_F32, 0 },
172 { GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0 },
173 { GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 },
174 { GX_VA_NULL, GX_POS_XY, GX_U8, 0 }, // NULL terminator is required
175 };
176
177 GDSetVtxDescv( vcd );
178 GDSetVtxAttrFmtv( GX_VTXFMT0, vat );
179 }
180
181 // Set the vertex array pointers and strides. The actual array
182 // pointers will be patched in later, so we need to keep track of
183 // these patch points.
184 // We add a bit to skip over the command token and register ID bytes.
185
186 setArrayOffsets[0] = GDGetCurrOffset() + CP_DATA_OFFSET;
187 GDSetArrayRaw(GX_VA_POS, 0, 12);
188
189 setArrayOffsets[1] = GDGetCurrOffset() + CP_DATA_OFFSET;
190 GDSetArrayRaw(GX_VA_NRM, 0, 12);
191
192 setArrayOffsets[2] = GDGetCurrOffset() + CP_DATA_OFFSET;
193 GDSetArrayRaw(GX_VA_TEX0, 0, 8);
194
195 // Commands to initialize (most of) texture ID 0 and texcoord 0 scale:
196 // This DL is used with the Draw display list, which assumes that
197 // texture ID 0 and texcoord 0 have been set up in this way.
198
199 // Since all the textures we're using are the same size and have mostly
200 // the same attributes, we can get away with this. Otherwise, these
201 // registers would have to be loaded for each face in the DrawList.
202
203 // Initialize TEXMAP0 lookup attributes.
204 GDSetTexLookupMode( GX_TEXMAP0, // tmap
205 GX_REPEAT, // wrap s
206 GX_REPEAT, // wrap t
207 GX_LIN_MIP_LIN, // min filt
208 GX_LINEAR, // mag filt
209 0.0f, // min LOD
210 7.0f, // max LOD
211 0.0f, // LOD bias
212 GX_FALSE, // bias clamp?
213 GX_TRUE, // do edge LOD?
214 GX_ANISO_1 ); // max aniso
215
216 // And texcoord0 scale parameters.
217 GDSetTexCoordScale2( GX_TEXCOORD0, // tcoord
218 128, GX_FALSE, GX_FALSE, // s size, bias, wrap
219 128, GX_FALSE, GX_FALSE ); // t size, bias, wrap
220
221 // Set the texture TLUT parameters. This will only be used by the
222 // texture format that is color-indexed.
223 GDSetTexTlut ( GX_TEXMAP0, TLUT0_ADDR, GX_TL_RGB565 );
224
225 // Need to save this offset for the LoadTlut command.
226 tlutAddrOffsets[0] = GDGetCurrOffset() + BP_CMD_LENGTH*2 + BP_DATA_OFFSET;
227
228 // Load the TLUT. Again, this is only needed for the CI texture.
229 // We don't know the correct memory address now; it will be patched later.
230 GDLoadTlutRaw ( 0, TLUT0_ADDR, GX_TLUT_256 );
231
232 // That's all the commands for that DL; now pad to 32-byte boundary.
233 GDPadCurr32();
234
235 GDFlushCurrToMem(); // not strictly needed for PC-side, but not a bad idea
236
237 //
238 // Create the cube drawing DL
239 //
240
241 // Draw DL: commands to select textures and draw the actual geometry.
242 // This display list must be paired with the Init DL. It assumes a
243 // particular texture setup which is setup by that DL. As a result,
244 // it can switch textures by changing only the minimum number of
245 // registers.
246
247 DrawList = OSAlloc( DRAW_SIZE );
248 ASSERT(DrawList);
249
250 texAddrOffsets = OSAlloc( 6 * sizeof(u32) );
251 ASSERT(texAddrOffsets);
252
253 GDInitGDLObj( &DrawDLO, DrawList, DRAW_SIZE );
254 GDSetCurrent( &DrawDLO );
255
256 // face 1
257
258 // Set texture format. This changes among the various faces.
259 GDSetTexImgAttr( GX_TEXMAP0, // tmap
260 128, // width
261 128, // height
262 GX_TF_RGB5A3 ); // format
263
264 // Set the texture TMEM cache usage for this texture.
265 // We make sure that each texture uses a different region.
266 // (See the comment for MyTmemRegions up above.)
267 GDSetTexCached( GX_TEXMAP0, MyTmemRegions[0][0], GX_TEXCACHE_32K,
268 MyTmemRegions[0][1], GX_TEXCACHE_32K );
269
270 // Save the offset that will indicate the texture main-memory address.
271 // We add a bit to skip over the command token and register ID bytes.
272 texAddrOffsets[0] = GDGetCurrOffset() + BP_DATA_OFFSET;
273
274 // Insert command to load the texture main-memory address.
275 // We use the raw form since we don't have a valid address to use now.
276 // The real address will be patched in later.
277 GDSetTexImgPtrRaw( GX_TEXMAP0, 0 );
278
279 // Draw face.
280 GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
281 GDPosition1x8( 0 ); GDNormal1x8( 0 ); GDTexCoord1x8( 0 );
282 GDPosition1x8( 1 ); GDNormal1x8( 1 ); GDTexCoord1x8( 1 );
283 GDPosition1x8( 2 ); GDNormal1x8( 2 ); GDTexCoord1x8( 2 );
284 GDPosition1x8( 3 ); GDNormal1x8( 3 ); GDTexCoord1x8( 3 );
285 GDEnd();
286
287 // That's it for this face.
288 // The next 5 faces follow mostly the same layout.
289
290 // face 2
291
292 GDSetTexImgAttr( GX_TEXMAP0, // tmap
293 128, // width
294 128, // height
295 GX_TF_CMPR ); // format
296
297 GDSetTexCached( GX_TEXMAP0, MyTmemRegions[1][0], GX_TEXCACHE_32K,
298 MyTmemRegions[1][1], GX_TEXCACHE_32K );
299
300 texAddrOffsets[1] = GDGetCurrOffset() + BP_DATA_OFFSET;
301
302 GDSetTexImgPtrRaw( GX_TEXMAP0, 0 );
303
304 GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
305 GDPosition1x8( 4 ); GDNormal1x8( 4 ); GDTexCoord1x8( 0 );
306 GDPosition1x8( 5 ); GDNormal1x8( 5 ); GDTexCoord1x8( 1 );
307 GDPosition1x8( 6 ); GDNormal1x8( 6 ); GDTexCoord1x8( 2 );
308 GDPosition1x8( 7 ); GDNormal1x8( 7 ); GDTexCoord1x8( 3 );
309 GDEnd();
310
311 // face 3
312
313 GDSetTexImgAttr( GX_TEXMAP0, // tmap
314 128, // width
315 128, // height
316 GX_TF_RGBA8 ); // format
317
318 GDSetTexCached( GX_TEXMAP0, MyTmemRegions[2][0], GX_TEXCACHE_32K,
319 MyTmemRegions[2][1], GX_TEXCACHE_32K );
320
321 texAddrOffsets[2] = GDGetCurrOffset() + BP_DATA_OFFSET;
322
323 GDSetTexImgPtrRaw( GX_TEXMAP0, 0 );
324
325 GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
326 GDPosition1x8( 2 ); GDNormal1x8( 2 ); GDTexCoord1x8( 0 );
327 GDPosition1x8( 6 ); GDNormal1x8( 6 ); GDTexCoord1x8( 1 );
328 GDPosition1x8( 5 ); GDNormal1x8( 5 ); GDTexCoord1x8( 2 );
329 GDPosition1x8( 3 ); GDNormal1x8( 3 ); GDTexCoord1x8( 3 );
330 GDEnd();
331
332 // face 4
333
334 GDSetTexImgAttr( GX_TEXMAP0, // tmap
335 128, // width
336 128, // height
337 GX_TF_I4 ); // format
338
339 GDSetTexCached( GX_TEXMAP0, MyTmemRegions[3][0], GX_TEXCACHE_32K,
340 MyTmemRegions[3][1], GX_TEXCACHE_32K );
341
342 texAddrOffsets[3] = GDGetCurrOffset() + BP_DATA_OFFSET;
343
344 GDSetTexImgPtrRaw( GX_TEXMAP0, 0 );
345
346 GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
347 GDPosition1x8( 1 ); GDNormal1x8( 1 ); GDTexCoord1x8( 0 );
348 GDPosition1x8( 0 ); GDNormal1x8( 0 ); GDTexCoord1x8( 1 );
349 GDPosition1x8( 4 ); GDNormal1x8( 4 ); GDTexCoord1x8( 2 );
350 GDPosition1x8( 7 ); GDNormal1x8( 7 ); GDTexCoord1x8( 3 );
351 GDEnd();
352
353 // face 5
354
355 GDSetTexImgAttr( GX_TEXMAP0, // tmap
356 128, // width
357 128, // height
358 GX_TF_IA8 ); // format
359
360 GDSetTexCached( GX_TEXMAP0, MyTmemRegions[4][0], GX_TEXCACHE_32K,
361 MyTmemRegions[4][1], GX_TEXCACHE_32K );
362
363 texAddrOffsets[4] = GDGetCurrOffset() + BP_DATA_OFFSET;
364
365 GDSetTexImgPtrRaw( GX_TEXMAP0, 0 );
366
367 GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
368 GDPosition1x8( 5 ); GDNormal1x8( 5 ); GDTexCoord1x8( 0 );
369 GDPosition1x8( 4 ); GDNormal1x8( 4 ); GDTexCoord1x8( 1 );
370 GDPosition1x8( 0 ); GDNormal1x8( 0 ); GDTexCoord1x8( 2 );
371 GDPosition1x8( 3 ); GDNormal1x8( 3 ); GDTexCoord1x8( 3 );
372 GDEnd();
373
374 // face 6
375
376 GDSetTexImgAttr( GX_TEXMAP0, // tmap
377 128, // width
378 128, // height
379 (GXTexFmt)GX_TF_C8 ); // format
380
381 GDSetTexCached( GX_TEXMAP0, MyTmemRegions[5][0], GX_TEXCACHE_32K,
382 MyTmemRegions[5][1], GX_TEXCACHE_32K );
383
384 // The color-index texture has different lookup properties:
385
386 GDSetTexLookupMode( GX_TEXMAP0, // tmap
387 GX_REPEAT, // wrap s
388 GX_REPEAT, // wrap t
389 GX_LIN_MIP_NEAR, // min filt
390 GX_LINEAR, // mag filt
391 0.0f, // min LOD
392 0.0f, // max LOD
393 0.0f, // LOD bias
394 GX_FALSE, // bias clamp?
395 GX_TRUE, // do edge LOD?
396 GX_ANISO_1 ); // max aniso
397
398 texAddrOffsets[5] = GDGetCurrOffset() + BP_DATA_OFFSET;
399
400 GDSetTexImgPtrRaw( GX_TEXMAP0, 0 );
401
402 GDBegin( GX_QUADS, GX_VTXFMT0, 4 );
403 GDPosition1x8( 6 ); GDNormal1x8( 6 ); GDTexCoord1x8( 0 );
404 GDPosition1x8( 2 ); GDNormal1x8( 2 ); GDTexCoord1x8( 1 );
405 GDPosition1x8( 1 ); GDNormal1x8( 1 ); GDTexCoord1x8( 2 );
406 GDPosition1x8( 7 ); GDNormal1x8( 7 ); GDTexCoord1x8( 3 );
407 GDEnd();
408
409 // pad & flush
410 GDPadCurr32();
411 GDFlushCurrToMem(); // not strictly needed for PC-side, but not a bad idea
412
413 GDSetCurrent(NULL); // bug-prevention
414 }
415