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