minor fixes + doc update
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
1 /* $Id: fxddtex.c,v 1.51 2003/10/14 14:56:45 dborca Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.0
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 /* Authors:
28 * David Bucciarelli
29 * Brian Paul
30 * Daryll Strauss
31 * Keith Whitwell
32 * Daniel Borca
33 * Hiroshi Morii
34 */
35
36
37 #ifdef HAVE_CONFIG_H
38 #include "conf.h"
39 #endif
40
41 #if defined(FX)
42
43 #include "fxdrv.h"
44 #include "enums.h"
45 #include "image.h"
46 #include "teximage.h"
47 #include "texformat.h"
48 #include "texstore.h"
49 #include "texutil.h"
50
51
52 void
53 fxPrintTextureData(tfxTexInfo * ti)
54 {
55 fprintf(stderr, "Texture Data:\n");
56 if (ti->tObj) {
57 fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
58 fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
59 fprintf(stderr, "\tSize: %d x %d\n",
60 ti->tObj->Image[ti->tObj->BaseLevel]->Width,
61 ti->tObj->Image[ti->tObj->BaseLevel]->Height);
62 }
63 else
64 fprintf(stderr, "\tName: UNNAMED\n");
65 fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
66 fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
67 fprintf(stderr, "\t%s\n", (ti->isInTM) ? "In TMU" : "Not in TMU");
68 if (ti->tm[0])
69 fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
70 (unsigned) ti->tm[0]->endAddr);
71 if (ti->tm[1])
72 fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
73 (unsigned) ti->tm[1]->endAddr);
74 fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
75 fprintf(stderr, "\tFilters: min %d min %d\n",
76 (int) ti->minFilt, (int) ti->maxFilt);
77 fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp,
78 (int) ti->tClamp);
79 fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
80 fprintf(stderr, "\t%s\n",
81 (ti->fixedPalette) ? "Fixed palette" : "Non fixed palette");
82 fprintf(stderr, "\t%s\n", (ti->validated) ? "Validated" : "Not validated");
83 }
84
85
86 /************************************************************************/
87 /*************************** Texture Mapping ****************************/
88 /************************************************************************/
89
90 static void
91 fxTexInvalidate(GLcontext * ctx, struct gl_texture_object *tObj)
92 {
93 fxMesaContext fxMesa = FX_CONTEXT(ctx);
94 tfxTexInfo *ti;
95
96 ti = fxTMGetTexInfo(tObj);
97 if (ti->isInTM)
98 fxTMMoveOutTM(fxMesa, tObj); /* TO DO: SLOW but easy to write */
99
100 ti->validated = GL_FALSE;
101 fxMesa->new_state |= FX_NEW_TEXTURING;
102 }
103
104 static tfxTexInfo *
105 fxAllocTexObjData(fxMesaContext fxMesa)
106 {
107 tfxTexInfo *ti;
108
109 if (!(ti = CALLOC(sizeof(tfxTexInfo)))) {
110 fprintf(stderr, "%s: ERROR: out of memory !\n", __FUNCTION__);
111 fxCloseHardware();
112 exit(-1);
113 }
114
115 ti->validated = GL_FALSE;
116 ti->isInTM = GL_FALSE;
117
118 ti->whichTMU = FX_TMU_NONE;
119
120 ti->tm[FX_TMU0] = NULL;
121 ti->tm[FX_TMU1] = NULL;
122
123 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
124 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
125
126 ti->sClamp = GR_TEXTURECLAMP_WRAP;
127 ti->tClamp = GR_TEXTURECLAMP_WRAP;
128
129 ti->mmMode = GR_MIPMAP_NEAREST;
130 ti->LODblend = FXFALSE;
131
132 return ti;
133 }
134
135 void
136 fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
137 {
138 fxMesaContext fxMesa = FX_CONTEXT(ctx);
139 tfxTexInfo *ti;
140
141 if (TDFX_DEBUG & VERBOSE_DRIVER) {
142 fprintf(stderr, "%s(%d, %x)\n", __FUNCTION__, tObj->Name,
143 (GLuint) tObj->DriverData);
144 }
145
146 if (target != GL_TEXTURE_2D)
147 return;
148
149 if (!tObj->DriverData) {
150 tObj->DriverData = fxAllocTexObjData(fxMesa);
151 }
152
153 ti = fxTMGetTexInfo(tObj);
154
155 fxMesa->texBindNumber++;
156 ti->lastTimeUsed = fxMesa->texBindNumber;
157
158 fxMesa->new_state |= FX_NEW_TEXTURING;
159 }
160
161 void
162 fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
163 const GLfloat * param)
164 {
165 fxMesaContext fxMesa = FX_CONTEXT(ctx);
166
167 if (TDFX_DEBUG & VERBOSE_DRIVER) {
168 if (param)
169 fprintf(stderr, "%s(%x, %x)\n", __FUNCTION__, pname, (GLint) (*param));
170 else
171 fprintf(stderr, "%s(%x)\n", __FUNCTION__, pname);
172 }
173
174 /* apply any lod biasing right now */
175 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
176 grTexLodBiasValue(GR_TMU0, *param);
177
178 if (fxMesa->haveTwoTMUs) {
179 grTexLodBiasValue(GR_TMU1, *param);
180 }
181
182 }
183
184 fxMesa->new_state |= FX_NEW_TEXTURING;
185 }
186
187 void
188 fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
189 GLenum pname, const GLfloat * params)
190 {
191 fxMesaContext fxMesa = FX_CONTEXT(ctx);
192 GLenum param = (GLenum) (GLint) params[0];
193 tfxTexInfo *ti;
194
195 if (TDFX_DEBUG & VERBOSE_DRIVER) {
196 fprintf(stderr, "fxDDTexParam(%d, %x, %s, %s)\n",
197 tObj->Name, (GLuint) tObj->DriverData,
198 _mesa_lookup_enum_by_nr(pname),
199 _mesa_lookup_enum_by_nr(param));
200 }
201
202 if (target != GL_TEXTURE_2D)
203 return;
204
205 if (!tObj->DriverData)
206 tObj->DriverData = fxAllocTexObjData(fxMesa);
207
208 ti = fxTMGetTexInfo(tObj);
209
210 switch (pname) {
211
212 case GL_TEXTURE_MIN_FILTER:
213 switch (param) {
214 case GL_NEAREST:
215 ti->mmMode = GR_MIPMAP_DISABLE;
216 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
217 ti->LODblend = FXFALSE;
218 break;
219 case GL_LINEAR:
220 ti->mmMode = GR_MIPMAP_DISABLE;
221 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
222 ti->LODblend = FXFALSE;
223 break;
224 case GL_NEAREST_MIPMAP_LINEAR:
225 if (fxMesa->haveTwoTMUs) {
226 ti->mmMode = GR_MIPMAP_NEAREST;
227 ti->LODblend = FXTRUE;
228 }
229 else {
230 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
231 ti->LODblend = FXFALSE;
232 }
233 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
234 break; /* ZZZ: we may have to fall through here for V3 */
235 case GL_NEAREST_MIPMAP_NEAREST:
236 ti->mmMode = GR_MIPMAP_NEAREST;
237 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
238 ti->LODblend = FXFALSE;
239 break;
240 case GL_LINEAR_MIPMAP_LINEAR:
241 /* ZZZ: HACK ALERT! trilinear is bugged! mipmap blending produce
242 incorrect filtered colors for the smallest mipmap levels. */
243 #if 0
244 if (fxMesa->haveTwoTMUs) {
245 ti->mmMode = GR_MIPMAP_NEAREST;
246 ti->LODblend = FXTRUE;
247 }
248 else {
249 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
250 ti->LODblend = FXFALSE;
251 }
252 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
253 break; /* ZZZ: we may have to fall through here for V3 */
254 #endif
255 case GL_LINEAR_MIPMAP_NEAREST:
256 ti->mmMode = GR_MIPMAP_NEAREST;
257 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
258 ti->LODblend = FXFALSE;
259 break;
260 default:
261 break;
262 }
263 fxTexInvalidate(ctx, tObj);
264 break;
265
266 case GL_TEXTURE_MAG_FILTER:
267 switch (param) {
268 case GL_NEAREST:
269 ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
270 break;
271 case GL_LINEAR:
272 ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
273 break;
274 default:
275 break;
276 }
277 fxTexInvalidate(ctx, tObj);
278 break;
279
280 case GL_TEXTURE_WRAP_S:
281 switch (param) {
282 case GL_MIRRORED_REPEAT:
283 ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
284 break;
285 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
286 case GL_CLAMP:
287 ti->sClamp = GR_TEXTURECLAMP_CLAMP;
288 break;
289 case GL_REPEAT:
290 ti->sClamp = GR_TEXTURECLAMP_WRAP;
291 break;
292 default:
293 break;
294 }
295 fxMesa->new_state |= FX_NEW_TEXTURING;
296 break;
297
298 case GL_TEXTURE_WRAP_T:
299 switch (param) {
300 case GL_MIRRORED_REPEAT:
301 ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
302 break;
303 case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
304 case GL_CLAMP:
305 ti->tClamp = GR_TEXTURECLAMP_CLAMP;
306 break;
307 case GL_REPEAT:
308 ti->tClamp = GR_TEXTURECLAMP_WRAP;
309 break;
310 default:
311 break;
312 }
313 fxMesa->new_state |= FX_NEW_TEXTURING;
314 break;
315
316 case GL_TEXTURE_BORDER_COLOR:
317 /* TO DO */
318 break;
319
320 case GL_TEXTURE_MIN_LOD:
321 /* TO DO */
322 break;
323 case GL_TEXTURE_MAX_LOD:
324 /* TO DO */
325 break;
326 case GL_TEXTURE_BASE_LEVEL:
327 fxTexInvalidate(ctx, tObj);
328 break;
329 case GL_TEXTURE_MAX_LEVEL:
330 fxTexInvalidate(ctx, tObj);
331 break;
332
333 default:
334 break;
335 }
336 }
337
338 void
339 fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
340 {
341 fxMesaContext fxMesa = FX_CONTEXT(ctx);
342 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
343
344 if (TDFX_DEBUG & VERBOSE_DRIVER) {
345 fprintf(stderr, "%s(%d, %p)\n", __FUNCTION__, tObj->Name, (void *) ti);
346 }
347
348 if (!ti)
349 return;
350
351 fxTMFreeTexture(fxMesa, tObj);
352
353 FREE(ti);
354 tObj->DriverData = NULL;
355 }
356
357 /*
358 * Return true if texture is resident, false otherwise.
359 */
360 GLboolean
361 fxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
362 {
363 tfxTexInfo *ti = fxTMGetTexInfo(tObj);
364 return (ti && ti->isInTM);
365 }
366
367
368
369 /*
370 * Convert a gl_color_table texture palette to Glide's format.
371 */
372 static void
373 convertPalette(FxU32 data[256], const struct gl_color_table *table)
374 {
375 const GLubyte *tableUB = (const GLubyte *) table->Table;
376 GLint width = table->Size;
377 FxU32 r, g, b, a;
378 GLint i;
379
380 ASSERT(!table->FloatTable);
381
382 switch (table->Format) {
383 case GL_INTENSITY:
384 for (i = 0; i < width; i++) {
385 r = tableUB[i];
386 g = tableUB[i];
387 b = tableUB[i];
388 a = tableUB[i];
389 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
390 }
391 break;
392 case GL_LUMINANCE:
393 for (i = 0; i < width; i++) {
394 r = tableUB[i];
395 g = tableUB[i];
396 b = tableUB[i];
397 a = 255;
398 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
399 }
400 break;
401 case GL_ALPHA:
402 for (i = 0; i < width; i++) {
403 r = g = b = 255;
404 a = tableUB[i];
405 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
406 }
407 break;
408 case GL_LUMINANCE_ALPHA:
409 for (i = 0; i < width; i++) {
410 r = g = b = tableUB[i * 2 + 0];
411 a = tableUB[i * 2 + 1];
412 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
413 }
414 break;
415 case GL_RGB:
416 for (i = 0; i < width; i++) {
417 r = tableUB[i * 3 + 0];
418 g = tableUB[i * 3 + 1];
419 b = tableUB[i * 3 + 2];
420 a = 255;
421 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
422 }
423 break;
424 case GL_RGBA:
425 for (i = 0; i < width; i++) {
426 r = tableUB[i * 4 + 0];
427 g = tableUB[i * 4 + 1];
428 b = tableUB[i * 4 + 2];
429 a = tableUB[i * 4 + 3];
430 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
431 }
432 break;
433 }
434 }
435
436
437 void
438 fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
439 {
440 fxMesaContext fxMesa = FX_CONTEXT(ctx);
441
442 if (tObj) {
443 /* per-texture palette */
444 tfxTexInfo *ti;
445 if (TDFX_DEBUG & VERBOSE_DRIVER) {
446 fprintf(stderr, "%s(%d, %x)\n", __FUNCTION__,
447 tObj->Name, (GLuint) tObj->DriverData);
448 }
449 if (!tObj->DriverData)
450 tObj->DriverData = fxAllocTexObjData(fxMesa);
451 ti = fxTMGetTexInfo(tObj);
452 convertPalette(ti->palette.data, &tObj->Palette);
453 fxTexInvalidate(ctx, tObj);
454 }
455 else {
456 /* global texture palette */
457 if (TDFX_DEBUG & VERBOSE_DRIVER) {
458 fprintf(stderr, "%s(global)\n", __FUNCTION__);
459 }
460 convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
461 fxMesa->new_state |= FX_NEW_TEXTURING;
462 }
463 }
464
465
466 void
467 fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
468 {
469 fxMesaContext fxMesa = FX_CONTEXT(ctx);
470
471 if (TDFX_DEBUG & VERBOSE_DRIVER) {
472 fprintf(stderr, "%s(%d)\n", __FUNCTION__, state);
473 }
474
475 if (state) {
476 fxMesa->haveGlobalPaletteTexture = 1;
477
478 grTexDownloadTable(GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette));
479 }
480 else {
481 fxMesa->haveGlobalPaletteTexture = 0;
482
483 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
484 (ctx->Texture.Unit[0]._Current != NULL)) {
485 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
486
487 if (!tObj->DriverData)
488 tObj->DriverData = fxAllocTexObjData(fxMesa);
489
490 fxTexInvalidate(ctx, tObj);
491 }
492 }
493 }
494
495
496 static int
497 logbase2(int n)
498 {
499 GLint i = 1;
500 GLint log2 = 0;
501
502 if (n < 0) {
503 return -1;
504 }
505
506 while (n > i) {
507 i *= 2;
508 log2++;
509 }
510 if (i != n) {
511 return -1;
512 }
513 else {
514 return log2;
515 }
516 }
517
518
519 int
520 fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar,
521 float *sscale, float *tscale,
522 int *wscale, int *hscale)
523 {
524 static GrLOD_t lod[12] = {
525 GR_LOD_LOG2_1,
526 GR_LOD_LOG2_2,
527 GR_LOD_LOG2_4,
528 GR_LOD_LOG2_8,
529 GR_LOD_LOG2_16,
530 GR_LOD_LOG2_32,
531 GR_LOD_LOG2_64,
532 GR_LOD_LOG2_128,
533 GR_LOD_LOG2_256,
534 GR_LOD_LOG2_512,
535 GR_LOD_LOG2_1024,
536 GR_LOD_LOG2_2048
537 };
538
539 int logw, logh, ws, hs;
540 GrLOD_t l;
541 GrAspectRatio_t aspectratio;
542 float s, t;
543
544 logw = logbase2(w);
545 logh = logbase2(h);
546
547 switch (logw - logh) {
548 case 0:
549 aspectratio = GR_ASPECT_LOG2_1x1;
550 l = lod[logw];
551 s = t = 256.0f;
552 ws = hs = 1;
553 break;
554 case 1:
555 aspectratio = GR_ASPECT_LOG2_2x1;
556 l = lod[logw];
557 s = 256.0f;
558 t = 128.0f;
559 ws = 1;
560 hs = 1;
561 break;
562 case 2:
563 aspectratio = GR_ASPECT_LOG2_4x1;
564 l = lod[logw];
565 s = 256.0f;
566 t = 64.0f;
567 ws = 1;
568 hs = 1;
569 break;
570 case 3:
571 aspectratio = GR_ASPECT_LOG2_8x1;
572 l = lod[logw];
573 s = 256.0f;
574 t = 32.0f;
575 ws = 1;
576 hs = 1;
577 break;
578 case -1:
579 aspectratio = GR_ASPECT_LOG2_1x2;
580 l = lod[logh];
581 s = 128.0f;
582 t = 256.0f;
583 ws = 1;
584 hs = 1;
585 break;
586 case -2:
587 aspectratio = GR_ASPECT_LOG2_1x4;
588 l = lod[logh];
589 s = 64.0f;
590 t = 256.0f;
591 ws = 1;
592 hs = 1;
593 break;
594 case -3:
595 aspectratio = GR_ASPECT_LOG2_1x8;
596 l = lod[logh];
597 s = 32.0f;
598 t = 256.0f;
599 ws = 1;
600 hs = 1;
601 break;
602 default:
603 if ((logw - logh) > 3) {
604 aspectratio = GR_ASPECT_LOG2_8x1;
605 l = lod[logw];
606 s = 256.0f;
607 t = 32.0f;
608 ws = 1;
609 hs = 1 << (logw - logh - 3);
610 } else /*if ((logw - logh) < -3)*/ {
611 aspectratio = GR_ASPECT_LOG2_1x8;
612 l = lod[logh];
613 s = 32.0f;
614 t = 256.0f;
615 ws = 1 << (logh - logw - 3);
616 hs = 1;
617 }
618 }
619
620 if (lodlevel)
621 (*lodlevel) = l;
622
623 if (ar)
624 (*ar) = aspectratio;
625
626 if (sscale)
627 (*sscale) = s;
628
629 if (tscale)
630 (*tscale) = t;
631
632 if (wscale)
633 (*wscale) = ws;
634
635 if (hscale)
636 (*hscale) = hs;
637
638
639 return 1;
640 }
641
642 static GLboolean
643 fxIsTexSupported(GLenum target, GLint internalFormat,
644 const struct gl_texture_image *image)
645 {
646 if (target != GL_TEXTURE_2D)
647 return GL_FALSE;
648
649 if (!fxTexGetInfo(image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL))
650 return GL_FALSE;
651
652 if (image->Border > 0)
653 return GL_FALSE;
654
655 return GL_TRUE;
656 }
657
658
659 /**********************************************************************/
660 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
661 /**********************************************************************/
662
663 /* Texel-fetch functions for software texturing and glGetTexImage().
664 * We should have been able to use some "standard" fetch functions (which
665 * may get defined in texutil.c) but we have to account for scaled texture
666 * images on tdfx hardware (the 8:1 aspect ratio limit).
667 * Hence, we need special functions here.
668 */
669
670 static void
671 fetch_intensity8(const struct gl_texture_image *texImage,
672 GLint i, GLint j, GLint k, GLvoid * texelOut)
673 {
674 GLchan *rgba = (GLchan *) texelOut;
675 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
676 const GLubyte *texel;
677
678 i = i * mml->wScale;
679 j = j * mml->hScale;
680
681 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
682 rgba[RCOMP] = *texel;
683 rgba[GCOMP] = *texel;
684 rgba[BCOMP] = *texel;
685 rgba[ACOMP] = *texel;
686 }
687
688
689 static void
690 fetch_luminance8(const struct gl_texture_image *texImage,
691 GLint i, GLint j, GLint k, GLvoid * texelOut)
692 {
693 GLchan *rgba = (GLchan *) texelOut;
694 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
695 const GLubyte *texel;
696
697 i = i * mml->wScale;
698 j = j * mml->hScale;
699
700 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
701 rgba[RCOMP] = *texel;
702 rgba[GCOMP] = *texel;
703 rgba[BCOMP] = *texel;
704 rgba[ACOMP] = 255;
705 }
706
707
708 static void
709 fetch_alpha8(const struct gl_texture_image *texImage,
710 GLint i, GLint j, GLint k, GLvoid * texelOut)
711 {
712 GLchan *rgba = (GLchan *) texelOut;
713 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
714 const GLubyte *texel;
715
716 i = i * mml->wScale;
717 j = j * mml->hScale;
718 i = i * mml->width / texImage->Width;
719 j = j * mml->height / texImage->Height;
720
721 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
722 rgba[RCOMP] = 255;
723 rgba[GCOMP] = 255;
724 rgba[BCOMP] = 255;
725 rgba[ACOMP] = *texel;
726 }
727
728
729 static void
730 fetch_index8(const struct gl_texture_image *texImage,
731 GLint i, GLint j, GLint k, GLvoid * texelOut)
732 {
733 GLchan *indexOut = (GLchan *) texelOut;
734 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
735 const GLubyte *texel;
736
737 i = i * mml->wScale;
738 j = j * mml->hScale;
739 i = i * mml->width / texImage->Width;
740 j = j * mml->height / texImage->Height;
741
742 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
743 *indexOut = *texel;
744 }
745
746
747 static void
748 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
749 GLint i, GLint j, GLint k, GLvoid * texelOut)
750 {
751 GLchan *rgba = (GLchan *) texelOut;
752 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
753 const GLubyte *texel;
754
755 i = i * mml->wScale;
756 j = j * mml->hScale;
757
758 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
759 rgba[RCOMP] = texel[0];
760 rgba[GCOMP] = texel[0];
761 rgba[BCOMP] = texel[0];
762 rgba[ACOMP] = texel[1];
763 }
764
765
766 static void
767 fetch_r5g6b5(const struct gl_texture_image *texImage,
768 GLint i, GLint j, GLint k, GLvoid * texelOut)
769 {
770 GLchan *rgba = (GLchan *) texelOut;
771 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
772 const GLushort *texel;
773
774 i = i * mml->wScale;
775 j = j * mml->hScale;
776
777 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
778 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
779 rgba[GCOMP] = FX_rgb_scale_6[(*texel >> 5) & 0x3F];
780 rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
781 rgba[ACOMP] = 255;
782 }
783
784
785 static void
786 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
787 GLint i, GLint j, GLint k, GLvoid * texelOut)
788 {
789 GLchan *rgba = (GLchan *) texelOut;
790 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
791 const GLushort *texel;
792
793 i = i * mml->wScale;
794 j = j * mml->hScale;
795
796 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
797 rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
798 rgba[GCOMP] = FX_rgb_scale_4[(*texel >> 8) & 0xF];
799 rgba[BCOMP] = FX_rgb_scale_4[(*texel >> 4) & 0xF];
800 rgba[ACOMP] = FX_rgb_scale_4[ *texel & 0xF];
801 }
802
803
804 static void
805 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
806 GLint i, GLint j, GLint k, GLvoid * texelOut)
807 {
808 GLchan *rgba = (GLchan *) texelOut;
809 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
810 const GLushort *texel;
811
812 i = i * mml->wScale;
813 j = j * mml->hScale;
814
815 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
816 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
817 rgba[GCOMP] = FX_rgb_scale_5[(*texel >> 6) & 0x1F];
818 rgba[BCOMP] = FX_rgb_scale_5[(*texel >> 1) & 0x1F];
819 rgba[ACOMP] = ((*texel) & 0x01) * 255;
820 }
821
822
823 static void
824 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
825 GLint i, GLint j, GLint k, GLvoid * texelOut)
826 {
827 GLchan *rgba = (GLchan *) texelOut;
828 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
829 const GLuint *texel;
830
831 i = i * mml->wScale;
832 j = j * mml->hScale;
833
834 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
835 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
836 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
837 rgba[BCOMP] = (((*texel) ) & 0xff);
838 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
839 }
840
841
842 static void
843 PrintTexture(int w, int h, int c, const GLubyte * data)
844 {
845 int i, j;
846 for (i = 0; i < h; i++) {
847 for (j = 0; j < w; j++) {
848 if (c == 2)
849 fprintf(stderr, "%02x %02x ", data[0], data[1]);
850 else if (c == 3)
851 fprintf(stderr, "%02x %02x %02x ", data[0], data[1], data[2]);
852 data += c;
853 }
854 fprintf(stderr, "\n");
855 }
856 }
857
858
859 const struct gl_texture_format *
860 fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
861 GLenum srcFormat, GLenum srcType )
862 {
863 fxMesaContext fxMesa = FX_CONTEXT(ctx);
864 GLboolean allow32bpt = fxMesa->HaveTexFmt;
865
866 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
867 fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
868 }
869
870 switch (internalFormat) {
871 case GL_INTENSITY:
872 case GL_INTENSITY4:
873 case GL_INTENSITY8:
874 case GL_INTENSITY12:
875 case GL_INTENSITY16:
876 case GL_COMPRESSED_INTENSITY:
877 return &_mesa_texformat_i8;
878 case 1:
879 case GL_LUMINANCE:
880 case GL_LUMINANCE4:
881 case GL_LUMINANCE8:
882 case GL_LUMINANCE12:
883 case GL_LUMINANCE16:
884 case GL_COMPRESSED_LUMINANCE:
885 return &_mesa_texformat_l8;
886 case GL_ALPHA:
887 case GL_ALPHA4:
888 case GL_ALPHA8:
889 case GL_ALPHA12:
890 case GL_ALPHA16:
891 case GL_COMPRESSED_ALPHA:
892 return &_mesa_texformat_a8;
893 case GL_COLOR_INDEX:
894 case GL_COLOR_INDEX1_EXT:
895 case GL_COLOR_INDEX2_EXT:
896 case GL_COLOR_INDEX4_EXT:
897 case GL_COLOR_INDEX8_EXT:
898 case GL_COLOR_INDEX12_EXT:
899 case GL_COLOR_INDEX16_EXT:
900 return &_mesa_texformat_ci8;
901 case 2:
902 case GL_LUMINANCE_ALPHA:
903 case GL_LUMINANCE4_ALPHA4:
904 case GL_LUMINANCE6_ALPHA2:
905 case GL_LUMINANCE8_ALPHA8:
906 case GL_LUMINANCE12_ALPHA4:
907 case GL_LUMINANCE12_ALPHA12:
908 case GL_LUMINANCE16_ALPHA16:
909 case GL_COMPRESSED_LUMINANCE_ALPHA:
910 return &_mesa_texformat_al88;
911 case GL_R3_G3_B2:
912 case GL_RGB4:
913 case GL_RGB5:
914 return &_mesa_texformat_rgb565;
915 case 3:
916 case GL_RGB:
917 case GL_COMPRESSED_RGB:
918 if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
919 return &_mesa_texformat_rgb565;
920 }
921 /* intentional fall through */
922 case GL_RGB8:
923 case GL_RGB10:
924 case GL_RGB12:
925 case GL_RGB16:
926 return (allow32bpt) ? &_mesa_texformat_argb8888
927 : &_mesa_texformat_rgb565;
928 case GL_RGBA2:
929 case GL_RGBA4:
930 return &_mesa_texformat_argb4444;
931 case 4:
932 case GL_RGBA:
933 case GL_COMPRESSED_RGBA:
934 if ( srcFormat == GL_BGRA ) {
935 if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
936 return &_mesa_texformat_argb8888;
937 }
938 else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
939 return &_mesa_texformat_argb4444;
940 }
941 else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
942 return &_mesa_texformat_argb1555;
943 }
944 }
945 /* intentional fall through */
946 case GL_RGBA8:
947 case GL_RGB10_A2:
948 case GL_RGBA12:
949 case GL_RGBA16:
950 return (allow32bpt) ? &_mesa_texformat_argb8888
951 : &_mesa_texformat_argb4444;
952 case GL_RGB5_A1:
953 return &_mesa_texformat_argb1555;
954 #if 0
955 /* GL_EXT_texture_compression_s3tc */
956 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
957 return &_mesa_texformat_rgb_dxt1;
958 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
959 return &_mesa_texformat_rgba_dxt1;
960 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
961 return &_mesa_texformat_rgba_dxt3;
962 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
963 return &_mesa_texformat_rgba_dxt5;
964 /*case GL_COMPRESSED_RGB_FXT1_3DFX:
965 case GL_COMPRESSED_RGBA_FXT1_3DFX:
966 return blah;*/
967 #endif
968 default:
969 _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
970 return NULL;
971 }
972 }
973
974
975 static GrTextureFormat_t
976 fxGlideFormat(GLint mesaFormat)
977 {
978 switch (mesaFormat) {
979 case MESA_FORMAT_I8:
980 return GR_TEXFMT_ALPHA_8;
981 case MESA_FORMAT_A8:
982 return GR_TEXFMT_ALPHA_8;
983 case MESA_FORMAT_L8:
984 return GR_TEXFMT_INTENSITY_8;
985 case MESA_FORMAT_CI8:
986 return GR_TEXFMT_P_8;
987 case MESA_FORMAT_AL88:
988 return GR_TEXFMT_ALPHA_INTENSITY_88;
989 case MESA_FORMAT_RGB565:
990 return GR_TEXFMT_RGB_565;
991 case MESA_FORMAT_ARGB4444:
992 return GR_TEXFMT_ARGB_4444;
993 case MESA_FORMAT_ARGB1555:
994 return GR_TEXFMT_ARGB_1555;
995 case MESA_FORMAT_ARGB8888:
996 return GR_TEXFMT_ARGB_8888;
997 #if 0
998 case MESA_FORMAT_RGB_DXT1:
999 case MESA_FORMAT_RGBA_DXT1:
1000 return GR_TEXFMT_ARGB_CMP_DXT1;
1001 case MESA_FORMAT_RGBA_DXT3:
1002 return GR_TEXFMT_ARGB_CMP_DXT3;
1003 case MESA_FORMAT_RGBA_DXT5:
1004 return GR_TEXFMT_ARGB_CMP_DXT5;
1005 /*case MESA_FORMAT_ARGB_CMP_FXT1:
1006 return GR_TEXFMT_ARGB_CMP_FXT1;
1007 case MESA_FORMAT_RGB_CMP_FXT1:
1008 return GL_COMPRESSED_RGBA_FXT1_3DFX;*/
1009 #endif
1010 default:
1011 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
1012 return 0;
1013 }
1014 }
1015
1016
1017 static FetchTexelFunc
1018 fxFetchFunction(GLint mesaFormat)
1019 {
1020 switch (mesaFormat) {
1021 case MESA_FORMAT_I8:
1022 return fetch_intensity8;
1023 case MESA_FORMAT_A8:
1024 return fetch_alpha8;
1025 case MESA_FORMAT_L8:
1026 return fetch_luminance8;
1027 case MESA_FORMAT_CI8:
1028 return fetch_index8;
1029 case MESA_FORMAT_AL88:
1030 return fetch_luminance8_alpha8;
1031 case MESA_FORMAT_RGB565:
1032 return fetch_r5g6b5;
1033 case MESA_FORMAT_ARGB4444:
1034 return fetch_r4g4b4a4;
1035 case MESA_FORMAT_ARGB1555:
1036 return fetch_r5g5b5a1;
1037 case MESA_FORMAT_ARGB8888:
1038 return fetch_a8r8g8b8;
1039 #if 0
1040 case MESA_FORMAT_RGB_DXT1:
1041 case MESA_FORMAT_RGBA_DXT1:
1042 case MESA_FORMAT_RGBA_DXT3:
1043 case MESA_FORMAT_RGBA_DXT5:
1044 return fetch_r4g4b4a4;
1045 #endif
1046 default:
1047 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1048 return NULL;
1049 }
1050 }
1051
1052 void
1053 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1054 GLint internalFormat, GLint width, GLint height, GLint border,
1055 GLenum format, GLenum type, const GLvoid * pixels,
1056 const struct gl_pixelstore_attrib *packing,
1057 struct gl_texture_object *texObj,
1058 struct gl_texture_image *texImage)
1059 {
1060 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1061 tfxTexInfo *ti;
1062 tfxMipMapLevel *mml;
1063 GLint texelBytes;
1064
1065 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1066 fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1067 texObj->Name, texImage->IntFormat, format, type,
1068 texImage->Width, texImage->Height);
1069 }
1070
1071 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1072 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1073 return;
1074 }
1075
1076 if (!texObj->DriverData) {
1077 texObj->DriverData = fxAllocTexObjData(fxMesa);
1078 if (!texObj->DriverData) {
1079 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1080 return;
1081 }
1082 }
1083 ti = fxTMGetTexInfo(texObj);
1084
1085 if (!texImage->DriverData) {
1086 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1087 if (!texImage->DriverData) {
1088 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1089 return;
1090 }
1091 }
1092 mml = FX_MIPMAP_DATA(texImage);
1093
1094 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1095 &mml->wScale, &mml->hScale);
1096
1097 mml->width = width * mml->wScale;
1098 mml->height = height * mml->hScale;
1099
1100
1101 /* choose the texture format */
1102 assert(ctx->Driver.ChooseTextureFormat);
1103 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1104 internalFormat, format, type);
1105 assert(texImage->TexFormat);
1106 texelBytes = texImage->TexFormat->TexelBytes;
1107 /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
1108
1109 if (mml->wScale != 1 || mml->hScale != 1) {
1110 /* rescale image to overcome 1:8 aspect limitation */
1111 GLvoid *tempImage;
1112 tempImage = MALLOC(width * height * texelBytes);
1113 if (!tempImage) {
1114 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1115 return;
1116 }
1117 /* unpack image, apply transfer ops and store in tempImage */
1118 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1119 texImage->TexFormat,
1120 tempImage,
1121 width, height, 1, 0, 0, 0,
1122 width * texelBytes,
1123 0, /* dstImageStride */
1124 format, type, pixels, packing);
1125 assert(!texImage->Data);
1126 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1127 if (!texImage->Data) {
1128 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1129 FREE(tempImage);
1130 return;
1131 }
1132 _mesa_rescale_teximage2d(texelBytes,
1133 mml->width * texelBytes, /* dst stride */
1134 width, height,
1135 mml->width, mml->height,
1136 tempImage /*src*/, texImage->Data /*dst*/ );
1137 FREE(tempImage);
1138 }
1139 else {
1140 /* no rescaling needed */
1141 assert(!texImage->Data);
1142 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1143 if (!texImage->Data) {
1144 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1145 return;
1146 }
1147 /* unpack image, apply transfer ops and store in texImage->Data */
1148 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1149 texImage->TexFormat, texImage->Data,
1150 width, height, 1, 0, 0, 0,
1151 texImage->Width * texelBytes,
1152 0, /* dstImageStride */
1153 format, type, pixels, packing);
1154 }
1155
1156 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1157 ti->info.format = mml->glideFormat;
1158 texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
1159
1160 /* [dBorca]
1161 * Hack alert: unsure...
1162 */
1163 if (!(fxMesa->new_state & FX_NEW_TEXTURING) && ti->validated && ti->isInTM) {
1164 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1165 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1166 }
1167 else {
1168 /*fprintf(stderr, "invalidate2\n"); */
1169 fxTexInvalidate(ctx, texObj);
1170 }
1171 }
1172
1173
1174 void
1175 fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1176 GLint xoffset, GLint yoffset,
1177 GLsizei width, GLsizei height,
1178 GLenum format, GLenum type, const GLvoid * pixels,
1179 const struct gl_pixelstore_attrib *packing,
1180 struct gl_texture_object *texObj,
1181 struct gl_texture_image *texImage)
1182 {
1183 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1184 tfxTexInfo *ti;
1185 tfxMipMapLevel *mml;
1186 GLint texelBytes;
1187
1188 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1189 fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
1190 }
1191
1192 if (!texObj->DriverData) {
1193 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1194 return;
1195 }
1196
1197 ti = fxTMGetTexInfo(texObj);
1198 assert(ti);
1199 mml = FX_MIPMAP_DATA(texImage);
1200 assert(mml);
1201
1202 assert(texImage->Data); /* must have an existing texture image! */
1203 assert(texImage->Format);
1204
1205 texelBytes = texImage->TexFormat->TexelBytes;
1206
1207 if (mml->wScale != 1 || mml->hScale != 1) {
1208 /* need to rescale subimage to match mipmap level's rescale factors */
1209 const GLint newWidth = width * mml->wScale;
1210 const GLint newHeight = height * mml->hScale;
1211 GLvoid *tempImage;
1212 GLubyte *destAddr;
1213 tempImage = MALLOC(width * height * texelBytes);
1214 if (!tempImage) {
1215 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1216 return;
1217 }
1218
1219 _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */
1220 texImage->TexFormat, /* dest format */
1221 (GLubyte *) tempImage, /* dest */
1222 width, height, 1, /* subimage size */
1223 0, 0, 0, /* subimage pos */
1224 width * texelBytes, /* dest row stride */
1225 0, /* dst image stride */
1226 format, type, pixels, packing);
1227
1228 /* now rescale */
1229 /* compute address of dest subimage within the overal tex image */
1230 destAddr = (GLubyte *) texImage->Data
1231 + (yoffset * mml->hScale * mml->width
1232 + xoffset * mml->wScale) * texelBytes;
1233
1234 _mesa_rescale_teximage2d(texelBytes,
1235 mml->width * texelBytes, /* dst stride */
1236 width, height,
1237 newWidth, newHeight,
1238 tempImage, destAddr);
1239
1240 FREE(tempImage);
1241 }
1242 else {
1243 /* no rescaling needed */
1244 _mesa_transfer_teximage(ctx, 2, texImage->Format, /* Tex int format */
1245 texImage->TexFormat, /* dest format */
1246 (GLubyte *) texImage->Data,/* dest */
1247 width, height, 1, /* subimage size */
1248 xoffset, yoffset, 0, /* subimage pos */
1249 mml->width * texelBytes, /* dest row stride */
1250 0, /* dst image stride */
1251 format, type, pixels, packing);
1252 }
1253
1254 /* [dBorca]
1255 * Hack alert: unsure...
1256 */
1257 if (!(fxMesa->new_state & FX_NEW_TEXTURING) && ti->validated && ti->isInTM)
1258 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1259 else
1260 fxTexInvalidate(ctx, texObj);
1261 }
1262
1263
1264 #else /* FX */
1265
1266 /*
1267 * Need this to provide at least one external definition.
1268 */
1269
1270 extern int gl_fx_dummy_function_ddtex(void);
1271 int
1272 gl_fx_dummy_function_ddtex(void)
1273 {
1274 return 0;
1275 }
1276
1277 #endif /* FX */