1 /*---------------------------------------------------------------------------*
2 Project: Dolphin GD library
3 File: GDTexture.c
4
5 Copyright 2001- 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 $Log: GDTexture.c,v $
14 Revision 1.3 2006/02/20 04:24:39 mitu
15 Changed include path from dolphin/ to revolution/.
16
17 Revision 1.2 2006/02/03 08:54:38 hirose
18 Avoided use of EPPC and use WIN32.
19
20 Revision 1.1.1.1 2005/05/12 02:15:49 yasuh-to
21 Ported from dolphin source tree.
22
23
24 7 2001/10/30 2:11p Hirose
25 Fixed time stamp problem.
26
27 7 2002/10/17 4:37p Hirose
28 Fixed image type bit setting of GDSetTexPreLoaded().
29
30 6 2001/10/13 2:27a Hirose
31 Changed GDSetTexCoordScale function.
32
33 5 2001/10/10 12:06p Carl
34 Fixed filter conversion table.
35
36 4 2001/10/04 4:46p Carl
37 Added GDLoadTlut, etc.
38
39 3 10/02/01 5:16p Carl
40 Fixed bug in GDSetTexTlut.
41
42 2 2001/09/14 6:43p Carl
43 Made OSCachedToPhysical a macro for non-EPPC.
44
45 1 2001/09/12 1:52p Carl
46 Initial revision of GD: Graphics Display List Library.
47
48 $NoKeywords: $
49 *---------------------------------------------------------------------------*/
50
51 #include <revolution/gd.h>
52 #include <revolution/os.h>
53
54 #if defined(WIN32) && !defined(OSCachedToPhysical)
55 #define OSCachedToPhysical(caddr) ((u32)((u8*)(caddr) - (0x80000000)))
56 #endif
57
58 /*---------------------------------------------------------------------------*/
59
60 // The table below is convenient for using the GX default TLUT allocation.
61 // It defines TMEM addresses for 20 TLUT's:
62 // - the first 16 TLUT's are 256 entry
63 // - the final 4 TLUT's are 1024 entry
64
65 #ifdef DEFINE_TLUT_TABLE
66 #define GX_TMEM_HI 0x80000
67 #define GX_32k 0x08000
68 #define GX_8k 0x02000
69 u32 GXTlutRegions[20] = {
70 GX_TMEM_HI + GX_32k*8 + GX_8k*0,
71 GX_TMEM_HI + GX_32k*8 + GX_8k*1,
72 GX_TMEM_HI + GX_32k*8 + GX_8k*2,
73 GX_TMEM_HI + GX_32k*8 + GX_8k*3,
74 GX_TMEM_HI + GX_32k*8 + GX_8k*4,
75 GX_TMEM_HI + GX_32k*8 + GX_8k*5,
76 GX_TMEM_HI + GX_32k*8 + GX_8k*6,
77 GX_TMEM_HI + GX_32k*8 + GX_8k*7,
78 GX_TMEM_HI + GX_32k*8 + GX_8k*8,
79 GX_TMEM_HI + GX_32k*8 + GX_8k*9,
80 GX_TMEM_HI + GX_32k*8 + GX_8k*10,
81 GX_TMEM_HI + GX_32k*8 + GX_8k*11,
82 GX_TMEM_HI + GX_32k*8 + GX_8k*12,
83 GX_TMEM_HI + GX_32k*8 + GX_8k*13,
84 GX_TMEM_HI + GX_32k*8 + GX_8k*14,
85 GX_TMEM_HI + GX_32k*8 + GX_8k*15,
86 GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*0,
87 GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*1,
88 GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*2,
89 GX_TMEM_HI + GX_32k*8 + GX_8k*16 + GX_32k*3,
90 };
91 #endif
92
93 // The tables below are used in the library code to map texmap ID's
94 // to register addresses. If you are linking with GX, you can use
95 // the same tables that are defined within GX.
96
97 #ifndef LINKING_WITH_GX
98
99 u8 GDTexMode0Ids[8] = {
100 TX_SETMODE0_I0_ID,
101 TX_SETMODE0_I1_ID,
102 TX_SETMODE0_I2_ID,
103 TX_SETMODE0_I3_ID,
104 TX_SETMODE0_I4_ID,
105 TX_SETMODE0_I5_ID,
106 TX_SETMODE0_I6_ID,
107 TX_SETMODE0_I7_ID,
108 };
109
110 u8 GDTexMode1Ids[8] = {
111 TX_SETMODE1_I0_ID,
112 TX_SETMODE1_I1_ID,
113 TX_SETMODE1_I2_ID,
114 TX_SETMODE1_I3_ID,
115 TX_SETMODE1_I4_ID,
116 TX_SETMODE1_I5_ID,
117 TX_SETMODE1_I6_ID,
118 TX_SETMODE1_I7_ID,
119 };
120
121 u8 GDTexImage0Ids[8] = {
122 TX_SETIMAGE0_I0_ID,
123 TX_SETIMAGE0_I1_ID,
124 TX_SETIMAGE0_I2_ID,
125 TX_SETIMAGE0_I3_ID,
126 TX_SETIMAGE0_I4_ID,
127 TX_SETIMAGE0_I5_ID,
128 TX_SETIMAGE0_I6_ID,
129 TX_SETIMAGE0_I7_ID,
130 };
131
132 u8 GDTexImage1Ids[8] = {
133 TX_SETIMAGE1_I0_ID,
134 TX_SETIMAGE1_I1_ID,
135 TX_SETIMAGE1_I2_ID,
136 TX_SETIMAGE1_I3_ID,
137 TX_SETIMAGE1_I4_ID,
138 TX_SETIMAGE1_I5_ID,
139 TX_SETIMAGE1_I6_ID,
140 TX_SETIMAGE1_I7_ID,
141 };
142
143 u8 GDTexImage2Ids[8] = {
144 TX_SETIMAGE2_I0_ID,
145 TX_SETIMAGE2_I1_ID,
146 TX_SETIMAGE2_I2_ID,
147 TX_SETIMAGE2_I3_ID,
148 TX_SETIMAGE2_I4_ID,
149 TX_SETIMAGE2_I5_ID,
150 TX_SETIMAGE2_I6_ID,
151 TX_SETIMAGE2_I7_ID,
152 };
153
154 u8 GDTexImage3Ids[8] = {
155 TX_SETIMAGE3_I0_ID,
156 TX_SETIMAGE3_I1_ID,
157 TX_SETIMAGE3_I2_ID,
158 TX_SETIMAGE3_I3_ID,
159 TX_SETIMAGE3_I4_ID,
160 TX_SETIMAGE3_I5_ID,
161 TX_SETIMAGE3_I6_ID,
162 TX_SETIMAGE3_I7_ID,
163 };
164
165 u8 GDTexTlutIds[8] = {
166 TX_SETTLUT_I0_ID,
167 TX_SETTLUT_I1_ID,
168 TX_SETTLUT_I2_ID,
169 TX_SETTLUT_I3_ID,
170 TX_SETTLUT_I4_ID,
171 TX_SETTLUT_I5_ID,
172 TX_SETTLUT_I6_ID,
173 TX_SETTLUT_I7_ID,
174 };
175
176 u8 GD2HWFiltConv[] = {
177 0, // TX_MIN_NEAREST, // GX_NEAR,
178 4, // TX_MIN_LINEAR, // GX_LINEAR,
179 1, // TX_MIN_NEAREST_MIPMAP_NEAREST, // GX_NEAR_MIP_NEAR,
180 5, // TX_MIN_LINEAR_MIPMAP_NEAREST, // GX_LIN_MIP_NEAR,
181 2, // TX_MIN_NEAREST_MIPMAP_LINEAR, // GX_NEAR_MIP_LIN,
182 6, // TX_MIN_LINEAR_MIPMAP_LINEAR, // GX_LIN_MIP_LIN
183 };
184
185 #else
186
187 // If we're linking with GX, no need to duplicate these arrays; just use GX's values.
188
189 #define GDTexMode0Ids GXTexMode0Ids
190 #define GDTexMode1Ids GXTexMode1Ids
191 #define GDTexImage0Ids GXTexImage0Ids
192 #define GDTexImage1Ids GXTexImage1Ids
193 #define GDTexImage2Ids GXTexImage2Ids
194 #define GDTexImage3Ids GXTexImage3Ids
195 #define GDTexTlutIds GXTexTlutIds
196 #define GD2HWFiltConv GX2HWFiltConv
197
198 #endif
199
200 /*---------------------------------------------------------------------------*/
201 // Name: GDSetTexLookupMode
202 //
203 // Description: Sets various texture lookup attributes for a given tex ID.
204 //
205 // Arguments: id: which texture ID will be set
206 // ...: parameters to set, as indicated by name
207 //
208 // Returns: none
209 //
210 /*---------------------------------------------------------------------------*/
211
GDSetTexLookupMode(GXTexMapID id,GXTexWrapMode wrap_s,GXTexWrapMode wrap_t,GXTexFilter min_filt,GXTexFilter mag_filt,f32 min_lod,f32 max_lod,f32 lod_bias,GXBool bias_clamp,GXBool do_edge_lod,GXAnisotropy max_aniso)212 void GDSetTexLookupMode ( GXTexMapID id,
213 GXTexWrapMode wrap_s,
214 GXTexWrapMode wrap_t,
215 GXTexFilter min_filt,
216 GXTexFilter mag_filt,
217 f32 min_lod,
218 f32 max_lod,
219 f32 lod_bias,
220 GXBool bias_clamp,
221 GXBool do_edge_lod,
222 GXAnisotropy max_aniso )
223 {
224 GDWriteBPCmd(TX_SETMODE0(wrap_s,
225 wrap_t,
226 (mag_filt == GX_LINEAR),
227 GD2HWFiltConv[min_filt],
228 !do_edge_lod,
229 (u8)((s8)(lod_bias*32.0f)),
230 max_aniso,
231 bias_clamp,
232 GDTexMode0Ids[id]));
233 GDWriteBPCmd(TX_SETMODE1((u8)(min_lod*16.0f),
234 (u8)(max_lod*16.0f),
235 GDTexMode1Ids[id]));
236 }
237
238 /*---------------------------------------------------------------------------*/
239 // Name: GDSetTexImgAttr
240 //
241 // Description: Sets image attributes for a given tex ID.
242 //
243 // Arguments: id: which texture ID will be set
244 // ...: parameters to set, as indicated by name
245 //
246 // Returns: none
247 //
248 /*---------------------------------------------------------------------------*/
249
GDSetTexImgAttr(GXTexMapID id,u16 width,u16 height,GXTexFmt format)250 void GDSetTexImgAttr ( GXTexMapID id, u16 width, u16 height, GXTexFmt format )
251 {
252 GDWriteBPCmd(TX_SETIMAGE0(width - 1,
253 height - 1,
254 format,
255 GDTexImage0Ids[id]));
256 }
257
258 /*---------------------------------------------------------------------------*/
259 // Name: GDSetTexImgPtr
260 //
261 // Description: Sets main-memory address for a given tex ID.
262 //
263 // Arguments: id: which texture ID will be set
264 // image_ptr: (cached) main-memory address of texture
265 //
266 // Returns: none
267 //
268 /*---------------------------------------------------------------------------*/
269
GDSetTexImgPtr(GXTexMapID id,void * image_ptr)270 void GDSetTexImgPtr ( GXTexMapID id, void *image_ptr )
271 {
272 GDWriteBPCmd(TX_SETIMAGE3(OSCachedToPhysical(image_ptr)>>5,
273 GDTexImage3Ids[id]));
274 }
275
276 /*---------------------------------------------------------------------------*/
277 // Name: GDSetTexImgPtrRaw
278 //
279 // Description: Sets main-memory address for a given tex ID.
280 // Doesn't do any modification of the ptr provided.
281 //
282 // Arguments: id: which texture ID will be set
283 // image_ptr_raw: a u24 parameter to be inserted where the
284 // HW-format address would otherwise go.
285 //
286 // Returns: none
287 //
288 /*---------------------------------------------------------------------------*/
289
GDSetTexImgPtrRaw(GXTexMapID id,u32 image_ptr_raw)290 void GDSetTexImgPtrRaw ( GXTexMapID id, u32 image_ptr_raw )
291 {
292 GDWriteBPCmd(TX_SETIMAGE3(image_ptr_raw, GDTexImage3Ids[id]));
293 }
294
295 /*---------------------------------------------------------------------------*/
296 // Name: GDPatchTexImgPtr
297 //
298 // Description: Alters texture memory address for a GDSetTexImgAddr command.
299 // We assume that the DL offset has been moved to the point
300 // BP_DATA_OFFSET bytes after where the GDSetTexImgAddr command
301 // was inserted. Only the texture address is changed.
302 //
303 // Arguments: image_ptr: (cached) main-memory address of texture
304 //
305 // Returns: none
306 //
307 /*---------------------------------------------------------------------------*/
308
GDPatchTexImgPtr(void * image_ptr)309 void GDPatchTexImgPtr ( void *image_ptr )
310 {
311 // Note: offset MUST be pointing to the 1st byte of register data
312
313 GDWrite_u24(OSCachedToPhysical(image_ptr)>>5); // write texture address
314 }
315
316 /*---------------------------------------------------------------------------*/
317 // Name: GDSetTexCached
318 //
319 // Description: Indicates that a texture is cached; sets cache parameters.
320 //
321 // Arguments: id: which texture ID will be set
322 // ...: parameters to set, as indicated by name
323 //
324 // Returns: none
325 //
326 /*---------------------------------------------------------------------------*/
327
GDSetTexCached(GXTexMapID id,u32 tmem_even,GXTexCacheSize size_even,u32 tmem_odd,GXTexCacheSize size_odd)328 void GDSetTexCached ( GXTexMapID id,
329 u32 tmem_even, GXTexCacheSize size_even,
330 u32 tmem_odd, GXTexCacheSize size_odd )
331 {
332 GDWriteBPCmd(TX_SETIMAGE1( tmem_even >> 5,
333 size_even+3,
334 size_even+3,
335 0,
336 GDTexImage1Ids[id]));
337 if (size_odd != GX_TEXCACHE_NONE && tmem_odd < GX_TMEM_MAX)
338 {
339 GDWriteBPCmd(TX_SETIMAGE2( tmem_odd >> 5,
340 size_odd+3,
341 size_odd+3,
342 GDTexImage2Ids[id]));
343 }
344 }
345
346 /*---------------------------------------------------------------------------*/
347 // Name: GDSetTexPreLoaded
348 //
349 // Description: Indicates that a texture is preloaded; sets TMEM parameters.
350 //
351 // Arguments: id: which texture ID will be set
352 // ...: parameters to set, as indicated by name
353 //
354 // Returns: none
355 //
356 /*---------------------------------------------------------------------------*/
357
GDSetTexPreLoaded(GXTexMapID id,u32 tmem_even,u32 tmem_odd)358 void GDSetTexPreLoaded ( GXTexMapID id, u32 tmem_even, u32 tmem_odd )
359 {
360 GDWriteBPCmd(TX_SETIMAGE1( tmem_even >> 5,
361 0,
362 0,
363 1,
364 GDTexImage1Ids[id]));
365 if (tmem_odd < GX_TMEM_MAX) // need to define this!
366 {
367 GDWriteBPCmd(TX_SETIMAGE2( tmem_odd >> 5,
368 0,
369 0,
370 GDTexImage2Ids[id]));
371 }
372 }
373
374 /*---------------------------------------------------------------------------*/
375 // Name: GDSetTexTlut
376 //
377 // Description: Sets TLUT parameters for a given tex ID.
378 //
379 // Arguments: id: which texture ID will be set
380 // ...: parameters to set, as indicated by name
381 //
382 // Returns: none
383 //
384 /*---------------------------------------------------------------------------*/
385
GDSetTexTlut(GXTexMapID id,u32 tmem_addr,GXTlutFmt format)386 void GDSetTexTlut ( GXTexMapID id, u32 tmem_addr, GXTlutFmt format )
387 {
388 GDWriteBPCmd(TX_SETTLUT( (tmem_addr-GX_TMEM_HALF) >> 9, format,
389 GDTexTlutIds[id]));
390 }
391
392 /*---------------------------------------------------------------------------*/
393 // Name: GDSetTexCoordScale
394 //
395 // Description: Sets texture scale parameters for a given texcoord (not tex!)
396 // ID. Uses the register mask to avoid changing the texture
397 // offset enable bits.
398 //
399 // Arguments: coord: which texcoord ID will be set
400 // ...: parameters to set, as indicated by name
401 //
402 // Returns: none
403 //
404 /*---------------------------------------------------------------------------*/
405
406 #define SU_TS0_MASK_SETTEXCOORDSCALE \
407 ( 0x00FFFF << SU_TS0_SSIZE_SHIFT )
408 #define SU_TS1_MASK_SETTEXCOORDSCALE \
409 ( 0x00FFFF << SU_TS1_TSIZE_SHIFT )
410
GDSetTexCoordScale(GXTexCoordID coord,u16 s_scale,u16 t_scale)411 void GDSetTexCoordScale ( GXTexCoordID coord, u16 s_scale, u16 t_scale )
412 {
413 // mask prevents write to bias, wrap and point/line offset enables
414 GDWriteBPCmd(SS_MASK(SU_TS0_MASK_SETTEXCOORDSCALE));
415 GDWriteBPCmd(SU_TS0( s_scale - 1, 0, 0, 0, 0,
416 SU_SSIZE0_ID + (u32) coord * 2));
417
418 GDWriteBPCmd(SS_MASK(SU_TS1_MASK_SETTEXCOORDSCALE));
419 GDWriteBPCmd(SU_TS1( t_scale - 1, 0, 0,
420 SU_TSIZE0_ID + (u32) coord * 2));
421 }
422
423 /*---------------------------------------------------------------------------*/
424 // Name: GDSetTexCoordScale2
425 //
426 // Description: Sets texture scale parameters for a given texcoord (not tex!)
427 // ID. Besides, this API sets texcoord bias and cycle wrap mode
428 // as well.
429 //
430 // Arguments: coord: which texcoord ID will be set
431 // ...: parameters to set, as indicated by name
432 //
433 // Returns: none
434 //
435 /*---------------------------------------------------------------------------*/
436
437 #define SU_TS0_MASK_SETTEXCOORDSCALE2 \
438 (( 0x00FFFF << SU_TS0_SSIZE_SHIFT ) | \
439 ( 0x000001 << SU_TS0_BS_SHIFT ) | \
440 ( 0x000001 << SU_TS0_WS_SHIFT ))
441
GDSetTexCoordScale2(GXTexCoordID coord,u16 s_scale,GXBool s_bias,GXBool s_wrap,u16 t_scale,GXBool t_bias,GXBool t_wrap)442 void GDSetTexCoordScale2 ( GXTexCoordID coord,
443 u16 s_scale, GXBool s_bias, GXBool s_wrap,
444 u16 t_scale, GXBool t_bias, GXBool t_wrap)
445 {
446 // mask prevents write to point & line offset enables
447 GDWriteBPCmd(SS_MASK(SU_TS0_MASK_SETTEXCOORDSCALE2));
448 GDWriteBPCmd(SU_TS0( s_scale - 1, s_bias, s_wrap, 0, 0,
449 SU_SSIZE0_ID + (u32) coord * 2));
450 GDWriteBPCmd(SU_TS1( t_scale - 1, t_bias, t_wrap,
451 SU_TSIZE0_ID + (u32) coord * 2));
452 }
453
454
455 /*---------------------------------------------------------------------------*/
456 // Name: GDSetTexCoordScaleandTOEs
457 //
458 // Description: Sets texture scale parameters for a given texcoord (not tex!)
459 // ID. Also sets the texture offset enable bits (TOEs).
460 //
461 // Arguments: coord: which texcoord ID will be set
462 // ...: parameters to set, as indicated by name
463 //
464 // Returns: none
465 //
466 /*---------------------------------------------------------------------------*/
467
GDSetTexCoordScaleAndTOEs(GXTexCoordID coord,u16 s_scale,GXBool s_bias,GXBool s_wrap,u16 t_scale,GXBool t_bias,GXBool t_wrap,GXBool line_offset,GXBool point_offset)468 void GDSetTexCoordScaleAndTOEs ( GXTexCoordID coord,
469 u16 s_scale, GXBool s_bias, GXBool s_wrap,
470 u16 t_scale, GXBool t_bias, GXBool t_wrap,
471 GXBool line_offset, GXBool point_offset)
472 {
473 GDWriteBPCmd(SU_TS0( s_scale - 1, s_bias, s_wrap, line_offset, point_offset,
474 SU_SSIZE0_ID + (u32) coord * 2));
475 GDWriteBPCmd(SU_TS1( t_scale - 1, t_bias, t_wrap,
476 SU_TSIZE0_ID + (u32) coord * 2));
477 }
478
479 /*---------------------------------------------------------------------------*/
480 // Name: GDLoadTlut
481 //
482 // Description: Loads a TLUT from main memory into TMEM.
483 //
484 // Arguments: tlut_ptr : (cached) main-memory address of TLUT
485 // tmem_addr : destination address of TLUT in TMEM
486 // size : size of the TLUT
487 //
488 // Returns: none
489 //
490 // Notes: For patching, you must save the following offset:
491 // GDGetCurrOffset() + BP_CMD_LENGTH * 2 + BP_DATA_OFFSET
492 //
493 /*---------------------------------------------------------------------------*/
494
GDLoadTlut(void * tlut_ptr,u32 tmem_addr,GXTlutSize size)495 void GDLoadTlut( void *tlut_ptr, u32 tmem_addr, GXTlutSize size )
496 {
497 ASSERTMSG((tmem_addr & 0x1ff)==0, "GDLoadTlut: invalid TMEM pointer");
498 ASSERTMSG((size <= 1024), "GDLoadTlut: invalid TLUT size");
499
500 // Flush the texture state (without modifying the indirect mask)
501 GDWriteBPCmd(SS_MASK(0xffff00));
502 GDWriteBPCmd((BU_IMASK_ID << 24));
503
504 GDWriteBPCmd(TX_LOADTLUT0( OSCachedToPhysical(tlut_ptr)>>5,
505 TX_LOADTLUT0_ID));
506
507 // Writing to this register will initiate the actual loading:
508 GDWriteBPCmd(TX_LOADTLUT1( (tmem_addr-GX_TMEM_HALF) >> 9, size,
509 TX_LOADTLUT1_ID));
510
511 // Flush the texture state (without modifying the indirect mask)
512 GDWriteBPCmd(SS_MASK(0xffff00));
513 GDWriteBPCmd((BU_IMASK_ID << 24));
514 }
515
516 /*---------------------------------------------------------------------------*/
517 // Name: GDLoadTlutRaw
518 //
519 // Description: Loads a TLUT from main memory into TMEM.
520 // Doesn't do any modification of the ptr provided.
521 //
522 // Arguments: tlut_ptr_raw : a u24 parameter to be inserted where the
523 // HW-format address would otherwise go.
524 // tmem_addr : destination address of TLUT in TMEM
525 // size : size of the TLUT
526 //
527 // Returns: none
528 //
529 // Notes: For patching, you must save the following offset:
530 // GDGetCurrOffset() + BP_CMD_LENGTH * 2 + BP_DATA_OFFSET
531 //
532 /*---------------------------------------------------------------------------*/
533
GDLoadTlutRaw(u32 tlut_ptr_raw,u32 tmem_addr,GXTlutSize size)534 void GDLoadTlutRaw( u32 tlut_ptr_raw, u32 tmem_addr, GXTlutSize size )
535 {
536 ASSERTMSG((size <= 1024), "GDLoadTlut: invalid TLUT size");
537
538 // Flush the texture state (without modifying the indirect mask)
539 GDWriteBPCmd(SS_MASK(0xffff00));
540 GDWriteBPCmd((BU_IMASK_ID << 24));
541
542 GDWriteBPCmd(TX_LOADTLUT0( tlut_ptr_raw, TX_LOADTLUT0_ID));
543
544 // Writing to this register will initiate the actual loading:
545 GDWriteBPCmd(TX_LOADTLUT1( (tmem_addr-GX_TMEM_HALF) >> 9, size,
546 TX_LOADTLUT1_ID));
547
548 // Flush the texture state (without modifying the indirect mask)
549 GDWriteBPCmd(SS_MASK(0xffff00));
550 GDWriteBPCmd((BU_IMASK_ID << 24));
551 }
552