replace color table FloatTable boolean with Type enum
[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[0][ti->tObj->BaseLevel]->Width,
60 ti->tObj->Image[0][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_1D) && (target != GL_TEXTURE_2D))
145 return;
146
147 if (!tObj->DriverData) {
148 tObj->DriverData = fxAllocTexObjData(fxMesa);
149 }
150 ti = fxTMGetTexInfo(tObj);
151
152 fxMesa->texBindNumber++;
153 ti->lastTimeUsed = fxMesa->texBindNumber;
154
155 fxMesa->new_state |= FX_NEW_TEXTURING;
156 }
157
158 void
159 fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
160 const GLfloat * param)
161 {
162 fxMesaContext fxMesa = FX_CONTEXT(ctx);
163
164 if (TDFX_DEBUG & VERBOSE_DRIVER) {
165 if (param)
166 fprintf(stderr, "fxDDTexEnv(%x, %x)\n", pname, (GLint) (*param));
167 else
168 fprintf(stderr, "fxDDTexEnv(%x)\n", pname);
169 }
170
171 /* apply any lod biasing right now */
172 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
173 grTexLodBiasValue(GR_TMU0, *param);
174
175 if (fxMesa->haveTwoTMUs) {
176 grTexLodBiasValue(GR_TMU1, *param);
177 }
178
179 }
180
181 fxMesa->new_state |= FX_NEW_TEXTURING;
182 }
183
184 void
185 fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
186 GLenum pname, const GLfloat * params)
187 {
188 fxMesaContext fxMesa = FX_CONTEXT(ctx);
189 GLenum param = (GLenum) (GLint) params[0];
190 tfxTexInfo *ti;
191
192 if (TDFX_DEBUG & VERBOSE_DRIVER) {
193 fprintf(stderr, "fxDDTexParam(%d, %x, %s, %s)\n",
194 tObj->Name, (GLuint) tObj->DriverData,
195 _mesa_lookup_enum_by_nr(pname),
196 _mesa_lookup_enum_by_nr(param));
197 }
198
199 if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
200 return;
201
202 if (!tObj->DriverData)
203 tObj->DriverData = fxAllocTexObjData(fxMesa);
204 ti = fxTMGetTexInfo(tObj);
205
206 switch (pname) {
207 case GL_TEXTURE_MIN_FILTER:
208 switch (param) {
209 case GL_NEAREST:
210 ti->mmMode = GR_MIPMAP_DISABLE;
211 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
212 ti->LODblend = FXFALSE;
213 break;
214 case GL_LINEAR:
215 ti->mmMode = GR_MIPMAP_DISABLE;
216 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
217 ti->LODblend = FXFALSE;
218 break;
219 case GL_NEAREST_MIPMAP_LINEAR:
220 /* [koolsmoky]
221 * trilinear is bugged! mipmap blending produce
222 * incorrect filtered colors for the smallest mipmap levels.
223 * [dBorca]
224 * currently Napalm can't do single-pass trilinear,
225 * because the way its combiners are set. So we fall back
226 * to GL_NEAREST_MIPMAP_NEAREST. We'll let true trilinear
227 * enabled for V2, V3. If user shoots foot, not our problem!
228 */
229 if (!fxMesa->HaveCmbExt) {
230 if (fxMesa->haveTwoTMUs) {
231 ti->mmMode = GR_MIPMAP_NEAREST;
232 ti->LODblend = FXTRUE;
233 } else {
234 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
235 ti->LODblend = FXFALSE;
236 }
237 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
238 break;
239 }
240 case GL_NEAREST_MIPMAP_NEAREST:
241 ti->mmMode = GR_MIPMAP_NEAREST;
242 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
243 ti->LODblend = FXFALSE;
244 break;
245 case GL_LINEAR_MIPMAP_LINEAR:
246 /* [koolsmoky]
247 * trilinear is bugged! mipmap blending produce
248 * incorrect filtered colors for the smallest mipmap levels.
249 * [dBorca]
250 * currently Napalm can't do single-pass trilinear,
251 * because the way its combiners are set. So we fall back
252 * to GL_LINEAR_MIPMAP_NEAREST. We'll let true trilinear
253 * enabled for V2, V3. If user shoots foot, not our problem!
254 */
255 if (!fxMesa->HaveCmbExt) {
256 if (fxMesa->haveTwoTMUs) {
257 ti->mmMode = GR_MIPMAP_NEAREST;
258 ti->LODblend = FXTRUE;
259 } else {
260 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
261 ti->LODblend = FXFALSE;
262 }
263 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
264 break;
265 }
266 case GL_LINEAR_MIPMAP_NEAREST:
267 ti->mmMode = GR_MIPMAP_NEAREST;
268 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
269 ti->LODblend = FXFALSE;
270 break;
271 default:
272 break;
273 }
274 fxTexInvalidate(ctx, tObj);
275 break;
276
277 case GL_TEXTURE_MAG_FILTER:
278 switch (param) {
279 case GL_NEAREST:
280 ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
281 break;
282 case GL_LINEAR:
283 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
284 break;
285 default:
286 break;
287 }
288 fxMesa->new_state |= FX_NEW_TEXTURING;
289 break;
290
291 case GL_TEXTURE_WRAP_S:
292 switch (param) {
293 case GL_MIRRORED_REPEAT:
294 ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
295 break;
296 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
297 case GL_CLAMP:
298 ti->sClamp = GR_TEXTURECLAMP_CLAMP;
299 break;
300 case GL_REPEAT:
301 ti->sClamp = GR_TEXTURECLAMP_WRAP;
302 break;
303 default:
304 break;
305 }
306 fxMesa->new_state |= FX_NEW_TEXTURING;
307 break;
308
309 case GL_TEXTURE_WRAP_T:
310 switch (param) {
311 case GL_MIRRORED_REPEAT:
312 ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
313 break;
314 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
315 case GL_CLAMP:
316 ti->tClamp = GR_TEXTURECLAMP_CLAMP;
317 break;
318 case GL_REPEAT:
319 ti->tClamp = GR_TEXTURECLAMP_WRAP;
320 break;
321 default:
322 break;
323 }
324 fxMesa->new_state |= FX_NEW_TEXTURING;
325 break;
326
327 case GL_TEXTURE_BORDER_COLOR:
328 /* TO DO */
329 break;
330
331 case GL_TEXTURE_MIN_LOD:
332 /* TO DO */
333 break;
334 case GL_TEXTURE_MAX_LOD:
335 /* TO DO */
336 break;
337 case GL_TEXTURE_BASE_LEVEL:
338 fxTexInvalidate(ctx, tObj);
339 break;
340 case GL_TEXTURE_MAX_LEVEL:
341 fxTexInvalidate(ctx, tObj);
342 break;
343
344 default:
345 break;
346 }
347 }
348
349 void
350 fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
351 {
352 fxMesaContext fxMesa = FX_CONTEXT(ctx);
353 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
354
355 if (TDFX_DEBUG & VERBOSE_DRIVER) {
356 fprintf(stderr, "fxDDTexDel(%d, %p)\n", tObj->Name, (void *) ti);
357 }
358
359 if (!ti)
360 return;
361
362 fxTMFreeTexture(fxMesa, tObj);
363
364 FREE(ti);
365 tObj->DriverData = NULL;
366
367 /* Free mipmap images and the texture object itself */
368 _mesa_delete_texture_object(ctx, tObj);
369 }
370
371
372 /**
373 * Allocate a new texture object.
374 * Called via ctx->Driver.NewTextureObject.
375 * Note: this function will be called during context creation to
376 * allocate the default texture objects.
377 */
378 struct gl_texture_object *
379 fxDDNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
380 {
381 struct gl_texture_object *obj;
382 obj = _mesa_new_texture_object(ctx, name, target);
383 return obj;
384 }
385
386
387 /*
388 * Return true if texture is resident, false otherwise.
389 */
390 GLboolean
391 fxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
392 {
393 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
394 return (ti && ti->isInTM);
395 }
396
397
398
399 /*
400 * Convert a gl_color_table texture palette to Glide's format.
401 */
402 static GrTexTable_t
403 convertPalette(const fxMesaContext fxMesa, FxU32 data[256], const struct gl_color_table *table)
404 {
405 const GLubyte *tableUB = (const GLubyte *) table->Table;
406 GLint width = table->Size;
407 FxU32 r, g, b, a;
408 GLint i;
409
410 ASSERT(table->Type == GL_UNSIGNED_BYTE);
411
412 switch (table->Format) {
413 case GL_INTENSITY:
414 for (i = 0; i < width; i++) {
415 r = tableUB[i];
416 g = tableUB[i];
417 b = tableUB[i];
418 a = tableUB[i];
419 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
420 }
421 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
422 case GL_LUMINANCE:
423 for (i = 0; i < width; i++) {
424 r = tableUB[i];
425 g = tableUB[i];
426 b = tableUB[i];
427 a = 255;
428 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
429 }
430 return GR_TEXTABLE_PALETTE;
431 case GL_ALPHA:
432 for (i = 0; i < width; i++) {
433 r = g = b = 255;
434 a = tableUB[i];
435 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
436 }
437 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
438 case GL_LUMINANCE_ALPHA:
439 for (i = 0; i < width; i++) {
440 r = g = b = tableUB[i * 2 + 0];
441 a = tableUB[i * 2 + 1];
442 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
443 }
444 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
445 default:
446 case GL_RGB:
447 for (i = 0; i < width; i++) {
448 r = tableUB[i * 3 + 0];
449 g = tableUB[i * 3 + 1];
450 b = tableUB[i * 3 + 2];
451 a = 255;
452 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
453 }
454 return GR_TEXTABLE_PALETTE;
455 case GL_RGBA:
456 for (i = 0; i < width; i++) {
457 r = tableUB[i * 4 + 0];
458 g = tableUB[i * 4 + 1];
459 b = tableUB[i * 4 + 2];
460 a = tableUB[i * 4 + 3];
461 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
462 }
463 return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
464 }
465 }
466
467
468 void
469 fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
470 {
471 fxMesaContext fxMesa = FX_CONTEXT(ctx);
472
473 if (tObj) {
474 /* per-texture palette */
475 tfxTexInfo *ti;
476 if (TDFX_DEBUG & VERBOSE_DRIVER) {
477 fprintf(stderr, "fxDDTexPalette(%d, %x)\n",
478 tObj->Name, (GLuint) tObj->DriverData);
479 }
480 /* This might be a proxy texture. */
481 if (!tObj->Palette.Table)
482 return;
483 if (!tObj->DriverData)
484 tObj->DriverData = fxAllocTexObjData(fxMesa);
485 ti = fxTMGetTexInfo(tObj);
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 /* [dBorca] tis beyond my comprehension */
518 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
519 (ctx->Texture.Unit[0]._Current != NULL)) {
520 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
521 if (!tObj->DriverData)
522 tObj->DriverData = fxAllocTexObjData(fxMesa);
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_1D) && (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, GLchan *rgba)
674 {
675 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
676 const GLubyte *texel;
677
678 i = i * mml->wScale;
679 j = j * mml->hScale;
680
681 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
682 rgba[RCOMP] = *texel;
683 rgba[GCOMP] = *texel;
684 rgba[BCOMP] = *texel;
685 rgba[ACOMP] = *texel;
686 }
687
688
689 static void
690 fetch_luminance8(const struct gl_texture_image *texImage,
691 GLint i, GLint j, GLint k, GLchan *rgba)
692 {
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, GLchan *rgba)
710 {
711 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
712 const GLubyte *texel;
713
714 i = i * mml->wScale;
715 j = j * mml->hScale;
716
717 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
718 rgba[RCOMP] = 255;
719 rgba[GCOMP] = 255;
720 rgba[BCOMP] = 255;
721 rgba[ACOMP] = *texel;
722 }
723
724
725 static void
726 fetch_index8(const struct gl_texture_image *texImage,
727 GLint i, GLint j, GLint k, GLchan *indexOut)
728 {
729 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
730 const GLubyte *texel;
731
732 i = i * mml->wScale;
733 j = j * mml->hScale;
734
735 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
736 *indexOut = *texel;
737 }
738
739
740 static void
741 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
742 GLint i, GLint j, GLint k, GLchan *rgba)
743 {
744 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
745 const GLubyte *texel;
746
747 i = i * mml->wScale;
748 j = j * mml->hScale;
749
750 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
751 rgba[RCOMP] = texel[0];
752 rgba[GCOMP] = texel[0];
753 rgba[BCOMP] = texel[0];
754 rgba[ACOMP] = texel[1];
755 }
756
757
758 static void
759 fetch_r5g6b5(const struct gl_texture_image *texImage,
760 GLint i, GLint j, GLint k, GLchan *rgba)
761 {
762 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
763 const GLushort *texel;
764
765 i = i * mml->wScale;
766 j = j * mml->hScale;
767
768 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
769 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
770 rgba[GCOMP] = FX_rgb_scale_6[(*texel >> 5) & 0x3F];
771 rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
772 rgba[ACOMP] = 255;
773 }
774
775
776 static void
777 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
778 GLint i, GLint j, GLint k, GLchan *rgba)
779 {
780 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
781 const GLushort *texel;
782
783 i = i * mml->wScale;
784 j = j * mml->hScale;
785
786 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
787 rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
788 rgba[GCOMP] = FX_rgb_scale_4[(*texel >> 8) & 0xF];
789 rgba[BCOMP] = FX_rgb_scale_4[(*texel >> 4) & 0xF];
790 rgba[ACOMP] = FX_rgb_scale_4[ *texel & 0xF];
791 }
792
793
794 static void
795 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
796 GLint i, GLint j, GLint k, GLchan *rgba)
797 {
798 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
799 const GLushort *texel;
800
801 i = i * mml->wScale;
802 j = j * mml->hScale;
803
804 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
805 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
806 rgba[GCOMP] = FX_rgb_scale_5[(*texel >> 6) & 0x1F];
807 rgba[BCOMP] = FX_rgb_scale_5[(*texel >> 1) & 0x1F];
808 rgba[ACOMP] = ((*texel) & 0x01) * 255;
809 }
810
811
812 static void
813 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
814 GLint i, GLint j, GLint k, GLchan *rgba)
815 {
816 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
817 const GLuint *texel;
818
819 i = i * mml->wScale;
820 j = j * mml->hScale;
821
822 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
823 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
824 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
825 rgba[BCOMP] = (((*texel) ) & 0xff);
826 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
827 }
828
829
830 static void
831 PrintTexture(int w, int h, int c, const GLubyte * data)
832 {
833 int i, j;
834 for (i = 0; i < h; i++) {
835 for (j = 0; j < w; j++) {
836 if (c == 2)
837 fprintf(stderr, "%02x %02x ", data[0], data[1]);
838 else if (c == 3)
839 fprintf(stderr, "%02x %02x %02x ", data[0], data[1], data[2]);
840 data += c;
841 }
842 fprintf(stderr, "\n");
843 }
844 }
845
846
847 GLboolean fxDDIsCompressedFormat ( GLcontext *ctx, GLenum internalFormat )
848 {
849 if ((internalFormat == GL_COMPRESSED_RGB_FXT1_3DFX) ||
850 (internalFormat == GL_COMPRESSED_RGBA_FXT1_3DFX) ||
851 (internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ||
852 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ||
853 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) ||
854 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) ||
855 (internalFormat == GL_RGB_S3TC) ||
856 (internalFormat == GL_RGB4_S3TC) ||
857 (internalFormat == GL_RGBA_S3TC) ||
858 (internalFormat == GL_RGBA4_S3TC)) {
859 return GL_TRUE;
860 }
861
862 /* [dBorca]
863 * we are handling differently the above formats from the generic
864 * GL_COMPRESSED_RGB[A]. For this, we will always have to separately
865 * check for the ones below!
866 */
867
868 #if FX_TC_NCC || FX_TC_NAPALM
869 if ((internalFormat == GL_COMPRESSED_RGB) || (internalFormat == GL_COMPRESSED_RGBA)) {
870 return GL_TRUE;
871 }
872 #endif
873
874 return GL_FALSE;
875 }
876
877
878 GLuint fxDDCompressedTextureSize (GLcontext *ctx,
879 GLsizei width, GLsizei height, GLsizei depth,
880 GLenum format)
881 {
882 GLuint size;
883 int wScale, hScale;
884
885 ASSERT(depth == 1);
886
887 /* Determine width and height scale factors for texture.
888 * Remember, Glide is limited to 8:1 aspect ratios.
889 */
890 fxTexGetInfo(width, height,
891 NULL, /* lod level */
892 NULL, /* aspect ratio */
893 NULL, NULL, /* sscale, tscale */
894 &wScale, &hScale);
895
896 width *= wScale;
897 height *= hScale;
898
899 switch (format) {
900 case GL_COMPRESSED_RGB_FXT1_3DFX:
901 case GL_COMPRESSED_RGBA_FXT1_3DFX:
902 /* round up width to next multiple of 8, height to next multiple of 4 */
903 width = (width + 7) & ~7;
904 height = (height + 3) & ~3;
905 /* 16 bytes per 8x4 tile of RGB[A] texels */
906 size = width * height / 2;
907 /* Textures smaller than 8x4 will effectively be made into 8x4 and
908 * take 16 bytes.
909 */
910 if (size < 16)
911 size = 16;
912 return size;
913 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
914 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
915 case GL_RGB_S3TC:
916 case GL_RGB4_S3TC:
917 /* round up width, height to next multiple of 4 */
918 width = (width + 3) & ~3;
919 height = (height + 3) & ~3;
920 /* 8 bytes per 4x4 tile of RGB[A] texels */
921 size = width * height / 2;
922 /* Textures smaller than 4x4 will effectively be made into 4x4 and
923 * take 8 bytes.
924 */
925 if (size < 8)
926 size = 8;
927 return size;
928 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
929 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
930 case GL_RGBA_S3TC:
931 case GL_RGBA4_S3TC:
932 /* round up width, height to next multiple of 4 */
933 width = (width + 3) & ~3;
934 height = (height + 3) & ~3;
935 /* 16 bytes per 4x4 tile of RGBA texels */
936 size = width * height; /* simple! */
937 /* Textures smaller than 4x4 will effectively be made into 4x4 and
938 * take 16 bytes.
939 */
940 if (size < 16)
941 size = 16;
942 return size;
943 case GL_COMPRESSED_RGB:
944 #if FX_TC_NAPALM
945 {
946 fxMesaContext fxMesa = FX_CONTEXT(ctx);
947 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
948 return fxDDCompressedTextureSize(ctx, width, height, 1, GL_COMPRESSED_RGB_FXT1_3DFX);
949 }
950 }
951 #endif
952 #if FX_TC_NCC
953 return (width * height * 8 >> 3) + 12 * 4;
954 #endif
955 case GL_COMPRESSED_RGBA:
956 #if FX_TC_NAPALM
957 {
958 fxMesaContext fxMesa = FX_CONTEXT(ctx);
959 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
960 return fxDDCompressedTextureSize(ctx, width, height, 1, GL_COMPRESSED_RGBA_FXT1_3DFX);
961 }
962 }
963 #endif
964 #if FX_TC_NCC
965 return (width * height * 16 >> 3) + 12 * 4;
966 #endif
967 default:
968 _mesa_problem(ctx, "bad texformat in fxDDCompressedTextureSize");
969 return 0;
970 }
971 }
972
973
974 const struct gl_texture_format *
975 fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
976 GLenum srcFormat, GLenum srcType )
977 {
978 fxMesaContext fxMesa = FX_CONTEXT(ctx);
979 GLboolean allow32bpt = fxMesa->HaveTexFmt;
980
981 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
982 fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
983 }
984
985 switch (internalFormat) {
986 case GL_COMPRESSED_RGB:
987 #if 0 && FX_TC_NAPALM /* [koolsmoky] */
988 if (ctx->Extensions.TDFX_texture_compression_FXT1) {
989 return &_mesa_texformat_rgb_fxt1;
990 } else if (ctx->Extensions.EXT_texture_compression_s3tc) {
991 return &_mesa_texformat_rgb_dxt1;
992 }
993 #endif
994 /* intentional fall through */
995 case 3:
996 case GL_RGB:
997 if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
998 return &_mesa_texformat_rgb565;
999 }
1000 /* intentional fall through */
1001 case GL_RGB8:
1002 case GL_RGB10:
1003 case GL_RGB12:
1004 case GL_RGB16:
1005 return (allow32bpt) ? &_mesa_texformat_argb8888
1006 : &_mesa_texformat_rgb565;
1007 case GL_RGBA2:
1008 case GL_RGBA4:
1009 return &_mesa_texformat_argb4444;
1010 case GL_COMPRESSED_RGBA:
1011 #if 0 && FX_TC_NAPALM /* [koolsmoky] */
1012 if (ctx->Extensions.TDFX_texture_compression_FXT1) {
1013 return &_mesa_texformat_rgba_fxt1;
1014 } else if (ctx->Extensions.EXT_texture_compression_s3tc) {
1015 return &_mesa_texformat_rgba_dxt3;
1016 }
1017 #endif
1018 /* intentional fall through */
1019 case 4:
1020 case GL_RGBA:
1021 if ( srcFormat == GL_BGRA ) {
1022 if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
1023 return &_mesa_texformat_argb8888;
1024 }
1025 else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
1026 return &_mesa_texformat_argb4444;
1027 }
1028 else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
1029 return &_mesa_texformat_argb1555;
1030 }
1031 }
1032 /* intentional fall through */
1033 case GL_RGBA8:
1034 case GL_RGB10_A2:
1035 case GL_RGBA12:
1036 case GL_RGBA16:
1037 return (allow32bpt) ? &_mesa_texformat_argb8888
1038 : &_mesa_texformat_argb4444;
1039 case GL_INTENSITY:
1040 case GL_INTENSITY4:
1041 case GL_INTENSITY8:
1042 case GL_INTENSITY12:
1043 case GL_INTENSITY16:
1044 case GL_COMPRESSED_INTENSITY:
1045 return &_mesa_texformat_i8;
1046 case 1:
1047 case GL_LUMINANCE:
1048 case GL_LUMINANCE4:
1049 case GL_LUMINANCE8:
1050 case GL_LUMINANCE12:
1051 case GL_LUMINANCE16:
1052 case GL_COMPRESSED_LUMINANCE:
1053 return &_mesa_texformat_l8;
1054 case GL_ALPHA:
1055 case GL_ALPHA4:
1056 case GL_ALPHA8:
1057 case GL_ALPHA12:
1058 case GL_ALPHA16:
1059 case GL_COMPRESSED_ALPHA:
1060 return &_mesa_texformat_a8;
1061 case GL_COLOR_INDEX:
1062 case GL_COLOR_INDEX1_EXT:
1063 case GL_COLOR_INDEX2_EXT:
1064 case GL_COLOR_INDEX4_EXT:
1065 case GL_COLOR_INDEX8_EXT:
1066 case GL_COLOR_INDEX12_EXT:
1067 case GL_COLOR_INDEX16_EXT:
1068 return &_mesa_texformat_ci8;
1069 case 2:
1070 case GL_LUMINANCE_ALPHA:
1071 case GL_LUMINANCE4_ALPHA4:
1072 case GL_LUMINANCE6_ALPHA2:
1073 case GL_LUMINANCE8_ALPHA8:
1074 case GL_LUMINANCE12_ALPHA4:
1075 case GL_LUMINANCE12_ALPHA12:
1076 case GL_LUMINANCE16_ALPHA16:
1077 case GL_COMPRESSED_LUMINANCE_ALPHA:
1078 return &_mesa_texformat_al88;
1079 case GL_R3_G3_B2:
1080 case GL_RGB4:
1081 case GL_RGB5:
1082 return &_mesa_texformat_rgb565;
1083 case GL_RGB5_A1:
1084 return &_mesa_texformat_argb1555;
1085 /* GL_EXT_texture_compression_s3tc */
1086 /* GL_S3_s3tc */
1087 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1088 case GL_RGB_S3TC:
1089 case GL_RGB4_S3TC:
1090 return &_mesa_texformat_rgb_dxt1;
1091 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1092 return &_mesa_texformat_rgba_dxt1;
1093 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1094 case GL_RGBA_S3TC:
1095 case GL_RGBA4_S3TC:
1096 return &_mesa_texformat_rgba_dxt3;
1097 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1098 return &_mesa_texformat_rgba_dxt5;
1099 /* GL_3DFX_texture_compression_FXT1 */
1100 case GL_COMPRESSED_RGB_FXT1_3DFX:
1101 return &_mesa_texformat_rgb_fxt1;
1102 case GL_COMPRESSED_RGBA_FXT1_3DFX:
1103 return &_mesa_texformat_rgba_fxt1;
1104 default:
1105 _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
1106 return NULL;
1107 }
1108 }
1109
1110
1111 static GrTextureFormat_t
1112 fxGlideFormat(GLint mesaFormat)
1113 {
1114 switch (mesaFormat) {
1115 case MESA_FORMAT_I8:
1116 return GR_TEXFMT_ALPHA_8;
1117 case MESA_FORMAT_A8:
1118 return GR_TEXFMT_ALPHA_8;
1119 case MESA_FORMAT_L8:
1120 return GR_TEXFMT_INTENSITY_8;
1121 case MESA_FORMAT_CI8:
1122 return GR_TEXFMT_P_8;
1123 case MESA_FORMAT_AL88:
1124 return GR_TEXFMT_ALPHA_INTENSITY_88;
1125 case MESA_FORMAT_RGB565:
1126 return GR_TEXFMT_RGB_565;
1127 case MESA_FORMAT_ARGB4444:
1128 return GR_TEXFMT_ARGB_4444;
1129 case MESA_FORMAT_ARGB1555:
1130 return GR_TEXFMT_ARGB_1555;
1131 case MESA_FORMAT_ARGB8888:
1132 return GR_TEXFMT_ARGB_8888;
1133 case MESA_FORMAT_RGB_FXT1:
1134 case MESA_FORMAT_RGBA_FXT1:
1135 return GR_TEXFMT_ARGB_CMP_FXT1;
1136 case MESA_FORMAT_RGB_DXT1:
1137 case MESA_FORMAT_RGBA_DXT1:
1138 return GR_TEXFMT_ARGB_CMP_DXT1;
1139 case MESA_FORMAT_RGBA_DXT3:
1140 return GR_TEXFMT_ARGB_CMP_DXT3;
1141 case MESA_FORMAT_RGBA_DXT5:
1142 return GR_TEXFMT_ARGB_CMP_DXT5;
1143 default:
1144 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
1145 return 0;
1146 }
1147 }
1148
1149
1150 static FetchTexelFuncC
1151 fxFetchFunction(GLint mesaFormat)
1152 {
1153 switch (mesaFormat) {
1154 case MESA_FORMAT_I8:
1155 return &fetch_intensity8;
1156 case MESA_FORMAT_A8:
1157 return &fetch_alpha8;
1158 case MESA_FORMAT_L8:
1159 return &fetch_luminance8;
1160 case MESA_FORMAT_CI8:
1161 return &fetch_index8;
1162 case MESA_FORMAT_AL88:
1163 return &fetch_luminance8_alpha8;
1164 case MESA_FORMAT_RGB565:
1165 return &fetch_r5g6b5;
1166 case MESA_FORMAT_ARGB4444:
1167 return &fetch_r4g4b4a4;
1168 case MESA_FORMAT_ARGB1555:
1169 return &fetch_r5g5b5a1;
1170 case MESA_FORMAT_ARGB8888:
1171 return &fetch_a8r8g8b8;
1172 case MESA_FORMAT_RGB_FXT1:
1173 case MESA_FORMAT_RGBA_FXT1:
1174 case MESA_FORMAT_RGB_DXT1:
1175 case MESA_FORMAT_RGBA_DXT1:
1176 case MESA_FORMAT_RGBA_DXT3:
1177 case MESA_FORMAT_RGBA_DXT5:
1178 return &fetch_r4g4b4a4;
1179 default:
1180 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1181 return NULL;
1182 }
1183 }
1184
1185 void
1186 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1187 GLint internalFormat, GLint width, GLint height, GLint border,
1188 GLenum format, GLenum type, const GLvoid * pixels,
1189 const struct gl_pixelstore_attrib *packing,
1190 struct gl_texture_object *texObj,
1191 struct gl_texture_image *texImage)
1192 {
1193 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1194 tfxTexInfo *ti;
1195 tfxMipMapLevel *mml;
1196 GLint texelBytes;
1197
1198 GLvoid *_final_texImage_Data;
1199 const struct gl_texture_format *_final_texImage_TexFormat;
1200
1201 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1202 fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1203 texObj->Name, texImage->IntFormat, format, type,
1204 texImage->Width, texImage->Height);
1205 }
1206
1207 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1208 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1209 return;
1210 }
1211
1212 if (!texObj->DriverData) {
1213 texObj->DriverData = fxAllocTexObjData(fxMesa);
1214 if (!texObj->DriverData) {
1215 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1216 return;
1217 }
1218 }
1219 ti = fxTMGetTexInfo(texObj);
1220
1221 if (!texImage->DriverData) {
1222 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1223 if (!texImage->DriverData) {
1224 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1225 return;
1226 }
1227 }
1228 mml = FX_MIPMAP_DATA(texImage);
1229
1230 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1231 &mml->wScale, &mml->hScale);
1232
1233 mml->width = width * mml->wScale;
1234 mml->height = height * mml->hScale;
1235
1236 #if 0 && FX_COMPRESS_S3TC_AS_FXT1_HACK
1237 /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
1238 /* [dBorca] we should update texture's attribute, then,
1239 * because if the application asks us to decompress, we
1240 * have to know the REAL format! Also, DXT3/5 might not
1241 * be correct, since it would mess with "compressedSize".
1242 * Ditto for GL_RGBA[4]_S3TC, which is always mapped to DXT3.
1243 */
1244 if (texImage->IsCompressed) {
1245 switch (internalFormat) {
1246 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1247 case GL_RGB_S3TC:
1248 case GL_RGB4_S3TC:
1249 internalFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
1250 break;
1251 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1252 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1253 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1254 case GL_RGBA_S3TC:
1255 case GL_RGBA4_S3TC:
1256 internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
1257 }
1258 }
1259 #endif
1260 #if 0 && FX_COMPRESS_DXT5_AS_DXT3_HACK
1261 /* [dBorca] either VSA is stupid at DXT5,
1262 * or our compression tool is broken. See
1263 * above for caveats.
1264 */
1265 if ((texImage->IsCompressed) &&
1266 (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)) {
1267 internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
1268 }
1269 #endif
1270
1271 /* choose the texture format */
1272 assert(ctx->Driver.ChooseTextureFormat);
1273 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1274 internalFormat, format, type);
1275 assert(texImage->TexFormat);
1276 texelBytes = texImage->TexFormat->TexelBytes;
1277 /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
1278
1279 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1280 /* dirty trick: will thrash CopyTex[Sub]Image */
1281 #if FX_TC_NCC || FX_TC_NAPALM
1282 if (internalFormat == GL_COMPRESSED_RGB) {
1283 #if FX_TC_NCC
1284 mml->glideFormat = GR_TEXFMT_YIQ_422;
1285 #endif
1286 #if FX_TC_NAPALM
1287 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1288 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1289 }
1290 #endif
1291 } else if (internalFormat == GL_COMPRESSED_RGBA) {
1292 #if FX_TC_NCC
1293 mml->glideFormat = GR_TEXFMT_AYIQ_8422;
1294 #endif
1295 #if FX_TC_NAPALM
1296 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1297 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1298 }
1299 #endif
1300 }
1301 #endif
1302
1303 /* allocate mipmap buffer */
1304 assert(!texImage->Data);
1305 if (texImage->IsCompressed) {
1306 texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
1307 texelBytes = 4;
1308 _final_texImage_TexFormat = &_mesa_texformat_argb8888;
1309 _final_texImage_Data = MALLOC(mml->width * mml->height * 4);
1310 if (!_final_texImage_Data) {
1311 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1312 return;
1313 }
1314 } else {
1315 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1316 _final_texImage_TexFormat = texImage->TexFormat;
1317 _final_texImage_Data = texImage->Data;
1318 }
1319 if (!texImage->Data) {
1320 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1321 return;
1322 }
1323
1324 if (mml->wScale != 1 || mml->hScale != 1) {
1325 /* rescale image to overcome 1:8 aspect limitation */
1326 GLvoid *tempImage;
1327 tempImage = MALLOC(width * height * texelBytes);
1328 if (!tempImage) {
1329 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1330 return;
1331 }
1332 /* unpack image, apply transfer ops and store in tempImage */
1333 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1334 _final_texImage_TexFormat,
1335 tempImage,
1336 width, height, 1, 0, 0, 0, /* src */
1337 width * texelBytes, /* dstRowStride */
1338 0, /* dstImageStride */
1339 format, type, pixels, packing);
1340 _mesa_rescale_teximage2d(texelBytes,
1341 mml->width * texelBytes, /* dst stride */
1342 width, height, /* src */
1343 mml->width, mml->height, /* dst */
1344 tempImage /*src*/, _final_texImage_Data /*dst*/ );
1345 FREE(tempImage);
1346 }
1347 else {
1348 /* no rescaling needed */
1349 /* unpack image, apply transfer ops and store in texImage->Data */
1350 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1351 _final_texImage_TexFormat, _final_texImage_Data,
1352 width, height, 1, 0, 0, 0,
1353 mml->width * texelBytes,
1354 0, /* dstImageStride */
1355 format, type, pixels, packing);
1356 }
1357
1358 /* now compress */
1359 if (texImage->IsCompressed) {
1360 #if FX_TC_NCC
1361 if ((mml->glideFormat == GR_TEXFMT_AYIQ_8422) ||
1362 (mml->glideFormat == GR_TEXFMT_YIQ_422)) {
1363 TxMip txMip, pxMip;
1364 txMip.width = mml->width;
1365 txMip.height = mml->height;
1366 txMip.depth = 1;
1367 txMip.data[0] = _final_texImage_Data;
1368 pxMip.data[0] = texImage->Data;
1369 fxMesa->Glide.txMipQuantize(&pxMip, &txMip, mml->glideFormat, TX_DITHER_ERR, TX_COMPRESSION_STATISTICAL);
1370 fxMesa->Glide.txPalToNcc((GuNccTable *)(&(ti->palette)), pxMip.pal);
1371 MEMCPY((char *)texImage->Data + texImage->CompressedSize - 12 * 4, &(ti->palette.data[16]), 12 * 4);
1372 } else
1373 #endif
1374 fxMesa->Glide.txImgQuantize(texImage->Data, _final_texImage_Data, mml->width, mml->height, mml->glideFormat, TX_DITHER_NONE);
1375 FREE(_final_texImage_Data);
1376 }
1377
1378 ti->info.format = mml->glideFormat;
1379 texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
1380
1381 /* [dBorca]
1382 * Hack alert: unsure...
1383 */
1384 if (0 && ti->validated && ti->isInTM) {
1385 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1386 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1387 }
1388 else {
1389 /*fprintf(stderr, "invalidate2\n"); */
1390 fxTexInvalidate(ctx, texObj);
1391 }
1392 }
1393
1394
1395 void
1396 fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1397 GLint xoffset, GLint yoffset,
1398 GLsizei width, GLsizei height,
1399 GLenum format, GLenum type, const GLvoid * pixels,
1400 const struct gl_pixelstore_attrib *packing,
1401 struct gl_texture_object *texObj,
1402 struct gl_texture_image *texImage)
1403 {
1404 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1405 tfxTexInfo *ti;
1406 tfxMipMapLevel *mml;
1407 GLint texelBytes;
1408
1409 /* [dBorca] Hack alert:
1410 * fix the goddamn texture compression here
1411 */
1412
1413 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1414 fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
1415 }
1416
1417 if (!texObj->DriverData) {
1418 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1419 return;
1420 }
1421
1422 ti = fxTMGetTexInfo(texObj);
1423 assert(ti);
1424 mml = FX_MIPMAP_DATA(texImage);
1425 assert(mml);
1426
1427 assert(texImage->Data); /* must have an existing texture image! */
1428 assert(texImage->Format);
1429
1430 texelBytes = texImage->TexFormat->TexelBytes;
1431
1432 if (mml->wScale != 1 || mml->hScale != 1) {
1433 /* need to rescale subimage to match mipmap level's rescale factors */
1434 const GLint newWidth = width * mml->wScale;
1435 const GLint newHeight = height * mml->hScale;
1436 GLvoid *tempImage;
1437 GLubyte *destAddr;
1438 tempImage = MALLOC(width * height * texelBytes);
1439 if (!tempImage) {
1440 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1441 return;
1442 }
1443
1444 _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */
1445 texImage->TexFormat, /* dest format */
1446 (GLubyte *) tempImage, /* dest */
1447 width, height, 1, /* subimage size */
1448 0, 0, 0, /* subimage pos */
1449 width * texelBytes, /* dest row stride */
1450 0, /* dst image stride */
1451 format, type, pixels, packing);
1452
1453 /* now rescale */
1454 /* compute address of dest subimage within the overal tex image */
1455 destAddr = (GLubyte *) texImage->Data
1456 + (yoffset * mml->hScale * mml->width
1457 + xoffset * mml->wScale) * texelBytes;
1458
1459 _mesa_rescale_teximage2d(texelBytes,
1460 mml->width * texelBytes, /* dst stride */
1461 width, height,
1462 newWidth, newHeight,
1463 tempImage, destAddr);
1464
1465 FREE(tempImage);
1466 }
1467 else {
1468 /* no rescaling needed */
1469 _mesa_transfer_teximage(ctx, 2, texImage->Format, /* Tex int format */
1470 texImage->TexFormat, /* dest format */
1471 (GLubyte *) texImage->Data,/* dest */
1472 width, height, 1, /* subimage size */
1473 xoffset, yoffset, 0, /* subimage pos */
1474 mml->width * texelBytes, /* dest row stride */
1475 0, /* dst image stride */
1476 format, type, pixels, packing);
1477 }
1478
1479 /* [dBorca]
1480 * Hack alert: unsure...
1481 */
1482 if (0 && ti->validated && ti->isInTM)
1483 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1484 else
1485 fxTexInvalidate(ctx, texObj);
1486 }
1487
1488
1489 void
1490 fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
1491 GLint level, GLint internalFormat,
1492 GLsizei width, GLsizei height, GLint border,
1493 GLsizei imageSize, const GLvoid *data,
1494 struct gl_texture_object *texObj,
1495 struct gl_texture_image *texImage)
1496 {
1497 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1498 tfxTexInfo *ti;
1499 tfxMipMapLevel *mml;
1500
1501 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1502 fprintf(stderr, "fxDDCompressedTexImage2D: id=%d int 0x%x %dx%d\n",
1503 texObj->Name, internalFormat,
1504 width, height);
1505 }
1506
1507 assert(texImage->IsCompressed);
1508
1509 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1510 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDCompressedTexImg()\n");
1511 return;
1512 }
1513
1514 if (!texObj->DriverData) {
1515 texObj->DriverData = fxAllocTexObjData(fxMesa);
1516 if (!texObj->DriverData) {
1517 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1518 return;
1519 }
1520 }
1521 ti = fxTMGetTexInfo(texObj);
1522
1523 if (!texImage->DriverData) {
1524 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1525 if (!texImage->DriverData) {
1526 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1527 return;
1528 }
1529 }
1530 mml = FX_MIPMAP_DATA(texImage);
1531
1532 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1533 &mml->wScale, &mml->hScale);
1534
1535 mml->width = width * mml->wScale;
1536 mml->height = height * mml->hScale;
1537
1538
1539 /* choose the texture format */
1540 assert(ctx->Driver.ChooseTextureFormat);
1541 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1542 internalFormat, -1/*format*/, -1/*type*/);
1543 assert(texImage->TexFormat);
1544
1545 /* Determine the appropriate Glide texel format,
1546 * given the user's internal texture format hint.
1547 */
1548 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1549 #if FX_TC_NCC || FX_TC_NAPALM
1550 if (internalFormat == GL_COMPRESSED_RGB) {
1551 #if FX_TC_NCC
1552 mml->glideFormat = GR_TEXFMT_YIQ_422;
1553 #endif
1554 #if FX_TC_NAPALM
1555 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1556 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1557 }
1558 #endif
1559 } else if (internalFormat == GL_COMPRESSED_RGBA) {
1560 #if FX_TC_NCC
1561 mml->glideFormat = GR_TEXFMT_AYIQ_8422;
1562 #endif
1563 #if FX_TC_NAPALM
1564 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1565 mml->glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
1566 }
1567 #endif
1568 }
1569 #endif
1570
1571 /* allocate new storage for texture image, if needed */
1572 if (!texImage->Data) {
1573 texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
1574 if (!texImage->Data) {
1575 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1576 return;
1577 }
1578 }
1579
1580 /* save the texture data */
1581 MEMCPY(texImage->Data, data, imageSize);
1582 #if FX_TC_NCC
1583 if ((mml->glideFormat == GR_TEXFMT_AYIQ_8422) ||
1584 (mml->glideFormat == GR_TEXFMT_YIQ_422)) {
1585 MEMCPY(&(ti->palette.data[16]), (char *)data + imageSize - 12 * 4, 12 * 4);
1586 }
1587 #endif
1588
1589 ti->info.format = mml->glideFormat;
1590 texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
1591
1592 /* [dBorca] Hack alert:
1593 * what about different size/texel? other anomalies? SW rescaling?
1594 */
1595
1596 /* [dBorca]
1597 * Hack alert: unsure...
1598 */
1599 if (0 && ti->validated && ti->isInTM) {
1600 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1601 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1602 }
1603 else {
1604 /*fprintf(stderr, "invalidate2\n"); */
1605 fxTexInvalidate(ctx, texObj);
1606 }
1607 }
1608
1609
1610 void
1611 fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
1612 GLint level, GLint xoffset,
1613 GLint yoffset, GLsizei width,
1614 GLint height, GLenum format,
1615 GLsizei imageSize, const GLvoid *data,
1616 struct gl_texture_object *texObj,
1617 struct gl_texture_image *texImage )
1618 {
1619 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1620 tfxTexInfo *ti;
1621 tfxMipMapLevel *mml;
1622
1623 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1624 fprintf(stderr, "fxDDCompressedTexSubImage2D: id=%d\n", texObj->Name);
1625 }
1626
1627 ti = fxTMGetTexInfo(texObj);
1628 assert(ti);
1629 mml = FX_MIPMAP_DATA(texImage);
1630 assert(mml);
1631
1632 /*
1633 * We punt if we are not replacing the entire image. This
1634 * is allowed by the spec.
1635 *
1636 * [dBorca] Hack alert:
1637 * ohwell, we should NOT! Look into _mesa_store_compressed_texsubimage2d
1638 * on how to calculate the sub-image.
1639 */
1640 if ((xoffset != 0) && (yoffset != 0)
1641 && (width != texImage->Width)
1642 && (height != texImage->Height)) {
1643 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(CHICKEN)");
1644 return;
1645 }
1646
1647 /* [dBorca] Hack alert:
1648 * what about different size/texel? other anomalies? SW rescaling?
1649 */
1650 MEMCPY(texImage->Data, data, imageSize);
1651
1652 /* [dBorca]
1653 * Hack alert: unsure...
1654 */
1655 if (0 && ti->validated && ti->isInTM)
1656 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1657 else
1658 fxTexInvalidate(ctx, texObj);
1659 }
1660
1661
1662 void
1663 fxDDTexImage1D (GLcontext *ctx, GLenum target, GLint level,
1664 GLint internalFormat, GLint width, GLint border,
1665 GLenum format, GLenum type, const GLvoid *pixels,
1666 const struct gl_pixelstore_attrib *packing,
1667 struct gl_texture_object *texObj,
1668 struct gl_texture_image *texImage)
1669 {
1670 fxDDTexImage2D(ctx, target, level,
1671 internalFormat, width, 1, border,
1672 format, type, pixels,
1673 packing,
1674 texObj,
1675 texImage);
1676 }
1677
1678
1679 GLboolean
1680 fxDDTestProxyTexImage (GLcontext *ctx, GLenum target,
1681 GLint level, GLint internalFormat,
1682 GLenum format, GLenum type,
1683 GLint width, GLint height,
1684 GLint depth, GLint border)
1685 {
1686 /* [dBorca]
1687 * TODO - maybe through fxTexValidate()
1688 */
1689 return _mesa_test_proxy_teximage(ctx, target,
1690 level, internalFormat,
1691 format, type,
1692 width, height,
1693 depth, border);
1694 }
1695
1696
1697 #else /* FX */
1698
1699 /*
1700 * Need this to provide at least one external definition.
1701 */
1702
1703 extern int gl_fx_dummy_function_ddtex(void);
1704 int
1705 gl_fx_dummy_function_ddtex(void)
1706 {
1707 return 0;
1708 }
1709
1710 #endif /* FX */