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