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