cleanups
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 4.0
4 *
5 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /* Authors:
26 * David Bucciarelli
27 * Brian Paul
28 * Daryll Strauss
29 * Keith Whitwell
30 * Daniel Borca
31 * Hiroshi Morii
32 */
33
34
35 #ifdef HAVE_CONFIG_H
36 #include "conf.h"
37 #endif
38
39 #if defined(FX)
40
41 #include "fxdrv.h"
42 #include "enums.h"
43 #include "image.h"
44 #include "teximage.h"
45 #include "texformat.h"
46 #include "texstore.h"
47 #include "texutil.h"
48
49
50 void
51 fxPrintTextureData(tfxTexInfo * ti)
52 {
53 fprintf(stderr, "Texture Data:\n");
54 if (ti->tObj) {
55 fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
56 fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
57 fprintf(stderr, "\tSize: %d x %d\n",
58 ti->tObj->Image[ti->tObj->BaseLevel]->Width,
59 ti->tObj->Image[ti->tObj->BaseLevel]->Height);
60 }
61 else
62 fprintf(stderr, "\tName: UNNAMED\n");
63 fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
64 fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
65 fprintf(stderr, "\t%s\n", (ti->isInTM) ? "In TMU" : "Not in TMU");
66 if (ti->tm[0])
67 fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
68 (unsigned) ti->tm[0]->endAddr);
69 if (ti->tm[1])
70 fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
71 (unsigned) ti->tm[1]->endAddr);
72 fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
73 fprintf(stderr, "\tFilters: min %d min %d\n",
74 (int) ti->minFilt, (int) ti->maxFilt);
75 fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp,
76 (int) ti->tClamp);
77 fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
78 fprintf(stderr, "\t%s\n",
79 (ti->fixedPalette) ? "Fixed palette" : "Non fixed palette");
80 fprintf(stderr, "\t%s\n", (ti->validated) ? "Validated" : "Not validated");
81 }
82
83
84 /************************************************************************/
85 /*************************** Texture Mapping ****************************/
86 /************************************************************************/
87
88 static void
89 fxTexInvalidate(GLcontext * ctx, struct gl_texture_object *tObj)
90 {
91 fxMesaContext fxMesa = FX_CONTEXT(ctx);
92 tfxTexInfo *ti;
93
94 ti = fxTMGetTexInfo(tObj);
95 if (ti->isInTM)
96 fxTMMoveOutTM(fxMesa, tObj); /* TO DO: SLOW but easy to write */
97
98 ti->validated = GL_FALSE;
99 fxMesa->new_state |= FX_NEW_TEXTURING;
100 }
101
102 static tfxTexInfo *
103 fxAllocTexObjData(fxMesaContext fxMesa)
104 {
105 tfxTexInfo *ti;
106
107 if (!(ti = CALLOC(sizeof(tfxTexInfo)))) {
108 fprintf(stderr, "fxAllocTexObjData: ERROR: out of memory !\n");
109 fxCloseHardware();
110 exit(-1);
111 }
112
113 ti->validated = GL_FALSE;
114 ti->isInTM = GL_FALSE;
115
116 ti->whichTMU = FX_TMU_NONE;
117
118 ti->tm[FX_TMU0] = NULL;
119 ti->tm[FX_TMU1] = NULL;
120
121 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
122 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
123
124 ti->sClamp = GR_TEXTURECLAMP_WRAP;
125 ti->tClamp = GR_TEXTURECLAMP_WRAP;
126
127 ti->mmMode = GR_MIPMAP_NEAREST;
128 ti->LODblend = FXFALSE;
129
130 return ti;
131 }
132
133 void
134 fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
135 {
136 fxMesaContext fxMesa = FX_CONTEXT(ctx);
137 tfxTexInfo *ti;
138
139 if (TDFX_DEBUG & VERBOSE_DRIVER) {
140 fprintf(stderr, "fxDDTexBind(%d, %x)\n", tObj->Name, (GLuint)tObj->DriverData);
141 }
142
143 if (target != GL_TEXTURE_2D)
144 return;
145
146 if (!tObj->DriverData) {
147 tObj->DriverData = fxAllocTexObjData(fxMesa);
148 }
149
150 ti = fxTMGetTexInfo(tObj);
151
152 fxMesa->texBindNumber++;
153 ti->lastTimeUsed = fxMesa->texBindNumber;
154
155 fxMesa->new_state |= FX_NEW_TEXTURING;
156 }
157
158 void
159 fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
160 const GLfloat * param)
161 {
162 fxMesaContext fxMesa = FX_CONTEXT(ctx);
163
164 if (TDFX_DEBUG & VERBOSE_DRIVER) {
165 if (param)
166 fprintf(stderr, "fxDDTexEnv(%x, %x)\n", pname, (GLint) (*param));
167 else
168 fprintf(stderr, "fxDDTexEnv(%x)\n", pname);
169 }
170
171 /* apply any lod biasing right now */
172 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
173 grTexLodBiasValue(GR_TMU0, *param);
174
175 if (fxMesa->haveTwoTMUs) {
176 grTexLodBiasValue(GR_TMU1, *param);
177 }
178
179 }
180
181 fxMesa->new_state |= FX_NEW_TEXTURING;
182 }
183
184 void
185 fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
186 GLenum pname, const GLfloat * params)
187 {
188 fxMesaContext fxMesa = FX_CONTEXT(ctx);
189 GLenum param = (GLenum) (GLint) params[0];
190 tfxTexInfo *ti;
191
192 if (TDFX_DEBUG & VERBOSE_DRIVER) {
193 fprintf(stderr, "fxDDTexParam(%d, %x, %s, %s)\n",
194 tObj->Name, (GLuint) tObj->DriverData,
195 _mesa_lookup_enum_by_nr(pname),
196 _mesa_lookup_enum_by_nr(param));
197 }
198
199 if (target != GL_TEXTURE_2D)
200 return;
201
202 if (!tObj->DriverData)
203 tObj->DriverData = fxAllocTexObjData(fxMesa);
204
205 ti = fxTMGetTexInfo(tObj);
206
207 switch (pname) {
208
209 case GL_TEXTURE_MIN_FILTER:
210 switch (param) {
211 case GL_NEAREST:
212 ti->mmMode = GR_MIPMAP_DISABLE;
213 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
214 ti->LODblend = FXFALSE;
215 break;
216 case GL_LINEAR:
217 ti->mmMode = GR_MIPMAP_DISABLE;
218 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
219 ti->LODblend = FXFALSE;
220 break;
221 case GL_NEAREST_MIPMAP_LINEAR:
222 /* ZZZ: HACK ALERT! disable LODBlend, because we can't implement
223 on Napalm. Ohwell, until at least I decide what to do...
224 trilinear is bugged! mipmap blending produce
225 incorrect filtered colors for the smallest mipmap levels. */
226 #if 0
227 if (fxMesa->haveTwoTMUs) {
228 ti->mmMode = GR_MIPMAP_NEAREST;
229 ti->LODblend = FXTRUE;
230 }
231 else {
232 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
233 ti->LODblend = FXFALSE;
234 }
235 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
236 break; /* ZZZ: we may have to fall through here for V3 */
237 #endif
238 case GL_NEAREST_MIPMAP_NEAREST:
239 ti->mmMode = GR_MIPMAP_NEAREST;
240 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
241 ti->LODblend = FXFALSE;
242 break;
243 case GL_LINEAR_MIPMAP_LINEAR:
244 /* ZZZ: HACK ALERT! trilinear is bugged! mipmap blending produce
245 incorrect filtered colors for the smallest mipmap levels. */
246 #if 0
247 if (fxMesa->haveTwoTMUs) {
248 ti->mmMode = GR_MIPMAP_NEAREST;
249 ti->LODblend = FXTRUE;
250 }
251 else {
252 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
253 ti->LODblend = FXFALSE;
254 }
255 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
256 break; /* ZZZ: we may have to fall through here for V3 */
257 #endif
258 case GL_LINEAR_MIPMAP_NEAREST:
259 ti->mmMode = GR_MIPMAP_NEAREST;
260 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
261 ti->LODblend = FXFALSE;
262 break;
263 default:
264 break;
265 }
266 fxTexInvalidate(ctx, tObj);
267 break;
268
269 case GL_TEXTURE_MAG_FILTER:
270 switch (param) {
271 case GL_NEAREST:
272 ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
273 break;
274 case GL_LINEAR:
275 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
276 break;
277 default:
278 break;
279 }
280 fxTexInvalidate(ctx, tObj);
281 break;
282
283 case GL_TEXTURE_WRAP_S:
284 switch (param) {
285 case GL_MIRRORED_REPEAT:
286 ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
287 break;
288 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
289 case GL_CLAMP:
290 ti->sClamp = GR_TEXTURECLAMP_CLAMP;
291 break;
292 case GL_REPEAT:
293 ti->sClamp = GR_TEXTURECLAMP_WRAP;
294 break;
295 default:
296 break;
297 }
298 fxMesa->new_state |= FX_NEW_TEXTURING;
299 break;
300
301 case GL_TEXTURE_WRAP_T:
302 switch (param) {
303 case GL_MIRRORED_REPEAT:
304 ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
305 break;
306 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
307 case GL_CLAMP:
308 ti->tClamp = GR_TEXTURECLAMP_CLAMP;
309 break;
310 case GL_REPEAT:
311 ti->tClamp = GR_TEXTURECLAMP_WRAP;
312 break;
313 default:
314 break;
315 }
316 fxMesa->new_state |= FX_NEW_TEXTURING;
317 break;
318
319 case GL_TEXTURE_BORDER_COLOR:
320 /* TO DO */
321 break;
322
323 case GL_TEXTURE_MIN_LOD:
324 /* TO DO */
325 break;
326 case GL_TEXTURE_MAX_LOD:
327 /* TO DO */
328 break;
329 case GL_TEXTURE_BASE_LEVEL:
330 fxTexInvalidate(ctx, tObj);
331 break;
332 case GL_TEXTURE_MAX_LEVEL:
333 fxTexInvalidate(ctx, tObj);
334 break;
335
336 default:
337 break;
338 }
339 }
340
341 void
342 fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
343 {
344 fxMesaContext fxMesa = FX_CONTEXT(ctx);
345 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
346
347 if (TDFX_DEBUG & VERBOSE_DRIVER) {
348 fprintf(stderr, "fxDDTexDel(%d, %p)\n", tObj->Name, (void *) ti);
349 }
350
351 if (!ti)
352 return;
353
354 fxTMFreeTexture(fxMesa, tObj);
355
356 FREE(ti);
357 tObj->DriverData = NULL;
358 }
359
360 /*
361 * Return true if texture is resident, false otherwise.
362 */
363 GLboolean
364 fxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
365 {
366 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
367 return (ti && ti->isInTM);
368 }
369
370
371
372 /*
373 * Convert a gl_color_table texture palette to Glide's format.
374 */
375 static GrTexTable_t
376 convertPalette(const fxMesaContext fxMesa, FxU32 data[256], const struct gl_color_table *table)
377 {
378 const GLubyte *tableUB = (const GLubyte *) table->Table;
379 GLint width = table->Size;
380 FxU32 r, g, b, a;
381 GLint i;
382
383 ASSERT(!table->FloatTable);
384
385 switch (table->Format) {
386 case GL_INTENSITY:
387 for (i = 0; i < width; i++) {
388 r = tableUB[i];
389 g = tableUB[i];
390 b = tableUB[i];
391 a = tableUB[i];
392 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
393 }
394 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
395 case GL_LUMINANCE:
396 for (i = 0; i < width; i++) {
397 r = tableUB[i];
398 g = tableUB[i];
399 b = tableUB[i];
400 a = 255;
401 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
402 }
403 return GR_TEXTABLE_PALETTE;
404 case GL_ALPHA:
405 for (i = 0; i < width; i++) {
406 r = g = b = 255;
407 a = tableUB[i];
408 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
409 }
410 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
411 case GL_LUMINANCE_ALPHA:
412 for (i = 0; i < width; i++) {
413 r = g = b = tableUB[i * 2 + 0];
414 a = tableUB[i * 2 + 1];
415 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
416 }
417 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
418 default:
419 case GL_RGB:
420 for (i = 0; i < width; i++) {
421 r = tableUB[i * 3 + 0];
422 g = tableUB[i * 3 + 1];
423 b = tableUB[i * 3 + 2];
424 a = 255;
425 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
426 }
427 return GR_TEXTABLE_PALETTE;
428 case GL_RGBA:
429 for (i = 0; i < width; i++) {
430 r = tableUB[i * 4 + 0];
431 g = tableUB[i * 4 + 1];
432 b = tableUB[i * 4 + 2];
433 a = tableUB[i * 4 + 3];
434 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
435 }
436 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
437 }
438 }
439
440
441 void
442 fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
443 {
444 fxMesaContext fxMesa = FX_CONTEXT(ctx);
445
446 if (tObj) {
447 /* per-texture palette */
448 tfxTexInfo *ti;
449 if (TDFX_DEBUG & VERBOSE_DRIVER) {
450 fprintf(stderr, "fxDDTexPalette(%d, %x)\n",
451 tObj->Name, (GLuint) tObj->DriverData);
452 }
453 if (!tObj->DriverData)
454 tObj->DriverData = fxAllocTexObjData(fxMesa);
455 ti = fxTMGetTexInfo(tObj);
456 ti->paltype = convertPalette(fxMesa, ti->palette.data, &tObj->Palette);
457 fxTexInvalidate(ctx, tObj);
458 }
459 else {
460 /* global texture palette */
461 if (TDFX_DEBUG & VERBOSE_DRIVER) {
462 fprintf(stderr, "fxDDTexPalette(global)\n");
463 }
464 fxMesa->glbPalType = convertPalette(fxMesa, fxMesa->glbPalette.data, &ctx->Texture.Palette);
465 fxMesa->new_state |= FX_NEW_TEXTURING;
466
467 grTexDownloadTable(fxMesa->glbPalType, &(fxMesa->glbPalette));
468 }
469 }
470
471
472 void
473 fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
474 {
475 fxMesaContext fxMesa = FX_CONTEXT(ctx);
476
477 if (TDFX_DEBUG & VERBOSE_DRIVER) {
478 fprintf(stderr, "fxDDTexUseGlbPalette(%d)\n", state);
479 }
480
481 if (state) {
482 fxMesa->haveGlobalPaletteTexture = 1;
483 }
484 else {
485 fxMesa->haveGlobalPaletteTexture = 0;
486
487 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
488 (ctx->Texture.Unit[0]._Current != NULL)) {
489 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
490
491 if (!tObj->DriverData)
492 tObj->DriverData = fxAllocTexObjData(fxMesa);
493
494 fxTexInvalidate(ctx, tObj);
495 }
496 }
497 }
498
499
500 static int
501 logbase2(int n)
502 {
503 GLint i = 1;
504 GLint log2 = 0;
505
506 if (n < 0) {
507 return -1;
508 }
509
510 while (n > i) {
511 i *= 2;
512 log2++;
513 }
514 if (i != n) {
515 return -1;
516 }
517 else {
518 return log2;
519 }
520 }
521
522
523 /* fxTexGetInfo
524 * w, h - source texture width and height
525 * lodlevel - Glide lod level token for the larger texture dimension
526 * ar - Glide aspect ratio token
527 * sscale - S scale factor used during triangle setup
528 * tscale - T scale factor used during triangle setup
529 * wscale - OpenGL -> Glide image width scale factor
530 * hscale - OpenGL -> Glide image height scale factor
531 */
532 int
533 fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar,
534 float *sscale, float *tscale,
535 int *wscale, int *hscale)
536 {
537 int logw, logh, ws, hs;
538 GrLOD_t l;
539 GrAspectRatio_t aspectratio;
540 float s, t;
541
542 logw = logbase2(w);
543 logh = logbase2(h);
544
545 l = MAX2(logw, logh);
546 aspectratio = logw - logh;
547 ws = hs = 1;
548
549 /* hardware only allows a maximum aspect ratio of 8x1, so handle
550 * |aspectratio| > 3 by scaling the image and using an 8x1 aspect
551 * ratio
552 */
553 switch (aspectratio) {
554 case 0:
555 s = 256.0f;
556 t = 256.0f;
557 break;
558 case 1:
559 s = 256.0f;
560 t = 128.0f;
561 break;
562 case 2:
563 s = 256.0f;
564 t = 64.0f;
565 break;
566 case 3:
567 s = 256.0f;
568 t = 32.0f;
569 break;
570 case -1:
571 s = 128.0f;
572 t = 256.0f;
573 break;
574 case -2:
575 s = 64.0f;
576 t = 256.0f;
577 break;
578 case -3:
579 s = 32.0f;
580 t = 256.0f;
581 break;
582 default:
583 if (aspectratio > 3) {
584 s = 256.0f;
585 t = 32.0f;
586 ws = 1;
587 hs = 1 << (aspectratio - 3);
588 aspectratio = GR_ASPECT_LOG2_8x1;
589 } else /*if (aspectratio < -3)*/ {
590 s = 32.0f;
591 t = 256.0f;
592 ws = 1 << (-aspectratio - 3);
593 hs = 1;
594 aspectratio = GR_ASPECT_LOG2_1x8;
595 }
596 }
597
598 if (lodlevel)
599 (*lodlevel) = l;
600
601 if (ar)
602 (*ar) = aspectratio;
603
604 if (sscale)
605 (*sscale) = s;
606
607 if (tscale)
608 (*tscale) = t;
609
610 if (wscale)
611 (*wscale) = ws;
612
613 if (hscale)
614 (*hscale) = hs;
615
616
617 return 1;
618 }
619
620 static GLboolean
621 fxIsTexSupported(GLenum target, GLint internalFormat,
622 const struct gl_texture_image *image)
623 {
624 if (target != GL_TEXTURE_2D)
625 return GL_FALSE;
626
627 #if 0
628 if (!fxTexGetInfo(image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL))
629 return GL_FALSE;
630 #endif
631
632 if (image->Border > 0)
633 return GL_FALSE;
634
635 return GL_TRUE;
636 }
637
638
639 /**********************************************************************/
640 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
641 /**********************************************************************/
642
643 /* Texel-fetch functions for software texturing and glGetTexImage().
644 * We should have been able to use some "standard" fetch functions (which
645 * may get defined in texutil.c) but we have to account for scaled texture
646 * images on tdfx hardware (the 8:1 aspect ratio limit).
647 * Hence, we need special functions here.
648 */
649
650 static void
651 fetch_intensity8(const struct gl_texture_image *texImage,
652 GLint i, GLint j, GLint k, GLvoid * texelOut)
653 {
654 GLchan *rgba = (GLchan *) texelOut;
655 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
656 const GLubyte *texel;
657
658 i = i * mml->wScale;
659 j = j * mml->hScale;
660
661 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
662 rgba[RCOMP] = *texel;
663 rgba[GCOMP] = *texel;
664 rgba[BCOMP] = *texel;
665 rgba[ACOMP] = *texel;
666 }
667
668
669 static void
670 fetch_luminance8(const struct gl_texture_image *texImage,
671 GLint i, GLint j, GLint k, GLvoid * texelOut)
672 {
673 GLchan *rgba = (GLchan *) texelOut;
674 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
675 const GLubyte *texel;
676
677 i = i * mml->wScale;
678 j = j * mml->hScale;
679
680 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
681 rgba[RCOMP] = *texel;
682 rgba[GCOMP] = *texel;
683 rgba[BCOMP] = *texel;
684 rgba[ACOMP] = 255;
685 }
686
687
688 static void
689 fetch_alpha8(const struct gl_texture_image *texImage,
690 GLint i, GLint j, GLint k, GLvoid * texelOut)
691 {
692 GLchan *rgba = (GLchan *) texelOut;
693 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
694 const GLubyte *texel;
695
696 i = i * mml->wScale;
697 j = j * mml->hScale;
698
699 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
700 rgba[RCOMP] = 255;
701 rgba[GCOMP] = 255;
702 rgba[BCOMP] = 255;
703 rgba[ACOMP] = *texel;
704 }
705
706
707 static void
708 fetch_index8(const struct gl_texture_image *texImage,
709 GLint i, GLint j, GLint k, GLvoid * texelOut)
710 {
711 GLchan *indexOut = (GLchan *) texelOut;
712 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
713 const GLubyte *texel;
714
715 i = i * mml->wScale;
716 j = j * mml->hScale;
717
718 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
719 *indexOut = *texel;
720 }
721
722
723 static void
724 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
725 GLint i, GLint j, GLint k, GLvoid * texelOut)
726 {
727 GLchan *rgba = (GLchan *) texelOut;
728 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
729 const GLubyte *texel;
730
731 i = i * mml->wScale;
732 j = j * mml->hScale;
733
734 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
735 rgba[RCOMP] = texel[0];
736 rgba[GCOMP] = texel[0];
737 rgba[BCOMP] = texel[0];
738 rgba[ACOMP] = texel[1];
739 }
740
741
742 static void
743 fetch_r5g6b5(const struct gl_texture_image *texImage,
744 GLint i, GLint j, GLint k, GLvoid * texelOut)
745 {
746 GLchan *rgba = (GLchan *) texelOut;
747 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
748 const GLushort *texel;
749
750 i = i * mml->wScale;
751 j = j * mml->hScale;
752
753 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
754 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
755 rgba[GCOMP] = FX_rgb_scale_6[(*texel >> 5) & 0x3F];
756 rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
757 rgba[ACOMP] = 255;
758 }
759
760
761 static void
762 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
763 GLint i, GLint j, GLint k, GLvoid * texelOut)
764 {
765 GLchan *rgba = (GLchan *) texelOut;
766 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
767 const GLushort *texel;
768
769 i = i * mml->wScale;
770 j = j * mml->hScale;
771
772 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
773 rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
774 rgba[GCOMP] = FX_rgb_scale_4[(*texel >> 8) & 0xF];
775 rgba[BCOMP] = FX_rgb_scale_4[(*texel >> 4) & 0xF];
776 rgba[ACOMP] = FX_rgb_scale_4[ *texel & 0xF];
777 }
778
779
780 static void
781 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
782 GLint i, GLint j, GLint k, GLvoid * texelOut)
783 {
784 GLchan *rgba = (GLchan *) texelOut;
785 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
786 const GLushort *texel;
787
788 i = i * mml->wScale;
789 j = j * mml->hScale;
790
791 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
792 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
793 rgba[GCOMP] = FX_rgb_scale_5[(*texel >> 6) & 0x1F];
794 rgba[BCOMP] = FX_rgb_scale_5[(*texel >> 1) & 0x1F];
795 rgba[ACOMP] = ((*texel) & 0x01) * 255;
796 }
797
798
799 static void
800 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
801 GLint i, GLint j, GLint k, GLvoid * texelOut)
802 {
803 GLchan *rgba = (GLchan *) texelOut;
804 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
805 const GLuint *texel;
806
807 i = i * mml->wScale;
808 j = j * mml->hScale;
809
810 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
811 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
812 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
813 rgba[BCOMP] = (((*texel) ) & 0xff);
814 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
815 }
816
817
818 static void
819 PrintTexture(int w, int h, int c, const GLubyte * data)
820 {
821 int i, j;
822 for (i = 0; i < h; i++) {
823 for (j = 0; j < w; j++) {
824 if (c == 2)
825 fprintf(stderr, "%02x %02x ", data[0], data[1]);
826 else if (c == 3)
827 fprintf(stderr, "%02x %02x %02x ", data[0], data[1], data[2]);
828 data += c;
829 }
830 fprintf(stderr, "\n");
831 }
832 }
833
834
835 GLboolean fxDDIsCompressedFormat ( GLcontext *ctx, GLenum internalFormat )
836 {
837 if ((internalFormat == GL_COMPRESSED_RGB_FXT1_3DFX) ||
838 (internalFormat == GL_COMPRESSED_RGBA_FXT1_3DFX) ||
839 (internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ||
840 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ||
841 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) ||
842 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) ||
843 (internalFormat == GL_RGB_S3TC) ||
844 (internalFormat == GL_RGB4_S3TC) ||
845 (internalFormat == GL_RGBA_S3TC) ||
846 (internalFormat == GL_RGBA4_S3TC)) {
847 return GL_TRUE;
848 }
849
850 /* [dBorca]
851 * we are handling differently the above formats from the generic
852 * GL_COMPRESSED_RGB[A]. For this, we will always have to separately
853 * check for the ones below!
854 */
855
856 #if FX_TC_NCC || FX_TC_NAPALM
857 if ((internalFormat == GL_COMPRESSED_RGB) || (internalFormat == GL_COMPRESSED_RGBA)) {
858 return GL_TRUE;
859 }
860 #endif
861
862 return GL_FALSE;
863 }
864
865
866 GLuint fxDDCompressedTextureSize (GLcontext *ctx,
867 GLsizei width, GLsizei height, GLsizei depth,
868 GLenum format)
869 {
870 GLuint size;
871 int wScale, hScale;
872
873 ASSERT(depth == 1);
874
875 /* Determine width and height scale factors for texture.
876 * Remember, Glide is limited to 8:1 aspect ratios.
877 */
878 fxTexGetInfo(width, height,
879 NULL, /* lod level */
880 NULL, /* aspect ratio */
881 NULL, NULL, /* sscale, tscale */
882 &wScale, &hScale);
883
884 width *= wScale;
885 height *= hScale;
886
887 switch (format) {
888 case GL_COMPRESSED_RGB_FXT1_3DFX:
889 case GL_COMPRESSED_RGBA_FXT1_3DFX:
890 /* round up width to next multiple of 8, height to next multiple of 4 */
891 width = (width + 7) & ~7;
892 height = (height + 3) & ~3;
893 /* 16 bytes per 8x4 tile of RGB[A] texels */
894 size = width * height / 2;
895 /* Textures smaller than 8x4 will effectively be made into 8x4 and
896 * take 16 bytes.
897 */
898 if (size < 16)
899 size = 16;
900 return size;
901 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
902 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
903 case GL_RGB_S3TC:
904 case GL_RGB4_S3TC:
905 /* round up width, height to next multiple of 4 */
906 width = (width + 3) & ~3;
907 height = (height + 3) & ~3;
908 /* 8 bytes per 4x4 tile of RGB[A] texels */
909 size = width * height / 2;
910 /* Textures smaller than 4x4 will effectively be made into 4x4 and
911 * take 8 bytes.
912 */
913 if (size < 8)
914 size = 8;
915 return size;
916 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
917 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
918 case GL_RGBA_S3TC:
919 case GL_RGBA4_S3TC:
920 /* round up width, height to next multiple of 4 */
921 width = (width + 3) & ~3;
922 height = (height + 3) & ~3;
923 /* 16 bytes per 4x4 tile of RGBA texels */
924 size = width * height; /* simple! */
925 /* Textures smaller than 4x4 will effectively be made into 4x4 and
926 * take 16 bytes.
927 */
928 if (size < 16)
929 size = 16;
930 return size;
931 case GL_COMPRESSED_RGB:
932 #if FX_TC_NAPALM
933 {
934 fxMesaContext fxMesa = FX_CONTEXT(ctx);
935 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
936 return fxDDCompressedTextureSize(ctx, width, height, 1, GL_COMPRESSED_RGB_FXT1_3DFX);
937 }
938 }
939 #endif
940 #if FX_TC_NCC
941 return (width * height * 8 >> 3) + 12 * 4;
942 #endif
943 case GL_COMPRESSED_RGBA:
944 #if FX_TC_NAPALM
945 {
946 fxMesaContext fxMesa = FX_CONTEXT(ctx);
947 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
948 return fxDDCompressedTextureSize(ctx, width, height, 1, GL_COMPRESSED_RGBA_FXT1_3DFX);
949 }
950 }
951 #endif
952 #if FX_TC_NCC
953 return (width * height * 16 >> 3) + 12 * 4;
954 #endif
955 default:
956 _mesa_problem(ctx, "bad texformat in fxDDCompressedTextureSize");
957 return 0;
958 }
959 }
960
961
962 const struct gl_texture_format *
963 fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
964 GLenum srcFormat, GLenum srcType )
965 {
966 fxMesaContext fxMesa = FX_CONTEXT(ctx);
967 GLboolean allow32bpt = fxMesa->HaveTexFmt;
968
969 /* [dBorca] Hack alert:
970 * There is something wrong with this!!! Take an example:
971 * 1) start HW rendering
972 * 2) create a texture like this:
973 * glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
974 * GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
975 * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
976 * 3) we get here with internalFormat==3 and return either
977 * _mesa_texformat_rgb565 or _mesa_texformat_argb8888
978 * 4) at some point, we encounter total rasterization fallback
979 * 5) displaying a polygon with the above textures yield garbage on areas
980 * where pixel is larger than a texel, because our already set texel
981 * function doesn't match the real _mesa_texformat_argb888
982 */
983
984 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
985 fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
986 }
987
988 switch (internalFormat) {
989 case GL_COMPRESSED_RGB:
990 #if 0 && FX_TC_NAPALM /* [koolsmoky] */
991 if (ctx->Extensions.TDFX_texture_compression_FXT1) {
992 return &_mesa_texformat_rgb_fxt1;
993 } else if (ctx->Extensions.EXT_texture_compression_s3tc) {
994 return &_mesa_texformat_rgb_dxt1;
995 }
996 #endif
997 /* intentional fall through */
998 case 3:
999 case GL_RGB:
1000 if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
1001 return &_mesa_texformat_rgb565;
1002 }
1003 /* intentional fall through */
1004 case GL_RGB8:
1005 case GL_RGB10:
1006 case GL_RGB12:
1007 case GL_RGB16:
1008 return (allow32bpt) ? &_mesa_texformat_argb8888
1009 : &_mesa_texformat_rgb565;
1010 case GL_RGBA2:
1011 case GL_RGBA4:
1012 return &_mesa_texformat_argb4444;
1013 case GL_COMPRESSED_RGBA:
1014 #if 0 && FX_TC_NAPALM /* [koolsmoky] */
1015 if (ctx->Extensions.TDFX_texture_compression_FXT1) {
1016 return &_mesa_texformat_rgba_fxt1;
1017 } else if (ctx->Extensions.EXT_texture_compression_s3tc) {
1018 return &_mesa_texformat_rgba_dxt3;
1019 }
1020 #endif
1021 /* intentional fall through */
1022 case 4:
1023 case GL_RGBA:
1024 if ( srcFormat == GL_BGRA ) {
1025 if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
1026 return &_mesa_texformat_argb8888;
1027 }
1028 else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
1029 return &_mesa_texformat_argb4444;
1030 }
1031 else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
1032 return &_mesa_texformat_argb1555;
1033 }
1034 }
1035 /* intentional fall through */
1036 case GL_RGBA8:
1037 case GL_RGB10_A2:
1038 case GL_RGBA12:
1039 case GL_RGBA16:
1040 return (allow32bpt) ? &_mesa_texformat_argb8888
1041 : &_mesa_texformat_argb4444;
1042 case GL_INTENSITY:
1043 case GL_INTENSITY4:
1044 case GL_INTENSITY8:
1045 case GL_INTENSITY12:
1046 case GL_INTENSITY16:
1047 case GL_COMPRESSED_INTENSITY:
1048 return &_mesa_texformat_i8;
1049 case 1:
1050 case GL_LUMINANCE:
1051 case GL_LUMINANCE4:
1052 case GL_LUMINANCE8:
1053 case GL_LUMINANCE12:
1054 case GL_LUMINANCE16:
1055 case GL_COMPRESSED_LUMINANCE:
1056 return &_mesa_texformat_l8;
1057 case GL_ALPHA:
1058 case GL_ALPHA4:
1059 case GL_ALPHA8:
1060 case GL_ALPHA12:
1061 case GL_ALPHA16:
1062 case GL_COMPRESSED_ALPHA:
1063 return &_mesa_texformat_a8;
1064 case GL_COLOR_INDEX:
1065 case GL_COLOR_INDEX1_EXT:
1066 case GL_COLOR_INDEX2_EXT:
1067 case GL_COLOR_INDEX4_EXT:
1068 case GL_COLOR_INDEX8_EXT:
1069 case GL_COLOR_INDEX12_EXT:
1070 case GL_COLOR_INDEX16_EXT:
1071 return &_mesa_texformat_ci8;
1072 case 2:
1073 case GL_LUMINANCE_ALPHA:
1074 case GL_LUMINANCE4_ALPHA4:
1075 case GL_LUMINANCE6_ALPHA2:
1076 case GL_LUMINANCE8_ALPHA8:
1077 case GL_LUMINANCE12_ALPHA4:
1078 case GL_LUMINANCE12_ALPHA12:
1079 case GL_LUMINANCE16_ALPHA16:
1080 case GL_COMPRESSED_LUMINANCE_ALPHA:
1081 return &_mesa_texformat_al88;
1082 case GL_R3_G3_B2:
1083 case GL_RGB4:
1084 case GL_RGB5:
1085 return &_mesa_texformat_rgb565;
1086 case GL_RGB5_A1:
1087 return &_mesa_texformat_argb1555;
1088 /* GL_EXT_texture_compression_s3tc */
1089 /* GL_S3_s3tc */
1090 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1091 case GL_RGB_S3TC:
1092 case GL_RGB4_S3TC:
1093 return &_mesa_texformat_rgb_dxt1;
1094 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1095 return &_mesa_texformat_rgba_dxt1;
1096 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1097 case GL_RGBA_S3TC:
1098 case GL_RGBA4_S3TC:
1099 return &_mesa_texformat_rgba_dxt3;
1100 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1101 return &_mesa_texformat_rgba_dxt5;
1102 /* GL_3DFX_texture_compression_FXT1 */
1103 case GL_COMPRESSED_RGB_FXT1_3DFX:
1104 return &_mesa_texformat_rgb_fxt1;
1105 case GL_COMPRESSED_RGBA_FXT1_3DFX:
1106 return &_mesa_texformat_rgba_fxt1;
1107 default:
1108 _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
1109 return NULL;
1110 }
1111 }
1112
1113
1114 static GrTextureFormat_t
1115 fxGlideFormat(GLint mesaFormat)
1116 {
1117 switch (mesaFormat) {
1118 case MESA_FORMAT_I8:
1119 return GR_TEXFMT_ALPHA_8;
1120 case MESA_FORMAT_A8:
1121 return GR_TEXFMT_ALPHA_8;
1122 case MESA_FORMAT_L8:
1123 return GR_TEXFMT_INTENSITY_8;
1124 case MESA_FORMAT_CI8:
1125 return GR_TEXFMT_P_8;
1126 case MESA_FORMAT_AL88:
1127 return GR_TEXFMT_ALPHA_INTENSITY_88;
1128 case MESA_FORMAT_RGB565:
1129 return GR_TEXFMT_RGB_565;
1130 case MESA_FORMAT_ARGB4444:
1131 return GR_TEXFMT_ARGB_4444;
1132 case MESA_FORMAT_ARGB1555:
1133 return GR_TEXFMT_ARGB_1555;
1134 case MESA_FORMAT_ARGB8888:
1135 return GR_TEXFMT_ARGB_8888;
1136 case MESA_FORMAT_RGB_FXT1:
1137 case MESA_FORMAT_RGBA_FXT1:
1138 return GR_TEXFMT_ARGB_CMP_FXT1;
1139 case MESA_FORMAT_RGB_DXT1:
1140 case MESA_FORMAT_RGBA_DXT1:
1141 return GR_TEXFMT_ARGB_CMP_DXT1;
1142 case MESA_FORMAT_RGBA_DXT3:
1143 return GR_TEXFMT_ARGB_CMP_DXT3;
1144 case MESA_FORMAT_RGBA_DXT5:
1145 return GR_TEXFMT_ARGB_CMP_DXT5;
1146 default:
1147 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
1148 return 0;
1149 }
1150 }
1151
1152
1153 static FetchTexelFunc
1154 fxFetchFunction(GLint mesaFormat)
1155 {
1156 switch (mesaFormat) {
1157 case MESA_FORMAT_I8:
1158 return &fetch_intensity8;
1159 case MESA_FORMAT_A8:
1160 return &fetch_alpha8;
1161 case MESA_FORMAT_L8:
1162 return &fetch_luminance8;
1163 case MESA_FORMAT_CI8:
1164 return &fetch_index8;
1165 case MESA_FORMAT_AL88:
1166 return &fetch_luminance8_alpha8;
1167 case MESA_FORMAT_RGB565:
1168 return &fetch_r5g6b5;
1169 case MESA_FORMAT_ARGB4444:
1170 return &fetch_r4g4b4a4;
1171 case MESA_FORMAT_ARGB1555:
1172 return &fetch_r5g5b5a1;
1173 case MESA_FORMAT_ARGB8888:
1174 return &fetch_a8r8g8b8;
1175 case MESA_FORMAT_RGB_FXT1:
1176 case MESA_FORMAT_RGBA_FXT1:
1177 case MESA_FORMAT_RGB_DXT1:
1178 case MESA_FORMAT_RGBA_DXT1:
1179 case MESA_FORMAT_RGBA_DXT3:
1180 case MESA_FORMAT_RGBA_DXT5:
1181 return &fetch_r4g4b4a4;
1182 default:
1183 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1184 return NULL;
1185 }
1186 }
1187
1188 void
1189 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1190 GLint internalFormat, GLint width, GLint height, GLint border,
1191 GLenum format, GLenum type, const GLvoid * pixels,
1192 const struct gl_pixelstore_attrib *packing,
1193 struct gl_texture_object *texObj,
1194 struct gl_texture_image *texImage)
1195 {
1196 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1197 tfxTexInfo *ti;
1198 tfxMipMapLevel *mml;
1199 GLint texelBytes;
1200
1201 GLvoid *_final_texImage_Data;
1202 const struct gl_texture_format *_final_texImage_TexFormat;
1203
1204 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1205 fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1206 texObj->Name, texImage->IntFormat, format, type,
1207 texImage->Width, texImage->Height);
1208 }
1209
1210 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1211 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1212 return;
1213 }
1214
1215 if (!texObj->DriverData) {
1216 texObj->DriverData = fxAllocTexObjData(fxMesa);
1217 if (!texObj->DriverData) {
1218 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1219 return;
1220 }
1221 }
1222 ti = fxTMGetTexInfo(texObj);
1223
1224 if (!texImage->DriverData) {
1225 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1226 if (!texImage->DriverData) {
1227 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1228 return;
1229 }
1230 }
1231 mml = FX_MIPMAP_DATA(texImage);
1232
1233 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1234 &mml->wScale, &mml->hScale);
1235
1236 mml->width = width * mml->wScale;
1237 mml->height = height * mml->hScale;
1238
1239 #if 0 && FX_COMPRESS_S3TC_AS_FXT1_HACK
1240 /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
1241 /* [dBorca] we should update texture's attribute, then,
1242 * because if the application asks us to decompress, we
1243 * have to know the REAL format! Also, DXT3/5 might not
1244 * be correct, since it would mess with "compressedSize".
1245 * Ditto for GL_RGBA[4]_S3TC, which is always mapped to DXT3.
1246 */
1247 if (texImage->IsCompressed) {
1248 switch (internalFormat) {
1249 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1250 case GL_RGB_S3TC:
1251 case GL_RGB4_S3TC:
1252 internalFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
1253 break;
1254 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1255 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1256 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1257 case GL_RGBA_S3TC:
1258 case GL_RGBA4_S3TC:
1259 internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
1260 }
1261 }
1262 #endif
1263 #if 1 || FX_COMPRESS_DXT5_AS_DXT3_HACK
1264 /* [dBorca] either VSA is stupid at DXT5,
1265 * or our compression tool is broken. See
1266 * above for caveats.
1267 */
1268 if ((texImage->IsCompressed) &&
1269 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) {
1270 internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
1271 }
1272 #endif
1273
1274 /* choose the texture format */
1275 assert(ctx->Driver.ChooseTextureFormat);
1276 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1277 internalFormat, format, type);
1278 assert(texImage->TexFormat);
1279 texelBytes = texImage->TexFormat->TexelBytes;
1280 /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
1281
1282 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1283 /* dirty trick: will thrash CopyTex[Sub]Image */
1284 #if FX_TC_NCC || FX_TC_NAPALM
1285 if (internalFormat == GL_COMPRESSED_RGB) {
1286 #if FX_TC_NCC
1287 mml->glideFormat = GR_TEXFMT_YIQ_422;
1288 #endif
1289 #if FX_TC_NAPALM
1290 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1291 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1292 }
1293 #endif
1294 } else if (internalFormat == GL_COMPRESSED_RGBA) {
1295 #if FX_TC_NCC
1296 mml->glideFormat = GR_TEXFMT_AYIQ_8422;
1297 #endif
1298 #if FX_TC_NAPALM
1299 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1300 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1301 }
1302 #endif
1303 }
1304 #endif
1305
1306 /* allocate mipmap buffer */
1307 assert(!texImage->Data);
1308 if (texImage->IsCompressed) {
1309 texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
1310 texelBytes = 4;
1311 _final_texImage_TexFormat = &_mesa_texformat_argb8888;
1312 _final_texImage_Data = MALLOC(mml->width * mml->height * 4);
1313 if (!_final_texImage_Data) {
1314 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1315 return;
1316 }
1317 } else {
1318 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1319 _final_texImage_TexFormat = texImage->TexFormat;
1320 _final_texImage_Data = texImage->Data;
1321 }
1322 if (!texImage->Data) {
1323 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1324 return;
1325 }
1326
1327 if (mml->wScale != 1 || mml->hScale != 1) {
1328 /* rescale image to overcome 1:8 aspect limitation */
1329 GLvoid *tempImage;
1330 tempImage = MALLOC(width * height * texelBytes);
1331 if (!tempImage) {
1332 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1333 return;
1334 }
1335 /* unpack image, apply transfer ops and store in tempImage */
1336 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1337 _final_texImage_TexFormat,
1338 tempImage,
1339 width, height, 1, 0, 0, 0, /* src */
1340 width * texelBytes, /* dstRowStride */
1341 0, /* dstImageStride */
1342 format, type, pixels, packing);
1343 _mesa_rescale_teximage2d(texelBytes,
1344 mml->width * texelBytes, /* dst stride */
1345 width, height, /* src */
1346 mml->width, mml->height, /* dst */
1347 tempImage /*src*/, _final_texImage_Data /*dst*/ );
1348 FREE(tempImage);
1349 }
1350 else {
1351 /* no rescaling needed */
1352 /* unpack image, apply transfer ops and store in texImage->Data */
1353 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1354 _final_texImage_TexFormat, _final_texImage_Data,
1355 width, height, 1, 0, 0, 0,
1356 mml->width * texelBytes,
1357 0, /* dstImageStride */
1358 format, type, pixels, packing);
1359 }
1360
1361 /* now compress */
1362 if (texImage->IsCompressed) {
1363 #if FX_TC_NCC
1364 if ((mml->glideFormat == GR_TEXFMT_AYIQ_8422) ||
1365 (mml->glideFormat == GR_TEXFMT_YIQ_422)) {
1366 TxMip txMip, pxMip;
1367 txMip.width = mml->width;
1368 txMip.height = mml->height;
1369 txMip.depth = 1;
1370 txMip.data[0] = _final_texImage_Data;
1371 pxMip.data[0] = texImage->Data;
1372 fxMesa->Glide.txMipQuantize(&pxMip, &txMip, mml->glideFormat, TX_DITHER_ERR, TX_COMPRESSION_STATISTICAL);
1373 fxMesa->Glide.txPalToNcc((GuNccTable *)(&(ti->palette)), pxMip.pal);
1374 MEMCPY((char *)texImage->Data + texImage->CompressedSize - 12 * 4, &(ti->palette.data[16]), 12 * 4);
1375 } else
1376 #endif
1377 fxMesa->Glide.txImgQuantize(texImage->Data, _final_texImage_Data, mml->width, mml->height, mml->glideFormat, TX_DITHER_NONE);
1378 FREE(_final_texImage_Data);
1379 }
1380
1381 ti->info.format = mml->glideFormat;
1382 texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
1383
1384 /* [dBorca]
1385 * Hack alert: unsure...
1386 */
1387 if (0 && ti->validated && ti->isInTM) {
1388 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1389 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1390 }
1391 else {
1392 /*fprintf(stderr, "invalidate2\n"); */
1393 fxTexInvalidate(ctx, texObj);
1394 }
1395 }
1396
1397
1398 void
1399 fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1400 GLint xoffset, GLint yoffset,
1401 GLsizei width, GLsizei height,
1402 GLenum format, GLenum type, const GLvoid * pixels,
1403 const struct gl_pixelstore_attrib *packing,
1404 struct gl_texture_object *texObj,
1405 struct gl_texture_image *texImage)
1406 {
1407 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1408 tfxTexInfo *ti;
1409 tfxMipMapLevel *mml;
1410 GLint texelBytes;
1411
1412 /* [dBorca] Hack alert:
1413 * fix the goddamn texture compression here
1414 */
1415
1416 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1417 fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
1418 }
1419
1420 if (!texObj->DriverData) {
1421 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1422 return;
1423 }
1424
1425 ti = fxTMGetTexInfo(texObj);
1426 assert(ti);
1427 mml = FX_MIPMAP_DATA(texImage);
1428 assert(mml);
1429
1430 assert(texImage->Data); /* must have an existing texture image! */
1431 assert(texImage->Format);
1432
1433 texelBytes = texImage->TexFormat->TexelBytes;
1434
1435 if (mml->wScale != 1 || mml->hScale != 1) {
1436 /* need to rescale subimage to match mipmap level's rescale factors */
1437 const GLint newWidth = width * mml->wScale;
1438 const GLint newHeight = height * mml->hScale;
1439 GLvoid *tempImage;
1440 GLubyte *destAddr;
1441 tempImage = MALLOC(width * height * texelBytes);
1442 if (!tempImage) {
1443 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1444 return;
1445 }
1446
1447 _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */
1448 texImage->TexFormat, /* dest format */
1449 (GLubyte *) tempImage, /* dest */
1450 width, height, 1, /* subimage size */
1451 0, 0, 0, /* subimage pos */
1452 width * texelBytes, /* dest row stride */
1453 0, /* dst image stride */
1454 format, type, pixels, packing);
1455
1456 /* now rescale */
1457 /* compute address of dest subimage within the overal tex image */
1458 destAddr = (GLubyte *) texImage->Data
1459 + (yoffset * mml->hScale * mml->width
1460 + xoffset * mml->wScale) * texelBytes;
1461
1462 _mesa_rescale_teximage2d(texelBytes,
1463 mml->width * texelBytes, /* dst stride */
1464 width, height,
1465 newWidth, newHeight,
1466 tempImage, destAddr);
1467
1468 FREE(tempImage);
1469 }
1470 else {
1471 /* no rescaling needed */
1472 _mesa_transfer_teximage(ctx, 2, texImage->Format, /* Tex int format */
1473 texImage->TexFormat, /* dest format */
1474 (GLubyte *) texImage->Data,/* dest */
1475 width, height, 1, /* subimage size */
1476 xoffset, yoffset, 0, /* subimage pos */
1477 mml->width * texelBytes, /* dest row stride */
1478 0, /* dst image stride */
1479 format, type, pixels, packing);
1480 }
1481
1482 /* [dBorca]
1483 * Hack alert: unsure...
1484 */
1485 if (0 && ti->validated && ti->isInTM)
1486 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1487 else
1488 fxTexInvalidate(ctx, texObj);
1489 }
1490
1491
1492 void
1493 fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
1494 GLint level, GLint internalFormat,
1495 GLsizei width, GLsizei height, GLint border,
1496 GLsizei imageSize, const GLvoid *data,
1497 struct gl_texture_object *texObj,
1498 struct gl_texture_image *texImage)
1499 {
1500 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1501 tfxTexInfo *ti;
1502 tfxMipMapLevel *mml;
1503
1504 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1505 fprintf(stderr, "fxDDCompressedTexImage2D: id=%d int 0x%x %dx%d\n",
1506 texObj->Name, internalFormat,
1507 width, height);
1508 }
1509
1510 assert(texImage->IsCompressed);
1511
1512 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1513 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDCompressedTexImg()\n");
1514 return;
1515 }
1516
1517 if (!texObj->DriverData) {
1518 texObj->DriverData = fxAllocTexObjData(fxMesa);
1519 if (!texObj->DriverData) {
1520 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1521 return;
1522 }
1523 }
1524 ti = fxTMGetTexInfo(texObj);
1525
1526 if (!texImage->DriverData) {
1527 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1528 if (!texImage->DriverData) {
1529 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1530 return;
1531 }
1532 }
1533 mml = FX_MIPMAP_DATA(texImage);
1534
1535 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1536 &mml->wScale, &mml->hScale);
1537
1538 mml->width = width * mml->wScale;
1539 mml->height = height * mml->hScale;
1540
1541
1542 /* choose the texture format */
1543 assert(ctx->Driver.ChooseTextureFormat);
1544 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1545 internalFormat, -1/*format*/, -1/*type*/);
1546 assert(texImage->TexFormat);
1547
1548 /* Determine the appropriate Glide texel format,
1549 * given the user's internal texture format hint.
1550 */
1551 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1552 #if FX_TC_NCC || FX_TC_NAPALM
1553 if (internalFormat == GL_COMPRESSED_RGB) {
1554 #if FX_TC_NCC
1555 mml->glideFormat = GR_TEXFMT_YIQ_422;
1556 #endif
1557 #if FX_TC_NAPALM
1558 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1559 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1560 }
1561 #endif
1562 } else if (internalFormat == GL_COMPRESSED_RGBA) {
1563 #if FX_TC_NCC
1564 mml->glideFormat = GR_TEXFMT_AYIQ_8422;
1565 #endif
1566 #if FX_TC_NAPALM
1567 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1568 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1569 }
1570 #endif
1571 }
1572 #endif
1573
1574 /* allocate new storage for texture image, if needed */
1575 if (!texImage->Data) {
1576 texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
1577 if (!texImage->Data) {
1578 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1579 return;
1580 }
1581 }
1582
1583 /* save the texture data */
1584 MEMCPY(texImage->Data, data, imageSize);
1585 #if FX_TC_NCC
1586 if ((mml->glideFormat == GR_TEXFMT_AYIQ_8422) ||
1587 (mml->glideFormat == GR_TEXFMT_YIQ_422)) {
1588 MEMCPY(&(ti->palette.data[16]), (char *)data + imageSize - 12 * 4, 12 * 4);
1589 }
1590 #endif
1591
1592 ti->info.format = mml->glideFormat;
1593 texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
1594
1595 /* [dBorca] Hack alert:
1596 * what about different size/texel? other anomalies? SW rescaling?
1597 */
1598
1599 /* [dBorca]
1600 * Hack alert: unsure...
1601 */
1602 if (0 && ti->validated && ti->isInTM) {
1603 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1604 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1605 }
1606 else {
1607 /*fprintf(stderr, "invalidate2\n"); */
1608 fxTexInvalidate(ctx, texObj);
1609 }
1610 }
1611
1612
1613 void
1614 fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
1615 GLint level, GLint xoffset,
1616 GLint yoffset, GLsizei width,
1617 GLint height, GLenum format,
1618 GLsizei imageSize, const GLvoid *data,
1619 struct gl_texture_object *texObj,
1620 struct gl_texture_image *texImage )
1621 {
1622 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1623 tfxTexInfo *ti;
1624 tfxMipMapLevel *mml;
1625
1626 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1627 fprintf(stderr, "fxDDCompressedTexSubImage2D: id=%d\n", texObj->Name);
1628 }
1629
1630 ti = fxTMGetTexInfo(texObj);
1631 assert(ti);
1632 mml = FX_MIPMAP_DATA(texImage);
1633 assert(mml);
1634
1635 /*
1636 * We punt if we are not replacing the entire image. This
1637 * is allowed by the spec.
1638 *
1639 * [dBorca] Hack alert:
1640 * ohwell, we should NOT! Look into _mesa_store_compressed_texsubimage2d
1641 * on how to calculate the sub-image.
1642 */
1643 if ((xoffset != 0) && (yoffset != 0)
1644 && (width != texImage->Width)
1645 && (height != texImage->Height)) {
1646 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(CHICKEN)");
1647 return;
1648 }
1649
1650 /* [dBorca] Hack alert:
1651 * what about different size/texel? other anomalies? SW rescaling?
1652 */
1653 MEMCPY(texImage->Data, data, imageSize);
1654
1655 /* [dBorca]
1656 * Hack alert: unsure...
1657 */
1658 if (0 && ti->validated && ti->isInTM)
1659 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1660 else
1661 fxTexInvalidate(ctx, texObj);
1662 }
1663
1664
1665 #else /* FX */
1666
1667 /*
1668 * Need this to provide at least one external definition.
1669 */
1670
1671 extern int gl_fx_dummy_function_ddtex(void);
1672 int
1673 gl_fx_dummy_function_ddtex(void)
1674 {
1675 return 0;
1676 }
1677
1678 #endif /* FX */