updated texture image handling - STILL UNTESTED
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 3.5
5 *
6 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
27 * terms stated above.
28 *
29 * Thank you for your contribution, David!
30 *
31 * Please make note of the above copyright/license statement. If you
32 * contributed code or bug fixes to this code under the previous (GNU
33 * Library) license and object to the new license, your code will be
34 * removed at your request. Please see the Mesa docs/COPYRIGHT file
35 * for more information.
36 *
37 * Additional Mesa/3Dfx driver developers:
38 * Daryll Strauss <daryll@precisioninsight.com>
39 * Keith Whitwell <keith@precisioninsight.com>
40 *
41 * See fxapi.h for more revision/author details.
42 */
43
44
45 #ifdef HAVE_CONFIG_H
46 #include "conf.h"
47 #endif
48
49 #if defined(FX)
50
51 #include "fxdrv.h"
52 #include "image.h"
53 #include "teximage.h"
54 #include "texstore.h"
55 #include "texutil.h"
56
57
58 void fxPrintTextureData(tfxTexInfo *ti)
59 {
60 fprintf(stderr, "Texture Data:\n");
61 if (ti->tObj) {
62 fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
63 fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
64 fprintf(stderr, "\tSize: %d x %d\n",
65 ti->tObj->Image[ti->tObj->BaseLevel]->Width,
66 ti->tObj->Image[ti->tObj->BaseLevel]->Height);
67 } else
68 fprintf(stderr, "\tName: UNNAMED\n");
69 fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
70 fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
71 fprintf(stderr, "\t%s\n", (ti->isInTM)?"In TMU":"Not in TMU");
72 if (ti->tm[0])
73 fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
74 (unsigned) ti->tm[0]->endAddr);
75 if (ti->tm[1])
76 fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
77 (unsigned) ti->tm[1]->endAddr);
78 fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
79 fprintf(stderr, "\tFilters: min %d min %d\n",
80 (int) ti->minFilt, (int) ti->maxFilt);
81 fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp, (int) ti->tClamp);
82 fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
83 fprintf(stderr, "\tInt Scales: s %d t %d\n",
84 ti->int_sScale/0x800000, ti->int_tScale/0x800000);
85 fprintf(stderr, "\t%s\n", (ti->fixedPalette)?"Fixed palette":"Non fixed palette");
86 fprintf(stderr, "\t%s\n", (ti->validated)?"Validated":"Not validated");
87 }
88
89
90 /************************************************************************/
91 /*************************** Texture Mapping ****************************/
92 /************************************************************************/
93
94 static void fxTexInvalidate(GLcontext *ctx, struct gl_texture_object *tObj)
95 {
96 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
97 tfxTexInfo *ti;
98
99 ti=fxTMGetTexInfo(tObj);
100 if (ti->isInTM) fxTMMoveOutTM(fxMesa,tObj); /* TO DO: SLOW but easy to write */
101
102 ti->validated=GL_FALSE;
103 fxMesa->new_state|=FX_NEW_TEXTURING;
104 }
105
106 static tfxTexInfo *fxAllocTexObjData(fxMesaContext fxMesa)
107 {
108 tfxTexInfo *ti;
109
110 if(!(ti=CALLOC(sizeof(tfxTexInfo)))) {
111 fprintf(stderr,"fx Driver: out of memory !\n");
112 fxCloseHardware();
113 exit(-1);
114 }
115
116 ti->validated=GL_FALSE;
117 ti->isInTM=GL_FALSE;
118
119 ti->whichTMU=FX_TMU_NONE;
120
121 ti->tm[FX_TMU0]=NULL;
122 ti->tm[FX_TMU1]=NULL;
123
124 ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
125 ti->maxFilt=GR_TEXTUREFILTER_BILINEAR;
126
127 ti->sClamp=GR_TEXTURECLAMP_WRAP;
128 ti->tClamp=GR_TEXTURECLAMP_WRAP;
129
130 ti->mmMode=GR_MIPMAP_NEAREST;
131 ti->LODblend=FXFALSE;
132
133 return ti;
134 }
135
136 void fxDDTexBind(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj)
137 {
138 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
139 tfxTexInfo *ti;
140
141 if (MESA_VERBOSE&VERBOSE_DRIVER) {
142 fprintf(stderr,"fxmesa: fxDDTexBind(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData);
143 }
144
145 if(target!=GL_TEXTURE_2D)
146 return;
147
148 if (!tObj->DriverData) {
149 tObj->DriverData=fxAllocTexObjData(fxMesa);
150 }
151
152 ti=fxTMGetTexInfo(tObj);
153
154 fxMesa->texBindNumber++;
155 ti->lastTimeUsed=fxMesa->texBindNumber;
156
157 fxMesa->new_state|=FX_NEW_TEXTURING;
158 }
159
160 void fxDDTexEnv(GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param)
161 {
162 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
163
164 if (MESA_VERBOSE&VERBOSE_DRIVER) {
165 if(param)
166 fprintf(stderr,"fxmesa: texenv(%x,%x)\n",pname,(GLint)(*param));
167 else
168 fprintf(stderr,"fxmesa: texenv(%x)\n",pname);
169 }
170
171 /* apply any lod biasing right now */
172 if (pname==GL_TEXTURE_LOD_BIAS_EXT) {
173 FX_grTexLodBiasValue(GR_TMU0,*param);
174
175 if(fxMesa->haveTwoTMUs) {
176 FX_grTexLodBiasValue(GR_TMU1,*param);
177 }
178
179 }
180
181 fxMesa->new_state|=FX_NEW_TEXTURING;
182 }
183
184 void fxDDTexParam(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj,
185 GLenum pname, const GLfloat *params)
186 {
187 fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
188 GLenum param=(GLenum)(GLint)params[0];
189 tfxTexInfo *ti;
190
191 if (MESA_VERBOSE&VERBOSE_DRIVER) {
192 fprintf(stderr,"fxmesa: fxDDTexParam(%d,%x,%x,%x)\n",tObj->Name,(GLuint)tObj->DriverData,pname,param);
193 }
194
195 if(target!=GL_TEXTURE_2D)
196 return;
197
198 if (!tObj->DriverData)
199 tObj->DriverData=fxAllocTexObjData(fxMesa);
200
201 ti=fxTMGetTexInfo(tObj);
202
203 switch(pname) {
204
205 case GL_TEXTURE_MIN_FILTER:
206 switch(param) {
207 case GL_NEAREST:
208 ti->mmMode=GR_MIPMAP_DISABLE;
209 ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
210 ti->LODblend=FXFALSE;
211 break;
212 case GL_LINEAR:
213 ti->mmMode=GR_MIPMAP_DISABLE;
214 ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
215 ti->LODblend=FXFALSE;
216 break;
217 case GL_NEAREST_MIPMAP_NEAREST:
218 ti->mmMode=GR_MIPMAP_NEAREST;
219 ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
220 ti->LODblend=FXFALSE;
221 break;
222 case GL_LINEAR_MIPMAP_NEAREST:
223 ti->mmMode=GR_MIPMAP_NEAREST;
224 ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
225 ti->LODblend=FXFALSE;
226 break;
227 case GL_NEAREST_MIPMAP_LINEAR:
228 if(fxMesa->haveTwoTMUs) {
229 ti->mmMode=GR_MIPMAP_NEAREST;
230 ti->LODblend=FXTRUE;
231 } else {
232 ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
233 ti->LODblend=FXFALSE;
234 }
235 ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
236 break;
237 case GL_LINEAR_MIPMAP_LINEAR:
238 if(fxMesa->haveTwoTMUs) {
239 ti->mmMode=GR_MIPMAP_NEAREST;
240 ti->LODblend=FXTRUE;
241 } else {
242 ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
243 ti->LODblend=FXFALSE;
244 }
245 ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
246 break;
247 default:
248 break;
249 }
250 fxTexInvalidate(ctx,tObj);
251 break;
252
253 case GL_TEXTURE_MAG_FILTER:
254 switch(param) {
255 case GL_NEAREST:
256 ti->maxFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
257 break;
258 case GL_LINEAR:
259 ti->maxFilt=GR_TEXTUREFILTER_BILINEAR;
260 break;
261 default:
262 break;
263 }
264 fxTexInvalidate(ctx,tObj);
265 break;
266
267 case GL_TEXTURE_WRAP_S:
268 switch(param) {
269 case GL_CLAMP:
270 ti->sClamp=GR_TEXTURECLAMP_CLAMP;
271 break;
272 case GL_REPEAT:
273 ti->sClamp=GR_TEXTURECLAMP_WRAP;
274 break;
275 default:
276 break;
277 }
278 fxMesa->new_state|=FX_NEW_TEXTURING;
279 break;
280
281 case GL_TEXTURE_WRAP_T:
282 switch(param) {
283 case GL_CLAMP:
284 ti->tClamp=GR_TEXTURECLAMP_CLAMP;
285 break;
286 case GL_REPEAT:
287 ti->tClamp=GR_TEXTURECLAMP_WRAP;
288 break;
289 default:
290 break;
291 }
292 fxMesa->new_state|=FX_NEW_TEXTURING;
293 break;
294
295 case GL_TEXTURE_BORDER_COLOR:
296 /* TO DO */
297 break;
298
299 case GL_TEXTURE_MIN_LOD:
300 /* TO DO */
301 break;
302 case GL_TEXTURE_MAX_LOD:
303 /* TO DO */
304 break;
305 case GL_TEXTURE_BASE_LEVEL:
306 fxTexInvalidate(ctx,tObj);
307 break;
308 case GL_TEXTURE_MAX_LEVEL:
309 fxTexInvalidate(ctx,tObj);
310 break;
311
312 default:
313 break;
314 }
315 }
316
317 void fxDDTexDel(GLcontext *ctx, struct gl_texture_object *tObj)
318 {
319 fxMesaContext fxMesa = FX_CONTEXT(ctx);
320 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
321
322 if (MESA_VERBOSE & VERBOSE_DRIVER) {
323 fprintf(stderr, "fxmesa: fxDDTexDel(%d,%p)\n", tObj->Name, ti);
324 }
325
326 if (!ti)
327 return;
328
329 fxTMFreeTexture(fxMesa, tObj);
330
331 FREE(ti);
332 tObj->DriverData = NULL;
333 }
334
335
336
337 /*
338 * Convert a gl_color_table texture palette to Glide's format.
339 */
340 static void
341 convertPalette(FxU32 data[256], const struct gl_color_table *table)
342 {
343 const GLubyte *tableUB = (const GLubyte *) table->Table;
344 GLint width = table->Size;
345 FxU32 r, g, b, a;
346 GLint i;
347
348 ASSERT(!table->FloatTable);
349
350 switch (table->Format) {
351 case GL_INTENSITY:
352 for (i = 0; i < width; i++) {
353 r = tableUB[i];
354 g = tableUB[i];
355 b = tableUB[i];
356 a = tableUB[i];
357 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
358 }
359 break;
360 case GL_LUMINANCE:
361 for (i = 0; i < width; i++) {
362 r = tableUB[i];
363 g = tableUB[i];
364 b = tableUB[i];
365 a = 255;
366 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
367 }
368 break;
369 case GL_ALPHA:
370 for (i = 0; i < width; i++) {
371 r = g = b = 255;
372 a = tableUB[i];
373 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
374 }
375 break;
376 case GL_LUMINANCE_ALPHA:
377 for (i = 0; i < width; i++) {
378 r = g = b = tableUB[i*2+0];
379 a = tableUB[i*2+1];
380 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
381 }
382 break;
383 case GL_RGB:
384 for (i = 0; i < width; i++) {
385 r = tableUB[i*3+0];
386 g = tableUB[i*3+1];
387 b = tableUB[i*3+2];
388 a = 255;
389 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
390 }
391 break;
392 case GL_RGBA:
393 for (i = 0; i < width; i++) {
394 r = tableUB[i*4+0];
395 g = tableUB[i*4+1];
396 b = tableUB[i*4+2];
397 a = tableUB[i*4+3];
398 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
399 }
400 break;
401 }
402 }
403
404
405 void fxDDTexPalette(GLcontext *ctx, struct gl_texture_object *tObj)
406 {
407 fxMesaContext fxMesa = FX_CONTEXT(ctx);
408
409 if (tObj) {
410 /* per-texture palette */
411 tfxTexInfo *ti;
412 if (MESA_VERBOSE & VERBOSE_DRIVER) {
413 fprintf(stderr, "fxmesa: fxDDTexPalette(%d,%x)\n",
414 tObj->Name, (GLuint) tObj->DriverData);
415 }
416 if (!tObj->DriverData)
417 tObj->DriverData = fxAllocTexObjData(fxMesa);
418 ti = fxTMGetTexInfo(tObj);
419 convertPalette(ti->palette.data, &tObj->Palette);
420 fxTexInvalidate(ctx, tObj);
421 }
422 else {
423 /* global texture palette */
424 if (MESA_VERBOSE & VERBOSE_DRIVER) {
425 fprintf(stderr, "fxmesa: fxDDTexPalette(global)\n");
426 }
427 convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
428 fxMesa->new_state |= FX_NEW_TEXTURING;
429 }
430 }
431
432
433 void fxDDTexUseGlbPalette(GLcontext *ctx, GLboolean state)
434 {
435 fxMesaContext fxMesa = FX_CONTEXT(ctx);
436
437 if (MESA_VERBOSE&VERBOSE_DRIVER) {
438 fprintf(stderr,"fxmesa: fxDDTexUseGlbPalette(%d)\n",state);
439 }
440
441 if (state) {
442 fxMesa->haveGlobalPaletteTexture = 1;
443
444 FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette));
445 if (fxMesa->haveTwoTMUs)
446 FX_grTexDownloadTable(GR_TMU1, GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette));
447 }
448 else {
449 fxMesa->haveGlobalPaletteTexture = 0;
450
451 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
452 (ctx->Texture.Unit[0]._Current != NULL)) {
453 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
454
455 if (!tObj->DriverData)
456 tObj->DriverData = fxAllocTexObjData(fxMesa);
457
458 fxTexInvalidate(ctx, tObj);
459 }
460 }
461 }
462
463
464 static int logbase2(int n)
465 {
466 GLint i = 1;
467 GLint log2 = 0;
468
469 if (n<0) {
470 return -1;
471 }
472
473 while (n > i) {
474 i *= 2;
475 log2++;
476 }
477 if (i != n) {
478 return -1;
479 }
480 else {
481 return log2;
482 }
483 }
484
485 /* Need different versions for different cpus.
486 */
487 #define INT_TRICK(l2) (0x800000 * l2)
488
489
490 int fxTexGetInfo(int w, int h, GrLOD_t *lodlevel, GrAspectRatio_t *ar,
491 float *sscale, float *tscale,
492 int *i_sscale, int *i_tscale,
493 int *wscale, int *hscale)
494 {
495
496 static GrLOD_t lod[9]={GR_LOD_256,GR_LOD_128,GR_LOD_64,GR_LOD_32,
497 GR_LOD_16,GR_LOD_8,GR_LOD_4,GR_LOD_2,GR_LOD_1};
498
499 int logw,logh,ws,hs;
500 GrLOD_t l;
501 GrAspectRatio_t aspectratio;
502 float s,t;
503 int is,it;
504
505 logw=logbase2(w);
506 logh=logbase2(h);
507
508 switch(logw-logh) {
509 case 0:
510 aspectratio=GR_ASPECT_1x1;
511 l=lod[8-logw];
512 s=t=256.0f;
513 is=it=INT_TRICK(8);
514 ws=hs=1;
515 break;
516 case 1:
517 aspectratio=GR_ASPECT_2x1;
518 l=lod[8-logw];
519 s=256.0f;
520 t=128.0f;
521 is=INT_TRICK(8);it=INT_TRICK(7);
522 ws=1;
523 hs=1;
524 break;
525 case 2:
526 aspectratio=GR_ASPECT_4x1;
527 l=lod[8-logw];
528 s=256.0f;
529 t=64.0f;
530 is=INT_TRICK(8);it=INT_TRICK(6);
531 ws=1;
532 hs=1;
533 break;
534 case 3:
535 aspectratio=GR_ASPECT_8x1;
536 l=lod[8-logw];
537 s=256.0f;
538 t=32.0f;
539 is=INT_TRICK(8);it=INT_TRICK(5);
540 ws=1;
541 hs=1;
542 break;
543 case 4:
544 aspectratio=GR_ASPECT_8x1;
545 l=lod[8-logw];
546 s=256.0f;
547 t=32.0f;
548 is=INT_TRICK(8);it=INT_TRICK(5);
549 ws=1;
550 hs=2;
551 break;
552 case 5:
553 aspectratio=GR_ASPECT_8x1;
554 l=lod[8-logw];
555 s=256.0f;
556 t=32.0f;
557 is=INT_TRICK(8);it=INT_TRICK(5);
558 ws=1;
559 hs=4;
560 break;
561 case 6:
562 aspectratio=GR_ASPECT_8x1;
563 l=lod[8-logw];
564 s=256.0f;
565 t=32.0f;
566 is=INT_TRICK(8);it=INT_TRICK(5);
567 ws=1;
568 hs=8;
569 break;
570 case 7:
571 aspectratio=GR_ASPECT_8x1;
572 l=lod[8-logw];
573 s=256.0f;
574 t=32.0f;
575 is=INT_TRICK(8);it=INT_TRICK(5);
576 ws=1;
577 hs=16;
578 break;
579 case 8:
580 aspectratio=GR_ASPECT_8x1;
581 l=lod[8-logw];
582 s=256.0f;
583 t=32.0f;
584 is=INT_TRICK(8);it=INT_TRICK(5);
585 ws=1;
586 hs=32;
587 break;
588 case -1:
589 aspectratio=GR_ASPECT_1x2;
590 l=lod[8-logh];
591 s=128.0f;
592 t=256.0f;
593 is=INT_TRICK(7);it=INT_TRICK(8);
594 ws=1;
595 hs=1;
596 break;
597 case -2:
598 aspectratio=GR_ASPECT_1x4;
599 l=lod[8-logh];
600 s=64.0f;
601 t=256.0f;
602 is=INT_TRICK(6);it=INT_TRICK(8);
603 ws=1;
604 hs=1;
605 break;
606 case -3:
607 aspectratio=GR_ASPECT_1x8;
608 l=lod[8-logh];
609 s=32.0f;
610 t=256.0f;
611 is=INT_TRICK(5);it=INT_TRICK(8);
612 ws=1;
613 hs=1;
614 break;
615 case -4:
616 aspectratio=GR_ASPECT_1x8;
617 l=lod[8-logh];
618 s=32.0f;
619 t=256.0f;
620 is=INT_TRICK(5);it=INT_TRICK(8);
621 ws=2;
622 hs=1;
623 break;
624 case -5:
625 aspectratio=GR_ASPECT_1x8;
626 l=lod[8-logh];
627 s=32.0f;
628 t=256.0f;
629 is=INT_TRICK(5);it=INT_TRICK(8);
630 ws=4;
631 hs=1;
632 break;
633 case -6:
634 aspectratio=GR_ASPECT_1x8;
635 l=lod[8-logh];
636 s=32.0f;
637 t=256.0f;
638 is=INT_TRICK(5);it=INT_TRICK(8);
639 ws=8;
640 hs=1;
641 break;
642 case -7:
643 aspectratio=GR_ASPECT_1x8;
644 l=lod[8-logh];
645 s=32.0f;
646 t=256.0f;
647 is=INT_TRICK(5);it=INT_TRICK(8);
648 ws=16;
649 hs=1;
650 break;
651 case -8:
652 aspectratio=GR_ASPECT_1x8;
653 l=lod[8-logh];
654 s=32.0f;
655 t=256.0f;
656 is=INT_TRICK(5);it=INT_TRICK(8);
657 ws=32;
658 hs=1;
659 break;
660 default:
661 return 0;
662 break;
663 }
664
665 if(lodlevel)
666 (*lodlevel)=l;
667
668 if(ar)
669 (*ar)=aspectratio;
670
671 if(sscale)
672 (*sscale)=s;
673
674 if(tscale)
675 (*tscale)=t;
676
677 if(wscale)
678 (*wscale)=ws;
679
680 if(hscale)
681 (*hscale)=hs;
682
683 if (i_sscale)
684 *i_sscale = is;
685
686 if (i_tscale)
687 *i_tscale = it;
688
689
690 return 1;
691 }
692
693 /*
694 * Given an OpenGL internal texture format, return the corresponding
695 * Glide internal texture format and base texture format.
696 */
697 void fxTexGetFormat(GLenum glformat, GrTextureFormat_t *tfmt, GLint *ifmt)
698 {
699 switch(glformat) {
700 case 1:
701 case GL_LUMINANCE:
702 case GL_LUMINANCE4:
703 case GL_LUMINANCE8:
704 case GL_LUMINANCE12:
705 case GL_LUMINANCE16:
706 if(tfmt)
707 (*tfmt)=GR_TEXFMT_INTENSITY_8;
708 if(ifmt)
709 (*ifmt)=GL_LUMINANCE;
710 break;
711 case 2:
712 case GL_LUMINANCE_ALPHA:
713 case GL_LUMINANCE4_ALPHA4:
714 case GL_LUMINANCE6_ALPHA2:
715 case GL_LUMINANCE8_ALPHA8:
716 case GL_LUMINANCE12_ALPHA4:
717 case GL_LUMINANCE12_ALPHA12:
718 case GL_LUMINANCE16_ALPHA16:
719 if(tfmt)
720 (*tfmt)=GR_TEXFMT_ALPHA_INTENSITY_88;
721 if(ifmt)
722 (*ifmt)=GL_LUMINANCE_ALPHA;
723 break;
724 case GL_INTENSITY:
725 case GL_INTENSITY4:
726 case GL_INTENSITY8:
727 case GL_INTENSITY12:
728 case GL_INTENSITY16:
729 if(tfmt)
730 (*tfmt)=GR_TEXFMT_ALPHA_8;
731 if(ifmt)
732 (*ifmt)=GL_INTENSITY;
733 break;
734 case GL_ALPHA:
735 case GL_ALPHA4:
736 case GL_ALPHA8:
737 case GL_ALPHA12:
738 case GL_ALPHA16:
739 if(tfmt)
740 (*tfmt)=GR_TEXFMT_ALPHA_8;
741 if(ifmt)
742 (*ifmt)=GL_ALPHA;
743 break;
744 case 3:
745 case GL_RGB:
746 case GL_R3_G3_B2:
747 case GL_RGB4:
748 case GL_RGB5:
749 case GL_RGB8:
750 case GL_RGB10:
751 case GL_RGB12:
752 case GL_RGB16:
753 if(tfmt)
754 (*tfmt)=GR_TEXFMT_RGB_565;
755 if(ifmt)
756 (*ifmt)=GL_RGB;
757 break;
758 case 4:
759 case GL_RGBA:
760 case GL_RGBA2:
761 case GL_RGBA4:
762 case GL_RGBA8:
763 case GL_RGB10_A2:
764 case GL_RGBA12:
765 case GL_RGBA16:
766 if(tfmt)
767 (*tfmt)=GR_TEXFMT_ARGB_4444;
768 if(ifmt)
769 (*ifmt)=GL_RGBA;
770 break;
771 case GL_RGB5_A1:
772 if(tfmt)
773 (*tfmt)=GR_TEXFMT_ARGB_1555;
774 if(ifmt)
775 (*ifmt)=GL_RGBA;
776 break;
777 case GL_COLOR_INDEX:
778 case GL_COLOR_INDEX1_EXT:
779 case GL_COLOR_INDEX2_EXT:
780 case GL_COLOR_INDEX4_EXT:
781 case GL_COLOR_INDEX8_EXT:
782 case GL_COLOR_INDEX12_EXT:
783 case GL_COLOR_INDEX16_EXT:
784 if(tfmt)
785 (*tfmt)=GR_TEXFMT_P_8;
786 if(ifmt)
787 (*ifmt)=GL_RGBA; /* XXX why is this RGBA? */
788 break;
789 default:
790 fprintf(stderr,
791 "fx Driver: unsupported internalFormat in fxTexGetFormat()\n");
792 fxCloseHardware();
793 exit(-1);
794 break;
795 }
796 }
797
798 static GLboolean fxIsTexSupported(GLenum target, GLint internalFormat,
799 const struct gl_texture_image *image)
800 {
801 if(target != GL_TEXTURE_2D)
802 return GL_FALSE;
803
804 if(!fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,
805 NULL,NULL))
806 return GL_FALSE;
807
808 if (image->Border > 0)
809 return GL_FALSE;
810
811 return GL_TRUE;
812 }
813
814
815 /**********************************************************************/
816 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
817 /**********************************************************************/
818
819 /* Texel-fetch functions for software texturing and glGetTexImage().
820 * We should have been able to use some "standard" fetch functions (which
821 * may get defined in texutil.c) but we have to account for scaled texture
822 * images on tdfx hardware (the 8:1 aspect ratio limit).
823 * Hence, we need special functions here.
824 */
825
826 static void
827 fetch_intensity8(GLcontext *ctx,
828 const struct gl_texture_object *texObj,
829 const struct gl_texture_image *texImage,
830 GLint i, GLint j, GLint k, GLchan rgba[4])
831 {
832 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
833 const GLubyte *texel;
834
835 i = i * mml->wScale;
836 j = j * mml->hScale;
837
838 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
839 rgba[RCOMP] = *texel;
840 rgba[GCOMP] = *texel;
841 rgba[BCOMP] = *texel;
842 rgba[ACOMP] = *texel;
843 }
844
845
846 static void
847 fetch_luminance8(GLcontext *ctx,
848 const struct gl_texture_object *texObj,
849 const struct gl_texture_image *texImage,
850 GLint i, GLint j, GLint k, GLchan rgba[4])
851 {
852 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
853 const GLubyte *texel;
854
855 i = i * mml->wScale;
856 j = j * mml->hScale;
857
858 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
859 rgba[RCOMP] = *texel;
860 rgba[GCOMP] = *texel;
861 rgba[BCOMP] = *texel;
862 rgba[ACOMP] = 255;
863
864 }
865
866
867 static void
868 fetch_alpha8(GLcontext *ctx,
869 const struct gl_texture_object *texObj,
870 const struct gl_texture_image *texImage,
871 GLint i, GLint j, GLint k, GLchan rgba[4])
872 {
873 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
874 const GLubyte *texel;
875
876 i = i * mml->wScale;
877 j = j * mml->hScale;
878 i = i * mml->width / texImage->Width;
879 j = j * mml->height / texImage->Height;
880
881 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
882 rgba[RCOMP] = 255;
883 rgba[GCOMP] = 255;
884 rgba[BCOMP] = 255;
885 rgba[ACOMP] = *texel;
886 }
887
888
889 static void
890 fetch_index8(GLcontext *ctx,
891 const struct gl_texture_object *texObj,
892 const struct gl_texture_image *texImage,
893 GLint i, GLint j, GLint k, GLchan rgba[4])
894 {
895 /* XXX todo */
896 }
897
898
899 static void
900 fetch_luminance8_alpha8(GLcontext *ctx,
901 const struct gl_texture_object *texObj,
902 const struct gl_texture_image *texImage,
903 GLint i, GLint j, GLint k, GLchan rgba[4])
904 {
905 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
906 const GLubyte *texel;
907
908 i = i * mml->wScale;
909 j = j * mml->hScale;
910
911 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
912 rgba[RCOMP] = texel[0];
913 rgba[GCOMP] = texel[0];
914 rgba[BCOMP] = texel[0];
915 rgba[ACOMP] = texel[1];
916 }
917
918 static void
919 fetch_r5g6b5(GLcontext *ctx,
920 const struct gl_texture_object *texObj,
921 const struct gl_texture_image *texImage,
922 GLint i, GLint j, GLint k, GLchan rgba[4])
923 {
924 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
925 const GLushort *texel;
926
927 i = i * mml->wScale;
928 j = j * mml->hScale;
929
930 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
931 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
932 rgba[GCOMP] = (((*texel) >> 5) & 0x3f) * 255 / 63;
933 rgba[BCOMP] = (((*texel) >> 0) & 0x1f) * 255 / 31;
934 rgba[ACOMP] = 255;
935 }
936
937
938 static void
939 fetch_r4g4b4a4(GLcontext *ctx,
940 const struct gl_texture_object *texObj,
941 const struct gl_texture_image *texImage,
942 GLint i, GLint j, GLint k, GLchan rgba[4])
943 {
944 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
945 const GLushort *texel;
946
947 i = i * mml->wScale;
948 j = j * mml->hScale;
949
950 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
951 rgba[RCOMP] = (((*texel) >> 12) & 0xf) * 255 / 15;
952 rgba[GCOMP] = (((*texel) >> 8) & 0xf) * 255 / 15;
953 rgba[BCOMP] = (((*texel) >> 4) & 0xf) * 255 / 15;
954 rgba[ACOMP] = (((*texel) >> 0) & 0xf) * 255 / 15;
955 }
956
957
958 static void
959 fetch_r5g5b5a1(GLcontext *ctx,
960 const struct gl_texture_object *texObj,
961 const struct gl_texture_image *texImage,
962 GLint i, GLint j, GLint k, GLchan rgba[4])
963 {
964 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
965 const GLushort *texel;
966
967 i = i * mml->wScale;
968 j = j * mml->hScale;
969
970 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
971 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
972 rgba[GCOMP] = (((*texel) >> 6) & 0x1f) * 255 / 31;
973 rgba[BCOMP] = (((*texel) >> 1) & 0x1f) * 255 / 31;
974 rgba[ACOMP] = (((*texel) >> 0) & 0x01) * 255;
975 }
976
977
978 static void PrintTexture(int w, int h, int c, const GLubyte *data)
979 {
980 int i, j;
981 for (i = 0; i < h; i++) {
982 for (j = 0; j < w; j++) {
983 if (c==2)
984 printf("%02x %02x ", data[0], data[1]);
985 else if (c==3)
986 printf("%02x %02x %02x ", data[0], data[1], data[2]);
987 data += c;
988 }
989 printf("\n");
990 }
991 }
992
993
994 void
995 fxDDTexImage2D(GLcontext *ctx, GLenum target, GLint level,
996 GLint internalFormat, GLint width, GLint height, GLint border,
997 GLenum format, GLenum type, const GLvoid *pixels,
998 const struct gl_pixelstore_attrib *packing,
999 struct gl_texture_object *texObj,
1000 struct gl_texture_image *texImage)
1001 {
1002 fxMesaContext fxMesa = (fxMesaContext)ctx->DriverCtx;
1003 GrTextureFormat_t gldformat;
1004 tfxTexInfo *ti = fxTMGetTexInfo(texObj);
1005 tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
1006 MesaIntTexFormat mesaFormat;
1007 GLint texelSize;
1008 GLboolean success;
1009
1010 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1011 gl_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1012 return;
1013 }
1014
1015 if (!texObj->DriverData)
1016 texObj->DriverData = fxAllocTexObjData(fxMesa);
1017
1018 if (!mml) {
1019 texImage->DriverData = MALLOC(sizeof(tfxMipMapLevel));
1020 mml = FX_MIPMAP_DATA(texImage);
1021 }
1022
1023 fxTexGetFormat(internalFormat, &gldformat, NULL);
1024
1025 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1026 NULL, NULL, &mml->wScale, &mml->hScale);
1027
1028 mml->width = texImage->Width * mml->wScale;
1029 mml->height = texImage->Height * mml->hScale;
1030
1031 switch (internalFormat) {
1032 case GL_INTENSITY:
1033 case GL_INTENSITY4:
1034 case GL_INTENSITY8:
1035 case GL_INTENSITY12:
1036 case GL_INTENSITY16:
1037 texImage->FetchTexel = fetch_intensity8;
1038 texelSize = 1;
1039 mesaFormat = MESA_I8;
1040 break;
1041 case 1:
1042 case GL_LUMINANCE:
1043 case GL_LUMINANCE4:
1044 case GL_LUMINANCE8:
1045 case GL_LUMINANCE12:
1046 case GL_LUMINANCE16:
1047 texImage->FetchTexel = fetch_luminance8;
1048 texelSize = 1;
1049 mesaFormat = MESA_L8;
1050 break;
1051 case GL_ALPHA:
1052 case GL_ALPHA4:
1053 case GL_ALPHA8:
1054 case GL_ALPHA12:
1055 case GL_ALPHA16:
1056 texImage->FetchTexel = fetch_alpha8;
1057 texelSize = 1;
1058 mesaFormat = MESA_A8;
1059 break;
1060 case GL_COLOR_INDEX:
1061 case GL_COLOR_INDEX1_EXT:
1062 case GL_COLOR_INDEX2_EXT:
1063 case GL_COLOR_INDEX4_EXT:
1064 case GL_COLOR_INDEX8_EXT:
1065 case GL_COLOR_INDEX12_EXT:
1066 case GL_COLOR_INDEX16_EXT:
1067 texImage->FetchTexel = fetch_index8;
1068 texelSize = 1;
1069 mesaFormat = MESA_C8;
1070 break;
1071 case 2:
1072 case GL_LUMINANCE_ALPHA:
1073 case GL_LUMINANCE4_ALPHA4:
1074 case GL_LUMINANCE6_ALPHA2:
1075 case GL_LUMINANCE8_ALPHA8:
1076 case GL_LUMINANCE12_ALPHA4:
1077 case GL_LUMINANCE12_ALPHA12:
1078 case GL_LUMINANCE16_ALPHA16:
1079 texImage->FetchTexel = fetch_luminance8_alpha8;
1080 texelSize = 2;
1081 mesaFormat = MESA_A8_L8;
1082 break;
1083 case 3:
1084 case GL_RGB:
1085 case GL_R3_G3_B2:
1086 case GL_RGB4:
1087 case GL_RGB5:
1088 case GL_RGB8:
1089 case GL_RGB10:
1090 case GL_RGB12:
1091 case GL_RGB16:
1092 texImage->FetchTexel = fetch_r5g6b5;
1093 texelSize = 2;
1094 mesaFormat = MESA_R5_G6_B5;
1095 break;
1096 case 4:
1097 case GL_RGBA:
1098 case GL_RGBA2:
1099 case GL_RGBA4:
1100 case GL_RGBA8:
1101 case GL_RGB10_A2:
1102 case GL_RGBA12:
1103 case GL_RGBA16:
1104 texImage->FetchTexel = fetch_r4g4b4a4;
1105 texelSize = 2;
1106 mesaFormat = MESA_A4_R4_G4_B4;
1107 break;
1108 case GL_RGB5_A1:
1109 texImage->FetchTexel = fetch_r5g5b5a1;
1110 texelSize = 2;
1111 mesaFormat = MESA_A1_R5_G5_B5;
1112 break;
1113 default:
1114 gl_problem(NULL, "tdfx driver: texbuildimagemap() bad format");
1115 return;
1116 }
1117
1118 _mesa_set_teximage_component_sizes(mesaFormat, texImage);
1119
1120 /* allocate new storage for texture image, if needed */
1121 texImage->Data = MALLOC(mml->width * mml->height * texelSize);
1122 if (!texImage->Data)
1123 return;
1124
1125 mml->glideFormat = gldformat;
1126 fxTexInvalidate(ctx, texObj);
1127
1128 /* store the texture image */
1129 if (ctx->_ImageTransferState) {
1130 success = GL_FALSE;
1131 }
1132 else {
1133 success = _mesa_convert_teximage(mesaFormat, mml->width, mml->height,
1134 texImage->Data, mml->width * texelSize,
1135 width, height,
1136 format, type, pixels, packing);
1137 }
1138
1139 if (!success) {
1140 /* First attempt at texture conversion failed. We may need to
1141 * do fancy pixel transfer ops or convert from an obscure texture
1142 * format.
1143 */
1144 GLenum simpleFormat = _mesa_base_tex_format(ctx, internalFormat);
1145 GLint comps = _mesa_components_in_format(simpleFormat);
1146 GLubyte *tempImage;
1147
1148 tempImage = MALLOC(width * height * comps * sizeof(GLubyte));
1149
1150 /* Apply pixel transfer ops and convert image format to something
1151 * simple (format = simpleFormat, type = CHAN_TYPE).
1152 */
1153 _mesa_transfer_teximage(ctx, 2, /* dimensions */
1154 simpleFormat, /* dest format */
1155 tempImage, /* dest addr */
1156 width, height, 1, /* src size */
1157 0, 0, 0, /* dst offsets */
1158 width * comps, /* dstRowStride */
1159 0, /* dstImageStride */
1160 format, type, pixels, packing /* src info */);
1161
1162 /* this conversion better work! */
1163 success = _mesa_convert_teximage(mesaFormat, mml->width, mml->height,
1164 texImage->Data, mml->width * texelSize,
1165 width, height,
1166 simpleFormat, CHAN_TYPE, tempImage,
1167 &_mesa_native_packing);
1168 assert(success);
1169 FREE(tempImage);
1170 }
1171
1172 if (ti->validated && ti->isInTM) {
1173 /*printf("reloadmipmaplevels\n");*/
1174 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1175 }
1176 else {
1177 /*printf("invalidate2\n");*/
1178 fxTexInvalidate(ctx,texObj);
1179 }
1180 }
1181
1182
1183 void
1184 fxDDTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
1185 GLint xoffset, GLint yoffset,
1186 GLsizei width, GLsizei height,
1187 GLenum format, GLenum type, const GLvoid *pixels,
1188 const struct gl_pixelstore_attrib *packing,
1189 struct gl_texture_object *texObj,
1190 struct gl_texture_image *texImage)
1191 {
1192 fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
1193 tfxTexInfo *ti;
1194 GLint texelSize;
1195 tfxMipMapLevel *mml;
1196 GLboolean success;
1197 MesaIntTexFormat mesaFormat;
1198
1199 if (!texObj->DriverData) {
1200 gl_problem(ctx, "problem in fxDDTexSubImage2D");
1201 return;
1202 }
1203
1204 ti = fxTMGetTexInfo(texObj);
1205 assert(ti);
1206 mml = FX_MIPMAP_DATA(texImage);
1207 assert(mml);
1208
1209 assert(texImage->Data); /* must have an existing texture image! */
1210
1211 switch (mml->glideFormat) {
1212 case GR_TEXFMT_INTENSITY_8:
1213 texelSize = 1;
1214 mesaFormat = MESA_I8;
1215 break;
1216 case GR_TEXFMT_ALPHA_8:
1217 texelSize = 1;
1218 mesaFormat = MESA_A8;
1219 break;
1220 case GR_TEXFMT_P_8:
1221 texelSize = 1;
1222 mesaFormat = MESA_C8;
1223 break;
1224 case GR_TEXFMT_ALPHA_INTENSITY_88:
1225 texelSize = 2;
1226 mesaFormat = MESA_A8_L8;
1227 break;
1228 case GR_TEXFMT_RGB_565:
1229 texelSize = 2;
1230 mesaFormat = MESA_R5_G6_B5;
1231 break;
1232 case GR_TEXFMT_ARGB_4444:
1233 texelSize = 2;
1234 mesaFormat = MESA_A4_R4_G4_B4;
1235 break;
1236 case GR_TEXFMT_ARGB_1555:
1237 texelSize = 2;
1238 mesaFormat = MESA_A1_R5_G5_B5;
1239 break;
1240 default:
1241 gl_problem(NULL, "tdfx driver: fxTexBuildSubImageMap() bad format");
1242 return;
1243 }
1244
1245 if (ctx->_ImageTransferState) {
1246 success = GL_FALSE;
1247 }
1248 else {
1249 success = _mesa_convert_texsubimage(mesaFormat, xoffset, yoffset,
1250 mml->width, mml->height,
1251 texImage->Data,
1252 mml->width * texelSize,
1253 width, height,
1254 texImage->Width, texImage->Height,
1255 format, type, pixels, packing);
1256 }
1257
1258 if (!success) {
1259 /* Incoming image might need scale/bias or is in an uncommon format
1260 * that _mesa_convert_texsubimage() can't deal with. Convert it to
1261 * a simpler format now.
1262 */
1263
1264 GLenum simpleFormat = _mesa_base_tex_format(ctx, texImage->IntFormat);
1265 GLint comps = _mesa_components_in_format(simpleFormat);
1266 GLubyte *tempImage;
1267 GLboolean success;
1268
1269 tempImage = MALLOC(width * height * comps * sizeof(GLubyte));
1270
1271 /* Apply pixel transfer ops and convert image format to something
1272 * simple (format = simpleFormat, type = CHAN_TYPE).
1273 */
1274 _mesa_transfer_teximage(ctx, 2, /* dimensions */
1275 simpleFormat, /* dest format */
1276 tempImage, /* dest addr */
1277 width, height, 1, /* src size */
1278 0, 0, 0, /* dst offsets */
1279 width * comps, /* dstRowStride */
1280 0, /* dstImageStride */
1281 format, type, pixels, packing /* src info */);
1282
1283 /* this conversion better work! */
1284 success = _mesa_convert_texsubimage(mesaFormat, xoffset, yoffset,
1285 mml->width, mml->height,
1286 texImage->Data,
1287 mml->width * texelSize, /* dstRowStride */
1288 width * mml->wScale,
1289 height * mml->hScale,
1290 width, height,
1291 simpleFormat, CHAN_TYPE, tempImage,
1292 &_mesa_native_packing);
1293 assert(success);
1294 FREE(tempImage);
1295 }
1296
1297 if (ti->validated && ti->isInTM)
1298 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1299 else
1300 fxTexInvalidate(ctx, texObj);
1301 }
1302
1303
1304 #else
1305
1306
1307 /*
1308 * Need this to provide at least one external definition.
1309 */
1310
1311 extern int gl_fx_dummy_function_ddtex(void);
1312 int gl_fx_dummy_function_ddtex(void)
1313 {
1314 return 0;
1315 }
1316
1317 #endif /* FX */