PANDORA: Make GLES context compatible with latest driver (FB only, no X11)
[mupen64plus-pandora.git] / source / gles2n64 / src / Textures.cpp
CommitLineData
34cf4058 1#include <time.h>
2#include <stdlib.h>
3#include <memory.h>
4
5#ifndef min
6#define min(a,b) ((a) < (b) ? (a) : (b))
7#endif
8
9#include "Common.h"
10#include "Config.h"
11#include "OpenGL.h"
12#include "Textures.h"
13#include "GBI.h"
14#include "RSP.h"
15#include "gDP.h"
16#include "gSP.h"
17#include "N64.h"
18#include "CRC.h"
19#include "convert.h"
20#include "2xSAI.h"
21//#include "FrameBuffer.h"
22
23#define FORMAT_NONE 0
24#define FORMAT_I8 1
25#define FORMAT_IA88 2
26#define FORMAT_RGBA4444 3
27#define FORMAT_RGBA5551 4
28#define FORMAT_RGBA8888 5
29
30//#define PRINT_TEXTUREFORMAT
31
32TextureCache cache;
33
34typedef u32 (*GetTexelFunc)( void *src, u16 x, u16 i, u8 palette );
35
36u32 GetNone( void *src, u16 x, u16 i, u8 palette )
37{
38 return 0x00000000;
39}
40
41u32 GetCI4IA_RGBA4444( void *src, u16 x, u16 i, u8 palette )
42{
43 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
44 if (x & 1)
45 return IA88_RGBA4444( *(u16*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
46 else
47 return IA88_RGBA4444( *(u16*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
48}
49
50u32 GetCI4IA_RGBA8888( void *src, u16 x, u16 i, u8 palette )
51{
52 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
53 if (x & 1)
54 return IA88_RGBA8888( *(u16*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
55 else
56 return IA88_RGBA8888( *(u16*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
57}
58
59u32 GetCI4RGBA_RGBA5551( void *src, u16 x, u16 i, u8 palette )
60{
61 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
62 if (x & 1)
63 return RGBA5551_RGBA5551( *(u16*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
64 else
65 return RGBA5551_RGBA5551( *(u16*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
66}
67
68u32 GetCI4RGBA_RGBA8888( void *src, u16 x, u16 i, u8 palette )
69{
70 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
71 if (x & 1)
72 return RGBA5551_RGBA8888( *(u16*)&TMEM[256 + (palette << 4) + (color4B & 0x0F)] );
73 else
74 return RGBA5551_RGBA8888( *(u16*)&TMEM[256 + (palette << 4) + (color4B >> 4)] );
75}
76
77u32 GetIA31_RGBA8888( void *src, u16 x, u16 i, u8 palette )
78{
79 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
80 return IA31_RGBA8888( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
81}
82
83u32 GetIA31_RGBA4444( void *src, u16 x, u16 i, u8 palette )
84{
85 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
86 return IA31_RGBA4444( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
87}
88
89u32 GetIA31_IA88( void *src, u16 x, u16 i, u8 palette )
90{
91 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
92 return IA31_IA88( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
93}
94
95u32 GetI4_RGBA8888( void *src, u16 x, u16 i, u8 palette )
96{
97 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
98 return I4_RGBA8888( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
99}
100
101u32 GetI4_RGBA4444( void *src, u16 x, u16 i, u8 palette )
102{
103 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
104 return I4_RGBA4444( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
105}
106
107u32 GetI4_I8( void *src, u16 x, u16 i, u8 palette )
108{
109 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
110 return I4_I8( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
111}
112
113
114u32 GetI4_IA88( void *src, u16 x, u16 i, u8 palette )
115{
116 u8 color4B = ((u8*)src)[(x>>1)^(i<<1)];
117 return I4_IA88( (x & 1) ? (color4B & 0x0F) : (color4B >> 4) );
118}
119
120u32 GetCI8IA_RGBA4444( void *src, u16 x, u16 i, u8 palette )
121{
122 return IA88_RGBA4444( *(u16*)&TMEM[256 + ((u8*)src)[x^(i<<1)]] );
123}
124
125u32 GetCI8IA_RGBA8888( void *src, u16 x, u16 i, u8 palette )
126{
127 return IA88_RGBA8888( *(u16*)&TMEM[256 + ((u8*)src)[x^(i<<1)]] );
128}
129
130u32 GetCI8RGBA_RGBA5551( void *src, u16 x, u16 i, u8 palette )
131{
132 return RGBA5551_RGBA5551( *(u16*)&TMEM[256 + ((u8*)src)[x^(i<<1)]] );
133}
134
135u32 GetCI8RGBA_RGBA8888( void *src, u16 x, u16 i, u8 palette )
136{
137 return RGBA5551_RGBA8888( *(u16*)&TMEM[256 + ((u8*)src)[x^(i<<1)]] );
138}
139
140u32 GetIA44_RGBA8888( void *src, u16 x, u16 i, u8 palette )
141{
142 return IA44_RGBA8888(((u8*)src)[x^(i<<1)]);
143}
144
145u32 GetIA44_RGBA4444( void *src, u16 x, u16 i, u8 palette )
146{
147 return IA44_RGBA4444(((u8*)src)[x^(i<<1)]);
148}
149
150u32 GetIA44_IA88( void *src, u16 x, u16 i, u8 palette )
151{
152 return IA44_IA88(((u8*)src)[x^(i<<1)]);
153}
154
155u32 GetI8_RGBA8888( void *src, u16 x, u16 i, u8 palette )
156{
157 return I8_RGBA8888(((u8*)src)[x^(i<<1)]);
158}
159
160u32 GetI8_I8( void *src, u16 x, u16 i, u8 palette )
161{
162 return ((u8*)src)[x^(i<<1)];
163}
164
165u32 GetI8_IA88( void *src, u16 x, u16 i, u8 palette )
166{
167 return I8_IA88(((u8*)src)[x^(i<<1)]);
168}
169
170u32 GetI8_RGBA4444( void *src, u16 x, u16 i, u8 palette )
171{
172 return I8_RGBA4444(((u8*)src)[x^(i<<1)]);
173}
174
175u32 GetRGBA5551_RGBA8888( void *src, u16 x, u16 i, u8 palette )
176{
177 return RGBA5551_RGBA8888( ((u16*)src)[x^i] );
178}
179
180u32 GetRGBA5551_RGBA5551( void *src, u16 x, u16 i, u8 palette )
181{
182 return RGBA5551_RGBA5551( ((u16*)src)[x^i] );
183}
184
185u32 GetIA88_RGBA8888( void *src, u16 x, u16 i, u8 palette )
186{
187 return IA88_RGBA8888(((u16*)src)[x^i]);
188}
189
190u32 GetIA88_RGBA4444( void *src, u16 x, u16 i, u8 palette )
191{
192 return IA88_RGBA4444(((u16*)src)[x^i]);
193}
194
195u32 GetIA88_IA88( void *src, u16 x, u16 i, u8 palette )
196{
197 return IA88_IA88(((u16*)src)[x^i]);
198}
199
200u32 GetRGBA8888_RGBA8888( void *src, u16 x, u16 i, u8 palette )
201{
202 return ((u32*)src)[x^i];
203}
204
205u32 GetRGBA8888_RGBA4444( void *src, u16 x, u16 i, u8 palette )
206{
207 return RGBA8888_RGBA4444(((u32*)src)[x^i]);
208}
209
210
211struct TextureFormat
212{
213 int format;
214 GetTexelFunc getTexel;
215 int lineShift, maxTexels;
216};
217
218
219TextureFormat textureFormatIA[4*6] =
220{
221 // 4-bit
222 { FORMAT_RGBA5551, GetCI4RGBA_RGBA5551, 4, 4096 }, // RGBA (SELECT)
223 { FORMAT_NONE, GetNone, 4, 8192 }, // YUV
224 { FORMAT_RGBA5551, GetCI4RGBA_RGBA5551, 4, 4096 }, // CI
225 { FORMAT_IA88, GetIA31_IA88, 4, 8192 }, // IA
226 { FORMAT_IA88, GetI4_IA88, 4, 8192 }, // I
227 { FORMAT_RGBA8888, GetCI4IA_RGBA8888, 4, 4096 }, // IA Palette
228 // 8-bit
229 { FORMAT_RGBA5551, GetCI8RGBA_RGBA5551, 3, 2048 }, // RGBA (SELECT)
230 { FORMAT_NONE, GetNone, 3, 4096 }, // YUV
231 { FORMAT_RGBA5551, GetCI8RGBA_RGBA5551, 3, 2048 }, // CI
232 { FORMAT_IA88, GetIA44_IA88, 3, 4096 }, // IA
233 { FORMAT_IA88, GetI8_IA88, 3, 4096 }, // I
234 { FORMAT_RGBA8888, GetCI8IA_RGBA8888, 3, 2048 }, // IA Palette
235 // 16-bit
236 { FORMAT_RGBA5551, GetRGBA5551_RGBA5551, 2, 2048 }, // RGBA
237 { FORMAT_NONE, GetNone, 2, 2048 }, // YUV
238 { FORMAT_NONE, GetNone, 2, 2048 }, // CI
239 { FORMAT_IA88, GetIA88_IA88, 2, 2048 }, // IA
240 { FORMAT_NONE, GetNone, 2, 2048 }, // I
241 { FORMAT_NONE, GetNone, 2, 2048 }, // IA Palette
242 // 32-bit
243 { FORMAT_RGBA8888, GetRGBA8888_RGBA8888, 2, 1024 }, // RGBA
244 { FORMAT_NONE, GetNone, 2, 1024 }, // YUV
245 { FORMAT_NONE, GetNone, 2, 1024 }, // CI
246 { FORMAT_NONE, GetNone, 2, 1024 }, // IA
247 { FORMAT_NONE, GetNone, 2, 1024 }, // I
248 { FORMAT_NONE, GetNone, 2, 1024 }, // IA Palette
249};
250
251TextureFormat textureFormatRGBA[4*6] =
252{
253 // 4-bit
254 { FORMAT_RGBA5551, GetCI4RGBA_RGBA5551, 4, 4096 }, // RGBA (SELECT)
255 { FORMAT_NONE, GetNone, 4, 8192 }, // YUV
256 { FORMAT_RGBA5551, GetCI4RGBA_RGBA5551, 4, 4096 }, // CI
257 { FORMAT_RGBA4444, GetIA31_RGBA4444, 4, 8192 }, // IA
258 { FORMAT_RGBA4444, GetI4_RGBA4444, 4, 8192 }, // I
259 { FORMAT_RGBA8888, GetCI4IA_RGBA8888, 4, 4096 }, // IA Palette
260 // 8-bit
261 { FORMAT_RGBA5551, GetCI8RGBA_RGBA5551, 3, 2048 }, // RGBA (SELECT)
262 { FORMAT_NONE, GetNone, 3, 4096 }, // YUV
263 { FORMAT_RGBA5551, GetCI8RGBA_RGBA5551, 3, 2048 }, // CI
264 { FORMAT_RGBA4444, GetIA44_RGBA4444, 3, 4096 }, // IA
265 { FORMAT_RGBA8888, GetI8_RGBA8888, 3, 4096 }, // I
266 { FORMAT_RGBA8888, GetCI8IA_RGBA8888, 3, 2048 }, // IA Palette
267 // 16-bit
268 { FORMAT_RGBA5551, GetRGBA5551_RGBA5551, 2, 2048 }, // RGBA
269 { FORMAT_NONE, GetNone, 2, 2048 }, // YUV
270 { FORMAT_NONE, GetNone, 2, 2048 }, // CI
271 { FORMAT_RGBA8888, GetIA88_RGBA8888, 2, 2048 }, // IA
272 { FORMAT_NONE, GetNone, 2, 2048 }, // I
273 { FORMAT_NONE, GetNone, 2, 2048 }, // IA Palette
274 // 32-bit
275 { FORMAT_RGBA8888, GetRGBA8888_RGBA8888, 2, 1024 }, // RGBA
276 { FORMAT_NONE, GetNone, 2, 1024 }, // YUV
277 { FORMAT_NONE, GetNone, 2, 1024 }, // CI
278 { FORMAT_NONE, GetNone, 2, 1024 }, // IA
279 { FORMAT_NONE, GetNone, 2, 1024 }, // I
280 { FORMAT_NONE, GetNone, 2, 1024 }, // IA Palette
281};
282
283
284TextureFormat *textureFormat = textureFormatIA;
285
286void __texture_format_rgba(int size, int format, TextureFormat *texFormat)
287{
288 if (size < G_IM_SIZ_16b)
289 {
290 if (gDP.otherMode.textureLUT == G_TT_NONE)
291 *texFormat = textureFormat[size*6 + G_IM_FMT_I];
292 else if (gDP.otherMode.textureLUT == G_TT_RGBA16)
293 *texFormat = textureFormat[size*6 + G_IM_FMT_CI];
294 else
295 *texFormat = textureFormat[size*6 + G_IM_FMT_IA];
296 }
297 else
298 {
299 *texFormat = textureFormat[size*6 + G_IM_FMT_RGBA];
300 }
301}
302
303void __texture_format_ci(int size, int format, TextureFormat *texFormat)
304{
305 switch(size)
306 {
307 case G_IM_SIZ_4b:
308 if (gDP.otherMode.textureLUT == G_TT_IA16)
309 *texFormat = textureFormat[G_IM_SIZ_4b*6 + G_IM_FMT_CI_IA];
310 else
311 *texFormat = textureFormat[G_IM_SIZ_4b*6 + G_IM_FMT_CI];
312 break;
313
314 case G_IM_SIZ_8b:
315 if (gDP.otherMode.textureLUT == G_TT_NONE)
316 *texFormat = textureFormat[G_IM_SIZ_8b*6 + G_IM_FMT_I];
317 else if (gDP.otherMode.textureLUT == G_TT_IA16)
318 *texFormat = textureFormat[G_IM_SIZ_8b*6 + G_IM_FMT_CI_IA];
319 else
320 *texFormat = textureFormat[G_IM_SIZ_8b*6 + G_IM_FMT_CI];
321 break;
322
323 default:
324 *texFormat = textureFormat[size*6 + format];
325 }
326}
327
328void __texture_format(int size, int format, TextureFormat *texFormat)
329{
330 if (format == G_IM_FMT_RGBA)
331 {
332 __texture_format_rgba(size, format, texFormat);
333 }
334 else if (format == G_IM_FMT_YUV)
335 {
336 *texFormat = textureFormat[size*6 + G_IM_FMT_YUV];
337 }
338 else if (format == G_IM_FMT_CI)
339 {
340 __texture_format_ci(size, format, texFormat);
341 }
342 else if (format == G_IM_FMT_IA)
343 {
344 if (gDP.otherMode.textureLUT != G_TT_NONE)
345 __texture_format_ci(size, format, texFormat);
346 else
347 *texFormat = textureFormat[size*6 + G_IM_FMT_IA];
348 }
349 else if (format == G_IM_FMT_I)
350 {
351 if (gDP.otherMode.textureLUT == G_TT_NONE)
352 *texFormat = textureFormat[size*6 + G_IM_FMT_I];
353 else
354 __texture_format_ci(size, format, texFormat);
355 }
356}
357
358
359int isTexCacheInit = 0;
360
361void TextureCache_Init()
362{
363 u32 dummyTexture[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
364
365 isTexCacheInit = 1;
366 cache.current[0] = NULL;
367 cache.current[1] = NULL;
368 cache.top = NULL;
369 cache.bottom = NULL;
370 cache.numCached = 0;
371 cache.cachedBytes = 0;
372
373#ifdef __HASHMAP_OPT
374 cache.hash.init(11);
375#endif
376
377 if (config.texture.useIA) textureFormat = textureFormatIA;
378 else textureFormat = textureFormatRGBA;
379
380 glPixelStorei(GL_PACK_ALIGNMENT, 1);
381 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
382 glGenTextures( 32, cache.glNoiseNames );
383
384 srand(time(NULL));
385 u8 noise[64*64*2];
386 for (u32 i = 0; i < 32; i++)
387 {
388 glBindTexture( GL_TEXTURE_2D, cache.glNoiseNames[i] );
389 for (u32 y = 0; y < 64; y++)
390 {
391 for (u32 x = 0; x < 64; x++)
392 {
393 u32 r = (rand()&0xFF);
394 noise[y*64*2+x*2] = r;
395 noise[y*64*2+x*2+1] = r;
396 }
397 }
398 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, 64, 64, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, noise);
399 }
400
401 cache.dummy = TextureCache_AddTop();
402 cache.dummy->address = 0;
403 cache.dummy->clampS = 1;
404 cache.dummy->clampT = 1;
405 cache.dummy->clampWidth = 4;
406 cache.dummy->clampHeight = 4;
407 cache.dummy->crc = 0;
408 cache.dummy->format = 0;
409 cache.dummy->size = 0;
410 cache.dummy->width = 4;
411 cache.dummy->height = 4;
412 cache.dummy->realWidth = 0;
413 cache.dummy->realHeight = 0;
414 cache.dummy->maskS = 0;
415 cache.dummy->maskT = 0;
416 cache.dummy->scaleS = 0.5f;
417 cache.dummy->scaleT = 0.5f;
418 cache.dummy->shiftScaleS = 1.0f;
419 cache.dummy->shiftScaleT = 1.0f;
420 cache.dummy->textureBytes = 64;
421 cache.dummy->tMem = 0;
422
423 glBindTexture( GL_TEXTURE_2D, cache.dummy->glName );
424 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, dummyTexture);
425
426 cache.cachedBytes = cache.dummy->textureBytes;
427 TextureCache_ActivateDummy(0);
428 TextureCache_ActivateDummy(1);
429 CRC_BuildTable();
430}
431
432bool TextureCache_Verify()
433{
434 u16 i = 0;
435 CachedTexture *current;
436
437 current = cache.top;
438
439 while (current)
440 {
441 i++;
442 current = current->lower;
443 }
444 if (i != cache.numCached) return false;
445
446 i = 0;
447 current = cache.bottom;
448 while (current)
449 {
450 i++;
451 current = current->higher;
452 }
453 if (i != cache.numCached) return false;
454
455 return true;
456}
457
458void TextureCache_RemoveBottom()
459{
460 CachedTexture *newBottom = cache.bottom->higher;
461
462#ifdef __HASHMAP_OPT
463 CachedTexture* tex= cache.hash.find(cache.bottom->crc);
464 if (tex == cache.bottom)
465 cache.hash.insert(cache.bottom->crc, NULL);
466#endif
467
468 glDeleteTextures( 1, &cache.bottom->glName );
469 cache.cachedBytes -= cache.bottom->textureBytes;
470
471 if (cache.bottom == cache.top)
472 cache.top = NULL;
473
474 free( cache.bottom );
475
476 cache.bottom = newBottom;
477
478 if (cache.bottom)
479 cache.bottom->lower = NULL;
480
481 cache.numCached--;
482}
483
484void TextureCache_Remove( CachedTexture *texture )
485{
486 if ((texture == cache.bottom) && (texture == cache.top))
487 {
488 cache.top = NULL;
489 cache.bottom = NULL;
490 }
491 else if (texture == cache.bottom)
492 {
493 cache.bottom = texture->higher;
494
495 if (cache.bottom)
496 cache.bottom->lower = NULL;
497 }
498 else if (texture == cache.top)
499 {
500 cache.top = texture->lower;
501
502 if (cache.top)
503 cache.top->higher = NULL;
504 }
505 else
506 {
507 texture->higher->lower = texture->lower;
508 texture->lower->higher = texture->higher;
509 }
510
511#ifdef __HASHMAP_OPT
512 CachedTexture* tex= cache.hash.find(texture->crc);
513 if (tex == texture);
514 cache.hash.insert(texture->crc, NULL);
515#endif
516
517 glDeleteTextures( 1, &texture->glName );
518 cache.cachedBytes -= texture->textureBytes;
519 free( texture );
520
521 cache.numCached--;
522}
523
524CachedTexture *TextureCache_AddTop()
525{
526 while (cache.cachedBytes > TEXTURECACHE_MAX)
527 {
528 if (cache.bottom != cache.dummy)
529 TextureCache_RemoveBottom();
530 else if (cache.dummy->higher)
531 TextureCache_Remove( cache.dummy->higher );
532 }
533
534 CachedTexture *newtop = (CachedTexture*)malloc( sizeof( CachedTexture ) );
535
536 glGenTextures( 1, &newtop->glName );
537
538 newtop->lower = cache.top;
539 newtop->higher = NULL;
540
541 if (cache.top)
542 cache.top->higher = newtop;
543
544 if (!cache.bottom)
545 cache.bottom = newtop;
546
547 cache.top = newtop;
548
549 cache.numCached++;
550
551 return newtop;
552}
553
554void TextureCache_MoveToTop( CachedTexture *newtop )
555{
556 if (newtop == cache.top) return;
557
558 if (newtop == cache.bottom)
559 {
560 cache.bottom = newtop->higher;
561 cache.bottom->lower = NULL;
562 }
563 else
564 {
565 newtop->higher->lower = newtop->lower;
566 newtop->lower->higher = newtop->higher;
567 }
568
569 newtop->higher = NULL;
570 newtop->lower = cache.top;
571 cache.top->higher = newtop;
572 cache.top = newtop;
573}
574
575void TextureCache_Destroy()
576{
577 while (cache.bottom)
578 TextureCache_RemoveBottom();
579
580 glDeleteTextures( 32, cache.glNoiseNames );
581 glDeleteTextures( 1, &cache.dummy->glName );
582
583#ifdef __HASHMAP_OPT
584 cache.hash.destroy();
585#endif
586
587 cache.top = NULL;
588 cache.bottom = NULL;
589}
590
591
592
593void TextureCache_LoadBackground( CachedTexture *texInfo )
594{
595 u32 *dest, *scaledDest;
596 u8 *swapped, *src;
597 u32 numBytes, bpl;
598 u32 x, y, j, tx, ty;
599 u16 clampSClamp, clampTClamp;
600
601 int bytePerPixel=0;
602 TextureFormat texFormat;
603 GetTexelFunc getTexel;
604 GLint glWidth=0, glHeight=0;
605 GLenum glType=0;
606 GLenum glFormat=0;
607
608 __texture_format(texInfo->size, texInfo->format, &texFormat);
609
610#ifdef PRINT_TEXTUREFORMAT
611 printf("BG LUT=%i, TEXTURE SIZE=%i, FORMAT=%i -> GL FORMAT=%i\n", gDP.otherMode.textureLUT, texInfo->size, texInfo->format, texFormat.format); fflush(stdout);
612#endif
613
614 if (texFormat.format == FORMAT_NONE)
615 {
616 LOG(LOG_WARNING, "No Texture Conversion function available, size=%i format=%i\n", texInfo->size, texInfo->format);
617 }
618
619 switch(texFormat.format)
620 {
621 case FORMAT_I8:
622 glFormat = GL_LUMINANCE;
623 glType = GL_UNSIGNED_BYTE;
624 bytePerPixel = 1;
625 break;
626 case FORMAT_IA88:
627 glFormat = GL_LUMINANCE_ALPHA;
628 glType = GL_UNSIGNED_BYTE;
629 bytePerPixel = 2;
630 break;
631 case FORMAT_RGBA4444:
632 glFormat = GL_RGBA;
633 glType = GL_UNSIGNED_SHORT_4_4_4_4;
634 bytePerPixel = 2;
635 break;
636 case FORMAT_RGBA5551:
637 glFormat = GL_RGBA;
638 glType = GL_UNSIGNED_SHORT_5_5_5_1;
639 bytePerPixel = 2;
640 break;
641 case FORMAT_RGBA8888:
642 glFormat = GL_RGBA;
643 glType = GL_UNSIGNED_BYTE;
644 bytePerPixel = 4;
645 break;
646 }
647
648 glWidth = texInfo->realWidth;
649 glHeight = texInfo->realHeight;
650 texInfo->textureBytes = (glWidth * glHeight) * bytePerPixel;
651 getTexel = texFormat.getTexel;
652
653 bpl = gSP.bgImage.width << gSP.bgImage.size >> 1;
654 numBytes = bpl * gSP.bgImage.height;
655 swapped = (u8*) malloc(numBytes);
656 dest = (u32*) malloc(texInfo->textureBytes);
657
658 if (!dest || !swapped)
659 {
660 LOG(LOG_ERROR, "Malloc failed!\n");
661 return;
662 }
663
664 UnswapCopy(&RDRAM[gSP.bgImage.address], swapped, numBytes);
665
666 clampSClamp = texInfo->width - 1;
667 clampTClamp = texInfo->height - 1;
668
669 j = 0;
670 for (y = 0; y < texInfo->realHeight; y++)
671 {
672 ty = min(y, clampTClamp);
673 src = &swapped[bpl * ty];
674 for (x = 0; x < texInfo->realWidth; x++)
675 {
676 tx = min(x, clampSClamp);
677 if (bytePerPixel == 4)
678 ((u32*)dest)[j++] = getTexel(src, tx, 0, texInfo->palette);
679 else if (bytePerPixel == 2)
680 ((u16*)dest)[j++] = getTexel(src, tx, 0, texInfo->palette);
681 else if (bytePerPixel == 1)
682 ((u8*)dest)[j++] = getTexel(src, tx, 0, texInfo->palette);
683 }
684 }
685
686 if (!config.texture.sai2x || (texFormat.format == FORMAT_I8 || texFormat.format == FORMAT_IA88))
687 {
688 glTexImage2D( GL_TEXTURE_2D, 0, glFormat, glWidth, glHeight, 0, glFormat, glType, dest);
689 }
690 else
691 {
692 LOG(LOG_VERBOSE, "Using 2xSAI Filter on Texture\n");
693 texInfo->textureBytes <<= 2;
694
695 scaledDest = (u32*) malloc( texInfo->textureBytes );
696
697 if (glType == GL_UNSIGNED_BYTE)
698 _2xSaI8888( (u32*)dest, (u32*)scaledDest, texInfo->realWidth, texInfo->realHeight, texInfo->clampS, texInfo->clampT );
699 if (glType == GL_UNSIGNED_SHORT_4_4_4_4)
700 _2xSaI4444( (u16*)dest, (u16*)scaledDest, texInfo->realWidth, texInfo->realHeight, texInfo->clampS, texInfo->clampT );
701 else
702 _2xSaI5551( (u16*)dest, (u16*)scaledDest, texInfo->realWidth, texInfo->realHeight, texInfo->clampS, texInfo->clampT );
703
704 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, texInfo->realWidth << 1, texInfo->realHeight << 1, 0, GL_RGBA, glType, scaledDest );
705
706 free( scaledDest );
707 }
708
709 free(dest);
710 free(swapped);
711
712
713 if (config.texture.enableMipmap)
714 glGenerateMipmap(GL_TEXTURE_2D);
715}
716
717void TextureCache_Load( CachedTexture *texInfo )
718{
719 u32 *dest, *scaledDest;
720
721 void *src;
722 u16 x, y, i, j, tx, ty, line;
723 u16 mirrorSBit, maskSMask, clampSClamp;
724 u16 mirrorTBit, maskTMask, clampTClamp;
725
726 int bytePerPixel=0;
727 TextureFormat texFormat;
728 GetTexelFunc getTexel;
729 GLint glWidth=0, glHeight=0;
730 GLenum glType=0;
731 GLenum glFormat=0;
732
733 __texture_format(texInfo->size, texInfo->format, &texFormat);
734
735#ifdef PRINT_TEXTUREFORMAT
736 printf("TEX LUT=%i, TEXTURE SIZE=%i, FORMAT=%i -> GL FORMAT=%i\n", gDP.otherMode.textureLUT, texInfo->size, texInfo->format, texFormat.format); fflush(stdout);
737#endif
738
739 if (texFormat.format == FORMAT_NONE)
740 {
741 LOG(LOG_WARNING, "No Texture Conversion function available, size=%i format=%i\n", texInfo->size, texInfo->format);
742 }
743
744 switch(texFormat.format)
745 {
746 case FORMAT_I8:
747 glFormat = GL_LUMINANCE;
748 glType = GL_UNSIGNED_BYTE;
749 bytePerPixel = 1;
750 break;
751 case FORMAT_IA88:
752 glFormat = GL_LUMINANCE_ALPHA;
753 glType = GL_UNSIGNED_BYTE;
754 bytePerPixel = 2;
755 break;
756 case FORMAT_RGBA4444:
757 glFormat = GL_RGBA;
758 glType = GL_UNSIGNED_SHORT_4_4_4_4;
759 bytePerPixel = 2;
760 break;
761 case FORMAT_RGBA5551:
762 glFormat = GL_RGBA;
763 glType = GL_UNSIGNED_SHORT_5_5_5_1;
764 bytePerPixel = 2;
765 break;
766 case FORMAT_RGBA8888:
767 glFormat = GL_RGBA;
768 glType = GL_UNSIGNED_BYTE;
769 bytePerPixel = 4;
770 break;
771 }
772
773 glWidth = texInfo->realWidth;
774 glHeight = texInfo->realHeight;
775 texInfo->textureBytes = (glWidth * glHeight) * bytePerPixel;
776 getTexel = texFormat.getTexel;
777
778 dest = (u32*)malloc(texInfo->textureBytes);
779
780 if (!dest)
781 {
782 LOG(LOG_ERROR, "Malloc failed!\n");
783 return;
784 }
785
786
787 line = texInfo->line;
788
789 if (texInfo->size == G_IM_SIZ_32b)
790 line <<= 1;
791
792 if (texInfo->maskS)
793 {
794 clampSClamp = texInfo->clampS ? texInfo->clampWidth - 1 : (texInfo->mirrorS ? (texInfo->width << 1) - 1 : texInfo->width - 1);
795 maskSMask = (1 << texInfo->maskS) - 1;
796 mirrorSBit = texInfo->mirrorS ? (1 << texInfo->maskS) : 0;
797 }
798 else
799 {
800 clampSClamp = min( texInfo->clampWidth, texInfo->width ) - 1;
801 maskSMask = 0xFFFF;
802 mirrorSBit = 0x0000;
803 }
804
805 if (texInfo->maskT)
806 {
807 clampTClamp = texInfo->clampT ? texInfo->clampHeight - 1 : (texInfo->mirrorT ? (texInfo->height << 1) - 1: texInfo->height - 1);
808 maskTMask = (1 << texInfo->maskT) - 1;
809 mirrorTBit = texInfo->mirrorT ? (1 << texInfo->maskT) : 0;
810 }
811 else
812 {
813 clampTClamp = min( texInfo->clampHeight, texInfo->height ) - 1;
814 maskTMask = 0xFFFF;
815 mirrorTBit = 0x0000;
816 }
817
818 // Hack for Zelda warp texture
819 if (((texInfo->tMem << 3) + (texInfo->width * texInfo->height << texInfo->size >> 1)) > 4096)
820 {
821 texInfo->tMem = 0;
822 }
823
824 // limit clamp values to min-0 (Perfect Dark has height=0 textures, making negative clamps)
825 if (clampTClamp & 0x8000) clampTClamp = 0;
826 if (clampSClamp & 0x8000) clampSClamp = 0;
827
828 j = 0;
829 for (y = 0; y < texInfo->realHeight; y++)
830 {
831 ty = min(y, clampTClamp) & maskTMask;
832 if (y & mirrorTBit) ty ^= maskTMask;
833 src = &TMEM[(texInfo->tMem + line * ty) & 511];
834 i = (ty & 1) << 1;
835 for (x = 0; x < texInfo->realWidth; x++)
836 {
837 tx = min(x, clampSClamp) & maskSMask;
838
839 if (x & mirrorSBit) tx ^= maskSMask;
840
841 if (bytePerPixel == 4)
842 {
843 ((u32*)dest)[j] = getTexel(src, tx, i, texInfo->palette);
844 }
845 else if (bytePerPixel == 2)
846 {
847 ((u16*)dest)[j] = getTexel(src, tx, i, texInfo->palette);
848 }
849 else if (bytePerPixel == 1)
850 {
851 ((u8*)dest)[j] = getTexel(src, tx, i, texInfo->palette);
852 }
853 j++;
854 }
855 }
856
857 if (!config.texture.sai2x || (texFormat.format == FORMAT_I8) || (texFormat.format == FORMAT_IA88))
858 {
859#ifdef PRINT_TEXTUREFORMAT
860 printf("j=%u DEST=0x%x SIZE=%i F=0x%x, W=%i, H=%i, T=0x%x\n", j, dest, texInfo->textureBytes,glFormat, glWidth, glHeight, glType); fflush(stdout);
861#endif
862 glTexImage2D( GL_TEXTURE_2D, 0, glFormat, glWidth, glHeight, 0, glFormat, glType, dest);
863 }
864 else
865 {
866 LOG(LOG_VERBOSE, "Using 2xSAI Filter on Texture\n");
867
868 texInfo->textureBytes <<= 2;
869
870 scaledDest = (u32*)malloc( texInfo->textureBytes );
871
872 if (glType == GL_UNSIGNED_BYTE)
873 _2xSaI8888( (u32*)dest, (u32*)scaledDest, texInfo->realWidth, texInfo->realHeight, 1, 1 );
874 else if (glType == GL_UNSIGNED_SHORT_4_4_4_4)
875 _2xSaI4444( (u16*)dest, (u16*)scaledDest, texInfo->realWidth, texInfo->realHeight, 1, 1 );
876 else
877 _2xSaI5551( (u16*)dest, (u16*)scaledDest, texInfo->realWidth, texInfo->realHeight, 1, 1 );
878
879 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, texInfo->realWidth << 1, texInfo->realHeight << 1, 0, GL_RGBA, glType, scaledDest );
880
881 free( scaledDest );
882 }
883
884 free(dest);
885
886 if (config.texture.enableMipmap)
887 glGenerateMipmap(GL_TEXTURE_2D);
888
889}
890
891#define max(a,b) ((a) > (b) ? (a) : (b))
892
893u32 TextureCache_CalculateCRC( u32 t, u32 width, u32 height )
894{
895 u32 crc;
896 u32 y, /*i,*/ bpl, lineBytes, line;
897 void *src;
898
899 bpl = width << gSP.textureTile[t]->size >> 1;
900 lineBytes = gSP.textureTile[t]->line << 3;
901
902 line = gSP.textureTile[t]->line;
903 if (gSP.textureTile[t]->size == G_IM_SIZ_32b)
904 line <<= 1;
905
906 crc = 0xFFFFFFFF;
907
908#ifdef __CRC_OPT
909 unsigned n = (config.texture.fastCRC) ? max(1, height / 8) : 1;
910#else
911 unsigned n = 1;
912#endif
913
914 for (y = 0; y < height; y += n)
915 {
916 src = (void*) &TMEM[(gSP.textureTile[t]->tmem + (y * line)) & 511];
917 crc = CRC_Calculate( crc, src, bpl );
918 }
919
920 if (gSP.textureTile[t]->format == G_IM_FMT_CI)
921 {
922 if (gSP.textureTile[t]->size == G_IM_SIZ_4b)
923 crc = CRC_Calculate( crc, &gDP.paletteCRC16[gSP.textureTile[t]->palette], 4 );
924 else if (gSP.textureTile[t]->size == G_IM_SIZ_8b)
925 crc = CRC_Calculate( crc, &gDP.paletteCRC256, 4 );
926 }
927 return crc;
928}
929
930void TextureCache_ActivateTexture( u32 t, CachedTexture *texture )
931{
932
933#ifdef __HASHMAP_OPT
934 cache.hash.insert(texture->crc, texture);
935#endif
936
937 glActiveTexture( GL_TEXTURE0 + t );
938 glBindTexture( GL_TEXTURE_2D, texture->glName );
939
940 // Set filter mode. Almost always bilinear, but check anyways
941 if ((gDP.otherMode.textureFilter == G_TF_BILERP) || (gDP.otherMode.textureFilter == G_TF_AVERAGE) || (config.texture.forceBilinear))
942 {
943 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
944 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
945 }
946 else
947 {
948 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
949 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
950 }
951
952 // Set clamping modes
953 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (texture->clampS) ? GL_CLAMP_TO_EDGE : GL_REPEAT );
954 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (texture->clampT) ? GL_CLAMP_TO_EDGE : GL_REPEAT );
955
956 if (config.texture.maxAnisotropy > 0)
957 {
958 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, config.texture.maxAnisotropy);
959 }
960
961 texture->lastDList = RSP.DList;
962 TextureCache_MoveToTop( texture );
963 cache.current[t] = texture;
964}
965
966void TextureCache_ActivateDummy( u32 t)
967{
968 glActiveTexture(GL_TEXTURE0 + t);
969 glBindTexture(GL_TEXTURE_2D, cache.dummy->glName );
970 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
971 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
972}
973
974int _background_compare(CachedTexture *current, u32 crc)
975{
976 if ((current != NULL) &&
977 (current->crc == crc) &&
978 (current->width == gSP.bgImage.width) &&
979 (current->height == gSP.bgImage.height) &&
980 (current->format == gSP.bgImage.format) &&
981 (current->size == gSP.bgImage.size))
982 return 1;
983 else
984 return 0;
985}
986
987void TextureCache_UpdateBackground()
988{
989 u32 numBytes = gSP.bgImage.width * gSP.bgImage.height << gSP.bgImage.size >> 1;
990 u32 crc;
991
992 crc = CRC_Calculate( 0xFFFFFFFF, &RDRAM[gSP.bgImage.address], numBytes );
993
994 if (gSP.bgImage.format == G_IM_FMT_CI)
995 {
996 if (gSP.bgImage.size == G_IM_SIZ_4b)
997 crc = CRC_Calculate( crc, &gDP.paletteCRC16[gSP.bgImage.palette], 4 );
998 else if (gSP.bgImage.size == G_IM_SIZ_8b)
999 crc = CRC_Calculate( crc, &gDP.paletteCRC256, 4 );
1000 }
1001
1002 //before we traverse cache, check to see if texture is already bound:
1003 if (_background_compare(cache.current[0], crc))
1004 {
1005 return;
1006 }
1007
1008#ifdef __HASHMAP_OPT
1009 CachedTexture *tex = cache.hash.find(crc);
1010 if (tex)
1011 {
1012 if (_background_compare(tex, crc))
1013 {
1014 TextureCache_ActivateTexture(0, tex);
1015 cache.hits++;
1016 return;
1017 }
1018 }
1019#endif
1020
1021 CachedTexture *current = cache.top;
1022 while (current)
1023 {
1024 if (_background_compare(current, crc))
1025 {
1026 TextureCache_ActivateTexture( 0, current );
1027 cache.hits++;
1028 return;
1029 }
1030 current = current->lower;
1031 }
1032 cache.misses++;
1033
1034 glActiveTexture(GL_TEXTURE0);
1035 cache.current[0] = TextureCache_AddTop();
1036
1037 glBindTexture( GL_TEXTURE_2D, cache.current[0]->glName );
1038 cache.current[0]->address = gSP.bgImage.address;
1039 cache.current[0]->crc = crc;
1040 cache.current[0]->format = gSP.bgImage.format;
1041 cache.current[0]->size = gSP.bgImage.size;
1042 cache.current[0]->width = gSP.bgImage.width;
1043 cache.current[0]->height = gSP.bgImage.height;
1044 cache.current[0]->clampWidth = gSP.bgImage.width;
1045 cache.current[0]->clampHeight = gSP.bgImage.height;
1046 cache.current[0]->palette = gSP.bgImage.palette;
1047 cache.current[0]->maskS = 0;
1048 cache.current[0]->maskT = 0;
1049 cache.current[0]->mirrorS = 0;
1050 cache.current[0]->mirrorT = 0;
1051 cache.current[0]->clampS = 1;
1052 cache.current[0]->clampT = 1;
1053 cache.current[0]->line = 0;
1054 cache.current[0]->tMem = 0;
1055 cache.current[0]->lastDList = RSP.DList;
1056
1057 cache.current[0]->realWidth = (config.texture.pow2) ? pow2(gSP.bgImage.width ) : gSP.bgImage.width;
1058 cache.current[0]->realHeight = (config.texture.pow2) ? pow2(gSP.bgImage.height) : gSP.bgImage.height;
1059
1060 cache.current[0]->scaleS = 1.0f / (f32)(cache.current[0]->realWidth);
1061 cache.current[0]->scaleT = 1.0f / (f32)(cache.current[0]->realHeight);
1062 cache.current[0]->shiftScaleS = 1.0f;
1063 cache.current[0]->shiftScaleT = 1.0f;
1064
1065 TextureCache_LoadBackground( cache.current[0] );
1066 TextureCache_ActivateTexture( 0, cache.current[0] );
1067
1068 cache.cachedBytes += cache.current[0]->textureBytes;
1069}
1070
1071int _texture_compare(u32 t, CachedTexture *current, u32 crc, u32 width, u32 height, u32 clampWidth, u32 clampHeight)
1072{
1073 if ((current != NULL) &&
1074 (current->crc == crc) &&
1075 (current->width == width) &&
1076 (current->height == height) &&
1077 (current->clampWidth == clampWidth) &&
1078 (current->clampHeight == clampHeight) &&
1079 (current->maskS == gSP.textureTile[t]->masks) &&
1080 (current->maskT == gSP.textureTile[t]->maskt) &&
1081 (current->mirrorS == gSP.textureTile[t]->mirrors) &&
1082 (current->mirrorT == gSP.textureTile[t]->mirrort) &&
1083 (current->clampS == gSP.textureTile[t]->clamps) &&
1084 (current->clampT == gSP.textureTile[t]->clampt) &&
1085 (current->format == gSP.textureTile[t]->format) &&
1086 (current->size == gSP.textureTile[t]->size))
1087 return 1;
1088 else
1089 return 0;
1090}
1091
1092
1093void TextureCache_Update( u32 t )
1094{
1095 CachedTexture *current;
1096
1097 u32 crc, maxTexels;
1098 u32 tileWidth, maskWidth, loadWidth, lineWidth, clampWidth, height;
1099 u32 tileHeight, maskHeight, loadHeight, lineHeight, clampHeight, width;
1100
1101 if (gDP.textureMode == TEXTUREMODE_BGIMAGE)
1102 {
1103 TextureCache_UpdateBackground();
1104 return;
1105 }
1106
1107 TextureFormat texFormat;
1108 __texture_format(gSP.textureTile[t]->size, gSP.textureTile[t]->format, &texFormat);
1109
1110 maxTexels = texFormat.maxTexels;
1111
1112 // Here comes a bunch of code that just calculates the texture size...I wish there was an easier way...
1113 tileWidth = gSP.textureTile[t]->lrs - gSP.textureTile[t]->uls + 1;
1114 tileHeight = gSP.textureTile[t]->lrt - gSP.textureTile[t]->ult + 1;
1115
1116 maskWidth = 1 << gSP.textureTile[t]->masks;
1117 maskHeight = 1 << gSP.textureTile[t]->maskt;
1118
1119 loadWidth = gDP.loadTile->lrs - gDP.loadTile->uls + 1;
1120 loadHeight = gDP.loadTile->lrt - gDP.loadTile->ult + 1;
1121
1122 lineWidth = gSP.textureTile[t]->line << texFormat.lineShift;
1123
1124 if (lineWidth) // Don't allow division by zero
1125 lineHeight = min( maxTexels / lineWidth, tileHeight );
1126 else
1127 lineHeight = 0;
1128
1129 if (gDP.textureMode == TEXTUREMODE_TEXRECT)
1130 {
1131 u32 texRectWidth = gDP.texRect.width - gSP.textureTile[t]->uls;
1132 u32 texRectHeight = gDP.texRect.height - gSP.textureTile[t]->ult;
1133
1134 if (gSP.textureTile[t]->masks && ((maskWidth * maskHeight) <= maxTexels))
1135 width = maskWidth;
1136 else if ((tileWidth * tileHeight) <= maxTexels)
1137 width = tileWidth;
1138 else if ((tileWidth * texRectHeight) <= maxTexels)
1139 width = tileWidth;
1140 else if ((texRectWidth * tileHeight) <= maxTexels)
1141 width = gDP.texRect.width;
1142 else if ((texRectWidth * texRectHeight) <= maxTexels)
1143 width = gDP.texRect.width;
1144 else if (gDP.loadType == LOADTYPE_TILE)
1145 width = loadWidth;
1146 else
1147 width = lineWidth;
1148
1149 if (gSP.textureTile[t]->maskt && ((maskWidth * maskHeight) <= maxTexels))
1150 height = maskHeight;
1151 else if ((tileWidth * tileHeight) <= maxTexels)
1152 height = tileHeight;
1153 else if ((tileWidth * texRectHeight) <= maxTexels)
1154 height = gDP.texRect.height;
1155 else if ((texRectWidth * tileHeight) <= maxTexels)
1156 height = tileHeight;
1157 else if ((texRectWidth * texRectHeight) <= maxTexels)
1158 height = gDP.texRect.height;
1159 else if (gDP.loadType == LOADTYPE_TILE)
1160 height = loadHeight;
1161 else
1162 height = lineHeight;
1163 }
1164 else
1165 {
1166 if (gSP.textureTile[t]->masks && ((maskWidth * maskHeight) <= maxTexels))
1167 width = maskWidth;
1168 else if ((tileWidth * tileHeight) <= maxTexels)
1169 width = tileWidth;
1170 else if (gDP.loadType == LOADTYPE_TILE)
1171 width = loadWidth;
1172 else
1173 width = lineWidth;
1174
1175 if (gSP.textureTile[t]->maskt && ((maskWidth * maskHeight) <= maxTexels))
1176 height = maskHeight;
1177 else if ((tileWidth * tileHeight) <= maxTexels)
1178 height = tileHeight;
1179 else if (gDP.loadType == LOADTYPE_TILE)
1180 height = loadHeight;
1181 else
1182 height = lineHeight;
1183 }
1184
1185 clampWidth = gSP.textureTile[t]->clamps ? tileWidth : width;
1186 clampHeight = gSP.textureTile[t]->clampt ? tileHeight : height;
1187
1188 if (clampWidth > 256)
1189 gSP.textureTile[t]->clamps = 0;
1190 if (clampHeight > 256)
1191 gSP.textureTile[t]->clampt = 0;
1192
1193 // Make sure masking is valid
1194 if (maskWidth > width)
1195 {
1196 gSP.textureTile[t]->masks = powof( width );
1197 maskWidth = 1 << gSP.textureTile[t]->masks;
1198 }
1199
1200 if (maskHeight > height)
1201 {
1202 gSP.textureTile[t]->maskt = powof( height );
1203 maskHeight = 1 << gSP.textureTile[t]->maskt;
1204 }
1205
1206 crc = TextureCache_CalculateCRC( t, width, height );
1207
1208 //before we traverse cache, check to see if texture is already bound:
1209 if (_texture_compare(t, cache.current[t], crc, width, height, clampWidth, clampHeight))
1210 {
1211 cache.hits++;
1212 return;
1213 }
1214
1215#ifdef __HASHMAP_OPT
1216 CachedTexture *tex = cache.hash.find(crc);
1217 if (tex)
1218 {
1219 if (_texture_compare(t, tex, crc, width, height, clampWidth, clampHeight))
1220 {
1221 TextureCache_ActivateTexture( t, tex);
1222 cache.hits++;
1223 return;
1224 }
1225 }
1226#endif
1227
1228 current = cache.top;
1229 while (current)
1230 {
1231 if (_texture_compare(t, current, crc, width, height, clampWidth, clampHeight))
1232 {
1233 TextureCache_ActivateTexture( t, current );
1234 cache.hits++;
1235 return;
1236 }
1237
1238 current = current->lower;
1239 }
1240
1241 cache.misses++;
1242
1243 glActiveTexture( GL_TEXTURE0 + t);
1244
1245 cache.current[t] = TextureCache_AddTop();
1246
1247 if (cache.current[t] == NULL)
1248 {
1249 LOG(LOG_ERROR, "Texture Cache Failure\n");
1250 }
1251
1252 glBindTexture( GL_TEXTURE_2D, cache.current[t]->glName );
1253
1254 cache.current[t]->address = gDP.textureImage.address;
1255 cache.current[t]->crc = crc;
1256
1257 cache.current[t]->format = gSP.textureTile[t]->format;
1258 cache.current[t]->size = gSP.textureTile[t]->size;
1259
1260 cache.current[t]->width = width;
1261 cache.current[t]->height = height;
1262 cache.current[t]->clampWidth = clampWidth;
1263 cache.current[t]->clampHeight = clampHeight;
1264 cache.current[t]->palette = gSP.textureTile[t]->palette;
1265 cache.current[t]->maskS = gSP.textureTile[t]->masks;
1266 cache.current[t]->maskT = gSP.textureTile[t]->maskt;
1267 cache.current[t]->mirrorS = gSP.textureTile[t]->mirrors;
1268 cache.current[t]->mirrorT = gSP.textureTile[t]->mirrort;
1269 cache.current[t]->clampS = gSP.textureTile[t]->clamps;
1270 cache.current[t]->clampT = gSP.textureTile[t]->clampt;
1271 cache.current[t]->line = gSP.textureTile[t]->line;
1272 cache.current[t]->tMem = gSP.textureTile[t]->tmem;
1273 cache.current[t]->lastDList = RSP.DList;
1274
1275
1276 if (cache.current[t]->clampS)
1277 cache.current[t]->realWidth = (config.texture.pow2) ? pow2(clampWidth) : clampWidth;
1278 else if (cache.current[t]->mirrorS)
1279 cache.current[t]->realWidth = maskWidth << 1;
1280 else
1281 cache.current[t]->realWidth = (config.texture.pow2) ? pow2(width) : width;
1282
1283 if (cache.current[t]->clampT)
1284 cache.current[t]->realHeight = (config.texture.pow2) ? pow2(clampHeight) : clampHeight;
1285 else if (cache.current[t]->mirrorT)
1286 cache.current[t]->realHeight = maskHeight << 1;
1287 else
1288 cache.current[t]->realHeight = (config.texture.pow2) ? pow2(height) : height;
1289
1290
1291 cache.current[t]->scaleS = 1.0f / (f32)(cache.current[t]->realWidth);
1292 cache.current[t]->scaleT = 1.0f / (f32)(cache.current[t]->realHeight);
1293
1294 // Hack for Zelda Sun
1295 if ((config.hackZelda) && (gDP.combine.mux == 0x00262a60150c937fLL))
1296 {
1297 if ((cache.current[t]->format = G_IM_FMT_I) && (cache.current[t]->size == G_IM_SIZ_8b) &&
1298 (cache.current[t]->width == 64))
1299 {
1300 cache.current[t]->scaleS *= 0.5f;
1301 cache.current[t]->scaleT *= 0.5f;
1302 }
1303 }
1304
1305 cache.current[t]->shiftScaleS = 1.0f;
1306 cache.current[t]->shiftScaleT = 1.0f;
1307
1308 cache.current[t]->offsetS = config.texture.sai2x ? 0.25f : 0.5f;
1309 cache.current[t]->offsetT = config.texture.sai2x ? 0.25f : 0.5f;
1310
1311 if (gSP.textureTile[t]->shifts > 10)
1312 cache.current[t]->shiftScaleS = (f32)(1 << (16 - gSP.textureTile[t]->shifts));
1313 else if (gSP.textureTile[t]->shifts > 0)
1314 cache.current[t]->shiftScaleS /= (f32)(1 << gSP.textureTile[t]->shifts);
1315
1316 if (gSP.textureTile[t]->shiftt > 10)
1317 cache.current[t]->shiftScaleT = (f32)(1 << (16 - gSP.textureTile[t]->shiftt));
1318 else if (gSP.textureTile[t]->shiftt > 0)
1319 cache.current[t]->shiftScaleT /= (f32)(1 << gSP.textureTile[t]->shiftt);
1320
1321 TextureCache_Load( cache.current[t] );
1322 TextureCache_ActivateTexture( t, cache.current[t] );
1323
1324 cache.cachedBytes += cache.current[t]->textureBytes;
1325}
1326
1327void TextureCache_ActivateNoise(u32 t)
1328{
1329 glActiveTexture(GL_TEXTURE0 + t);
1330 glBindTexture(GL_TEXTURE_2D, cache.glNoiseNames[RSP.DList & 0x1F]);
1331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
1332 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
1333}
1334