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