Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / tdfx / tdfx_tex.c
1 /* -*- mode: c; c-basic-offset: 3 -*-
2  *
3  * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4  *
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 /*
28  * New fixes:
29  *      Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
30  *
31  * Original rewrite:
32  *      Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
33  *
34  * Authors:
35  *      Gareth Hughes <gareth@valinux.com>
36  *      Brian Paul <brianp@valinux.com>
37  *
38  */
39
40
41 #include "main/enums.h"
42 #include "main/image.h"
43 #include "main/mipmap.h"
44 #include "main/texcompress.h"
45 #include "main/teximage.h"
46 #include "main/texstore.h"
47 #include "main/texobj.h"
48 #include "tdfx_context.h"
49 #include "tdfx_tex.h"
50 #include "tdfx_texman.h"
51
52
53 /* no borders! can't halve 1x1! (stride > width * comp) not allowed */
54 static void
55 _mesa_halve2x2_teximage2d ( struct gl_context *ctx,
56                             struct gl_texture_image *texImage,
57                             GLuint bytesPerPixel,
58                             GLint srcWidth, GLint srcHeight,
59                             const GLvoid *srcImage, GLvoid *dstImage )
60 {
61    GLint i, j, k;
62    GLint dstWidth = srcWidth / 2;
63    GLint dstHeight = srcHeight / 2;
64    GLint srcRowStride = srcWidth * bytesPerPixel;
65    GLubyte *src = (GLubyte *)srcImage;
66    GLubyte *dst = dstImage;
67    GLuint dstImageOffsets = 0;
68
69    GLuint bpt = 0;
70    GLubyte *_s = NULL;
71    GLubyte *_d = NULL;
72    GLenum _t = 0;
73
74    if (texImage->TexFormat == MESA_FORMAT_RGB565) {
75       _t = GL_UNSIGNED_SHORT_5_6_5_REV;
76       bpt = bytesPerPixel;
77    } else if (texImage->TexFormat == MESA_FORMAT_ARGB4444) {
78       _t = GL_UNSIGNED_SHORT_4_4_4_4_REV;
79       bpt = bytesPerPixel;
80    } else if (texImage->TexFormat == MESA_FORMAT_ARGB1555) {
81       _t = GL_UNSIGNED_SHORT_1_5_5_5_REV;
82       bpt = bytesPerPixel;
83    }
84    if (bpt) {
85       bytesPerPixel = 4;
86       srcRowStride = srcWidth * bytesPerPixel;
87       if (dstWidth == 0) {
88          dstWidth = 1;
89       }
90       if (dstHeight == 0) {
91          dstHeight = 1;
92       }
93       _s = src = MALLOC(srcRowStride * srcHeight);
94       _d = dst = MALLOC(dstWidth * bytesPerPixel * dstHeight);
95       _mesa_texstore(ctx, 2, GL_RGBA,
96                      MESA_FORMAT_RGBA8888_REV, src,
97                      0, 0, 0, /* dstX/Y/Zoffset */
98                      srcRowStride, /* dstRowStride */
99                      &dstImageOffsets,
100                      srcWidth, srcHeight, 1,
101                      texImage->_BaseFormat, _t, srcImage, &ctx->DefaultPacking);
102    }
103
104    if (srcHeight == 1) {
105       for (i = 0; i < dstWidth; i++) {
106          for (k = 0; k < bytesPerPixel; k++) {
107             dst[0] = (src[0] + src[bytesPerPixel] + 1) / 2;
108             src++;
109             dst++;
110          }
111          src += bytesPerPixel;
112       }
113    } else if (srcWidth == 1) {
114       for (j = 0; j < dstHeight; j++) {
115          for (k = 0; k < bytesPerPixel; k++) {
116             dst[0] = (src[0] + src[srcRowStride] + 1) / 2;
117             src++;
118             dst++;
119          }
120          src += srcRowStride;
121       }
122    } else {
123       for (j = 0; j < dstHeight; j++) {
124          for (i = 0; i < dstWidth; i++) {
125             for (k = 0; k < bytesPerPixel; k++) {
126                dst[0] = (src[0] +
127                          src[bytesPerPixel] +
128                          src[srcRowStride] +
129                          src[srcRowStride + bytesPerPixel] + 2) / 4;
130                src++;
131                dst++;
132             }
133             src += bytesPerPixel;
134          }
135          src += srcRowStride;
136       }
137    }
138
139    if (bpt) {
140       src = _s;
141       dst = _d;
142       _mesa_texstore(ctx, 2, texImage->_BaseFormat,
143                      texImage->TexFormat, dstImage,
144                      0, 0, 0, /* dstX/Y/Zoffset */
145                      dstWidth * bpt,
146                      &dstImageOffsets,
147                      dstWidth, dstHeight, 1,
148                      GL_BGRA, CHAN_TYPE, dst, &ctx->DefaultPacking);
149       FREE(dst);
150       FREE(src);
151    }
152 }
153
154
155 static int
156 logbase2(int n)
157 {
158     GLint i = 1;
159     GLint log2 = 0;
160
161     if (n < 0) {
162         return -1;
163     }
164
165     while (n > i) {
166         i *= 2;
167         log2++;
168     }
169     if (i != n) {
170         return -1;
171     }
172     else {
173         return log2;
174     }
175 }
176
177
178 static void
179 tdfxGenerateMipmap(struct gl_context *ctx, GLenum target,
180                    struct gl_texture_object *texObj)
181 {
182    GLint mipWidth, mipHeight;
183    tdfxMipMapLevel *mip;
184    struct gl_texture_image *mipImage; /* the new/next image */
185    struct gl_texture_image *texImage;
186    const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
187    GLint level = texObj->BaseLevel;
188    GLsizei width, height, texelBytes;
189    const tdfxMipMapLevel *mml;
190
191    texImage = _mesa_get_tex_image(ctx, texObj, target, level);
192    texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
193
194    mml = TDFX_TEXIMAGE_DATA(texImage);
195
196    width = texImage->Width;
197    height = texImage->Height;
198    while (level < texObj->MaxLevel && level < maxLevels - 1) {
199       mipWidth = width / 2;
200       if (!mipWidth) {
201          mipWidth = 1;
202       }
203       mipHeight = height / 2;
204       if (!mipHeight) {
205          mipHeight = 1;
206       }
207       if ((mipWidth == width) && (mipHeight == height)) {
208          break;
209       }
210       ++level;
211       mipImage = _mesa_select_tex_image(ctx, texObj, target, level);
212       mip = TDFX_TEXIMAGE_DATA(mipImage);
213       _mesa_halve2x2_teximage2d(ctx,
214                                 texImage,
215                                 texelBytes,
216                                 mml->width, mml->height,
217                                 texImage->Data, mipImage->Data);
218       texImage = mipImage;
219       mml = mip;
220       width = mipWidth;
221       height = mipHeight;
222    }
223 }
224
225
226 /*
227  * Compute various texture image parameters.
228  * Input:  w, h - source texture width and height
229  * Output:  lodlevel - Glide lod level token for the larger texture dimension
230  *          aspectratio - Glide aspect ratio token
231  *          sscale - S scale factor used during triangle setup
232  *          tscale - T scale factor used during triangle setup
233  *          wscale - OpenGL -> Glide image width scale factor
234  *          hscale - OpenGL -> Glide image height scale factor
235  *
236  * Sample results:
237  *      w    h       lodlevel               aspectRatio
238  *     128  128  GR_LOD_LOG2_128 (=7)  GR_ASPECT_LOG2_1x1 (=0)
239  *      64   64  GR_LOD_LOG2_64 (=6)   GR_ASPECT_LOG2_1x1 (=0)
240  *      64   32  GR_LOD_LOG2_64 (=6)   GR_ASPECT_LOG2_2x1 (=1)
241  *      32   64  GR_LOD_LOG2_64 (=6)   GR_ASPECT_LOG2_1x2 (=-1)
242  *      32   32  GR_LOD_LOG2_32 (=5)   GR_ASPECT_LOG2_1x1 (=0)
243  */
244 static void
245 tdfxTexGetInfo(const struct gl_context *ctx, int w, int h,
246                GrLOD_t *lodlevel, GrAspectRatio_t *aspectratio,
247                float *sscale, float *tscale,
248                int *wscale, int *hscale)
249 {
250     int logw, logh, ar, lod, ws, hs;
251     float s, t;
252
253     ASSERT(w >= 1);
254     ASSERT(h >= 1);
255
256     logw = logbase2(w);
257     logh = logbase2(h);
258     ar = logw - logh;  /* aspect ratio = difference in log dimensions */
259     s = t = 256.0;
260     ws = hs = 1;
261
262     /* Hardware only allows a maximum aspect ratio of 8x1, so handle
263        |ar| > 3 by scaling the image and using an 8x1 aspect ratio */
264     if (ar >= 0) {
265         ASSERT(w >= h);
266         lod = logw;
267         if (ar <= GR_ASPECT_LOG2_8x1) {
268             t = 256 >> ar;
269         }
270         else {
271             /* have to stretch image height */
272             t = 32.0;
273             hs = 1 << (ar - 3);
274             ar = GR_ASPECT_LOG2_8x1;
275         }
276     }
277     else {
278         ASSERT(w < h);
279         lod = logh;
280         if (ar >= GR_ASPECT_LOG2_1x8) {
281             s = 256 >> -ar;
282         }
283         else {
284             /* have to stretch image width */
285             s = 32.0;
286             ws = 1 << (-ar - 3);
287             ar = GR_ASPECT_LOG2_1x8;
288         }
289     }
290
291     if (lodlevel)
292         *lodlevel = (GrLOD_t) lod;
293     if (aspectratio)
294         *aspectratio = (GrAspectRatio_t) ar;
295     if (sscale)
296         *sscale = s;
297     if (tscale)
298         *tscale = t;
299     if (wscale)
300         *wscale = ws;
301     if (hscale)
302         *hscale = hs;
303 }
304
305
306 /*
307  * We need to call this when a texture object's minification filter
308  * or texture image sizes change.
309  */
310 static void RevalidateTexture(struct gl_context *ctx, struct gl_texture_object *tObj)
311 {
312     tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
313     GLint minl, maxl;
314
315     if (!ti)
316        return;
317
318     minl = maxl = tObj->BaseLevel;
319
320     if (tObj->Image[0][minl]) {
321        maxl = MIN2(tObj->MaxLevel, tObj->Image[0][minl]->MaxLog2);
322
323        /* compute largeLodLog2, aspect ratio and texcoord scale factors */
324        tdfxTexGetInfo(ctx, tObj->Image[0][minl]->Width, tObj->Image[0][minl]->Height,
325                       &ti->info.largeLodLog2,
326                       &ti->info.aspectRatioLog2,
327                       &(ti->sScale), &(ti->tScale), NULL, NULL);
328     }
329
330     if (tObj->Image[0][maxl] && (tObj->Sampler.MinFilter != GL_NEAREST) && (tObj->Sampler.MinFilter != GL_LINEAR)) {
331         /* mipmapping: need to compute smallLodLog2 */
332         tdfxTexGetInfo(ctx, tObj->Image[0][maxl]->Width,
333                        tObj->Image[0][maxl]->Height,
334                        &ti->info.smallLodLog2, NULL,
335                        NULL, NULL, NULL, NULL);
336     }
337     else {
338         /* not mipmapping: smallLodLog2 = largeLodLog2 */
339         ti->info.smallLodLog2 = ti->info.largeLodLog2;
340         maxl = minl;
341     }
342
343     ti->minLevel = minl;
344     ti->maxLevel = maxl;
345     ti->info.data = NULL;
346
347    /* this is necessary because of fxDDCompressedTexImage2D */
348    if (ti->padded) {
349       struct gl_texture_image *texImage = tObj->Image[0][minl];
350       tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
351       if (mml->wScale != 1 || mml->hScale != 1) {
352          ti->sScale /= mml->wScale;
353          ti->tScale /= mml->hScale;
354       }
355    }
356 }
357
358
359 static tdfxTexInfo *
360 fxAllocTexObjData(tdfxContextPtr fxMesa)
361 {
362     tdfxTexInfo *ti;
363
364     if (!(ti = CALLOC(sizeof(tdfxTexInfo)))) {
365         _mesa_problem(NULL, "tdfx driver: out of memory");
366         return NULL;
367     }
368
369     ti->isInTM = GL_FALSE;
370
371     ti->whichTMU = TDFX_TMU_NONE;
372
373     ti->tm[TDFX_TMU0] = NULL;
374     ti->tm[TDFX_TMU1] = NULL;
375
376     ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
377     ti->magFilt = GR_TEXTUREFILTER_BILINEAR;
378
379     ti->sClamp = GR_TEXTURECLAMP_WRAP;
380     ti->tClamp = GR_TEXTURECLAMP_WRAP;
381
382     ti->mmMode = GR_MIPMAP_NEAREST;
383     ti->LODblend = FXFALSE;
384
385     return ti;
386 }
387
388
389 /*
390  * Called via glBindTexture.
391  */
392 static void
393 tdfxBindTexture(struct gl_context * ctx, GLenum target,
394                   struct gl_texture_object *tObj)
395 {
396     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
397     tdfxTexInfo *ti;
398
399     if (MESA_VERBOSE & VERBOSE_DRIVER) {
400         fprintf(stderr, "fxmesa: fxDDTexBind(%d,%p)\n", tObj->Name,
401                 tObj->DriverData);
402     }
403
404     if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
405         return;
406
407     if (!tObj->DriverData) {
408         tObj->DriverData = fxAllocTexObjData(fxMesa);
409     }
410
411     ti = TDFX_TEXTURE_DATA(tObj);
412     ti->lastTimeUsed = fxMesa->texBindNumber++;
413
414     fxMesa->new_state |= TDFX_NEW_TEXTURE;
415 }
416
417
418 /*
419  * Called via glTexEnv.
420  */
421 static void
422 tdfxTexEnv(struct gl_context * ctx, GLenum target, GLenum pname,
423              const GLfloat * param)
424 {
425     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
426
427     if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
428         if (param)
429             fprintf(stderr, "fxmesa: texenv(%x,%x)\n", pname,
430                     (GLint) (*param));
431         else
432             fprintf(stderr, "fxmesa: texenv(%x)\n", pname);
433     }
434
435     /* XXX this is a bit of a hack to force the Glide texture
436      * state to be updated.
437      */
438     fxMesa->TexState.EnvMode[ctx->Texture.CurrentUnit]  = 0;
439
440     fxMesa->new_state |= TDFX_NEW_TEXTURE;
441 }
442
443
444 /*
445  * Called via glTexParameter.
446  */
447 static void
448 tdfxTexParameter(struct gl_context * ctx, GLenum target,
449                    struct gl_texture_object *tObj,
450                    GLenum pname, const GLfloat * params)
451 {
452     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
453     GLenum param = (GLenum) (GLint) params[0];
454     tdfxTexInfo *ti;
455
456     if (MESA_VERBOSE & VERBOSE_DRIVER) {
457         fprintf(stderr, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj->Name,
458                 tObj->DriverData, pname, param);
459     }
460
461     if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
462         return;
463
464     if (!tObj->DriverData)
465         tObj->DriverData = fxAllocTexObjData(fxMesa);
466
467     ti = TDFX_TEXTURE_DATA(tObj);
468
469     switch (pname) {
470     case GL_TEXTURE_MIN_FILTER:
471         switch (param) {
472         case GL_NEAREST:
473             ti->mmMode = GR_MIPMAP_DISABLE;
474             ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
475             ti->LODblend = FXFALSE;
476             break;
477         case GL_LINEAR:
478             ti->mmMode = GR_MIPMAP_DISABLE;
479             ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
480             ti->LODblend = FXFALSE;
481             break;
482         case GL_NEAREST_MIPMAP_LINEAR:
483             if (!fxMesa->Glide.HaveCombineExt) {
484                  if (fxMesa->haveTwoTMUs) {
485                      ti->mmMode = GR_MIPMAP_NEAREST;
486                      ti->LODblend = FXTRUE;
487                  }
488                  else {
489                      ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
490                      ti->LODblend = FXFALSE;
491                  }
492                  ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
493                  break;
494             }
495             /* XXX Voodoo3/Banshee mipmap blending seems to produce
496              * incorrectly filtered colors for the smallest mipmap levels.
497              * To work-around we fall-through here and use a different filter.
498              */
499         case GL_NEAREST_MIPMAP_NEAREST:
500             ti->mmMode = GR_MIPMAP_NEAREST;
501             ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
502             ti->LODblend = FXFALSE;
503             break;
504         case GL_LINEAR_MIPMAP_LINEAR:
505             if (!fxMesa->Glide.HaveCombineExt) {
506                 if (fxMesa->haveTwoTMUs) {
507                     ti->mmMode = GR_MIPMAP_NEAREST;
508                     ti->LODblend = FXTRUE;
509                 }
510                 else {
511                     ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
512                     ti->LODblend = FXFALSE;
513                 }
514                 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
515                 break;
516             }
517             /* XXX Voodoo3/Banshee mipmap blending seems to produce
518              * incorrectly filtered colors for the smallest mipmap levels.
519              * To work-around we fall-through here and use a different filter.
520              */
521         case GL_LINEAR_MIPMAP_NEAREST:
522             ti->mmMode = GR_MIPMAP_NEAREST;
523             ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
524             ti->LODblend = FXFALSE;
525             break;
526         default:
527             break;
528         }
529         ti->reloadImages = GL_TRUE;
530         RevalidateTexture(ctx, tObj);
531         fxMesa->new_state |= TDFX_NEW_TEXTURE;
532         break;
533
534     case GL_TEXTURE_MAG_FILTER:
535         switch (param) {
536         case GL_NEAREST:
537             ti->magFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
538             break;
539         case GL_LINEAR:
540             ti->magFilt = GR_TEXTUREFILTER_BILINEAR;
541             break;
542         default:
543             break;
544         }
545         fxMesa->new_state |= TDFX_NEW_TEXTURE;
546         break;
547
548     case GL_TEXTURE_WRAP_S:
549         switch (param) {
550         case GL_CLAMP_TO_BORDER:
551         case GL_CLAMP_TO_EDGE:
552         case GL_CLAMP:
553             ti->sClamp = GR_TEXTURECLAMP_CLAMP;
554             break;
555         case GL_REPEAT:
556             ti->sClamp = GR_TEXTURECLAMP_WRAP;
557             break;
558         case GL_MIRRORED_REPEAT:
559             ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
560             break;
561         default:
562             break;
563         }
564         fxMesa->new_state |= TDFX_NEW_TEXTURE;
565         break;
566
567     case GL_TEXTURE_WRAP_T:
568         switch (param) {
569         case GL_CLAMP_TO_BORDER:
570         case GL_CLAMP_TO_EDGE:
571         case GL_CLAMP:
572             ti->tClamp = GR_TEXTURECLAMP_CLAMP;
573             break;
574         case GL_REPEAT:
575             ti->tClamp = GR_TEXTURECLAMP_WRAP;
576             break;
577         case GL_MIRRORED_REPEAT:
578             ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
579             break;
580         default:
581             break;
582         }
583         fxMesa->new_state |= TDFX_NEW_TEXTURE;
584         break;
585
586     case GL_TEXTURE_BORDER_COLOR:
587         /* TO DO */
588         break;
589     case GL_TEXTURE_MIN_LOD:
590         /* TO DO */
591         break;
592     case GL_TEXTURE_MAX_LOD:
593         /* TO DO */
594         break;
595     case GL_TEXTURE_BASE_LEVEL:
596         RevalidateTexture(ctx, tObj);
597         break;
598     case GL_TEXTURE_MAX_LEVEL:
599         RevalidateTexture(ctx, tObj);
600         break;
601
602     default:
603         break;
604     }
605 }
606
607
608 /*
609  * Called via glDeleteTextures to delete a texture object.
610  * Here, we delete the Glide data associated with the texture.
611  */
612 static void
613 tdfxDeleteTexture(struct gl_context * ctx, struct gl_texture_object *tObj)
614 {
615     if (ctx && ctx->DriverCtx) {
616         tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
617         tdfxTMFreeTexture(fxMesa, tObj);
618         fxMesa->new_state |= TDFX_NEW_TEXTURE;
619         /* Free mipmap images and the texture object itself */
620         _mesa_delete_texture_object(ctx, tObj);
621     }
622 }
623
624
625 /*
626  * Return true if texture is resident, false otherwise.
627  */
628 static GLboolean
629 tdfxIsTextureResident(struct gl_context *ctx, struct gl_texture_object *tObj)
630 {
631     tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
632     return (GLboolean) (ti && ti->isInTM);
633 }
634
635
636
637 /*
638  * Convert a gl_color_table texture palette to Glide's format.
639  */
640 static GrTexTable_t
641 convertPalette(FxU32 data[256], const struct gl_color_table *table)
642 {
643     const GLubyte *tableUB = table->TableUB;
644     GLint width = table->Size;
645     FxU32 r, g, b, a;
646     GLint i;
647
648     switch (table->_BaseFormat) {
649     case GL_INTENSITY:
650         for (i = 0; i < width; i++) {
651             r = tableUB[i];
652             g = tableUB[i];
653             b = tableUB[i];
654             a = tableUB[i];
655             data[i] = (a << 24) | (r << 16) | (g << 8) | b;
656         }
657         return GR_TEXTABLE_PALETTE_6666_EXT;
658     case GL_LUMINANCE:
659         for (i = 0; i < width; i++) {
660             r = tableUB[i];
661             g = tableUB[i];
662             b = tableUB[i];
663             a = 255;
664             data[i] = (a << 24) | (r << 16) | (g << 8) | b;
665         }
666         return GR_TEXTABLE_PALETTE;
667     case GL_ALPHA:
668         for (i = 0; i < width; i++) {
669             r = g = b = 255;
670             a = tableUB[i];
671             data[i] = (a << 24) | (r << 16) | (g << 8) | b;
672         }
673         return GR_TEXTABLE_PALETTE_6666_EXT;
674     case GL_LUMINANCE_ALPHA:
675         for (i = 0; i < width; i++) {
676             r = g = b = tableUB[i * 2 + 0];
677             a = tableUB[i * 2 + 1];
678             data[i] = (a << 24) | (r << 16) | (g << 8) | b;
679         }
680         return GR_TEXTABLE_PALETTE_6666_EXT;
681     case GL_RGB:
682         for (i = 0; i < width; i++) {
683             r = tableUB[i * 3 + 0];
684             g = tableUB[i * 3 + 1];
685             b = tableUB[i * 3 + 2];
686             a = 255;
687             data[i] = (a << 24) | (r << 16) | (g << 8) | b;
688         }
689         return GR_TEXTABLE_PALETTE;
690     case GL_RGBA:
691         for (i = 0; i < width; i++) {
692             r = tableUB[i * 4 + 0];
693             g = tableUB[i * 4 + 1];
694             b = tableUB[i * 4 + 2];
695             a = tableUB[i * 4 + 3];
696             data[i] = (a << 24) | (r << 16) | (g << 8) | b;
697         }
698         return GR_TEXTABLE_PALETTE_6666_EXT;
699     default:
700         /* XXX fixme: how can this happen? */
701         _mesa_error(NULL, GL_INVALID_ENUM, "convertPalette: table->_BaseFormat == %s",
702                                            _mesa_lookup_enum_by_nr(table->_BaseFormat));
703         return GR_TEXTABLE_PALETTE;
704     }
705 }
706
707
708
709 static void
710 tdfxUpdateTexturePalette(struct gl_context * ctx, struct gl_texture_object *tObj)
711 {
712     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
713
714     if (tObj) {
715         /* per-texture palette */
716         tdfxTexInfo *ti;
717         
718         /* This might be a proxy texture. */
719         if (!tObj->Palette.TableUB)
720             return;
721             
722         if (!tObj->DriverData)
723             tObj->DriverData = fxAllocTexObjData(fxMesa);
724         ti = TDFX_TEXTURE_DATA(tObj);
725         assert(ti);
726         ti->paltype = convertPalette(ti->palette.data, &tObj->Palette);
727         /*tdfxTexInvalidate(ctx, tObj);*/
728     }
729     else {
730         /* global texture palette */
731         fxMesa->TexPalette.Type = convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
732         fxMesa->TexPalette.Data = &(fxMesa->glbPalette.data);
733         fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
734     }
735     fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX too heavy-handed */
736 }
737
738
739 /**********************************************************************/
740 /**** NEW TEXTURE IMAGE FUNCTIONS                                  ****/
741 /**********************************************************************/
742
743 #if 000
744 static FxBool TexusFatalError = FXFALSE;
745 static FxBool TexusError = FXFALSE;
746
747 #define TX_DITHER_NONE                                  0x00000000
748
749 static void
750 fxTexusError(const char *string, FxBool fatal)
751 {
752     _mesa_problem(NULL, string);
753    /*
754     * Just propagate the fatal value up.
755     */
756     TexusError = FXTRUE;
757     TexusFatalError = fatal;
758 }
759 #endif
760
761
762 static gl_format
763 tdfxChooseTextureFormat( struct gl_context *ctx, GLint internalFormat,
764                            GLenum srcFormat, GLenum srcType )
765 {
766    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
767    const GLboolean allow32bpt = TDFX_IS_NAPALM(fxMesa);
768
769    switch (internalFormat) {
770    case GL_ALPHA:
771    case GL_ALPHA4:
772    case GL_ALPHA8:
773    case GL_ALPHA12:
774    case GL_ALPHA16:
775    case GL_COMPRESSED_ALPHA:
776       return MESA_FORMAT_A8;
777    case 1:
778    case GL_LUMINANCE:
779    case GL_LUMINANCE4:
780    case GL_LUMINANCE8:
781    case GL_LUMINANCE12:
782    case GL_LUMINANCE16:
783    case GL_COMPRESSED_LUMINANCE:
784       return MESA_FORMAT_L8;
785    case 2:
786    case GL_LUMINANCE_ALPHA:
787    case GL_LUMINANCE4_ALPHA4:
788    case GL_LUMINANCE6_ALPHA2:
789    case GL_LUMINANCE8_ALPHA8:
790    case GL_LUMINANCE12_ALPHA4:
791    case GL_LUMINANCE12_ALPHA12:
792    case GL_LUMINANCE16_ALPHA16:
793    case GL_COMPRESSED_LUMINANCE_ALPHA:
794       return MESA_FORMAT_AL88;
795    case GL_INTENSITY:
796    case GL_INTENSITY4:
797    case GL_INTENSITY8:
798    case GL_INTENSITY12:
799    case GL_INTENSITY16:
800    case GL_COMPRESSED_INTENSITY:
801       return MESA_FORMAT_I8;
802    case GL_R3_G3_B2:
803    case GL_RGB4:
804    case GL_RGB5:
805       return MESA_FORMAT_RGB565;
806    case GL_COMPRESSED_RGB:
807       /* intentional fall-through */
808    case 3:
809    case GL_RGB:
810      if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
811        return MESA_FORMAT_RGB565;
812      }
813      /* intentional fall through */
814    case GL_RGB8:
815    case GL_RGB10:
816    case GL_RGB12:
817    case GL_RGB16:
818       return (allow32bpt) ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
819    case GL_RGBA2:
820    case GL_RGBA4:
821       return MESA_FORMAT_ARGB4444;
822    case GL_COMPRESSED_RGBA:
823       /* intentional fall-through */
824    case 4:
825    case GL_RGBA:
826      if ( srcFormat == GL_BGRA ) {
827        if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
828          return MESA_FORMAT_ARGB8888;
829        }
830        else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
831          return MESA_FORMAT_ARGB4444;
832        }
833        else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
834          return MESA_FORMAT_ARGB1555;
835        }
836      }
837      /* intentional fall through */
838    case GL_RGBA8:
839    case GL_RGB10_A2:
840    case GL_RGBA12:
841    case GL_RGBA16:
842       return allow32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
843    case GL_RGB5_A1:
844       return MESA_FORMAT_ARGB1555;
845    case GL_COLOR_INDEX:
846    case GL_COLOR_INDEX1_EXT:
847    case GL_COLOR_INDEX2_EXT:
848    case GL_COLOR_INDEX4_EXT:
849    case GL_COLOR_INDEX8_EXT:
850    case GL_COLOR_INDEX12_EXT:
851    case GL_COLOR_INDEX16_EXT:
852       return MESA_FORMAT_CI8;
853    /* GL_EXT_texture_compression_s3tc */
854    /* GL_S3_s3tc */
855    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
856    case GL_RGB_S3TC:
857    case GL_RGB4_S3TC:
858       return MESA_FORMAT_RGB_DXT1;
859    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
860       return MESA_FORMAT_RGBA_DXT1;
861    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
862    case GL_RGBA_S3TC:
863    case GL_RGBA4_S3TC:
864       return MESA_FORMAT_RGBA_DXT3;
865    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
866       return MESA_FORMAT_RGBA_DXT5;
867    /* GL_3DFX_texture_compression_FXT1 */
868    case GL_COMPRESSED_RGB_FXT1_3DFX:
869       return MESA_FORMAT_RGB_FXT1;
870    case GL_COMPRESSED_RGBA_FXT1_3DFX:
871       return MESA_FORMAT_RGBA_FXT1;
872    default:
873       _mesa_problem(ctx, "unexpected format in tdfxChooseTextureFormat");
874       return MESA_FORMAT_NONE;
875    }
876 }
877
878
879 /*
880  * Return the Glide format for the given mesa texture format.
881  */
882 static GrTextureFormat_t
883 fxGlideFormat(GLint mesaFormat)
884 {
885    switch (mesaFormat) {
886    case MESA_FORMAT_I8:
887       return GR_TEXFMT_ALPHA_8;
888    case MESA_FORMAT_A8:
889       return GR_TEXFMT_ALPHA_8;
890    case MESA_FORMAT_L8:
891       return GR_TEXFMT_INTENSITY_8;
892    case MESA_FORMAT_CI8:
893       return GR_TEXFMT_P_8;
894    case MESA_FORMAT_AL88:
895       return GR_TEXFMT_ALPHA_INTENSITY_88;
896    case MESA_FORMAT_RGB565:
897       return GR_TEXFMT_RGB_565;
898    case MESA_FORMAT_ARGB4444:
899       return GR_TEXFMT_ARGB_4444;
900    case MESA_FORMAT_ARGB1555:
901       return GR_TEXFMT_ARGB_1555;
902    case MESA_FORMAT_ARGB8888:
903       return GR_TEXFMT_ARGB_8888;
904    case MESA_FORMAT_RGB_FXT1:
905    case MESA_FORMAT_RGBA_FXT1:
906      return GR_TEXFMT_ARGB_CMP_FXT1;
907    case MESA_FORMAT_RGB_DXT1:
908    case MESA_FORMAT_RGBA_DXT1:
909      return GR_TEXFMT_ARGB_CMP_DXT1;
910    case MESA_FORMAT_RGBA_DXT3:
911      return GR_TEXFMT_ARGB_CMP_DXT3;
912    case MESA_FORMAT_RGBA_DXT5:
913      return GR_TEXFMT_ARGB_CMP_DXT5;
914    default:
915       _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
916       return 0;
917    }
918 }
919
920
921 /* Texel-fetch functions for software texturing and glGetTexImage().
922  * We should have been able to use some "standard" fetch functions (which
923  * may get defined in texutil.c) but we have to account for scaled texture
924  * images on tdfx hardware (the 8:1 aspect ratio limit).
925  * Hence, we need special functions here.
926  */
927 extern void
928 fxt1_decode_1 (const void *texture, int width,
929                int i, int j, unsigned char *rgba);
930
931 static void
932 fetch_intensity8(const struct gl_texture_image *texImage,
933                  GLint i, GLint j, GLint k, GLchan * rgba)
934 {
935     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
936     const GLubyte *texel;
937
938     i = i * mml->wScale;
939     j = j * mml->hScale;
940
941     texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
942     rgba[RCOMP] = *texel;
943     rgba[GCOMP] = *texel;
944     rgba[BCOMP] = *texel;
945     rgba[ACOMP] = *texel;
946 }
947
948
949 static void
950 fetch_luminance8(const struct gl_texture_image *texImage,
951                  GLint i, GLint j, GLint k, GLchan * rgba)
952 {
953     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
954     const GLubyte *texel;
955
956     i = i * mml->wScale;
957     j = j * mml->hScale;
958
959     texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
960     rgba[RCOMP] = *texel;
961     rgba[GCOMP] = *texel;
962     rgba[BCOMP] = *texel;
963     rgba[ACOMP] = 255;
964 }
965
966
967 static void
968 fetch_alpha8(const struct gl_texture_image *texImage,
969              GLint i, GLint j, GLint k, GLchan * rgba)
970 {
971     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
972     const GLubyte *texel;
973
974     i = i * mml->wScale;
975     j = j * mml->hScale;
976
977     texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
978     rgba[RCOMP] = 255;
979     rgba[GCOMP] = 255;
980     rgba[BCOMP] = 255;
981     rgba[ACOMP] = *texel;
982 }
983
984
985 static void
986 fetch_index8(const struct gl_texture_image *texImage,
987              GLint i, GLint j, GLint k, GLchan * indexOut)
988 {
989     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
990     const GLubyte *texel;
991
992     i = i * mml->wScale;
993     j = j * mml->hScale;
994
995     texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
996     *indexOut = *texel;
997 }
998
999
1000 static void
1001 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
1002                         GLint i, GLint j, GLint k, GLchan * rgba)
1003 {
1004     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1005     const GLubyte *texel;
1006
1007     i = i * mml->wScale;
1008     j = j * mml->hScale;
1009
1010     texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
1011     rgba[RCOMP] = texel[0];
1012     rgba[GCOMP] = texel[0];
1013     rgba[BCOMP] = texel[0];
1014     rgba[ACOMP] = texel[1];
1015 }
1016
1017
1018 static void
1019 fetch_r5g6b5(const struct gl_texture_image *texImage,
1020              GLint i, GLint j, GLint k, GLchan * rgba)
1021 {
1022     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1023     const GLushort *texel;
1024
1025     i = i * mml->wScale;
1026     j = j * mml->hScale;
1027
1028     texel = ((GLushort *) texImage->Data) + j * mml->width + i;
1029     rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
1030     rgba[GCOMP] = (((*texel) >> 5) & 0x3f) * 255 / 63;
1031     rgba[BCOMP] = (((*texel) >> 0) & 0x1f) * 255 / 31;
1032     rgba[ACOMP] = 255;
1033 }
1034
1035
1036 static void
1037 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
1038                GLint i, GLint j, GLint k, GLchan * rgba)
1039 {
1040     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1041     const GLushort *texel;
1042
1043     i = i * mml->wScale;
1044     j = j * mml->hScale;
1045
1046     texel = ((GLushort *) texImage->Data) + j * mml->width + i;
1047     rgba[RCOMP] = (((*texel) >> 12) & 0xf) * 255 / 15;
1048     rgba[GCOMP] = (((*texel) >> 8) & 0xf) * 255 / 15;
1049     rgba[BCOMP] = (((*texel) >> 4) & 0xf) * 255 / 15;
1050     rgba[ACOMP] = (((*texel) >> 0) & 0xf) * 255 / 15;
1051 }
1052
1053
1054 static void
1055 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
1056                GLint i, GLint j, GLint k, GLchan * rgba)
1057 {
1058     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1059     const GLushort *texel;
1060
1061     i = i * mml->wScale;
1062     j = j * mml->hScale;
1063
1064     texel = ((GLushort *) texImage->Data) + j * mml->width + i;
1065     rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
1066     rgba[GCOMP] = (((*texel) >> 6) & 0x1f) * 255 / 31;
1067     rgba[BCOMP] = (((*texel) >> 1) & 0x1f) * 255 / 31;
1068     rgba[ACOMP] = (((*texel) >> 0) & 0x01) * 255;
1069 }
1070
1071
1072 static void
1073 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
1074                GLint i, GLint j, GLint k, GLchan * rgba)
1075 {
1076     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1077     const GLuint *texel;
1078
1079     i = i * mml->wScale;
1080     j = j * mml->hScale;
1081
1082     texel = ((GLuint *) texImage->Data) + j * mml->width + i;
1083     rgba[RCOMP] = (((*texel) >> 16) & 0xff);
1084     rgba[GCOMP] = (((*texel) >>  8) & 0xff);
1085     rgba[BCOMP] = (((*texel)      ) & 0xff);
1086     rgba[ACOMP] = (((*texel) >> 24) & 0xff);
1087 }
1088
1089
1090 static void
1091 fetch_rgb_fxt1(const struct gl_texture_image *texImage,
1092                GLint i, GLint j, GLint k, GLchan *rgba)
1093 {
1094     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1095
1096     i = i * mml->wScale;
1097     j = j * mml->hScale;
1098
1099     fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
1100     rgba[ACOMP] = 255;
1101 }
1102
1103
1104 static void
1105 fetch_rgba_fxt1(const struct gl_texture_image *texImage,
1106                 GLint i, GLint j, GLint k, GLchan *rgba)
1107 {
1108     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1109
1110     i = i * mml->wScale;
1111     j = j * mml->hScale;
1112
1113     fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
1114 }
1115
1116
1117 static void
1118 fetch_rgb_dxt1(const struct gl_texture_image *texImage,
1119                GLint i, GLint j, GLint k, GLchan *rgba)
1120 {
1121     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1122
1123     i = i * mml->wScale;
1124     j = j * mml->hScale;
1125
1126     /* XXX Get fetch func from _mesa_get_texel_fetch_func()
1127     _mesa_texformat_rgb_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
1128     */
1129 }
1130
1131
1132 static void
1133 fetch_rgba_dxt1(const struct gl_texture_image *texImage,
1134                 GLint i, GLint j, GLint k, GLchan *rgba)
1135 {
1136     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1137
1138     i = i * mml->wScale;
1139     j = j * mml->hScale;
1140
1141     /* XXX Get fetch func from _mesa_get_texel_fetch_func()
1142     _mesa_texformat_rgba_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
1143     */
1144 }
1145
1146
1147 static void
1148 fetch_rgba_dxt3(const struct gl_texture_image *texImage,
1149                 GLint i, GLint j, GLint k, GLchan *rgba)
1150 {
1151     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1152
1153     i = i * mml->wScale;
1154     j = j * mml->hScale;
1155
1156     /* XXX Get fetch func from _mesa_get_texel_fetch_func()
1157     _mesa_texformat_rgba_dxt3.FetchTexel2D(texImage, i, j, k, rgba);
1158     */
1159 }
1160
1161
1162 static void
1163 fetch_rgba_dxt5(const struct gl_texture_image *texImage,
1164                 GLint i, GLint j, GLint k, GLchan *rgba)
1165 {
1166     const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1167
1168     i = i * mml->wScale;
1169     j = j * mml->hScale;
1170
1171     /* XXX Get fetch func from _mesa_get_texel_fetch_func()
1172     _mesa_texformat_rgba_dxt5.FetchTexel2D(texImage, i, j, k, rgba);
1173     */
1174 }
1175
1176
1177 static FetchTexelFuncC
1178 fxFetchFunction(GLint mesaFormat)
1179 {
1180    switch (mesaFormat) {
1181    case MESA_FORMAT_I8:
1182       return &fetch_intensity8;
1183    case MESA_FORMAT_A8:
1184       return &fetch_alpha8;
1185    case MESA_FORMAT_L8:
1186       return &fetch_luminance8;
1187    case MESA_FORMAT_CI8:
1188       return &fetch_index8;
1189    case MESA_FORMAT_AL88:
1190       return &fetch_luminance8_alpha8;
1191    case MESA_FORMAT_RGB565:
1192       return &fetch_r5g6b5;
1193    case MESA_FORMAT_ARGB4444:
1194       return &fetch_r4g4b4a4;
1195    case MESA_FORMAT_ARGB1555:
1196       return &fetch_r5g5b5a1;
1197    case MESA_FORMAT_ARGB8888:
1198       return &fetch_a8r8g8b8;
1199    case MESA_FORMAT_RGB_FXT1:
1200       return &fetch_rgb_fxt1;
1201    case MESA_FORMAT_RGBA_FXT1:
1202       return &fetch_rgba_fxt1;
1203    case MESA_FORMAT_RGB_DXT1:
1204       return &fetch_rgb_dxt1;
1205    case MESA_FORMAT_RGBA_DXT1:
1206       return &fetch_rgba_dxt1;
1207    case MESA_FORMAT_RGBA_DXT3:
1208       return &fetch_rgba_dxt3;
1209    case MESA_FORMAT_RGBA_DXT5:
1210       return &fetch_rgba_dxt5;
1211    default:
1212       _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1213       return NULL;
1214    }
1215 }
1216
1217
1218 static GLboolean
1219 adjust2DRatio (struct gl_context *ctx,
1220                GLint xoffset, GLint yoffset,
1221                GLint width, GLint height,
1222                GLenum format, GLenum type, const GLvoid *pixels,
1223                const struct gl_pixelstore_attrib *packing,
1224                tdfxMipMapLevel *mml,
1225                struct gl_texture_image *texImage,
1226                GLint texelBytes,
1227                GLint dstRowStride)
1228 {
1229    const GLint newWidth = width * mml->wScale;
1230    const GLint newHeight = height * mml->hScale;
1231    GLvoid *tempImage;
1232    GLuint dstImageOffsets = 0;
1233
1234    if (!_mesa_is_format_compressed(texImage->TexFormat)) {
1235       GLubyte *destAddr;
1236
1237       tempImage = MALLOC(width * height * texelBytes);
1238       if (!tempImage) {
1239          return GL_FALSE;
1240       }
1241
1242       _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1243                      texImage->TexFormat, tempImage,
1244                      0, 0, 0, /* dstX/Y/Zoffset */
1245                      width * texelBytes, /* dstRowStride */
1246                      &dstImageOffsets,
1247                      width, height, 1,
1248                      format, type, pixels, packing);
1249
1250       /* now rescale */
1251       /* compute address of dest subimage within the overal tex image */
1252       destAddr = (GLubyte *) texImage->Data
1253          + (yoffset * mml->hScale * mml->width
1254             + xoffset * mml->wScale) * texelBytes;
1255
1256       _mesa_rescale_teximage2d(texelBytes,
1257                                width,
1258                                dstRowStride, /* dst stride */
1259                                width, height,
1260                                newWidth, newHeight,
1261                                tempImage, destAddr);
1262    } else {
1263       const GLint rawBytes = 4;
1264       GLvoid *rawImage = MALLOC(width * height * rawBytes);
1265
1266       if (!rawImage) {
1267          return GL_FALSE;
1268       }
1269       tempImage = MALLOC(newWidth * newHeight * rawBytes);
1270       if (!tempImage) {
1271          FREE(rawImage);
1272          return GL_FALSE;
1273       }
1274       /* unpack image, apply transfer ops and store in rawImage */
1275       _mesa_texstore(ctx, 2, GL_RGBA,
1276                      MESA_FORMAT_RGBA8888_REV, rawImage,
1277                      0, 0, 0, /* dstX/Y/Zoffset */
1278                      width * rawBytes, /* dstRowStride */
1279                      &dstImageOffsets,
1280                      width, height, 1,
1281                      format, type, pixels, packing);
1282       _mesa_rescale_teximage2d(rawBytes,
1283                                width,
1284                                newWidth * rawBytes, /* dst stride */
1285                                width, height, /* src */
1286                                newWidth, newHeight, /* dst */
1287                                rawImage /*src*/, tempImage /*dst*/ );
1288       _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1289                      texImage->TexFormat, texImage->Data,
1290                      xoffset * mml->wScale, yoffset * mml->hScale, 0, /* dstX/Y/Zoffset */
1291                      dstRowStride,
1292                      &dstImageOffsets,
1293                      newWidth, newHeight, 1,
1294                      GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
1295       FREE(rawImage);
1296    }
1297
1298    FREE(tempImage);
1299
1300    return GL_TRUE;
1301 }
1302
1303
1304 static void
1305 tdfxTexImage2D(struct gl_context *ctx, GLenum target, GLint level,
1306                GLint internalFormat, GLint width, GLint height, GLint border,
1307                GLenum format, GLenum type, const GLvoid *pixels,
1308                const struct gl_pixelstore_attrib *packing,
1309                struct gl_texture_object *texObj,
1310                struct gl_texture_image *texImage)
1311 {
1312     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1313     tdfxTexInfo *ti;
1314     tdfxMipMapLevel *mml;
1315     GLint texelBytes, dstRowStride;
1316     GLuint mesaFormat;
1317
1318     /*
1319     printf("TexImage id=%d int 0x%x  format 0x%x  type 0x%x  %dx%d\n",
1320            texObj->Name, texImage->InternalFormat, format, type,
1321            texImage->Width, texImage->Height);
1322     */
1323
1324     ti = TDFX_TEXTURE_DATA(texObj);
1325     if (!ti) {
1326         texObj->DriverData = fxAllocTexObjData(fxMesa);
1327         if (!texObj->DriverData) {
1328             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1329             return;
1330         }
1331         ti = TDFX_TEXTURE_DATA(texObj);
1332     }
1333     assert(ti);
1334
1335     mml = TDFX_TEXIMAGE_DATA(texImage);
1336     if (!mml) {
1337         texImage->DriverData = CALLOC(sizeof(tdfxMipMapLevel));
1338         if (!texImage->DriverData) {
1339             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1340             return;
1341         }
1342         mml = TDFX_TEXIMAGE_DATA(texImage);
1343     }
1344
1345     /* Determine width and height scale factors for texture.
1346      * Remember, Glide is limited to 8:1 aspect ratios.
1347      */
1348     tdfxTexGetInfo(ctx,
1349                    texImage->Width, texImage->Height,
1350                    NULL,       /* lod level          */
1351                    NULL,       /* aspect ratio       */
1352                    NULL, NULL, /* sscale, tscale     */
1353                    &mml->wScale, &mml->hScale);
1354
1355     /* rescaled size: */
1356     mml->width = width * mml->wScale;
1357     mml->height = height * mml->hScale;
1358
1359 #if FX_COMPRESS_S3TC_AS_FXT1_HACK
1360     /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
1361     /* [dBorca] we should update texture's attribute, then,
1362      * because if the application asks us to decompress, we
1363      * have to know the REAL format! Also, DXT3/5 might not
1364      * be correct, since it would mess with "compressedSize".
1365      * Ditto for GL_RGBA[4]_S3TC, which is always mapped to DXT3.
1366      */
1367     if (_mesa_is_format_compressed(texImage->TexFormat)) {
1368       switch (internalFormat) {
1369       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1370       case GL_RGB_S3TC:
1371       case GL_RGB4_S3TC:
1372         internalFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
1373         break;
1374       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1375       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1376       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1377       case GL_RGBA_S3TC:
1378       case GL_RGBA4_S3TC:
1379         internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
1380       }
1381       texImage->InternalFormat = internalFormat;
1382     }
1383 #endif
1384 #if FX_TC_NAPALM
1385     if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1386        GLenum texNapalm = 0;
1387        if (internalFormat == GL_COMPRESSED_RGB) {
1388           texNapalm = GL_COMPRESSED_RGB_FXT1_3DFX;
1389        } else if (internalFormat == GL_COMPRESSED_RGBA) {
1390           texNapalm = GL_COMPRESSED_RGBA_FXT1_3DFX;
1391        }
1392        if (texNapalm) {
1393           texImage->InternalFormat = internalFormat = texNapalm;
1394           _mesa_is_format_compressed(texImage->TexFormat) = GL_TRUE;
1395        }
1396     }
1397 #endif
1398
1399     mesaFormat = texImage->TexFormat;
1400     mml->glideFormat = fxGlideFormat(mesaFormat);
1401     ti->info.format = mml->glideFormat;
1402     texImage->FetchTexelc = fxFetchFunction(mesaFormat);
1403     texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
1404
1405     if (_mesa_is_format_compressed(texImage->TexFormat)) {
1406        GLuint compressedSize = _mesa_format_image_size(mesaFormat, mml->width,
1407                                                        mml->height, 1);
1408        dstRowStride = _mesa_format_row_stride(texImage->TexFormat, mml->width);
1409        texImage->Data = _mesa_alloc_texmemory(compressedSize);
1410     } else {
1411        dstRowStride = mml->width * texelBytes;
1412        texImage->Data = _mesa_alloc_texmemory(mml->width * mml->height * texelBytes);
1413     }
1414     if (!texImage->Data) {
1415        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1416        return;
1417     }
1418
1419     if (pixels != NULL) {
1420        if (mml->wScale != 1 || mml->hScale != 1) {
1421           /* rescale image to overcome 1:8 aspect limitation */
1422           if (!adjust2DRatio(ctx,
1423                             0, 0,
1424                             width, height,
1425                             format, type, pixels,
1426                             packing,
1427                             mml,
1428                             texImage,
1429                             texelBytes,
1430                             dstRowStride)
1431              ) {
1432              _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1433              return;
1434           }
1435        }
1436        else {
1437           /* no rescaling needed */
1438           /* unpack image, apply transfer ops and store in texImage->Data */
1439           _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1440                          texImage->TexFormat, texImage->Data,
1441                          0, 0, 0, /* dstX/Y/Zoffset */
1442                          dstRowStride,
1443                          texImage->ImageOffsets,
1444                          width, height, 1,
1445                          format, type, pixels, packing);
1446        }
1447     }
1448
1449     RevalidateTexture(ctx, texObj);
1450
1451     ti->reloadImages = GL_TRUE;
1452     fxMesa->new_state |= TDFX_NEW_TEXTURE;
1453 }
1454
1455
1456 static void
1457 tdfxTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level,
1458                     GLint xoffset, GLint yoffset,
1459                     GLsizei width, GLsizei height,
1460                     GLenum format, GLenum type,
1461                     const GLvoid *pixels,
1462                     const struct gl_pixelstore_attrib *packing,
1463                     struct gl_texture_object *texObj,
1464                     struct gl_texture_image *texImage )
1465 {
1466     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1467     tdfxTexInfo *ti;
1468     tdfxMipMapLevel *mml;
1469     GLint texelBytes, dstRowStride;
1470
1471     if (!texObj->DriverData) {
1472         _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1473         return;
1474     }
1475
1476     ti = TDFX_TEXTURE_DATA(texObj);
1477     assert(ti);
1478     mml = TDFX_TEXIMAGE_DATA(texImage);
1479     assert(mml);
1480
1481     assert(texImage->Data);     /* must have an existing texture image! */
1482     assert(texImage->_BaseFormat);
1483
1484     texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
1485     if (_mesa_is_format_compressed(texImage->TexFormat)) {
1486        dstRowStride = _mesa_format_row_stride(texImage->TexFormat, mml->width);
1487     } else {
1488        dstRowStride = mml->width * texelBytes;
1489     }
1490
1491     if (mml->wScale != 1 || mml->hScale != 1) {
1492         /* need to rescale subimage to match mipmap level's rescale factors */
1493         if (!adjust2DRatio(ctx,
1494                             xoffset, yoffset,
1495                             width, height,
1496                             format, type, pixels,
1497                             packing,
1498                             mml,
1499                             texImage,
1500                             texelBytes,
1501                             dstRowStride)
1502            ) {
1503            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1504            return;
1505         }
1506     }
1507     else {
1508         /* no rescaling needed */
1509        _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1510                       texImage->TexFormat, texImage->Data,
1511                       xoffset, yoffset, 0,
1512                       dstRowStride,
1513                       texImage->ImageOffsets,
1514                       width, height, 1,
1515                       format, type, pixels, packing);
1516     }
1517
1518     ti->reloadImages = GL_TRUE; /* signal the image needs to be reloaded */
1519     fxMesa->new_state |= TDFX_NEW_TEXTURE;  /* XXX this might be a bit much */
1520 }
1521
1522
1523 static void
1524 tdfxTexImage1D(struct gl_context *ctx, GLenum target, GLint level,
1525                GLint internalFormat, GLint width, GLint border,
1526                GLenum format, GLenum type, const GLvoid *pixels,
1527                const struct gl_pixelstore_attrib *packing,
1528                struct gl_texture_object *texObj,
1529                struct gl_texture_image *texImage)
1530 {
1531  tdfxTexImage2D(ctx, target, level,
1532                 internalFormat, width, 1, border,
1533                 format, type, pixels,
1534                 packing,
1535                 texObj,
1536                 texImage);
1537 }
1538
1539 static void
1540 tdfxTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level,
1541                     GLint xoffset,
1542                     GLsizei width,
1543                     GLenum format, GLenum type,
1544                     const GLvoid *pixels,
1545                     const struct gl_pixelstore_attrib *packing,
1546                     struct gl_texture_object *texObj,
1547                     struct gl_texture_image *texImage )
1548 {
1549  tdfxTexSubImage2D(ctx, target, level,
1550                     xoffset, 0,
1551                     width, 1,
1552                     format, type,
1553                     pixels,
1554                     packing,
1555                     texObj,
1556                     texImage);
1557 }
1558
1559 /**********************************************************************/
1560 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS                           ****/
1561 /**********************************************************************/
1562
1563 static void
1564 tdfxCompressedTexImage2D (struct gl_context *ctx, GLenum target,
1565                           GLint level, GLint internalFormat,
1566                           GLsizei width, GLsizei height, GLint border,
1567                           GLsizei imageSize, const GLvoid *data,
1568                           struct gl_texture_object *texObj,
1569                           struct gl_texture_image *texImage)
1570 {
1571     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1572     tdfxTexInfo *ti;
1573     tdfxMipMapLevel *mml;
1574     gl_format mesaFormat;
1575     GLuint compressedSize = 0;
1576
1577     if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) {
1578         fprintf(stderr, "tdfxCompressedTexImage2D: id=%d int 0x%x  %dx%d\n",
1579                         texObj->Name, internalFormat,
1580                         width, height);
1581     }
1582
1583     if ((target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) || texImage->Border > 0) {
1584        _mesa_problem(NULL, "tdfx: unsupported texture in tdfxCompressedTexImg()\n");
1585        return;
1586     }
1587
1588     ti = TDFX_TEXTURE_DATA(texObj);
1589     if (!ti) {
1590         texObj->DriverData = fxAllocTexObjData(fxMesa);
1591         if (!texObj->DriverData) {
1592             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1593             return;
1594         }
1595         ti = TDFX_TEXTURE_DATA(texObj);
1596     }
1597     assert(ti);
1598
1599     mml = TDFX_TEXIMAGE_DATA(texImage);
1600     if (!mml) {
1601         texImage->DriverData = CALLOC(sizeof(tdfxMipMapLevel));
1602         if (!texImage->DriverData) {
1603             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1604             return;
1605         }
1606         mml = TDFX_TEXIMAGE_DATA(texImage);
1607     }
1608
1609     tdfxTexGetInfo(ctx, width, height, NULL, NULL, NULL, NULL,
1610                 &mml->wScale, &mml->hScale);
1611
1612     mml->width = width * mml->wScale;
1613     mml->height = height * mml->hScale;
1614
1615
1616     /* Determine the appropriate Glide texel format,
1617      * given the user's internal texture format hint.
1618      */
1619     mesaFormat = texImage->TexFormat;
1620     mml->glideFormat = fxGlideFormat(mesaFormat);
1621     ti->info.format = mml->glideFormat;
1622     texImage->FetchTexelc = fxFetchFunction(mesaFormat);
1623
1624     /* allocate new storage for texture image, if needed */
1625     if (!texImage->Data) {
1626        compressedSize = _mesa_format_image_size(mesaFormat, mml->width,
1627                                                 mml->height, 1);
1628        texImage->Data = _mesa_alloc_texmemory(compressedSize);
1629        if (!texImage->Data) {
1630           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1631           return;
1632        }
1633     }
1634
1635     /* save the texture data */
1636     if (mml->wScale != 1 || mml->hScale != 1) {
1637        /* [dBorca] Hack alert:
1638         * now we're screwed. We can't decompress,
1639         * unless we do it in HW (via textureBuffer).
1640         * We still have some chances:
1641         * 1) we got FXT1 textures - we CAN decompress, rescale for
1642         *    aspectratio, then compress back.
1643         * 2) there is a chance that MIN("s", "t") won't be overflowed.
1644         *    Thus, we don't care about textureclamp and we could lower
1645         *    MIN("uscale", "vscale") below 32. We still have to have
1646         *    our data aligned inside a 8:1 rectangle.
1647         * 3) just in case if MIN("s", "t") gets overflowed with GL_REPEAT,
1648         *    we replicate the data over the padded area.
1649         * For now, we take 2) + 3) but texelfetchers will be wrong!
1650         */
1651        const GLuint mesaFormat = texImage->TexFormat;
1652        GLuint srcRowStride = _mesa_format_row_stride(mesaFormat, width);
1653  
1654        GLuint destRowStride = _mesa_format_row_stride(mesaFormat,
1655                                                    mml->width);
1656  
1657        _mesa_upscale_teximage2d(srcRowStride, (height+3) / 4,
1658                                 destRowStride, (mml->height+3) / 4,
1659                                 1, data, srcRowStride,
1660                                 texImage->Data);
1661        ti->padded = GL_TRUE;
1662     } else {
1663        memcpy(texImage->Data, data, compressedSize);
1664     }
1665
1666     RevalidateTexture(ctx, texObj);
1667
1668     ti->reloadImages = GL_TRUE;
1669     fxMesa->new_state |= TDFX_NEW_TEXTURE;
1670 }
1671
1672
1673 static void
1674 tdfxCompressedTexSubImage2D( struct gl_context *ctx, GLenum target,
1675                              GLint level, GLint xoffset,
1676                              GLint yoffset, GLsizei width,
1677                              GLint height, GLenum format,
1678                              GLsizei imageSize, const GLvoid *data,
1679                              struct gl_texture_object *texObj,
1680                              struct gl_texture_image *texImage )
1681 {
1682     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1683     tdfxTexInfo *ti;
1684     tdfxMipMapLevel *mml;
1685     GLint destRowStride, srcRowStride;
1686     GLint i, rows;
1687     GLubyte *dest;
1688     const GLuint mesaFormat = texImage->TexFormat;
1689
1690     if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) {
1691         fprintf(stderr, "tdfxCompressedTexSubImage2D: id=%d\n", texObj->Name);
1692     }
1693
1694     ti = TDFX_TEXTURE_DATA(texObj);
1695     assert(ti);
1696     mml = TDFX_TEXIMAGE_DATA(texImage);
1697     assert(mml);
1698
1699     srcRowStride = _mesa_format_row_stride(mesaFormat, width);
1700
1701     destRowStride = _mesa_format_row_stride(mesaFormat, mml->width);
1702     dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
1703                                           mesaFormat,
1704                                           mml->width,
1705                                (GLubyte*) texImage->Data);
1706
1707     rows = height / 4; /* [dBorca] hardcoded 4, but works for FXT1/DXTC */
1708
1709     for (i = 0; i < rows; i++) {
1710        memcpy(dest, data, srcRowStride);
1711        dest += destRowStride;
1712        data = (GLvoid *)((intptr_t)data + (intptr_t)srcRowStride);
1713     }
1714
1715     /* [dBorca] Hack alert:
1716      * see fxDDCompressedTexImage2D for caveats
1717      */
1718     if (mml->wScale != 1 || mml->hScale != 1) {
1719        srcRowStride = _mesa_format_row_stride(mesaFormat, texImage->Width);
1720  
1721        destRowStride = _mesa_format_row_stride(mesaFormat, mml->width);
1722        _mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4,
1723                                 destRowStride, mml->height / 4,
1724                                 1, texImage->Data, destRowStride,
1725                                 texImage->Data);
1726     }
1727
1728     RevalidateTexture(ctx, texObj);
1729
1730     ti->reloadImages = GL_TRUE;
1731     fxMesa->new_state |= TDFX_NEW_TEXTURE;
1732 }
1733
1734
1735 #if     0
1736 static void
1737 PrintTexture(int w, int h, int c, const GLubyte * data)
1738 {
1739     int i, j;
1740     for (i = 0; i < h; i++) {
1741         for (j = 0; j < w; j++) {
1742             if (c == 2)
1743                 printf("%02x %02x  ", data[0], data[1]);
1744             else if (c == 3)
1745                 printf("%02x %02x %02x  ", data[0], data[1], data[2]);
1746             data += c;
1747         }
1748         printf("\n");
1749     }
1750 }
1751 #endif
1752
1753
1754 GLboolean
1755 tdfxTestProxyTexImage(struct gl_context *ctx, GLenum target,
1756                         GLint level, GLint internalFormat,
1757                         GLenum format, GLenum type,
1758                         GLint width, GLint height,
1759                         GLint depth, GLint border)
1760 {
1761     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1762     struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
1763     struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
1764
1765     switch (target) {
1766     case GL_PROXY_TEXTURE_1D:
1767         /*JJJ wrong*/
1768     case GL_PROXY_TEXTURE_2D:
1769         {
1770             struct gl_texture_object *tObj;
1771             tdfxTexInfo *ti;
1772             int memNeeded;
1773
1774             tObj = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
1775             if (!tObj->DriverData)
1776                 tObj->DriverData = fxAllocTexObjData(fxMesa);
1777             ti = TDFX_TEXTURE_DATA(tObj);
1778             assert(ti);
1779
1780             /* assign the parameters to test against */
1781             tObj->Image[0][level]->Width = width;
1782             tObj->Image[0][level]->Height = height;
1783             tObj->Image[0][level]->Border = border;
1784 #if 0
1785             tObj->Image[0][level]->InternalFormat = internalFormat;
1786 #endif
1787             if (level == 0) {
1788                /* don't use mipmap levels > 0 */
1789                tObj->Sampler.MinFilter = tObj->Sampler.MagFilter = GL_NEAREST;
1790             }
1791             else {
1792                /* test with all mipmap levels */
1793                tObj->Sampler.MinFilter = GL_LINEAR_MIPMAP_LINEAR;
1794                tObj->Sampler.MagFilter = GL_NEAREST;
1795             }
1796             RevalidateTexture(ctx, tObj);
1797
1798             /*
1799             printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1800             printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1801             printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1802             printf("glide format 0x%x\n", ti->info.format);
1803             printf("data %p\n", ti->info.data);
1804             printf("lodblend %d\n", (int) ti->LODblend);
1805             */
1806
1807             /* determine where texture will reside */
1808             if (ti->LODblend && !shared->umaTexMemory) {
1809                 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1810                 memNeeded = fxMesa->Glide.grTexTextureMemRequired(
1811                                         GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1812             }
1813             else {
1814                 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1815                 memNeeded = fxMesa->Glide.grTexTextureMemRequired(
1816                                         GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1817             }
1818             /*
1819             printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1820             */
1821             if (memNeeded > shared->totalTexMem[0])
1822                 return GL_FALSE;
1823             else
1824                 return GL_TRUE;
1825         }
1826     case GL_PROXY_TEXTURE_3D:
1827         return GL_TRUE;  /* software rendering */
1828     default:
1829         return GL_TRUE;  /* never happens, silence compiler */
1830     }
1831 }
1832
1833
1834 /**
1835  * Allocate a new texture object.
1836  * Called via ctx->Driver.NewTextureObject.
1837  * Note: this function will be called during context creation to
1838  * allocate the default texture objects.
1839  * Note: we could use containment here to 'derive' the driver-specific
1840  * texture object from the core mesa gl_texture_object.  Not done at this time.
1841  */
1842 static struct gl_texture_object *
1843 tdfxNewTextureObject( struct gl_context *ctx, GLuint name, GLenum target )
1844 {
1845    struct gl_texture_object *obj;
1846    obj = _mesa_new_texture_object(ctx, name, target);
1847    return obj;
1848 }
1849
1850
1851 void tdfxInitTextureFuncs( struct dd_function_table *functions )
1852 {
1853    functions->BindTexture               = tdfxBindTexture;
1854    functions->NewTextureObject          = tdfxNewTextureObject;
1855    functions->DeleteTexture             = tdfxDeleteTexture;
1856    functions->TexEnv                    = tdfxTexEnv;
1857    functions->TexParameter              = tdfxTexParameter;
1858    functions->ChooseTextureFormat       = tdfxChooseTextureFormat;
1859    functions->TexImage1D                = tdfxTexImage1D;
1860    functions->TexSubImage1D             = tdfxTexSubImage1D;
1861    functions->TexImage2D                = tdfxTexImage2D;
1862    functions->TexSubImage2D             = tdfxTexSubImage2D;
1863    functions->IsTextureResident         = tdfxIsTextureResident;
1864    functions->CompressedTexImage2D      = tdfxCompressedTexImage2D;
1865    functions->CompressedTexSubImage2D   = tdfxCompressedTexSubImage2D;
1866    functions->UpdateTexturePalette      = tdfxUpdateTexturePalette;
1867    functions->GenerateMipmap            = tdfxGenerateMipmap;
1868 }