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