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