Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[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 #elif defined(TEXREDBLACK)
76 typedef struct _texbsp
77 {
78   unsigned int id;
79   int color;
80   struct _texbsp *left;
81   struct _texbsp *right;
82   struct _texbsp *parent;
83 } texbsp;
84
85 static int nbTex = 0;
86 static texbsp *list = NULL;
87 #else
88 typedef struct _texlist
89 {
90   unsigned int id;
91   struct _texlist *next;
92 } texlist;
93
94 static int nbTex = 0;
95 static texlist *list = NULL;
96 #endif
97
98 #ifdef _WIN32
99 extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
100 extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
101 extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
102 #endif
103 #ifdef TEXREDBLACK
104 // utilitie function for red-black tree
105 // taken from Wikipedia
106 // http://en.wikipedia.org/wiki/Red-black_tree
107 #define BLACK   0
108 #define RED             1
109 //**** Family stuff ****
110 texbsp *grandparent(texbsp *n)
111 {
112  if ((n != NULL) && (n->parent != NULL))
113   return n->parent->parent;
114  else
115   return NULL;
116 }
117 texbsp *sibling(texbsp *n) 
118 {
119  if ((n != NULL) && (n->parent != NULL))
120   if (n == n->parent->left)
121     return n->parent->right;
122   else
123     return n->parent->left;
124  else
125         return NULL;
126 }
127 texbsp *uncle(texbsp *n)
128 {
129  texbsp *g = grandparent(n);
130  if (g == NULL)
131   return NULL; // No grandparent means no uncle
132  if (n->parent == g->left)
133   return g->right;
134  else
135   return g->left;
136 }
137 //**** Search functions ****
138 texbsp* lookup_node(GLuint key) 
139 {
140  texbsp* n = texlist;
141  while (n != NULL) {
142   int comp_result = (int)key - (int)n->id;
143   if (comp_result == 0) {
144    return n;
145   } else if (comp_result < 0) {
146    n = n->left;
147   } else {
148    n = n->right;
149   }
150  }
151  return n;
152 }
153 GLuint rbtree_lookup(GLuint key) 
154 {
155  texbsp* n = lookup_node(key);
156  return n == NULL ? NULL : n->id;
157 }
158 //**** Basic insertion / replace ****
159 texbsp* new_node(GLuint id, int node_color, texbsp* left, texbsp* right) 
160 {
161   texbsp* result = malloc(sizeof(texbsp));
162   result->id = id;
163   result->color = node_color;
164   result->left = left;
165   result->right = right;
166   if (left  != NULL)  left->parent = result;
167   if (right != NULL) right->parent = result;
168   result->parent = NULL;
169   return result;
170 }
171 void replace_node(texbsp* oldn, texbsp* newn) 
172 {
173  if (oldn->parent == NULL) {
174   list = newn;
175  } else {
176   if (oldn == oldn->parent->left)
177    oldn->parent->left = newn;
178   else
179    oldn->parent->right = newn;
180  }
181  if (newn != NULL) {
182   newn->parent = oldn->parent;
183  }
184 }
185 //**** Rotation functions ****
186 void rotate_left(texbsp* n) 
187 {
188  texbsp* r = n->right;
189  replace_node(n, r);
190  n->right = r->left;
191  if (r->left != NULL) {
192   r->left->parent = n;
193  }
194  r->left = n;
195  n->parent = r;
196 }
197 void rotate_right(texbsp* n) 
198 {
199  node L = n->left;
200  replace_node(n, L);
201  n->left = L->right;
202  if (L->right != NULL) {
203   L->right->parent = n;
204  }
205  L->right = n;
206  n->parent = L;
207 }
208 //**** Insertion cases ****
209 void insert_case1(texbsp *n)
210 {
211  if (n->parent == NULL)
212   n->color = BLACK;
213  else
214   insert_case2(n);
215 }
216 void insert_case2(texbsp *n)
217 {
218  if (n->parent->color == BLACK)
219   return; 
220  else
221   insert_case3(n);
222 }
223 void insert_case3(texbsp *n)
224 {
225  texbsp *u = uncle(n), *g;
226  
227  if ((u != NULL) && (u->color == RED)) {
228   n->parent->color = BLACK;
229   u->color = BLACK;
230   g = grandparent(n);
231   g->color = RED;
232   insert_case1(g);
233  } else {
234   insert_case4(n);
235  }
236 }
237 void insert_case4(texbsp *n)
238 {
239  texbsp *g = grandparent(n);
240  
241  if ((n == n->parent->right) && (n->parent == g->left)) {
242   rotate_left(n->parent);
243   n = n->left; 
244  } else if ((n == n->parent->left) && (n->parent == g->right)) {
245   rotate_right(n->parent);
246   n = n->right; 
247  }
248  insert_case5(n);
249 }
250 void insert_case5(texbsp *n)
251 {
252  struct node *g = grandparent(n);
253  
254  n->parent->color = BLACK;
255  g->color = RED;
256  if (n == n->parent->left)
257   rotate_right(g);
258  else
259   rotate_left(g);
260 }
261 void rbtree_insert(GLuint key) 
262 {
263  texbsp* inserted_node = new_node(key, RED, NULL, NULL);
264  if (list == NULL) {
265   list = inserted_node;
266  } else {
267   texbsp* n = t->root;
268   while (1) {
269    int comp_result = (int)key - (int)n->id;
270    if (comp_result == 0) {
271     free (inserted_node);
272     return;
273    } else if (comp_result < 0) {
274     if (n->left == NULL) {
275      n->left = inserted_node;
276      break;
277     } else {
278      n = n->left;
279     }
280    } else {
281     if (n->right == NULL) {
282      n->right = inserted_node;
283      break;
284     } else {
285      n = n->right;
286     }
287    }
288   }
289   inserted_node->parent = n;
290  }
291  insert_case1(t, inserted_node);
292 }
293 //**** Removing cases ****
294
295 #endif
296 void remove_tex(unsigned int idmin, unsigned int idmax)
297 {
298 #ifdef TEXBSP
299         GLuint texlist[nbTex];
300         int     nbdel = 0;
301         // 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
302         texbsp *aux = list;
303         bool reattach = false;
304         texbsp *debut, *fin, *temp;
305         // Empty list, easy
306         if (list==NULL) return;
307         if ((idmin==0x00000000) && (idmax==0xffffffff)) {
308                 // delete everything, quite easy
309                 debut = list->right;
310                 fin = list->left;
311                 while ((debut) && (fin)) {
312                         if (debut) {
313                                 texlist[nbdel++]=debut->id;
314                                 temp = debut->right;
315                                 free(debut);
316                                 debut = temp;
317                         }
318                         if (fin) {
319                                 texlist[nbdel++]=fin->id;
320                                 temp = fin->left;
321                                 free(fin);
322                                 fin = temp;
323                         }
324                 }
325                 texlist[nbdel++]=list->id;
326                 free(list);
327                 list=NULL;
328                 glDeleteTextures(nbdel, texlist);
329                 nbTex = 0;
330                 return;
331         }
332         // General case, range delete
333         // find starting point.
334         debut = list;
335         while ((debut->id > idmin) && (debut->right!=NULL)) {
336            debut = debut->right;
337         }
338         while ((debut->left!=NULL) && (debut->left->id < idmin)) {
339                 debut = debut->left;
340         }
341         fin = debut->right;
342         // and now delete
343         while ((debut!=NULL) && (debut->id >= idmin) && (debut->id < idmax))
344         {
345                 temp = debut->left;
346                 texlist[nbdel++]=debut->id;
347                 free(debut);
348                 debut=temp;
349         }
350         // rechain the list
351         if (fin) fin->left = debut;
352         if (debut) debut->right = fin;
353         if (debut) list = debut; else list = fin;               //change ankor
354         glDeleteTextures(nbdel, texlist);
355         nbTex -= nbdel;
356         return;
357 #else
358   unsigned int *t;
359   int n = 0;
360   texlist *aux = list;
361   int sz = nbTex;
362   if (aux == NULL) return;
363   t = (unsigned int*)malloc(sz * sizeof(int));
364   while (aux && aux->id >= idmin && aux->id < idmax)
365   {
366     if (n >= sz)
367       t = (unsigned int *) realloc(t, ++sz*sizeof(int));
368     t[n++] = aux->id;
369     aux = aux->next;
370     free(list);
371     list = aux;
372     nbTex--;
373   }
374   while (aux != NULL && aux->next != NULL)
375   {
376     if (aux->next->id >= idmin && aux->next->id < idmax)
377     {
378       texlist *aux2 = aux->next->next;
379       if (n >= sz)
380         t = (unsigned int *) realloc(t, ++sz*sizeof(int));
381       t[n++] = aux->next->id;
382       free(aux->next);
383       aux->next = aux2;
384       nbTex--;
385     }
386     aux = aux->next;
387   }
388   glDeleteTextures(n, t);
389   free(t);
390   //printf("RMVTEX nbtex is now %d (%06x - %06x)\n", nbTex, idmin, idmax);
391 #endif
392 }
393
394
395 void add_tex(unsigned int id)
396 {
397 #ifdef TEXBSP
398 //printf("add_tex(%u)\n", id);
399  if (list == NULL) {
400 //printf("add root\n");
401         list = (texbsp*)malloc(sizeof(texbsp));
402         list->left = NULL; list->right = NULL;
403         list->id = id;
404         nbTex++;
405         return;
406  }
407  texbsp *bsp = list;
408  if (bsp->id>=id) {     // go left
409 // printf("Go left\n");
410         while ((bsp->left!=NULL) && (bsp->left->id > id))
411         {
412                 bsp=bsp->left;
413         }
414         if (bsp->id = id) return;
415         texbsp *aux = bsp->left;
416         texbsp *ins = (texbsp*)malloc(sizeof(texbsp)); 
417         ins->left = aux;
418         ins->right = bsp;
419         ins->id = id;
420         bsp->left = ins;
421         if (aux) aux->right = ins;
422         nbTex++;
423         list=bsp;       // new ankor
424         return;
425  } else {                       // go right
426 //printf("Go right\n");
427         while ((bsp->right!=NULL) && (bsp->right->id < id))
428         {
429 //printf("right\n");
430                 bsp=bsp->right;
431         }
432 //printf("stopped at %u\n", bsp->id);
433         if (bsp->id = id) return;
434         texbsp *aux = bsp->right;
435         texbsp *ins = (texbsp*)malloc(sizeof(texbsp)); 
436         ins->right = aux;
437         ins->left = bsp;
438         ins->id = id;
439         bsp->right = ins;
440         if (aux) aux->left = ins;
441         nbTex++;
442         list=bsp;       // new ankor
443         return;
444  }
445 #else
446   texlist *aux = list;
447   texlist *aux2;
448   //printf("ADDTEX nbtex is now %d (%06x)\n", nbTex, id);
449   if (list == NULL || id < list->id)
450   {
451     nbTex++;
452     list = (texlist*)malloc(sizeof(texlist));
453     list->next = aux;
454     list->id = id;
455     return;
456   }
457   while (aux->next != NULL && aux->next->id < id) aux = aux->next;
458   // ZIGGY added this test so that add_tex now accept re-adding an existing texture
459   if (aux->next != NULL && aux->next->id == id) return;
460   nbTex++;
461   aux2 = aux->next;
462   aux->next = (texlist*)malloc(sizeof(texlist));
463   aux->next->id = id;
464   aux->next->next = aux2;
465 #endif
466 }
467
468 void init_textures()
469 {
470   tex0_width = tex0_height = tex1_width = tex1_height = 2;
471   // ZIGGY because remove_tex isn't called (Pj64 doesn't like it), it's better
472   // to leave these so that they'll be reused (otherwise we have a memory leak)
473   //    list = NULL;
474   //    nbTex = 0;
475
476   if (!texture) texture = (unsigned char*)malloc(2048*2048*4);
477 }
478
479 void free_textures()
480 {
481 #ifndef WIN32
482   // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
483   remove_tex(0x00000000, 0xFFFFFFFF);
484 #endif
485   if (texture != NULL) {
486     free(texture);
487     texture = NULL;
488   }
489 }
490
491 FX_ENTRY FxU32 FX_CALL
492 grTexMinAddress( GrChipID_t tmu )
493 {
494   LOG("grTexMinAddress(%d)\r\n", tmu);
495   if (UMAmode)
496     return 0;
497   else
498     return tmu*TMU_SIZE;
499 }
500
501 FX_ENTRY FxU32 FX_CALL
502 grTexMaxAddress( GrChipID_t tmu )
503 {
504   LOG("grTexMaxAddress(%d)\r\n", tmu);
505   if (UMAmode)
506     return TMU_SIZE*2 - 1;
507   else
508     return tmu*TMU_SIZE + TMU_SIZE - 1;
509 }
510
511 FX_ENTRY FxU32 FX_CALL
512 grTexTextureMemRequired( FxU32     evenOdd,
513                         GrTexInfo *info   )
514 {
515   int width, height;
516   LOG("grTextureMemRequired(%d)\r\n", evenOdd);
517   if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexTextureMemRequired : loading more than one LOD");
518
519   if (info->aspectRatioLog2 < 0)
520   {
521     height = 1 << info->largeLodLog2;
522     width = height >> -info->aspectRatioLog2;
523   }
524   else
525   {
526     width = 1 << info->largeLodLog2;
527     height = width >> info->aspectRatioLog2;
528   }
529
530   switch(info->format)
531   {
532   case GR_TEXFMT_ALPHA_8:
533   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
534   case GR_TEXFMT_ALPHA_INTENSITY_44:
535     return width*height;
536     break;
537   case GR_TEXFMT_ARGB_1555:
538   case GR_TEXFMT_ARGB_4444:
539   case GR_TEXFMT_ALPHA_INTENSITY_88:
540   case GR_TEXFMT_RGB_565:
541     return (width*height)<<1;
542     break;
543   case GR_TEXFMT_ARGB_8888:
544     return (width*height)<<2;
545     break;
546   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
547     return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
548   case GR_TEXFMT_ARGB_CMP_DXT3:
549     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
550   case GR_TEXFMT_ARGB_CMP_DXT5:
551     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
552   case GR_TEXFMT_ARGB_CMP_FXT1:
553     return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
554   default:
555     display_warning("grTexTextureMemRequired : unknown texture format: %x", info->format);
556   }
557   return 0;
558 }
559
560 FX_ENTRY FxU32 FX_CALL
561 grTexCalcMemRequired(
562                      GrLOD_t lodmin, GrLOD_t lodmax,
563                      GrAspectRatio_t aspect, GrTextureFormat_t fmt)
564 {
565   int width, height;
566   LOG("grTexCalcMemRequired(%d, %d, %d, %d)\r\n", lodmin, lodmax, aspect, fmt);
567   if (lodmax != lodmin) display_warning("grTexCalcMemRequired : loading more than one LOD");
568
569   if (aspect < 0)
570   {
571     height = 1 << lodmax;
572     width = height >> -aspect;
573   }
574   else
575   {
576     width = 1 << lodmax;
577     height = width >> aspect;
578   }
579
580   switch(fmt)
581   {
582   case GR_TEXFMT_ALPHA_8:
583   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
584   case GR_TEXFMT_ALPHA_INTENSITY_44:
585     return width*height;
586     break;
587   case GR_TEXFMT_ARGB_1555:
588   case GR_TEXFMT_ARGB_4444:
589   case GR_TEXFMT_ALPHA_INTENSITY_88:
590   case GR_TEXFMT_RGB_565:
591     return (width*height)<<1;
592     break;
593   case GR_TEXFMT_ARGB_8888:
594     return (width*height)<<2;
595     break;
596   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
597     return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
598   case GR_TEXFMT_ARGB_CMP_DXT3:
599     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
600   case GR_TEXFMT_ARGB_CMP_DXT5:
601     return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
602   case GR_TEXFMT_ARGB_CMP_FXT1:
603     return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
604   default:
605     display_warning("grTexTextureMemRequired : unknown texture format: %x", fmt);
606   }
607   return 0;
608 }
609
610 int grTexFormatSize(int fmt)
611 {
612   int factor = -1;
613   switch(fmt) {
614   case GR_TEXFMT_ALPHA_8:
615   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
616     factor = 1;
617     break;
618   case GR_TEXFMT_ALPHA_INTENSITY_44:
619     factor = 1;
620     break;
621   case GR_TEXFMT_RGB_565:
622     factor = 2;
623     break;
624   case GR_TEXFMT_ARGB_1555:
625     factor = 2;
626     break;
627   case GR_TEXFMT_ALPHA_INTENSITY_88:
628     factor = 2;
629     break;
630   case GR_TEXFMT_ARGB_4444:
631     factor = 2;
632     break;
633   case GR_TEXFMT_ARGB_8888:
634     factor = 4;
635     break;
636   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
637     factor = 8;                  // HACKALERT: factor holds block bytes
638     break;
639   case GR_TEXFMT_ARGB_CMP_DXT3:  // FXT1,DXT1,5 support - H.Morii
640     factor = 16;                  // HACKALERT: factor holds block bytes
641     break;
642   case GR_TEXFMT_ARGB_CMP_DXT5:
643     factor = 16;
644     break;
645   case GR_TEXFMT_ARGB_CMP_FXT1:
646     factor = 8;
647     break;
648   default:
649     display_warning("grTexFormatSize : unknown texture format: %x", fmt);
650   }
651   return factor;
652 }
653
654 int grTexFormat2GLPackedFmt(int fmt, int * gltexfmt, int * glpixfmt, int * glpackfmt)
655 {
656     *gltexfmt = GL_RGBA;
657     *glpixfmt = GL_RGBA;
658     *glpackfmt = GL_UNSIGNED_BYTE;
659     return 0;
660 /*
661   int factor = -1;
662   switch(fmt) {
663   case GR_TEXFMT_ALPHA_8:
664     factor = 1;
665     *gltexfmt = GL_INTENSITY8;
666     *glpixfmt = GL_LUMINANCE;
667     *glpackfmt = GL_UNSIGNED_BYTE;
668     break;
669   case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
670     factor = 1;
671     *gltexfmt = GL_LUMINANCE8;
672     *glpixfmt = GL_LUMINANCE;
673     *glpackfmt = GL_UNSIGNED_BYTE;
674     break;
675   case GR_TEXFMT_ALPHA_INTENSITY_44:
676     break;
677   case GR_TEXFMT_RGB_565:
678     factor = 2;
679     *gltexfmt = GL_RGB;
680     *glpixfmt = GL_RGB;
681     *glpackfmt = GL_UNSIGNED_SHORT_5_6_5;
682     break;
683   case GR_TEXFMT_ARGB_1555:
684     if (ati_sucks > 0) return -1; // ATI sucks as usual (fixes slowdown on ATI)
685     factor = 2;
686     *gltexfmt = GL_RGB5_A1;
687     *glpixfmt = GL_BGRA;
688     *glpackfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV;
689     break;
690   case GR_TEXFMT_ALPHA_INTENSITY_88:
691     factor = 2;
692     *gltexfmt = GL_LUMINANCE8_ALPHA8;
693     *glpixfmt = GL_LUMINANCE_ALPHA;
694     *glpackfmt = GL_UNSIGNED_BYTE;
695     break;
696   case GR_TEXFMT_ARGB_4444:
697     factor = 2;
698     *gltexfmt = GL_RGBA4;
699     *glpixfmt = GL_BGRA;
700     *glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV;
701     break;
702   case GR_TEXFMT_ARGB_8888:
703     factor = 4;
704     *gltexfmt = GL_RGBA8;
705     *glpixfmt = GL_BGRA;
706     *glpackfmt = GL_UNSIGNED_INT_8_8_8_8_REV;
707     break;
708   case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
709     // HACKALERT: 3Dfx Glide uses GR_TEXFMT_ARGB_CMP_DXT1 for both opaque DXT1 and DXT1 with 1bit alpha.
710     // GlideHQ compiled with GLIDE64_DXTN option enabled, uses opaqe DXT1 only.
711     factor = 8; // HACKALERT: factor holds block bytes
712     *gltexfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // these variables aren't used
713     *glpixfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
714     *glpackfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
715     break;
716   case GR_TEXFMT_ARGB_CMP_DXT3:
717     factor = 16;
718     *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
719     *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
720     *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
721     break;
722   case GR_TEXFMT_ARGB_CMP_DXT5:
723     factor = 16;
724     *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
725     *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
726     *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
727     break;
728   case GR_TEXFMT_ARGB_CMP_FXT1:
729     factor = 8;
730     *gltexfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
731     *glpixfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
732     *glpackfmt = GL_COMPRESSED_RGBA_FXT1_3DFX; // XXX: what should we do about GL_COMPRESSED_RGB_FXT1_3DFX?
733     break;
734   default:
735     display_warning("grTexFormat2GLPackedFmt : unknown texture format: %x", fmt);
736   }
737   return factor;
738 */
739 }
740
741 FX_ENTRY void FX_CALL
742 grTexDownloadMipMap( GrChipID_t tmu,
743                     FxU32      startAddress,
744                     FxU32      evenOdd,
745                     GrTexInfo  *info )
746 {
747   int width, height, i, j;
748   int factor;
749   int glformat = 0;
750   int gltexfmt, glpixfmt, glpackfmt;
751   LOG("grTexDownloadMipMap(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
752   if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexDownloadMipMap : loading more than one LOD");
753
754   if (info->aspectRatioLog2 < 0)
755   {
756     height = 1 << info->largeLodLog2;
757     width = height >> -info->aspectRatioLog2;
758   }
759   else
760   {
761     width = 1 << info->largeLodLog2;
762     height = width >> info->aspectRatioLog2;
763   }
764
765   if (!packed_pixels_support)
766     factor = -1;
767   else
768     factor = grTexFormat2GLPackedFmt(info->format, &gltexfmt, &glpixfmt, &glpackfmt);
769
770   if (factor < 0) {
771
772     // VP fixed the texture conversions to be more accurate, also swapped
773     // the for i/j loops so that is is less likely to break the memory cache
774     register int n = 0, m = 0;
775     switch(info->format)
776     {
777     case GR_TEXFMT_ALPHA_8:
778       for (i=0; i<height; i++)
779       {
780         for (j=0; j<width; j++)
781         {
782           unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
783           texel |= (texel << 8);
784           texel |= (texel << 16);
785           ((unsigned int*)texture)[n] = texel;
786           m++;
787           n++;
788         }
789       }
790       factor = 1;
791       glformat = GL_RGBA;
792       break;
793     case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
794       for (i=0; i<height; i++)
795       {
796         for (j=0; j<width; j++)
797         {
798           unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
799           texel |= (0xFF000000 | (texel << 16) | (texel << 8));
800           ((unsigned int*)texture)[n] = texel;
801           m++;
802           n++;
803         }
804       }
805       factor = 1;
806       glformat = GL_ALPHA;
807       break;
808     case GR_TEXFMT_ALPHA_INTENSITY_44:
809 #if 1
810       for (i=0; i<height; i++)
811       {
812         for (j=0; j<width; j++)
813         {
814           unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
815 #if 1
816           /* accurate conversion */
817           unsigned int texel_hi = (texel & 0x000000F0) << 20;
818           unsigned int texel_low = texel & 0x0000000F;
819           texel_low |= (texel_low << 4);
820           texel_hi |= ((texel_hi << 4) | (texel_low << 16) | (texel_low << 8) | texel_low);
821 #else
822           unsigned int texel_hi = (texel & 0x000000F0) << 24;
823           unsigned int texel_low = (texel & 0x0000000F) << 4;
824           texel_hi |= ((texel_low << 16) | (texel_low << 8) | texel_low);
825 #endif
826           ((unsigned int*)texture)[n] = texel_hi;
827           m++;
828           n++;
829         }
830       }
831       factor = 1;
832       glformat = GL_LUMINANCE_ALPHA;
833 #endif
834       break;
835     case GR_TEXFMT_RGB_565:
836       for (i=0; i<height; i++)
837       {
838         for (j=0; j<width; j++)
839         {
840           unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
841           unsigned int B = texel & 0x0000F800;
842           unsigned int G = texel & 0x000007E0;
843           unsigned int R = texel & 0x0000001F;
844 #if 0
845           /* accurate conversion */
846           ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | ((R >> 2) << 16) | (G << 5) | ((G >> 9) << 8) | (B >> 8) | (B >> 13);
847 #else
848           ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | (G << 5) | (B >> 8);
849 #endif
850           m++;
851           n++;
852         }
853       }
854       factor = 2;
855       glformat = GL_RGB;
856       break;
857     case GR_TEXFMT_ARGB_1555:
858       for (i=0; i<height; i++)
859       {
860         for (j=0; j<width; j++)
861         {
862           unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
863           unsigned int A = texel & 0x00008000 ? 0xFF000000 : 0;
864           unsigned int B = texel & 0x00007C00;
865           unsigned int G = texel & 0x000003E0;
866           unsigned int R = texel & 0x0000001F;
867 #if 0
868           /* accurate conversion */
869           ((unsigned int*)texture)[n] = A | (R << 19) | ((R >> 2) << 16) | (G << 6) | ((G >> 8) << 8) | (B >> 7) | (B >> 12);
870 #else
871           ((unsigned int*)texture)[n] = A | (R << 19) | (G << 6) | (B >> 7);
872 #endif
873           m++;
874           n++;
875         }
876       }
877       factor = 2;
878       glformat = GL_RGBA;
879       break;
880     case GR_TEXFMT_ALPHA_INTENSITY_88:
881       for (i=0; i<height; i++)
882       {
883         for (j=0; j<width; j++)
884         {
885           unsigned int AI = (unsigned int)((unsigned short*)info->data)[m];
886           unsigned int I = (unsigned int)(AI & 0x000000FF);
887           ((unsigned int*)texture)[n] = (AI << 16) | (I << 8) | I;
888           m++;
889           n++;
890         }
891       }
892       factor = 2;
893       glformat = GL_LUMINANCE_ALPHA;
894       break;
895     case GR_TEXFMT_ARGB_4444:
896
897       for (i=0; i<height; i++)
898       {
899         for (j=0; j<width; j++)
900         {
901           unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
902           unsigned int A = texel & 0x0000F000;
903           unsigned int B = texel & 0x00000F00;
904           unsigned int G = texel & 0x000000F0;
905           unsigned int R = texel & 0x0000000F;
906 #if 0
907           /* accurate conversion */
908           ((unsigned int*)texture)[n] = (A << 16) | (A << 12) | (R << 20) | (R << 16) | (G << 8) | (G << 4) | (B >> 4) | (B >> 8);
909 #else
910           ((unsigned int*)texture)[n] = (A << 16) | (R << 20) | (G << 8) | (B >> 4);
911 #endif
912           m++;
913           n++;
914         }
915       }
916       factor = 2;
917       glformat = GL_RGBA;
918       break;
919     case GR_TEXFMT_ARGB_8888:
920       for (i=0; i<height; i++)
921       {
922         for (j=0; j<width; j++)
923         {
924           unsigned int texel = ((unsigned int*)info->data)[m];
925           unsigned int A = texel & 0xFF000000;
926           unsigned int B = texel & 0x00FF0000;
927           unsigned int G = texel & 0x0000FF00;
928           unsigned int R = texel & 0x000000FF;
929           ((unsigned int*)texture)[n] = A | (R << 16) | G | (B >> 16);
930           m++;
931           n++;
932         }
933       }
934       factor = 4;
935       glformat = GL_RGBA;
936       break;
937 /*
938     case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
939       factor = 8;                 // HACKALERT: factor holds block bytes
940       glformat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
941       break;
942     case GR_TEXFMT_ARGB_CMP_DXT3: // FXT1,DXT1,5 support - H.Morii
943       factor = 16;                 // HACKALERT: factor holds block bytes
944       glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
945       break;
946     case GR_TEXFMT_ARGB_CMP_DXT5:
947       factor = 16;
948       glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
949       break;
950     case GR_TEXFMT_ARGB_CMP_FXT1:
951       factor = 8;
952       glformat = GL_COMPRESSED_RGBA_FXT1_3DFX;
953       break;
954 */
955     default:
956       display_warning("grTexDownloadMipMap : unknown texture format: %x", info->format);
957       factor = 0;
958     }
959   }
960
961   if (nbTextureUnits <= 2)
962     glActiveTexture(GL_TEXTURE1);
963   else
964     glActiveTexture(GL_TEXTURE2);
965
966   switch(info->format)
967   {
968   case GR_TEXFMT_ARGB_CMP_DXT1:
969   case GR_TEXFMT_ARGB_CMP_DXT3:
970   case GR_TEXFMT_ARGB_CMP_DXT5:
971   case GR_TEXFMT_ARGB_CMP_FXT1:
972     remove_tex(startAddress+1, startAddress+1+((width*height*factor)>>4));
973     break;
974   default:
975     remove_tex(startAddress+1, startAddress+1+(width*height*factor));
976   }
977
978   add_tex(startAddress+1);
979   glBindTexture(GL_TEXTURE_2D, startAddress+1);
980
981   if (largest_supported_anisotropy > 1.0f)
982     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
983
984   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
985 /*
986   switch(info->format)
987   {
988   case GR_TEXFMT_ARGB_CMP_DXT1:
989   case GR_TEXFMT_ARGB_CMP_DXT3:
990   case GR_TEXFMT_ARGB_CMP_DXT5:
991   case GR_TEXFMT_ARGB_CMP_FXT1:
992     glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, (glformat ? glformat : gltexfmt), width, height, 0, (width*height*factor)>>4, info->data);
993     break;
994   default:
995     if (glformat) {
996       glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
997     } else
998       glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, info->data);
999   }
1000 */
1001
1002   glBindTexture(GL_TEXTURE_2D, default_texture);
1003 }
1004
1005 int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info );
1006
1007 FX_ENTRY void FX_CALL
1008 grTexSource( GrChipID_t tmu,
1009             FxU32      startAddress,
1010             FxU32      evenOdd,
1011             GrTexInfo  *info )
1012 {
1013   LOG("grTexSource(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
1014
1015   if (tmu == GR_TMU1 || nbTextureUnits <= 2)
1016   {
1017     if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
1018     glActiveTexture(GL_TEXTURE0);
1019
1020     if (info->aspectRatioLog2 < 0)
1021     {
1022       tex0_height = 256;
1023       tex0_width = tex0_height >> -info->aspectRatioLog2;
1024     }
1025     else
1026     {
1027       tex0_width = 256;
1028       tex0_height = tex0_width >> info->aspectRatioLog2;
1029     }
1030
1031     glBindTexture(GL_TEXTURE_2D, startAddress+1);
1032 #ifdef VPDEBUG
1033     dump_tex(startAddress+1);
1034 #endif
1035     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0);
1036     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0);
1037     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0);
1038     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0);
1039   }
1040   else
1041   {
1042     glActiveTexture(GL_TEXTURE1);
1043
1044     if (info->aspectRatioLog2 < 0)
1045     {
1046       tex1_height = 256;
1047       tex1_width = tex1_height >> -info->aspectRatioLog2;
1048     }
1049     else
1050     {
1051       tex1_width = 256;
1052       tex1_height = tex1_width >> info->aspectRatioLog2;
1053     }
1054
1055     glBindTexture(GL_TEXTURE_2D, startAddress+1);
1056 #ifdef VPDEBUG
1057     dump_tex(startAddress+1);
1058 #endif
1059     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1);
1060     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1);
1061     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
1062     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
1063   }
1064   if(!CheckTextureBufferFormat(tmu, startAddress+1, info))
1065   {
1066     if(tmu == 0 && blackandwhite1 != 0)
1067     {
1068       blackandwhite1 = 0;
1069       need_to_compile = 1;
1070     }
1071     if(tmu == 1 && blackandwhite0 != 0)
1072     {
1073       blackandwhite0 = 0;
1074       need_to_compile = 1;
1075     }
1076   }
1077
1078 #if 0
1079   extern int auxbuffer;
1080   static int oldbuffer;
1081   FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
1082   if (auxbuffer == GR_BUFFER_AUXBUFFER && auxbuffer != oldbuffer)
1083     grAuxBufferExt(auxbuffer);
1084   oldbuffer = auxbuffer;
1085 #endif
1086 }
1087
1088 FX_ENTRY void FX_CALL
1089 grTexDetailControl(
1090                    GrChipID_t tmu,
1091                    int lod_bias,
1092                    FxU8 detail_scale,
1093                    float detail_max
1094                    )
1095 {
1096   LOG("grTexDetailControl(%d,%d,%d,%d)\r\n", tmu, lod_bias, detail_scale, detail_max);
1097   if (lod_bias != 31 && detail_scale != 7)
1098   {
1099     if (!lod_bias && !detail_scale && !detail_max) return;
1100     else
1101       display_warning("grTexDetailControl : %d, %d, %f", lod_bias, detail_scale, detail_max);
1102   }
1103   lambda = detail_max;
1104   if(lambda > 1.0f)
1105   {
1106     lambda = 1.0f - (255.0f - lambda);
1107   }
1108   if(lambda > 1.0f) display_warning("lambda:%f", lambda);
1109
1110   set_lambda();
1111 }
1112
1113 FX_ENTRY void FX_CALL
1114 grTexLodBiasValue(GrChipID_t tmu, float bias )
1115 {
1116   LOG("grTexLodBiasValue(%d,%f)\r\n", tmu, bias);
1117 }
1118
1119 FX_ENTRY void FX_CALL
1120 grTexFilterMode(
1121                 GrChipID_t tmu,
1122                 GrTextureFilterMode_t minfilter_mode,
1123                 GrTextureFilterMode_t magfilter_mode
1124                 )
1125 {
1126   LOG("grTexFilterMode(%d,%d,%d)\r\n", tmu, minfilter_mode, magfilter_mode);
1127   if (tmu == GR_TMU1 || nbTextureUnits <= 2)
1128   {
1129     if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
1130     if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter0 = GL_NEAREST;
1131     else min_filter0 = GL_LINEAR;
1132
1133     if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter0 = GL_NEAREST;
1134     else mag_filter0 = GL_LINEAR;
1135
1136     glActiveTexture(GL_TEXTURE0);
1137     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0);
1138     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0);
1139   }
1140   else
1141   {
1142     if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter1 = GL_NEAREST;
1143     else min_filter1 = GL_LINEAR;
1144
1145     if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter1 = GL_NEAREST;
1146     else mag_filter1 = GL_LINEAR;
1147
1148     glActiveTexture(GL_TEXTURE1);
1149     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1);
1150     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1);
1151   }
1152 }
1153
1154 FX_ENTRY void FX_CALL
1155 grTexClampMode(
1156                GrChipID_t tmu,
1157                GrTextureClampMode_t s_clampmode,
1158                GrTextureClampMode_t t_clampmode
1159                )
1160 {
1161   LOG("grTexClampMode(%d, %d, %d)\r\n", tmu, s_clampmode, t_clampmode);
1162   if (tmu == GR_TMU1 || nbTextureUnits <= 2)
1163   {
1164     if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
1165     switch(s_clampmode)
1166     {
1167     case GR_TEXTURECLAMP_WRAP:
1168       wrap_s0 = GL_REPEAT;
1169       break;
1170     case GR_TEXTURECLAMP_CLAMP:
1171       wrap_s0 = GL_CLAMP_TO_EDGE;
1172       break;
1173     case GR_TEXTURECLAMP_MIRROR_EXT:
1174       wrap_s0 = GL_MIRRORED_REPEAT;
1175       break;
1176     default:
1177       display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode);
1178     }
1179     switch(t_clampmode)
1180     {
1181     case GR_TEXTURECLAMP_WRAP:
1182       wrap_t0 = GL_REPEAT;
1183       break;
1184     case GR_TEXTURECLAMP_CLAMP:
1185       wrap_t0 = GL_CLAMP_TO_EDGE;
1186       break;
1187     case GR_TEXTURECLAMP_MIRROR_EXT:
1188       wrap_t0 = GL_MIRRORED_REPEAT;
1189       break;
1190     default:
1191       display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
1192     }
1193     glActiveTexture(GL_TEXTURE0);
1194     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0);
1195     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0);
1196   }
1197   else
1198   {
1199     switch(s_clampmode)
1200     {
1201     case GR_TEXTURECLAMP_WRAP:
1202       wrap_s1 = GL_REPEAT;
1203       break;
1204     case GR_TEXTURECLAMP_CLAMP:
1205       wrap_s1 = GL_CLAMP_TO_EDGE;
1206       break;
1207     case GR_TEXTURECLAMP_MIRROR_EXT:
1208       wrap_s1 = GL_MIRRORED_REPEAT;
1209       break;
1210     default:
1211       display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode);
1212     }
1213     switch(t_clampmode)
1214     {
1215     case GR_TEXTURECLAMP_WRAP:
1216       wrap_t1 = GL_REPEAT;
1217       break;
1218     case GR_TEXTURECLAMP_CLAMP:
1219       wrap_t1 = GL_CLAMP_TO_EDGE;
1220       break;
1221     case GR_TEXTURECLAMP_MIRROR_EXT:
1222       wrap_t1 = GL_MIRRORED_REPEAT;
1223       break;
1224     default:
1225       display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
1226     }
1227     glActiveTexture(GL_TEXTURE1);
1228     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
1229     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
1230   }
1231 }