glide driver (wip)
[mesa.git] / src / mesa / drivers / glide / fxddtex.c
1 /* $Id: fxddtex.c,v 1.50 2003/10/13 11:14:58 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
359 /*
360 * Convert a gl_color_table texture palette to Glide's format.
361 */
362 static void
363 convertPalette(FxU32 data[256], const struct gl_color_table *table)
364 {
365 const GLubyte *tableUB = (const GLubyte *) table->Table;
366 GLint width = table->Size;
367 FxU32 r, g, b, a;
368 GLint i;
369
370 ASSERT(!table->FloatTable);
371
372 switch (table->Format) {
373 case GL_INTENSITY:
374 for (i = 0; i < width; i++) {
375 r = tableUB[i];
376 g = tableUB[i];
377 b = tableUB[i];
378 a = tableUB[i];
379 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
380 }
381 break;
382 case GL_LUMINANCE:
383 for (i = 0; i < width; i++) {
384 r = tableUB[i];
385 g = tableUB[i];
386 b = tableUB[i];
387 a = 255;
388 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
389 }
390 break;
391 case GL_ALPHA:
392 for (i = 0; i < width; i++) {
393 r = g = b = 255;
394 a = tableUB[i];
395 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
396 }
397 break;
398 case GL_LUMINANCE_ALPHA:
399 for (i = 0; i < width; i++) {
400 r = g = b = tableUB[i * 2 + 0];
401 a = tableUB[i * 2 + 1];
402 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
403 }
404 break;
405 case GL_RGB:
406 for (i = 0; i < width; i++) {
407 r = tableUB[i * 3 + 0];
408 g = tableUB[i * 3 + 1];
409 b = tableUB[i * 3 + 2];
410 a = 255;
411 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
412 }
413 break;
414 case GL_RGBA:
415 for (i = 0; i < width; i++) {
416 r = tableUB[i * 4 + 0];
417 g = tableUB[i * 4 + 1];
418 b = tableUB[i * 4 + 2];
419 a = tableUB[i * 4 + 3];
420 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
421 }
422 break;
423 }
424 }
425
426
427 void
428 fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
429 {
430 fxMesaContext fxMesa = FX_CONTEXT(ctx);
431
432 if (tObj) {
433 /* per-texture palette */
434 tfxTexInfo *ti;
435 if (TDFX_DEBUG & VERBOSE_DRIVER) {
436 fprintf(stderr, "%s(%d, %x)\n", __FUNCTION__,
437 tObj->Name, (GLuint) tObj->DriverData);
438 }
439 if (!tObj->DriverData)
440 tObj->DriverData = fxAllocTexObjData(fxMesa);
441 ti = fxTMGetTexInfo(tObj);
442 convertPalette(ti->palette.data, &tObj->Palette);
443 fxTexInvalidate(ctx, tObj);
444 }
445 else {
446 /* global texture palette */
447 if (TDFX_DEBUG & VERBOSE_DRIVER) {
448 fprintf(stderr, "%s(global)\n", __FUNCTION__);
449 }
450 convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
451 fxMesa->new_state |= FX_NEW_TEXTURING;
452 }
453 }
454
455
456 void
457 fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
458 {
459 fxMesaContext fxMesa = FX_CONTEXT(ctx);
460
461 if (TDFX_DEBUG & VERBOSE_DRIVER) {
462 fprintf(stderr, "%s(%d)\n", __FUNCTION__, state);
463 }
464
465 if (state) {
466 fxMesa->haveGlobalPaletteTexture = 1;
467
468 grTexDownloadTable(GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette));
469 }
470 else {
471 fxMesa->haveGlobalPaletteTexture = 0;
472
473 if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) &&
474 (ctx->Texture.Unit[0]._Current != NULL)) {
475 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
476
477 if (!tObj->DriverData)
478 tObj->DriverData = fxAllocTexObjData(fxMesa);
479
480 fxTexInvalidate(ctx, tObj);
481 }
482 }
483 }
484
485
486 static int
487 logbase2(int n)
488 {
489 GLint i = 1;
490 GLint log2 = 0;
491
492 if (n < 0) {
493 return -1;
494 }
495
496 while (n > i) {
497 i *= 2;
498 log2++;
499 }
500 if (i != n) {
501 return -1;
502 }
503 else {
504 return log2;
505 }
506 }
507
508
509 int
510 fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar,
511 float *sscale, float *tscale,
512 int *wscale, int *hscale)
513 {
514 static GrLOD_t lod[12] = {
515 GR_LOD_LOG2_1,
516 GR_LOD_LOG2_2,
517 GR_LOD_LOG2_4,
518 GR_LOD_LOG2_8,
519 GR_LOD_LOG2_16,
520 GR_LOD_LOG2_32,
521 GR_LOD_LOG2_64,
522 GR_LOD_LOG2_128,
523 GR_LOD_LOG2_256,
524 GR_LOD_LOG2_512,
525 GR_LOD_LOG2_1024,
526 GR_LOD_LOG2_2048
527 };
528
529 int logw, logh, ws, hs;
530 GrLOD_t l;
531 GrAspectRatio_t aspectratio;
532 float s, t;
533
534 logw = logbase2(w);
535 logh = logbase2(h);
536
537 switch (logw - logh) {
538 case 0:
539 aspectratio = GR_ASPECT_LOG2_1x1;
540 l = lod[logw];
541 s = t = 256.0f;
542 ws = hs = 1;
543 break;
544 case 1:
545 aspectratio = GR_ASPECT_LOG2_2x1;
546 l = lod[logw];
547 s = 256.0f;
548 t = 128.0f;
549 ws = 1;
550 hs = 1;
551 break;
552 case 2:
553 aspectratio = GR_ASPECT_LOG2_4x1;
554 l = lod[logw];
555 s = 256.0f;
556 t = 64.0f;
557 ws = 1;
558 hs = 1;
559 break;
560 case 3:
561 aspectratio = GR_ASPECT_LOG2_8x1;
562 l = lod[logw];
563 s = 256.0f;
564 t = 32.0f;
565 ws = 1;
566 hs = 1;
567 break;
568 case -1:
569 aspectratio = GR_ASPECT_LOG2_1x2;
570 l = lod[logh];
571 s = 128.0f;
572 t = 256.0f;
573 ws = 1;
574 hs = 1;
575 break;
576 case -2:
577 aspectratio = GR_ASPECT_LOG2_1x4;
578 l = lod[logh];
579 s = 64.0f;
580 t = 256.0f;
581 ws = 1;
582 hs = 1;
583 break;
584 case -3:
585 aspectratio = GR_ASPECT_LOG2_1x8;
586 l = lod[logh];
587 s = 32.0f;
588 t = 256.0f;
589 ws = 1;
590 hs = 1;
591 break;
592 default:
593 if ((logw - logh) > 3) {
594 aspectratio = GR_ASPECT_LOG2_8x1;
595 l = lod[logw];
596 s = 256.0f;
597 t = 32.0f;
598 ws = 1;
599 hs = 1 << (logw - logh - 3);
600 } else /*if ((logw - logh) < -3)*/ {
601 aspectratio = GR_ASPECT_LOG2_1x8;
602 l = lod[logh];
603 s = 32.0f;
604 t = 256.0f;
605 ws = 1 << (logh - logw - 3);
606 hs = 1;
607 }
608 }
609
610 if (lodlevel)
611 (*lodlevel) = l;
612
613 if (ar)
614 (*ar) = aspectratio;
615
616 if (sscale)
617 (*sscale) = s;
618
619 if (tscale)
620 (*tscale) = t;
621
622 if (wscale)
623 (*wscale) = ws;
624
625 if (hscale)
626 (*hscale) = hs;
627
628
629 return 1;
630 }
631
632 static GLboolean
633 fxIsTexSupported(GLenum target, GLint internalFormat,
634 const struct gl_texture_image *image)
635 {
636 if (target != GL_TEXTURE_2D)
637 return GL_FALSE;
638
639 if (!fxTexGetInfo(image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL))
640 return GL_FALSE;
641
642 if (image->Border > 0)
643 return GL_FALSE;
644
645 return GL_TRUE;
646 }
647
648
649 /**********************************************************************/
650 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
651 /**********************************************************************/
652
653 /* Texel-fetch functions for software texturing and glGetTexImage().
654 * We should have been able to use some "standard" fetch functions (which
655 * may get defined in texutil.c) but we have to account for scaled texture
656 * images on tdfx hardware (the 8:1 aspect ratio limit).
657 * Hence, we need special functions here.
658 */
659
660 static void
661 fetch_intensity8(const struct gl_texture_image *texImage,
662 GLint i, GLint j, GLint k, GLvoid * texelOut)
663 {
664 GLchan *rgba = (GLchan *) texelOut;
665 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
666 const GLubyte *texel;
667
668 i = i * mml->wScale;
669 j = j * mml->hScale;
670
671 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
672 rgba[RCOMP] = *texel;
673 rgba[GCOMP] = *texel;
674 rgba[BCOMP] = *texel;
675 rgba[ACOMP] = *texel;
676 }
677
678
679 static void
680 fetch_luminance8(const struct gl_texture_image *texImage,
681 GLint i, GLint j, GLint k, GLvoid * texelOut)
682 {
683 GLchan *rgba = (GLchan *) texelOut;
684 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
685 const GLubyte *texel;
686
687 i = i * mml->wScale;
688 j = j * mml->hScale;
689
690 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
691 rgba[RCOMP] = *texel;
692 rgba[GCOMP] = *texel;
693 rgba[BCOMP] = *texel;
694 rgba[ACOMP] = 255;
695 }
696
697
698 static void
699 fetch_alpha8(const struct gl_texture_image *texImage,
700 GLint i, GLint j, GLint k, GLvoid * texelOut)
701 {
702 GLchan *rgba = (GLchan *) texelOut;
703 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
704 const GLubyte *texel;
705
706 i = i * mml->wScale;
707 j = j * mml->hScale;
708 i = i * mml->width / texImage->Width;
709 j = j * mml->height / texImage->Height;
710
711 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
712 rgba[RCOMP] = 255;
713 rgba[GCOMP] = 255;
714 rgba[BCOMP] = 255;
715 rgba[ACOMP] = *texel;
716 }
717
718
719 static void
720 fetch_index8(const struct gl_texture_image *texImage,
721 GLint i, GLint j, GLint k, GLvoid * texelOut)
722 {
723 GLchan *indexOut = (GLchan *) texelOut;
724 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
725 const GLubyte *texel;
726
727 i = i * mml->wScale;
728 j = j * mml->hScale;
729 i = i * mml->width / texImage->Width;
730 j = j * mml->height / texImage->Height;
731
732 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
733 *indexOut = *texel;
734 }
735
736
737 static void
738 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
739 GLint i, GLint j, GLint k, GLvoid * texelOut)
740 {
741 GLchan *rgba = (GLchan *) texelOut;
742 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
743 const GLubyte *texel;
744
745 i = i * mml->wScale;
746 j = j * mml->hScale;
747
748 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
749 rgba[RCOMP] = texel[0];
750 rgba[GCOMP] = texel[0];
751 rgba[BCOMP] = texel[0];
752 rgba[ACOMP] = texel[1];
753 }
754
755
756 static void
757 fetch_r5g6b5(const struct gl_texture_image *texImage,
758 GLint i, GLint j, GLint k, GLvoid * texelOut)
759 {
760 GLchan *rgba = (GLchan *) texelOut;
761 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
762 const GLushort *texel;
763
764 i = i * mml->wScale;
765 j = j * mml->hScale;
766
767 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
768 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
769 rgba[GCOMP] = FX_rgb_scale_6[(*texel >> 5) & 0x3F];
770 rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
771 rgba[ACOMP] = 255;
772 }
773
774
775 static void
776 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
777 GLint i, GLint j, GLint k, GLvoid * texelOut)
778 {
779 GLchan *rgba = (GLchan *) texelOut;
780 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
781 const GLushort *texel;
782
783 i = i * mml->wScale;
784 j = j * mml->hScale;
785
786 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
787 rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
788 rgba[GCOMP] = FX_rgb_scale_4[(*texel >> 8) & 0xF];
789 rgba[BCOMP] = FX_rgb_scale_4[(*texel >> 4) & 0xF];
790 rgba[ACOMP] = FX_rgb_scale_4[ *texel & 0xF];
791 }
792
793
794 static void
795 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
796 GLint i, GLint j, GLint k, GLvoid * texelOut)
797 {
798 GLchan *rgba = (GLchan *) texelOut;
799 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
800 const GLushort *texel;
801
802 i = i * mml->wScale;
803 j = j * mml->hScale;
804
805 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
806 rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
807 rgba[GCOMP] = FX_rgb_scale_5[(*texel >> 6) & 0x1F];
808 rgba[BCOMP] = FX_rgb_scale_5[(*texel >> 1) & 0x1F];
809 rgba[ACOMP] = ((*texel) & 0x01) * 255;
810 }
811
812
813 static void
814 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
815 GLint i, GLint j, GLint k, GLvoid * texelOut)
816 {
817 GLchan *rgba = (GLchan *) texelOut;
818 const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
819 const GLuint *texel;
820
821 i = i * mml->wScale;
822 j = j * mml->hScale;
823
824 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
825 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
826 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
827 rgba[BCOMP] = (((*texel) ) & 0xff);
828 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
829 }
830
831
832 static void
833 PrintTexture(int w, int h, int c, const GLubyte * data)
834 {
835 int i, j;
836 for (i = 0; i < h; i++) {
837 for (j = 0; j < w; j++) {
838 if (c == 2)
839 fprintf(stderr, "%02x %02x ", data[0], data[1]);
840 else if (c == 3)
841 fprintf(stderr, "%02x %02x %02x ", data[0], data[1], data[2]);
842 data += c;
843 }
844 fprintf(stderr, "\n");
845 }
846 }
847
848
849 const struct gl_texture_format *
850 fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
851 GLenum srcFormat, GLenum srcType )
852 {
853 fxMesaContext fxMesa = FX_CONTEXT(ctx);
854 GLboolean allow32bpt = fxMesa->HaveTexFmt;
855
856 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
857 fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
858 }
859
860 switch (internalFormat) {
861 case GL_INTENSITY:
862 case GL_INTENSITY4:
863 case GL_INTENSITY8:
864 case GL_INTENSITY12:
865 case GL_INTENSITY16:
866 case GL_COMPRESSED_INTENSITY:
867 return &_mesa_texformat_i8;
868 case 1:
869 case GL_LUMINANCE:
870 case GL_LUMINANCE4:
871 case GL_LUMINANCE8:
872 case GL_LUMINANCE12:
873 case GL_LUMINANCE16:
874 case GL_COMPRESSED_LUMINANCE:
875 return &_mesa_texformat_l8;
876 case GL_ALPHA:
877 case GL_ALPHA4:
878 case GL_ALPHA8:
879 case GL_ALPHA12:
880 case GL_ALPHA16:
881 case GL_COMPRESSED_ALPHA:
882 return &_mesa_texformat_a8;
883 case GL_COLOR_INDEX:
884 case GL_COLOR_INDEX1_EXT:
885 case GL_COLOR_INDEX2_EXT:
886 case GL_COLOR_INDEX4_EXT:
887 case GL_COLOR_INDEX8_EXT:
888 case GL_COLOR_INDEX12_EXT:
889 case GL_COLOR_INDEX16_EXT:
890 return &_mesa_texformat_ci8;
891 case 2:
892 case GL_LUMINANCE_ALPHA:
893 case GL_LUMINANCE4_ALPHA4:
894 case GL_LUMINANCE6_ALPHA2:
895 case GL_LUMINANCE8_ALPHA8:
896 case GL_LUMINANCE12_ALPHA4:
897 case GL_LUMINANCE12_ALPHA12:
898 case GL_LUMINANCE16_ALPHA16:
899 case GL_COMPRESSED_LUMINANCE_ALPHA:
900 return &_mesa_texformat_al88;
901 case GL_R3_G3_B2:
902 case GL_RGB4:
903 case GL_RGB5:
904 return &_mesa_texformat_rgb565;
905 case 3:
906 case GL_RGB:
907 case GL_COMPRESSED_RGB:
908 if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
909 return &_mesa_texformat_rgb565;
910 }
911 /* intentional fall through */
912 case GL_RGB8:
913 case GL_RGB10:
914 case GL_RGB12:
915 case GL_RGB16:
916 return (allow32bpt) ? &_mesa_texformat_argb8888
917 : &_mesa_texformat_rgb565;
918 case GL_RGBA2:
919 case GL_RGBA4:
920 return &_mesa_texformat_argb4444;
921 case 4:
922 case GL_RGBA:
923 case GL_COMPRESSED_RGBA:
924 if ( srcFormat == GL_BGRA ) {
925 if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
926 return &_mesa_texformat_argb8888;
927 }
928 else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
929 return &_mesa_texformat_argb4444;
930 }
931 else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
932 return &_mesa_texformat_argb1555;
933 }
934 }
935 /* intentional fall through */
936 case GL_RGBA8:
937 case GL_RGB10_A2:
938 case GL_RGBA12:
939 case GL_RGBA16:
940 return (allow32bpt) ? &_mesa_texformat_argb8888
941 : &_mesa_texformat_argb4444;
942 case GL_RGB5_A1:
943 return &_mesa_texformat_argb1555;
944 #if 0
945 /* GL_EXT_texture_compression_s3tc */
946 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
947 return &_mesa_texformat_rgb_dxt1;
948 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
949 return &_mesa_texformat_rgba_dxt1;
950 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
951 return &_mesa_texformat_rgba_dxt3;
952 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
953 return &_mesa_texformat_rgba_dxt5;
954 /*case GL_COMPRESSED_RGB_FXT1_3DFX:
955 case GL_COMPRESSED_RGBA_FXT1_3DFX:
956 return blah;*/
957 #endif
958 default:
959 _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
960 return NULL;
961 }
962 }
963
964
965 static GrTextureFormat_t
966 fxGlideFormat(GLint mesaFormat)
967 {
968 switch (mesaFormat) {
969 case MESA_FORMAT_I8:
970 return GR_TEXFMT_ALPHA_8;
971 case MESA_FORMAT_A8:
972 return GR_TEXFMT_ALPHA_8;
973 case MESA_FORMAT_L8:
974 return GR_TEXFMT_INTENSITY_8;
975 case MESA_FORMAT_CI8:
976 return GR_TEXFMT_P_8;
977 case MESA_FORMAT_AL88:
978 return GR_TEXFMT_ALPHA_INTENSITY_88;
979 case MESA_FORMAT_RGB565:
980 return GR_TEXFMT_RGB_565;
981 case MESA_FORMAT_ARGB4444:
982 return GR_TEXFMT_ARGB_4444;
983 case MESA_FORMAT_ARGB1555:
984 return GR_TEXFMT_ARGB_1555;
985 case MESA_FORMAT_ARGB8888:
986 return GR_TEXFMT_ARGB_8888;
987 #if 0
988 case MESA_FORMAT_RGB_DXT1:
989 case MESA_FORMAT_RGBA_DXT1:
990 return GR_TEXFMT_ARGB_CMP_DXT1;
991 case MESA_FORMAT_RGBA_DXT3:
992 return GR_TEXFMT_ARGB_CMP_DXT3;
993 case MESA_FORMAT_RGBA_DXT5:
994 return GR_TEXFMT_ARGB_CMP_DXT5;
995 /*case MESA_FORMAT_ARGB_CMP_FXT1:
996 return GR_TEXFMT_ARGB_CMP_FXT1;
997 case MESA_FORMAT_RGB_CMP_FXT1:
998 return GL_COMPRESSED_RGBA_FXT1_3DFX;*/
999 #endif
1000 default:
1001 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
1002 return 0;
1003 }
1004 }
1005
1006
1007 static FetchTexelFunc
1008 fxFetchFunction(GLint mesaFormat)
1009 {
1010 switch (mesaFormat) {
1011 case MESA_FORMAT_I8:
1012 return fetch_intensity8;
1013 case MESA_FORMAT_A8:
1014 return fetch_alpha8;
1015 case MESA_FORMAT_L8:
1016 return fetch_luminance8;
1017 case MESA_FORMAT_CI8:
1018 return fetch_index8;
1019 case MESA_FORMAT_AL88:
1020 return fetch_luminance8_alpha8;
1021 case MESA_FORMAT_RGB565:
1022 return fetch_r5g6b5;
1023 case MESA_FORMAT_ARGB4444:
1024 return fetch_r4g4b4a4;
1025 case MESA_FORMAT_ARGB1555:
1026 return fetch_r5g5b5a1;
1027 case MESA_FORMAT_ARGB8888:
1028 return fetch_a8r8g8b8;
1029 #if 0
1030 case MESA_FORMAT_RGB_DXT1:
1031 case MESA_FORMAT_RGBA_DXT1:
1032 case MESA_FORMAT_RGBA_DXT3:
1033 case MESA_FORMAT_RGBA_DXT5:
1034 return fetch_r4g4b4a4;
1035 #endif
1036 default:
1037 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1038 return NULL;
1039 }
1040 }
1041
1042 void
1043 fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
1044 GLint internalFormat, GLint width, GLint height, GLint border,
1045 GLenum format, GLenum type, const GLvoid * pixels,
1046 const struct gl_pixelstore_attrib *packing,
1047 struct gl_texture_object *texObj,
1048 struct gl_texture_image *texImage)
1049 {
1050 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1051 tfxTexInfo *ti;
1052 tfxMipMapLevel *mml;
1053 GLint texelBytes;
1054
1055 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1056 fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1057 texObj->Name, texImage->IntFormat, format, type,
1058 texImage->Width, texImage->Height);
1059 }
1060
1061 if (!fxIsTexSupported(target, internalFormat, texImage)) {
1062 _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
1063 return;
1064 }
1065
1066 if (!texObj->DriverData) {
1067 texObj->DriverData = fxAllocTexObjData(fxMesa);
1068 if (!texObj->DriverData) {
1069 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1070 return;
1071 }
1072 }
1073 ti = fxTMGetTexInfo(texObj);
1074
1075 if (!texImage->DriverData) {
1076 texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
1077 if (!texImage->DriverData) {
1078 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1079 return;
1080 }
1081 }
1082 mml = FX_MIPMAP_DATA(texImage);
1083
1084 fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
1085 &mml->wScale, &mml->hScale);
1086
1087 mml->width = width * mml->wScale;
1088 mml->height = height * mml->hScale;
1089
1090
1091 /* choose the texture format */
1092 assert(ctx->Driver.ChooseTextureFormat);
1093 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1094 internalFormat, format, type);
1095 assert(texImage->TexFormat);
1096 texelBytes = texImage->TexFormat->TexelBytes;
1097 /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
1098
1099 if (mml->wScale != 1 || mml->hScale != 1) {
1100 /* rescale image to overcome 1:8 aspect limitation */
1101 GLvoid *tempImage;
1102 tempImage = MALLOC(width * height * texelBytes);
1103 if (!tempImage) {
1104 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1105 return;
1106 }
1107 /* unpack image, apply transfer ops and store in tempImage */
1108 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1109 texImage->TexFormat,
1110 tempImage,
1111 width, height, 1, 0, 0, 0,
1112 width * texelBytes,
1113 0, /* dstImageStride */
1114 format, type, pixels, packing);
1115 assert(!texImage->Data);
1116 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1117 if (!texImage->Data) {
1118 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1119 FREE(tempImage);
1120 return;
1121 }
1122 _mesa_rescale_teximage2d(texelBytes,
1123 mml->width * texelBytes, /* dst stride */
1124 width, height,
1125 mml->width, mml->height,
1126 tempImage /*src*/, texImage->Data /*dst*/ );
1127 FREE(tempImage);
1128 }
1129 else {
1130 /* no rescaling needed */
1131 assert(!texImage->Data);
1132 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
1133 if (!texImage->Data) {
1134 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1135 return;
1136 }
1137 /* unpack image, apply transfer ops and store in texImage->Data */
1138 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1139 texImage->TexFormat, texImage->Data,
1140 width, height, 1, 0, 0, 0,
1141 texImage->Width * texelBytes,
1142 0, /* dstImageStride */
1143 format, type, pixels, packing);
1144 }
1145
1146 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
1147 ti->info.format = mml->glideFormat;
1148 texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
1149
1150 /* [dBorca]
1151 * Hack alert: unsure...
1152 */
1153 if (!(fxMesa->new_state & FX_NEW_TEXTURING) && ti->validated && ti->isInTM) {
1154 /*fprintf(stderr, "reloadmipmaplevels\n"); */
1155 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1156 }
1157 else {
1158 /*fprintf(stderr, "invalidate2\n"); */
1159 fxTexInvalidate(ctx, texObj);
1160 }
1161 }
1162
1163
1164 void
1165 fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
1166 GLint xoffset, GLint yoffset,
1167 GLsizei width, GLsizei height,
1168 GLenum format, GLenum type, const GLvoid * pixels,
1169 const struct gl_pixelstore_attrib *packing,
1170 struct gl_texture_object *texObj,
1171 struct gl_texture_image *texImage)
1172 {
1173 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1174 tfxTexInfo *ti;
1175 tfxMipMapLevel *mml;
1176 GLint texelBytes;
1177
1178 if (TDFX_DEBUG & VERBOSE_TEXTURE) {
1179 fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
1180 }
1181
1182 if (!texObj->DriverData) {
1183 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1184 return;
1185 }
1186
1187 ti = fxTMGetTexInfo(texObj);
1188 assert(ti);
1189 mml = FX_MIPMAP_DATA(texImage);
1190 assert(mml);
1191
1192 assert(texImage->Data); /* must have an existing texture image! */
1193 assert(texImage->Format);
1194
1195 texelBytes = texImage->TexFormat->TexelBytes;
1196
1197 if (mml->wScale != 1 || mml->hScale != 1) {
1198 /* need to rescale subimage to match mipmap level's rescale factors */
1199 const GLint newWidth = width * mml->wScale;
1200 const GLint newHeight = height * mml->hScale;
1201 GLvoid *tempImage;
1202 GLubyte *destAddr;
1203 tempImage = MALLOC(width * height * texelBytes);
1204 if (!tempImage) {
1205 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1206 return;
1207 }
1208
1209 _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */
1210 texImage->TexFormat, /* dest format */
1211 (GLubyte *) tempImage, /* dest */
1212 width, height, 1, /* subimage size */
1213 0, 0, 0, /* subimage pos */
1214 width * texelBytes, /* dest row stride */
1215 0, /* dst image stride */
1216 format, type, pixels, packing);
1217
1218 /* now rescale */
1219 /* compute address of dest subimage within the overal tex image */
1220 destAddr = (GLubyte *) texImage->Data
1221 + (yoffset * mml->hScale * mml->width
1222 + xoffset * mml->wScale) * texelBytes;
1223
1224 _mesa_rescale_teximage2d(texelBytes,
1225 mml->width * texelBytes, /* dst stride */
1226 width, height,
1227 newWidth, newHeight,
1228 tempImage, destAddr);
1229
1230 FREE(tempImage);
1231 }
1232 else {
1233 /* no rescaling needed */
1234 _mesa_transfer_teximage(ctx, 2, texImage->Format, /* Tex int format */
1235 texImage->TexFormat, /* dest format */
1236 (GLubyte *) texImage->Data,/* dest */
1237 width, height, 1, /* subimage size */
1238 xoffset, yoffset, 0, /* subimage pos */
1239 mml->width * texelBytes, /* dest row stride */
1240 0, /* dst image stride */
1241 format, type, pixels, packing);
1242 }
1243
1244 /* [dBorca]
1245 * Hack alert: unsure...
1246 */
1247 if (!(fxMesa->new_state & FX_NEW_TEXTURING) && ti->validated && ti->isInTM)
1248 fxTMReloadMipMapLevel(fxMesa, texObj, level);
1249 else
1250 fxTexInvalidate(ctx, texObj);
1251 }
1252
1253
1254 #else /* FX */
1255
1256 /*
1257 * Need this to provide at least one external definition.
1258 */
1259
1260 extern int gl_fx_dummy_function_ddtex(void);
1261 int
1262 gl_fx_dummy_function_ddtex(void)
1263 {
1264 return 0;
1265 }
1266
1267 #endif /* FX */