GLES2GLIDE: Disabled Texture optim, it's full of bug...
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glitch64 / textures.cpp
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002  Dave2001
4 * Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #ifdef _WIN32
22 #include <windows.h>
23 #else // _WIN32
24 #include <stdlib.h>
25 #endif // _WIN32
26 #include "glide.h"
27 #include "main.h"
28 #include <stdio.h>
29
30 #include "../Glide64/ticks.h"
31
32 /* Napalm extensions to GrTextureFormat_t */
33 #define GR_TEXFMT_ARGB_CMP_FXT1           0x11
34 #define GR_TEXFMT_ARGB_8888               0x12
35 #define GR_TEXFMT_YUYV_422                0x13
36 #define GR_TEXFMT_UYVY_422                0x14
37 #define GR_TEXFMT_AYUV_444                0x15
38 #define GR_TEXFMT_ARGB_CMP_DXT1           0x16
39 #define GR_TEXFMT_ARGB_CMP_DXT2           0x17
40 #define GR_TEXFMT_ARGB_CMP_DXT3           0x18
41 #define GR_TEXFMT_ARGB_CMP_DXT4           0x19
42 #define GR_TEXFMT_ARGB_CMP_DXT5           0x1A
43 #define GR_TEXTFMT_RGB_888                0xFF
44
45 int TMU_SIZE = 8*2048*2048;
46 static unsigned char* texture = NULL;
47
48 int packed_pixels_support = -1;
49 int ati_sucks = -1;
50 float largest_supported_anisotropy = 1.0f;
51
52 #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
53 #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
54 #endif
55
56 int tex0_width, tex0_height, tex1_width, tex1_height;
57 float lambda;
58
59 static int min_filter0, mag_filter0, wrap_s0, wrap_t0;
60 static int min_filter1, mag_filter1, wrap_s1, wrap_t1;
61
62 unsigned char *filter(unsigned char *source, int width, int height, int *width2, int *height2);
63
64 //#define TEXBSP
65 #ifdef TEXBSP
66 typedef struct _texbsp
67 {
68   unsigned int id;
69   struct _texbsp *left;
70   struct _texbsp *right;
71 } texbsp;
72
73 static int nbTex = 0;
74 static texbsp *list = NULL;
75 #else
76 typedef struct _texlist
77 {
78   unsigned int id;
79   struct _texlist *next;
80 } texlist;
81
82 static int nbTex = 0;
83 static texlist *list = NULL;
84 #endif
85
86 #ifdef _WIN32
87 extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
88 extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
89 extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
90 #endif
91 #ifdef TEXBSP
92 void print_tex(bool detail=false)
93 {
94         texbsp *bsp = list;
95         int i=0;
96         if (!bsp) {
97                 printf("empty list (%s)", (nbTex==i)?"OK":"/!\\ KO");
98                 return;
99         }
100         bool ok=true;
101         while (bsp->left) bsp=bsp->left;
102         do {
103                 i++;
104                 if (detail) printf("%u\t", bsp->id);
105                 if (bsp->right) if (bsp->id>=bsp->right->id) ok=false;
106                 bsp=bsp->right;
107         } while (bsp);
108         printf("%s%s (taille %i/%i %s)\n",(detail)?"\n":"", (ok)?"OK":"KO", nbTex, i, (nbTex==i)?"OK":"/!\\ KO");
109         if (nbTex!=i && !detail) print_tex(true);
110 }
111 #endif
112 void remove_tex(unsigned int idmin, unsigned int idmax)
113 {
114 #ifdef TEXBSP
115 if ((idmin==18449 && idmax==22545) || (idmin==28689 || idmax==30737)) {printf("delete %u->%u, list=", idmin, idmax); print_tex(true);}
116         GLuint texlist[nbTex];
117         int     nbdel = 0;
118         // 1st look at initial point that is <= at idmin and than go right until id > idmax. Deleting all in between, and reattach list is needed
119         texbsp *aux = list;
120         bool reattach = false;
121         texbsp *debut, *fin, *temp;
122         // Empty list, easy
123         if (list==NULL) return;
124         if ((idmin==0x00000000) && (idmax==0xffffffff)) {
125                 // delete everything, quite easy
126                 debut = list->left;
127                 fin = list->right;
128                 while ((debut) || (fin)) {
129                         if (debut) {
130                                 texlist[nbdel++]=debut->id;
131                                 temp = debut->left;
132                                 free(debut);
133                                 debut = temp;
134                         }
135                         if (fin) {
136                                 texlist[nbdel++]=fin->id;
137                                 temp = fin->right;
138                                 free(fin);
139                                 fin = temp;
140                         }
141                 }
142                 texlist[nbdel++]=list->id;
143                 free(list);
144                 list=NULL;
145                 glDeleteTextures(nbdel, texlist);
146                 nbTex = 0;
147 //print_tex();
148                 return;
149         }
150         // General case, range delete
151         // find starting point.
152         debut = list;
153         while ((debut->id > idmin) && (debut->left!=NULL)) {
154            debut = debut->left;
155         }
156         while ((debut->right!=NULL) && (debut->right->id <= idmin)) {
157                 debut = debut->right;
158         }
159         fin = debut->left;
160         // and now delete
161         while ((debut!=NULL) && (debut->id >= idmin) && (debut->id < idmax))
162         {
163                 temp = debut->right;
164                 texlist[nbdel++]=debut->id;
165                 free(debut);
166                 debut=temp;
167         }
168         if (!nbdel)     return;
169         // rechain the list
170         if (fin) fin->right = debut;
171         if (debut) debut->left = fin;
172         if (debut) list = debut; else list = fin;               //change ankor
173         nbTex -= nbdel;
174         glDeleteTextures(nbdel, texlist);
175 printf("deleted (%i) %u->%u, list=", nbdel, idmin, idmax); print_tex();
176         return;
177 #else
178   unsigned int *t;
179   int n = 0;
180   texlist *aux = list;
181   int sz = nbTex;
182   if (aux == NULL) return;
183   t = (unsigned int*)malloc(sz * sizeof(int));
184   while (aux && aux->id >= idmin && aux->id < idmax)
185   {
186     if (n >= sz)
187       t = (unsigned int *) realloc(t, ++sz*sizeof(int));
188     t[n++] = aux->id;
189     aux = aux->next;
190     free(list);
191     list = aux;
192     nbTex--;
193   }
194   while (aux != NULL && aux->next != NULL)
195   {
196     if (aux->next->id >= idmin && aux->next->id < idmax)
197     {
198       texlist *aux2 = aux->next->next;
199       if (n >= sz)
200         t = (unsigned int *) realloc(t, ++sz*sizeof(int));
201       t[n++] = aux->next->id;
202       free(aux->next);
203       aux->next = aux2;
204       nbTex--;
205     }
206     aux = aux->next;
207   }
208   glDeleteTextures(n, t);
209   free(t);
210   //printf("RMVTEX nbtex is now %d (%06x - %06x)\n", nbTex, idmin, idmax);
211 #endif
212 }
213
214
215 void add_tex(unsigned int id)
216 {
217 #ifdef TEXBSP
218  if (list == NULL) {
219         list = (texbsp*)malloc(sizeof(texbsp));
220         list->left = NULL; list->right = NULL;
221         list->id = id;
222         nbTex++;
223         return;
224  }
225  texbsp *bsp = list;
226 if (id>TMU_SIZE*2) {printf("/!\\ add (%u), anchor=%u, list=", id, bsp->id); print_tex();}
227  if (bsp->id>=id) {     // go left
228         while ((bsp->left!=NULL) && (bsp->id > id))
229         {
230                 bsp=bsp->left;
231         }
232         if (bsp->id == id) return;
233         texbsp *ins = (texbsp*)malloc(sizeof(texbsp)); 
234         ins->id = id;
235         if ((bsp->id > id) && (bsp->left==NULL)) {
236                 bsp->left = ins;
237                 ins->right = bsp;
238                 ins->left = NULL;
239         } else {
240                 texbsp *aux = bsp->right;
241                 ins->left = bsp;
242                 ins->right = aux;
243                 bsp->right = ins;
244                 if (aux) aux->left = ins;
245         }
246         nbTex++;
247         list=bsp;       // new ankor
248         return;
249  } else {                       // go right
250         while ((bsp->right!=NULL) && (bsp->id < id))
251         {
252                 bsp=bsp->right;
253         }
254         if (bsp->id == id) return;
255         texbsp *ins = (texbsp*)malloc(sizeof(texbsp)); 
256         ins->id = id;
257         if ((bsp->id < id) && (bsp->right==NULL)) {     // add at end of chain !
258                 bsp->right = ins;
259                 ins->left = bsp;
260                 ins->right = NULL;
261         } else {        // insert in chain
262                 texbsp *aux = bsp->left;
263                 ins->right = bsp;
264                 ins->left = aux;
265                 bsp->left = ins;
266                 if (aux) aux->right = ins;
267         }
268         nbTex++;
269         list=bsp;       // new ankor
270         return;
271  }
272 #else
273   texlist *aux = list;
274   texlist *aux2;
275   //printf("ADDTEX nbtex is now %d (%06x)\n", nbTex, id);
276   if (list == NULL || id < list->id)
277   {
278     nbTex++;
279     list = (texlist*)malloc(sizeof(texlist));
280     list->next = aux;
281     list->id = id;
282     return;
283   }
284   while (aux->next != NULL && aux->next->id < id) aux = aux->next;
285   // ZIGGY added this test so that add_tex now accept re-adding an existing texture
286   if (aux->next != NULL && aux->next->id == id) return;
287   nbTex++;
288   aux2 = aux->next;
289   aux->next = (texlist*)malloc(sizeof(texlist));
290   aux->next->id = id;
291   aux->next->next = aux2;
292 #endif
293 }
294
295 void init_textures()
296 {
297   tex0_width = tex0_height = tex1_width = tex1_height = 2;
298   // ZIGGY because remove_tex isn't called (Pj64 doesn't like it), it's better
299   // to leave these so that they'll be reused (otherwise we have a memory leak)
300   //    list = NULL;
301   //    nbTex = 0;
302
303   if (!texture) texture = (unsigned char*)malloc(2048*2048*4);
304   #ifdef TEXBSP
305   list = NULL;
306   nbTex = 0;
307   #endif
308 }
309
310 void free_textures()
311 {
312 #ifndef WIN32
313   // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
314   remove_tex(0x00000000, 0xFFFFFFFF);
315 #endif
316   if (texture != NULL) {
317     free(texture);
318     texture = NULL;
319   }
320 }
321
322 FX_ENTRY FxU32 FX_CALL
323 grTexMinAddress( GrChipID_t tmu )
324 {
325   LOG("grTexMinAddress(%d)\r\n", tmu);
326   if (UMAmode)
327     return 0;
328   else
329     return tmu*TMU_SIZE;
330 }
331
332 FX_ENTRY FxU32 FX_CALL
333 grTexMaxAddress( GrChipID_t tmu )
334 {
335   LOG("grTexMaxAddress(%d)\r\n", tmu);
336   if (UMAmode)
337     return TMU_SIZE*2 - 1;
338   else
339     return tmu*TMU_SIZE + TMU_SIZE - 1;
340 }
341
342 FX_ENTRY FxU32 FX_CALL
343 grTexTextureMemRequired( FxU32     evenOdd,
344                         GrTexInfo *info   )
345 {
346   int width, height;
347   LOG("grTextureMemRequired(%d)\r\n", evenOdd);
348   if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexTextureMemRequired : loading more than one LOD");
349
350   if (info->aspectRatioLog2 < 0)
351   {
352     height = 1 << info->largeLodLog2;
353     width = height >> -info->aspectRatioLog2;
354   }
355   else
356   {
357     width = 1 << info->largeLodLog2;
358     height = width >> info->aspectRatioLog2;
359   }
360
361   switch(info->format)
362   {
363   case GR_TEXFMT_ALPHA_8:
364   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
365   case GR_TEXFMT_ALPHA_INTENSITY_44:
366     return width*height;
367     break;
368   case GR_TEXFMT_ARGB_1555:
369   case GR_TEXFMT_ARGB_4444:
370   case GR_TEXFMT_ALPHA_INTENSITY_88:
371   case GR_TEXFMT_RGB_565:
372     return (width*height)<<1;
373     break;
374   case GR_TEXFMT_ARGB_8888:
375     return (width*height)<<2;
376     break;
377   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
378     return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
379   case GR_TEXFMT_ARGB_CMP_DXT3:
380     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
381   case GR_TEXFMT_ARGB_CMP_DXT5:
382     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
383   case GR_TEXFMT_ARGB_CMP_FXT1:
384     return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
385   default:
386     display_warning("grTexTextureMemRequired : unknown texture format: %x", info->format);
387   }
388   return 0;
389 }
390
391 FX_ENTRY FxU32 FX_CALL
392 grTexCalcMemRequired(
393                      GrLOD_t lodmin, GrLOD_t lodmax,
394                      GrAspectRatio_t aspect, GrTextureFormat_t fmt)
395 {
396   int width, height;
397   LOG("grTexCalcMemRequired(%d, %d, %d, %d)\r\n", lodmin, lodmax, aspect, fmt);
398   if (lodmax != lodmin) display_warning("grTexCalcMemRequired : loading more than one LOD");
399
400   if (aspect < 0)
401   {
402     height = 1 << lodmax;
403     width = height >> -aspect;
404   }
405   else
406   {
407     width = 1 << lodmax;
408     height = width >> aspect;
409   }
410
411   switch(fmt)
412   {
413   case GR_TEXFMT_ALPHA_8:
414   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
415   case GR_TEXFMT_ALPHA_INTENSITY_44:
416     return width*height;
417     break;
418   case GR_TEXFMT_ARGB_1555:
419   case GR_TEXFMT_ARGB_4444:
420   case GR_TEXFMT_ALPHA_INTENSITY_88:
421   case GR_TEXFMT_RGB_565:
422     return (width*height)<<1;
423     break;
424   case GR_TEXFMT_ARGB_8888:
425     return (width*height)<<2;
426     break;
427   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
428     return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
429   case GR_TEXFMT_ARGB_CMP_DXT3:
430     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
431   case GR_TEXFMT_ARGB_CMP_DXT5:
432     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
433   case GR_TEXFMT_ARGB_CMP_FXT1:
434     return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
435   default:
436     display_warning("grTexTextureMemRequired : unknown texture format: %x", fmt);
437   }
438   return 0;
439 }
440
441 int grTexFormatSize(int fmt)
442 {
443   int factor = -1;
444   switch(fmt) {
445   case GR_TEXFMT_ALPHA_8:
446   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
447     factor = 1;
448     break;
449   case GR_TEXFMT_ALPHA_INTENSITY_44:
450     factor = 1;
451     break;
452   case GR_TEXFMT_RGB_565:
453     factor = 2;
454     break;
455   case GR_TEXFMT_ARGB_1555:
456     factor = 2;
457     break;
458   case GR_TEXFMT_ALPHA_INTENSITY_88:
459     factor = 2;
460     break;
461   case GR_TEXFMT_ARGB_4444:
462     factor = 2;
463     break;
464   case GR_TEXFMT_ARGB_8888:
465     factor = 4;
466     break;
467   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
468     factor = 8;                  // HACKALERT: factor holds block bytes
469     break;
470   case GR_TEXFMT_ARGB_CMP_DXT3:  // FXT1,DXT1,5 support - H.Morii
471     factor = 16;                  // HACKALERT: factor holds block bytes
472     break;
473   case GR_TEXFMT_ARGB_CMP_DXT5:
474     factor = 16;
475     break;
476   case GR_TEXFMT_ARGB_CMP_FXT1:
477     factor = 8;
478     break;
479   default:
480     display_warning("grTexFormatSize : unknown texture format: %x", fmt);
481   }
482   return factor;
483 }
484
485 int grTexFormat2GLPackedFmt(int fmt, int * gltexfmt, int * glpixfmt, int * glpackfmt)
486 {
487     *gltexfmt = GL_RGBA;
488     *glpixfmt = GL_RGBA;
489     *glpackfmt = GL_UNSIGNED_BYTE;
490     return 0;
491 /*
492   int factor = -1;
493   switch(fmt) {
494   case GR_TEXFMT_ALPHA_8:
495     factor = 1;
496     *gltexfmt = GL_INTENSITY8;
497     *glpixfmt = GL_LUMINANCE;
498     *glpackfmt = GL_UNSIGNED_BYTE;
499     break;
500   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
501     factor = 1;
502     *gltexfmt = GL_LUMINANCE8;
503     *glpixfmt = GL_LUMINANCE;
504     *glpackfmt = GL_UNSIGNED_BYTE;
505     break;
506   case GR_TEXFMT_ALPHA_INTENSITY_44:
507     break;
508   case GR_TEXFMT_RGB_565:
509     factor = 2;
510     *gltexfmt = GL_RGB;
511     *glpixfmt = GL_RGB;
512     *glpackfmt = GL_UNSIGNED_SHORT_5_6_5;
513     break;
514   case GR_TEXFMT_ARGB_1555:
515     if (ati_sucks > 0) return -1; // ATI sucks as usual (fixes slowdown on ATI)
516     factor = 2;
517     *gltexfmt = GL_RGB5_A1;
518     *glpixfmt = GL_BGRA;
519     *glpackfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV;
520     break;
521   case GR_TEXFMT_ALPHA_INTENSITY_88:
522     factor = 2;
523     *gltexfmt = GL_LUMINANCE8_ALPHA8;
524     *glpixfmt = GL_LUMINANCE_ALPHA;
525     *glpackfmt = GL_UNSIGNED_BYTE;
526     break;
527   case GR_TEXFMT_ARGB_4444:
528     factor = 2;
529     *gltexfmt = GL_RGBA4;
530     *glpixfmt = GL_BGRA;
531     *glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV;
532     break;
533   case GR_TEXFMT_ARGB_8888:
534     factor = 4;
535     *gltexfmt = GL_RGBA8;
536     *glpixfmt = GL_BGRA;
537     *glpackfmt = GL_UNSIGNED_INT_8_8_8_8_REV;
538     break;
539   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
540     // HACKALERT: 3Dfx Glide uses GR_TEXFMT_ARGB_CMP_DXT1 for both opaque DXT1 and DXT1 with 1bit alpha.
541     // GlideHQ compiled with GLIDE64_DXTN option enabled, uses opaqe DXT1 only.
542     factor = 8; // HACKALERT: factor holds block bytes
543     *gltexfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // these variables aren't used
544     *glpixfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
545     *glpackfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
546     break;
547   case GR_TEXFMT_ARGB_CMP_DXT3:
548     factor = 16;
549     *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
550     *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
551     *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
552     break;
553   case GR_TEXFMT_ARGB_CMP_DXT5:
554     factor = 16;
555     *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
556     *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
557     *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
558     break;
559   case GR_TEXFMT_ARGB_CMP_FXT1:
560     factor = 8;
561     *gltexfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
562     *glpixfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
563     *glpackfmt = GL_COMPRESSED_RGBA_FXT1_3DFX; // XXX: what should we do about GL_COMPRESSED_RGB_FXT1_3DFX?
564     break;
565   default:
566     display_warning("grTexFormat2GLPackedFmt : unknown texture format: %x", fmt);
567   }
568   return factor;
569 */
570 }
571
572 FX_ENTRY void FX_CALL
573 grTexDownloadMipMap( GrChipID_t tmu,
574                     FxU32      startAddress,
575                     FxU32      evenOdd,
576                     GrTexInfo  *info )
577 {
578   int width, height, i, j;
579   int factor;
580   int glformat = 0;
581   int gltexfmt, glpixfmt, glpackfmt;
582   LOG("grTexDownloadMipMap(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
583   if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexDownloadMipMap : loading more than one LOD");
584
585   if (info->aspectRatioLog2 < 0)
586   {
587     height = 1 << info->largeLodLog2;
588     width = height >> -info->aspectRatioLog2;
589   }
590   else
591   {
592     width = 1 << info->largeLodLog2;
593     height = width >> info->aspectRatioLog2;
594   }
595
596   if (!packed_pixels_support)
597     factor = -1;
598   else
599     factor = grTexFormat2GLPackedFmt(info->format, &gltexfmt, &glpixfmt, &glpackfmt);
600
601   if (factor < 0) {
602
603     // VP fixed the texture conversions to be more accurate, also swapped
604     // the for i/j loops so that is is less likely to break the memory cache
605     register int n = 0, m = 0;
606     switch(info->format)
607     {
608     case GR_TEXFMT_ALPHA_8:
609       for (i=0; i<height; i++)
610       {
611         for (j=0; j<width; j++)
612         {
613           unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
614           texel |= (texel << 8);
615           texel |= (texel << 16);
616           ((unsigned int*)texture)[n] = texel;
617           m++;
618           n++;
619         }
620       }
621       factor = 1;
622       glformat = GL_RGBA;
623       break;
624     case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
625       for (i=0; i<height; i++)
626       {
627         for (j=0; j<width; j++)
628         {
629           unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
630           texel |= (0xFF000000 | (texel << 16) | (texel << 8));
631           ((unsigned int*)texture)[n] = texel;
632           m++;
633           n++;
634         }
635       }
636       factor = 1;
637       glformat = GL_ALPHA;
638       break;
639     case GR_TEXFMT_ALPHA_INTENSITY_44:
640 #if 1
641       for (i=0; i<height; i++)
642       {
643         for (j=0; j<width; j++)
644         {
645           unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
646 #if 1
647           /* accurate conversion */
648           unsigned int texel_hi = (texel & 0x000000F0) << 20;
649           unsigned int texel_low = texel & 0x0000000F;
650           texel_low |= (texel_low << 4);
651           texel_hi |= ((texel_hi << 4) | (texel_low << 16) | (texel_low << 8) | texel_low);
652 #else
653           unsigned int texel_hi = (texel & 0x000000F0) << 24;
654           unsigned int texel_low = (texel & 0x0000000F) << 4;
655           texel_hi |= ((texel_low << 16) | (texel_low << 8) | texel_low);
656 #endif
657           ((unsigned int*)texture)[n] = texel_hi;
658           m++;
659           n++;
660         }
661       }
662       factor = 1;
663       glformat = GL_LUMINANCE_ALPHA;
664 #endif
665       break;
666     case GR_TEXFMT_RGB_565:
667       for (i=0; i<height; i++)
668       {
669         for (j=0; j<width; j++)
670         {
671           unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
672           unsigned int B = texel & 0x0000F800;
673           unsigned int G = texel & 0x000007E0;
674           unsigned int R = texel & 0x0000001F;
675 #if 0
676           /* accurate conversion */
677           ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | ((R >> 2) << 16) | (G << 5) | ((G >> 9) << 8) | (B >> 8) | (B >> 13);
678 #else
679           ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | (G << 5) | (B >> 8);
680 #endif
681           m++;
682           n++;
683         }
684       }
685       factor = 2;
686       glformat = GL_RGB;
687       break;
688     case GR_TEXFMT_ARGB_1555:
689       for (i=0; i<height; i++)
690       {
691         for (j=0; j<width; j++)
692         {
693           unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
694           unsigned int A = texel & 0x00008000 ? 0xFF000000 : 0;
695           unsigned int B = texel & 0x00007C00;
696           unsigned int G = texel & 0x000003E0;
697           unsigned int R = texel & 0x0000001F;
698 #if 0
699           /* accurate conversion */
700           ((unsigned int*)texture)[n] = A | (R << 19) | ((R >> 2) << 16) | (G << 6) | ((G >> 8) << 8) | (B >> 7) | (B >> 12);
701 #else
702           ((unsigned int*)texture)[n] = A | (R << 19) | (G << 6) | (B >> 7);
703 #endif
704           m++;
705           n++;
706         }
707       }
708       factor = 2;
709       glformat = GL_RGBA;
710       break;
711     case GR_TEXFMT_ALPHA_INTENSITY_88:
712       for (i=0; i<height; i++)
713       {
714         for (j=0; j<width; j++)
715         {
716           unsigned int AI = (unsigned int)((unsigned short*)info->data)[m];
717           unsigned int I = (unsigned int)(AI & 0x000000FF);
718           ((unsigned int*)texture)[n] = (AI << 16) | (I << 8) | I;
719           m++;
720           n++;
721         }
722       }
723       factor = 2;
724       glformat = GL_LUMINANCE_ALPHA;
725       break;
726     case GR_TEXFMT_ARGB_4444:
727
728       for (i=0; i<height; i++)
729       {
730         for (j=0; j<width; j++)
731         {
732           unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
733           unsigned int A = texel & 0x0000F000;
734           unsigned int B = texel & 0x00000F00;
735           unsigned int G = texel & 0x000000F0;
736           unsigned int R = texel & 0x0000000F;
737 #if 0
738           /* accurate conversion */
739           ((unsigned int*)texture)[n] = (A << 16) | (A << 12) | (R << 20) | (R << 16) | (G << 8) | (G << 4) | (B >> 4) | (B >> 8);
740 #else
741           ((unsigned int*)texture)[n] = (A << 16) | (R << 20) | (G << 8) | (B >> 4);
742 #endif
743           m++;
744           n++;
745         }
746       }
747       factor = 2;
748       glformat = GL_RGBA;
749       break;
750     case GR_TEXFMT_ARGB_8888:
751       for (i=0; i<height; i++)
752       {
753         for (j=0; j<width; j++)
754         {
755           unsigned int texel = ((unsigned int*)info->data)[m];
756           unsigned int A = texel & 0xFF000000;
757           unsigned int B = texel & 0x00FF0000;
758           unsigned int G = texel & 0x0000FF00;
759           unsigned int R = texel & 0x000000FF;
760           ((unsigned int*)texture)[n] = A | (R << 16) | G | (B >> 16);
761           m++;
762           n++;
763         }
764       }
765       factor = 4;
766       glformat = GL_RGBA;
767       break;
768 /*
769     case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
770       factor = 8;                 // HACKALERT: factor holds block bytes
771       glformat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
772       break;
773     case GR_TEXFMT_ARGB_CMP_DXT3: // FXT1,DXT1,5 support - H.Morii
774       factor = 16;                 // HACKALERT: factor holds block bytes
775       glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
776       break;
777     case GR_TEXFMT_ARGB_CMP_DXT5:
778       factor = 16;
779       glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
780       break;
781     case GR_TEXFMT_ARGB_CMP_FXT1:
782       factor = 8;
783       glformat = GL_COMPRESSED_RGBA_FXT1_3DFX;
784       break;
785 */
786     default:
787       display_warning("grTexDownloadMipMap : unknown texture format: %x", info->format);
788       factor = 0;
789     }
790   }
791
792   if (nbTextureUnits <= 2)
793     glActiveTexture(GL_TEXTURE1);
794   else
795     glActiveTexture(GL_TEXTURE2);
796
797   switch(info->format)
798   {
799   case GR_TEXFMT_ARGB_CMP_DXT1:
800   case GR_TEXFMT_ARGB_CMP_DXT3:
801   case GR_TEXFMT_ARGB_CMP_DXT5:
802   case GR_TEXFMT_ARGB_CMP_FXT1:
803     remove_tex(startAddress+1, startAddress+1+((width*height*factor)>>4));
804     break;
805   default:
806     remove_tex(startAddress+1, startAddress+1+(width*height*factor));
807   }
808
809   add_tex(startAddress+1);
810   glBindTexture(GL_TEXTURE_2D, startAddress+1);
811
812   if (largest_supported_anisotropy > 1.0f)
813     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
814
815   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
816 /*
817   switch(info->format)
818   {
819   case GR_TEXFMT_ARGB_CMP_DXT1:
820   case GR_TEXFMT_ARGB_CMP_DXT3:
821   case GR_TEXFMT_ARGB_CMP_DXT5:
822   case GR_TEXFMT_ARGB_CMP_FXT1:
823     glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, (glformat ? glformat : gltexfmt), width, height, 0, (width*height*factor)>>4, info->data);
824     break;
825   default:
826     if (glformat) {
827       glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
828     } else
829       glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, info->data);
830   }
831 */
832
833   glBindTexture(GL_TEXTURE_2D, default_texture);
834 }
835
836 int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info );
837
838 FX_ENTRY void FX_CALL
839 grTexSource( GrChipID_t tmu,
840             FxU32      startAddress,
841             FxU32      evenOdd,
842             GrTexInfo  *info )
843 {
844   LOG("grTexSource(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
845
846   if (tmu == GR_TMU1 || nbTextureUnits <= 2)
847   {
848     if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
849     glActiveTexture(GL_TEXTURE0);
850
851     if (info->aspectRatioLog2 < 0)
852     {
853       tex0_height = 256;
854       tex0_width = tex0_height >> -info->aspectRatioLog2;
855     }
856     else
857     {
858       tex0_width = 256;
859       tex0_height = tex0_width >> info->aspectRatioLog2;
860     }
861
862     glBindTexture(GL_TEXTURE_2D, startAddress+1);
863 #ifdef VPDEBUG
864     dump_tex(startAddress+1);
865 #endif
866     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0);
867     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0);
868     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0);
869     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0);
870   }
871   else
872   {
873     glActiveTexture(GL_TEXTURE1);
874
875     if (info->aspectRatioLog2 < 0)
876     {
877       tex1_height = 256;
878       tex1_width = tex1_height >> -info->aspectRatioLog2;
879     }
880     else
881     {
882       tex1_width = 256;
883       tex1_height = tex1_width >> info->aspectRatioLog2;
884     }
885
886     glBindTexture(GL_TEXTURE_2D, startAddress+1);
887 #ifdef VPDEBUG
888     dump_tex(startAddress+1);
889 #endif
890     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1);
891     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1);
892     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
893     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
894   }
895   if(!CheckTextureBufferFormat(tmu, startAddress+1, info))
896   {
897     if(tmu == 0 && blackandwhite1 != 0)
898     {
899       blackandwhite1 = 0;
900       need_to_compile = 1;
901     }
902     if(tmu == 1 && blackandwhite0 != 0)
903     {
904       blackandwhite0 = 0;
905       need_to_compile = 1;
906     }
907   }
908
909 #if 0
910   extern int auxbuffer;
911   static int oldbuffer;
912   FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
913   if (auxbuffer == GR_BUFFER_AUXBUFFER && auxbuffer != oldbuffer)
914     grAuxBufferExt(auxbuffer);
915   oldbuffer = auxbuffer;
916 #endif
917 }
918
919 FX_ENTRY void FX_CALL
920 grTexDetailControl(
921                    GrChipID_t tmu,
922                    int lod_bias,
923                    FxU8 detail_scale,
924                    float detail_max
925                    )
926 {
927   LOG("grTexDetailControl(%d,%d,%d,%d)\r\n", tmu, lod_bias, detail_scale, detail_max);
928   if (lod_bias != 31 && detail_scale != 7)
929   {
930     if (!lod_bias && !detail_scale && !detail_max) return;
931     else
932       display_warning("grTexDetailControl : %d, %d, %f", lod_bias, detail_scale, detail_max);
933   }
934   lambda = detail_max;
935   if(lambda > 1.0f)
936   {
937     lambda = 1.0f - (255.0f - lambda);
938   }
939   if(lambda > 1.0f) display_warning("lambda:%f", lambda);
940
941   set_lambda();
942 }
943
944 FX_ENTRY void FX_CALL
945 grTexLodBiasValue(GrChipID_t tmu, float bias )
946 {
947   LOG("grTexLodBiasValue(%d,%f)\r\n", tmu, bias);
948 }
949
950 FX_ENTRY void FX_CALL
951 grTexFilterMode(
952                 GrChipID_t tmu,
953                 GrTextureFilterMode_t minfilter_mode,
954                 GrTextureFilterMode_t magfilter_mode
955                 )
956 {
957   LOG("grTexFilterMode(%d,%d,%d)\r\n", tmu, minfilter_mode, magfilter_mode);
958   if (tmu == GR_TMU1 || nbTextureUnits <= 2)
959   {
960     if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
961     if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter0 = GL_NEAREST;
962     else min_filter0 = GL_LINEAR;
963
964     if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter0 = GL_NEAREST;
965     else mag_filter0 = GL_LINEAR;
966
967     glActiveTexture(GL_TEXTURE0);
968     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0);
969     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0);
970   }
971   else
972   {
973     if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter1 = GL_NEAREST;
974     else min_filter1 = GL_LINEAR;
975
976     if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter1 = GL_NEAREST;
977     else mag_filter1 = GL_LINEAR;
978
979     glActiveTexture(GL_TEXTURE1);
980     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1);
981     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1);
982   }
983 }
984
985 FX_ENTRY void FX_CALL
986 grTexClampMode(
987                GrChipID_t tmu,
988                GrTextureClampMode_t s_clampmode,
989                GrTextureClampMode_t t_clampmode
990                )
991 {
992   LOG("grTexClampMode(%d, %d, %d)\r\n", tmu, s_clampmode, t_clampmode);
993   if (tmu == GR_TMU1 || nbTextureUnits <= 2)
994   {
995     if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
996     switch(s_clampmode)
997     {
998     case GR_TEXTURECLAMP_WRAP:
999       wrap_s0 = GL_REPEAT;
1000       break;
1001     case GR_TEXTURECLAMP_CLAMP:
1002       wrap_s0 = GL_CLAMP_TO_EDGE;
1003       break;
1004     case GR_TEXTURECLAMP_MIRROR_EXT:
1005       wrap_s0 = GL_MIRRORED_REPEAT;
1006       break;
1007     default:
1008       display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode);
1009     }
1010     switch(t_clampmode)
1011     {
1012     case GR_TEXTURECLAMP_WRAP:
1013       wrap_t0 = GL_REPEAT;
1014       break;
1015     case GR_TEXTURECLAMP_CLAMP:
1016       wrap_t0 = GL_CLAMP_TO_EDGE;
1017       break;
1018     case GR_TEXTURECLAMP_MIRROR_EXT:
1019       wrap_t0 = GL_MIRRORED_REPEAT;
1020       break;
1021     default:
1022       display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
1023     }
1024     glActiveTexture(GL_TEXTURE0);
1025     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0);
1026     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0);
1027   }
1028   else
1029   {
1030     switch(s_clampmode)
1031     {
1032     case GR_TEXTURECLAMP_WRAP:
1033       wrap_s1 = GL_REPEAT;
1034       break;
1035     case GR_TEXTURECLAMP_CLAMP:
1036       wrap_s1 = GL_CLAMP_TO_EDGE;
1037       break;
1038     case GR_TEXTURECLAMP_MIRROR_EXT:
1039       wrap_s1 = GL_MIRRORED_REPEAT;
1040       break;
1041     default:
1042       display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode);
1043     }
1044     switch(t_clampmode)
1045     {
1046     case GR_TEXTURECLAMP_WRAP:
1047       wrap_t1 = GL_REPEAT;
1048       break;
1049     case GR_TEXTURECLAMP_CLAMP:
1050       wrap_t1 = GL_CLAMP_TO_EDGE;
1051       break;
1052     case GR_TEXTURECLAMP_MIRROR_EXT:
1053       wrap_t1 = GL_MIRRORED_REPEAT;
1054       break;
1055     default:
1056       display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
1057     }
1058     glActiveTexture(GL_TEXTURE1);
1059     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
1060     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
1061   }
1062 }