Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glitch64 / textures.cpp
CommitLineData
98e75f2d 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
45int TMU_SIZE = 8*2048*2048;
46static unsigned char* texture = NULL;
47
48int packed_pixels_support = -1;
49int ati_sucks = -1;
50float largest_supported_anisotropy = 1.0f;
51
52#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
53#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
54#endif
55
56int tex0_width, tex0_height, tex1_width, tex1_height;
57float lambda;
58
59static int min_filter0, mag_filter0, wrap_s0, wrap_t0;
60static int min_filter1, mag_filter1, wrap_s1, wrap_t1;
61
62unsigned char *filter(unsigned char *source, int width, int height, int *width2, int *height2);
63
64#define TEXBSP
65#ifdef TEXBSP
66typedef struct _texbsp
67{
68 unsigned int id;
69 struct _texbsp *left;
70 struct _texbsp *right;
71} texbsp;
72
73static int nbTex = 0;
74static texbsp *list = NULL;
75#elif defined(TEXREDBLACK)
76typedef 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
85static int nbTex = 0;
86static texbsp *list = NULL;
87#else
88typedef struct _texlist
89{
90 unsigned int id;
91 struct _texlist *next;
92} texlist;
93
94static int nbTex = 0;
95static texlist *list = NULL;
96#endif
97
98#ifdef _WIN32
99extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
100extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
101extern 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 ****
110texbsp *grandparent(texbsp *n)
111{
112 if ((n != NULL) && (n->parent != NULL))
113 return n->parent->parent;
114 else
115 return NULL;
116}
117texbsp *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}
127texbsp *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 ****
138texbsp* 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}
153GLuint rbtree_lookup(GLuint key)
154{
155 texbsp* n = lookup_node(key);
156 return n == NULL ? NULL : n->id;
157}
158//**** Basic insertion / replace ****
159texbsp* 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}
171void 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 ****
186void 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}
197void 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 ****
209void insert_case1(texbsp *n)
210{
211 if (n->parent == NULL)
212 n->color = BLACK;
213 else
214 insert_case2(n);
215}
216void insert_case2(texbsp *n)
217{
218 if (n->parent->color == BLACK)
219 return;
220 else
221 insert_case3(n);
222}
223void 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}
237void 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}
250void 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}
261void 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
296void 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
395void 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
468void 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
479void 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
491FX_ENTRY FxU32 FX_CALL
492grTexMinAddress( 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
501FX_ENTRY FxU32 FX_CALL
502grTexMaxAddress( 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
511FX_ENTRY FxU32 FX_CALL
512grTexTextureMemRequired( 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
560FX_ENTRY FxU32 FX_CALL
561grTexCalcMemRequired(
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
610int 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
654int 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
741FX_ENTRY void FX_CALL
742grTexDownloadMipMap( 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
1005int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info );
1006
1007FX_ENTRY void FX_CALL
1008grTexSource( 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
1088FX_ENTRY void FX_CALL
1089grTexDetailControl(
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
1113FX_ENTRY void FX_CALL
1114grTexLodBiasValue(GrChipID_t tmu, float bias )
1115{
1116 LOG("grTexLodBiasValue(%d,%f)\r\n", tmu, bias);
1117}
1118
1119FX_ENTRY void FX_CALL
1120grTexFilterMode(
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
1154FX_ENTRY void FX_CALL
1155grTexClampMode(
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}