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