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