drivers: use new _mesa_texstore() function
[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->MesaFormat == MESA_FORMAT_RGB565) {
76 _t = GL_UNSIGNED_SHORT_5_6_5_REV;
77 bpt = bytesPerPixel;
78 } else if (texImage->TexFormat->MesaFormat == MESA_FORMAT_ARGB4444) {
79 _t = GL_UNSIGNED_SHORT_4_4_4_4_REV;
80 bpt = bytesPerPixel;
81 } else if (texImage->TexFormat->MesaFormat == 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_rgba8888(ctx, 2, GL_RGBA,
97 &_mesa_texformat_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 assert(!texImage->IsCompressed);
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 const struct gl_texture_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_texformat_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_texformat_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_texformat_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_texformat_i8;
803 case GL_R3_G3_B2:
804 case GL_RGB4:
805 case GL_RGB5:
806 return &_mesa_texformat_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_texformat_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_texformat_argb8888
820 : &_mesa_texformat_rgb565;
821 case GL_RGBA2:
822 case GL_RGBA4:
823 return &_mesa_texformat_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_texformat_argb8888;
831 }
832 else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
833 return &_mesa_texformat_argb4444;
834 }
835 else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
836 return &_mesa_texformat_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_texformat_argb8888
845 : &_mesa_texformat_argb4444;
846 case GL_RGB5_A1:
847 return &_mesa_texformat_argb1555;
848 case GL_COLOR_INDEX:
849 case GL_COLOR_INDEX1_EXT:
850 case GL_COLOR_INDEX2_EXT:
851 case GL_COLOR_INDEX4_EXT:
852 case GL_COLOR_INDEX8_EXT:
853 case GL_COLOR_INDEX12_EXT:
854 case GL_COLOR_INDEX16_EXT:
855 return &_mesa_texformat_ci8;
856 /* GL_EXT_texture_compression_s3tc */
857 /* GL_S3_s3tc */
858 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
859 case GL_RGB_S3TC:
860 case GL_RGB4_S3TC:
861 return &_mesa_texformat_rgb_dxt1;
862 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
863 return &_mesa_texformat_rgba_dxt1;
864 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
865 case GL_RGBA_S3TC:
866 case GL_RGBA4_S3TC:
867 return &_mesa_texformat_rgba_dxt3;
868 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
869 return &_mesa_texformat_rgba_dxt5;
870 /* GL_3DFX_texture_compression_FXT1 */
871 case GL_COMPRESSED_RGB_FXT1_3DFX:
872 return &_mesa_texformat_rgb_fxt1;
873 case GL_COMPRESSED_RGBA_FXT1_3DFX:
874 return &_mesa_texformat_rgba_fxt1;
875 default:
876 _mesa_problem(ctx, "unexpected format in tdfxChooseTextureFormat");
877 return NULL;
878 }
879 }
880
881
882 /*
883 * Return the Glide format for the given mesa texture format.
884 */
885 static GrTextureFormat_t
886 fxGlideFormat(GLint mesaFormat)
887 {
888 switch (mesaFormat) {
889 case MESA_FORMAT_I8:
890 return GR_TEXFMT_ALPHA_8;
891 case MESA_FORMAT_A8:
892 return GR_TEXFMT_ALPHA_8;
893 case MESA_FORMAT_L8:
894 return GR_TEXFMT_INTENSITY_8;
895 case MESA_FORMAT_CI8:
896 return GR_TEXFMT_P_8;
897 case MESA_FORMAT_AL88:
898 return GR_TEXFMT_ALPHA_INTENSITY_88;
899 case MESA_FORMAT_RGB565:
900 return GR_TEXFMT_RGB_565;
901 case MESA_FORMAT_ARGB4444:
902 return GR_TEXFMT_ARGB_4444;
903 case MESA_FORMAT_ARGB1555:
904 return GR_TEXFMT_ARGB_1555;
905 case MESA_FORMAT_ARGB8888:
906 return GR_TEXFMT_ARGB_8888;
907 case MESA_FORMAT_RGB_FXT1:
908 case MESA_FORMAT_RGBA_FXT1:
909 return GR_TEXFMT_ARGB_CMP_FXT1;
910 case MESA_FORMAT_RGB_DXT1:
911 case MESA_FORMAT_RGBA_DXT1:
912 return GR_TEXFMT_ARGB_CMP_DXT1;
913 case MESA_FORMAT_RGBA_DXT3:
914 return GR_TEXFMT_ARGB_CMP_DXT3;
915 case MESA_FORMAT_RGBA_DXT5:
916 return GR_TEXFMT_ARGB_CMP_DXT5;
917 default:
918 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
919 return 0;
920 }
921 }
922
923
924 /* Texel-fetch functions for software texturing and glGetTexImage().
925 * We should have been able to use some "standard" fetch functions (which
926 * may get defined in texutil.c) but we have to account for scaled texture
927 * images on tdfx hardware (the 8:1 aspect ratio limit).
928 * Hence, we need special functions here.
929 */
930 extern void
931 fxt1_decode_1 (const void *texture, int width,
932 int i, int j, unsigned char *rgba);
933
934 static void
935 fetch_intensity8(const struct gl_texture_image *texImage,
936 GLint i, GLint j, GLint k, GLchan * rgba)
937 {
938 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
939 const GLubyte *texel;
940
941 i = i * mml->wScale;
942 j = j * mml->hScale;
943
944 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
945 rgba[RCOMP] = *texel;
946 rgba[GCOMP] = *texel;
947 rgba[BCOMP] = *texel;
948 rgba[ACOMP] = *texel;
949 }
950
951
952 static void
953 fetch_luminance8(const struct gl_texture_image *texImage,
954 GLint i, GLint j, GLint k, GLchan * rgba)
955 {
956 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
957 const GLubyte *texel;
958
959 i = i * mml->wScale;
960 j = j * mml->hScale;
961
962 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
963 rgba[RCOMP] = *texel;
964 rgba[GCOMP] = *texel;
965 rgba[BCOMP] = *texel;
966 rgba[ACOMP] = 255;
967 }
968
969
970 static void
971 fetch_alpha8(const struct gl_texture_image *texImage,
972 GLint i, GLint j, GLint k, GLchan * rgba)
973 {
974 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
975 const GLubyte *texel;
976
977 i = i * mml->wScale;
978 j = j * mml->hScale;
979
980 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
981 rgba[RCOMP] = 255;
982 rgba[GCOMP] = 255;
983 rgba[BCOMP] = 255;
984 rgba[ACOMP] = *texel;
985 }
986
987
988 static void
989 fetch_index8(const struct gl_texture_image *texImage,
990 GLint i, GLint j, GLint k, GLchan * indexOut)
991 {
992 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
993 const GLubyte *texel;
994
995 i = i * mml->wScale;
996 j = j * mml->hScale;
997
998 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
999 *indexOut = *texel;
1000 }
1001
1002
1003 static void
1004 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
1005 GLint i, GLint j, GLint k, GLchan * rgba)
1006 {
1007 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1008 const GLubyte *texel;
1009
1010 i = i * mml->wScale;
1011 j = j * mml->hScale;
1012
1013 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
1014 rgba[RCOMP] = texel[0];
1015 rgba[GCOMP] = texel[0];
1016 rgba[BCOMP] = texel[0];
1017 rgba[ACOMP] = texel[1];
1018 }
1019
1020
1021 static void
1022 fetch_r5g6b5(const struct gl_texture_image *texImage,
1023 GLint i, GLint j, GLint k, GLchan * rgba)
1024 {
1025 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1026 const GLushort *texel;
1027
1028 i = i * mml->wScale;
1029 j = j * mml->hScale;
1030
1031 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
1032 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
1033 rgba[GCOMP] = (((*texel) >> 5) & 0x3f) * 255 / 63;
1034 rgba[BCOMP] = (((*texel) >> 0) & 0x1f) * 255 / 31;
1035 rgba[ACOMP] = 255;
1036 }
1037
1038
1039 static void
1040 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
1041 GLint i, GLint j, GLint k, GLchan * rgba)
1042 {
1043 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1044 const GLushort *texel;
1045
1046 i = i * mml->wScale;
1047 j = j * mml->hScale;
1048
1049 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
1050 rgba[RCOMP] = (((*texel) >> 12) & 0xf) * 255 / 15;
1051 rgba[GCOMP] = (((*texel) >> 8) & 0xf) * 255 / 15;
1052 rgba[BCOMP] = (((*texel) >> 4) & 0xf) * 255 / 15;
1053 rgba[ACOMP] = (((*texel) >> 0) & 0xf) * 255 / 15;
1054 }
1055
1056
1057 static void
1058 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
1059 GLint i, GLint j, GLint k, GLchan * rgba)
1060 {
1061 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1062 const GLushort *texel;
1063
1064 i = i * mml->wScale;
1065 j = j * mml->hScale;
1066
1067 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
1068 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
1069 rgba[GCOMP] = (((*texel) >> 6) & 0x1f) * 255 / 31;
1070 rgba[BCOMP] = (((*texel) >> 1) & 0x1f) * 255 / 31;
1071 rgba[ACOMP] = (((*texel) >> 0) & 0x01) * 255;
1072 }
1073
1074
1075 static void
1076 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
1077 GLint i, GLint j, GLint k, GLchan * rgba)
1078 {
1079 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1080 const GLuint *texel;
1081
1082 i = i * mml->wScale;
1083 j = j * mml->hScale;
1084
1085 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
1086 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
1087 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
1088 rgba[BCOMP] = (((*texel) ) & 0xff);
1089 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
1090 }
1091
1092
1093 static void
1094 fetch_rgb_fxt1(const struct gl_texture_image *texImage,
1095 GLint i, GLint j, GLint k, GLchan *rgba)
1096 {
1097 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1098
1099 i = i * mml->wScale;
1100 j = j * mml->hScale;
1101
1102 fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
1103 rgba[ACOMP] = 255;
1104 }
1105
1106
1107 static void
1108 fetch_rgba_fxt1(const struct gl_texture_image *texImage,
1109 GLint i, GLint j, GLint k, GLchan *rgba)
1110 {
1111 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1112
1113 i = i * mml->wScale;
1114 j = j * mml->hScale;
1115
1116 fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
1117 }
1118
1119
1120 static void
1121 fetch_rgb_dxt1(const struct gl_texture_image *texImage,
1122 GLint i, GLint j, GLint k, GLchan *rgba)
1123 {
1124 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1125
1126 i = i * mml->wScale;
1127 j = j * mml->hScale;
1128
1129 _mesa_texformat_rgb_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
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 _mesa_texformat_rgba_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
1143 }
1144
1145
1146 static void
1147 fetch_rgba_dxt3(const struct gl_texture_image *texImage,
1148 GLint i, GLint j, GLint k, GLchan *rgba)
1149 {
1150 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1151
1152 i = i * mml->wScale;
1153 j = j * mml->hScale;
1154
1155 _mesa_texformat_rgba_dxt3.FetchTexel2D(texImage, i, j, k, rgba);
1156 }
1157
1158
1159 static void
1160 fetch_rgba_dxt5(const struct gl_texture_image *texImage,
1161 GLint i, GLint j, GLint k, GLchan *rgba)
1162 {
1163 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
1164
1165 i = i * mml->wScale;
1166 j = j * mml->hScale;
1167
1168 _mesa_texformat_rgba_dxt5.FetchTexel2D(texImage, i, j, k, rgba);
1169 }
1170
1171
1172 static FetchTexelFuncC
1173 fxFetchFunction(GLint mesaFormat)
1174 {
1175 switch (mesaFormat) {
1176 case MESA_FORMAT_I8:
1177 return &fetch_intensity8;
1178 case MESA_FORMAT_A8:
1179 return &fetch_alpha8;
1180 case MESA_FORMAT_L8:
1181 return &fetch_luminance8;
1182 case MESA_FORMAT_CI8:
1183 return &fetch_index8;
1184 case MESA_FORMAT_AL88:
1185 return &fetch_luminance8_alpha8;
1186 case MESA_FORMAT_RGB565:
1187 return &fetch_r5g6b5;
1188 case MESA_FORMAT_ARGB4444:
1189 return &fetch_r4g4b4a4;
1190 case MESA_FORMAT_ARGB1555:
1191 return &fetch_r5g5b5a1;
1192 case MESA_FORMAT_ARGB8888:
1193 return &fetch_a8r8g8b8;
1194 case MESA_FORMAT_RGB_FXT1:
1195 return &fetch_rgb_fxt1;
1196 case MESA_FORMAT_RGBA_FXT1:
1197 return &fetch_rgba_fxt1;
1198 case MESA_FORMAT_RGB_DXT1:
1199 return &fetch_rgb_dxt1;
1200 case MESA_FORMAT_RGBA_DXT1:
1201 return &fetch_rgba_dxt1;
1202 case MESA_FORMAT_RGBA_DXT3:
1203 return &fetch_rgba_dxt3;
1204 case MESA_FORMAT_RGBA_DXT5:
1205 return &fetch_rgba_dxt5;
1206 default:
1207 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
1208 return NULL;
1209 }
1210 }
1211
1212
1213 static GLboolean
1214 adjust2DRatio (GLcontext *ctx,
1215 GLint xoffset, GLint yoffset,
1216 GLint width, GLint height,
1217 GLenum format, GLenum type, const GLvoid *pixels,
1218 const struct gl_pixelstore_attrib *packing,
1219 tdfxMipMapLevel *mml,
1220 struct gl_texture_image *texImage,
1221 GLint texelBytes,
1222 GLint dstRowStride)
1223 {
1224 const GLint newWidth = width * mml->wScale;
1225 const GLint newHeight = height * mml->hScale;
1226 GLvoid *tempImage;
1227 GLuint dstImageOffsets = 0;
1228
1229 if (!texImage->IsCompressed) {
1230 GLubyte *destAddr;
1231
1232 tempImage = MALLOC(width * height * texelBytes);
1233 if (!tempImage) {
1234 return GL_FALSE;
1235 }
1236
1237 _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1238 texImage->TexFormat, tempImage,
1239 0, 0, 0, /* dstX/Y/Zoffset */
1240 width * texelBytes, /* dstRowStride */
1241 &dstImageOffsets,
1242 width, height, 1,
1243 format, type, pixels, packing);
1244
1245 /* now rescale */
1246 /* compute address of dest subimage within the overal tex image */
1247 destAddr = (GLubyte *) texImage->Data
1248 + (yoffset * mml->hScale * mml->width
1249 + xoffset * mml->wScale) * texelBytes;
1250
1251 _mesa_rescale_teximage2d(texelBytes,
1252 width,
1253 dstRowStride, /* dst stride */
1254 width, height,
1255 newWidth, newHeight,
1256 tempImage, destAddr);
1257 } else {
1258 const GLint rawBytes = 4;
1259 GLvoid *rawImage = MALLOC(width * height * rawBytes);
1260
1261 if (!rawImage) {
1262 return GL_FALSE;
1263 }
1264 tempImage = MALLOC(newWidth * newHeight * rawBytes);
1265 if (!tempImage) {
1266 FREE(rawImage);
1267 return GL_FALSE;
1268 }
1269 /* unpack image, apply transfer ops and store in rawImage */
1270 _mesa_texstore_rgba8888(ctx, 2, GL_RGBA,
1271 &_mesa_texformat_rgba8888_rev, rawImage,
1272 0, 0, 0, /* dstX/Y/Zoffset */
1273 width * rawBytes, /* dstRowStride */
1274 &dstImageOffsets,
1275 width, height, 1,
1276 format, type, pixels, packing);
1277 _mesa_rescale_teximage2d(rawBytes,
1278 width,
1279 newWidth * rawBytes, /* dst stride */
1280 width, height, /* src */
1281 newWidth, newHeight, /* dst */
1282 rawImage /*src*/, tempImage /*dst*/ );
1283 _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1284 texImage->TexFormat, texImage->Data,
1285 xoffset * mml->wScale, yoffset * mml->hScale, 0, /* dstX/Y/Zoffset */
1286 dstRowStride,
1287 &dstImageOffsets,
1288 newWidth, newHeight, 1,
1289 GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
1290 FREE(rawImage);
1291 }
1292
1293 FREE(tempImage);
1294
1295 return GL_TRUE;
1296 }
1297
1298
1299 static void
1300 tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level,
1301 GLint internalFormat, GLint width, GLint height, GLint border,
1302 GLenum format, GLenum type, const GLvoid *pixels,
1303 const struct gl_pixelstore_attrib *packing,
1304 struct gl_texture_object *texObj,
1305 struct gl_texture_image *texImage)
1306 {
1307 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1308 tdfxTexInfo *ti;
1309 tdfxMipMapLevel *mml;
1310 GLint texelBytes, dstRowStride;
1311 GLuint mesaFormat;
1312
1313 /*
1314 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1315 texObj->Name, texImage->InternalFormat, format, type,
1316 texImage->Width, texImage->Height);
1317 */
1318
1319 ti = TDFX_TEXTURE_DATA(texObj);
1320 if (!ti) {
1321 texObj->DriverData = fxAllocTexObjData(fxMesa);
1322 if (!texObj->DriverData) {
1323 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1324 return;
1325 }
1326 ti = TDFX_TEXTURE_DATA(texObj);
1327 }
1328 assert(ti);
1329
1330 mml = TDFX_TEXIMAGE_DATA(texImage);
1331 if (!mml) {
1332 texImage->DriverData = CALLOC(sizeof(tdfxMipMapLevel));
1333 if (!texImage->DriverData) {
1334 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1335 return;
1336 }
1337 mml = TDFX_TEXIMAGE_DATA(texImage);
1338 }
1339
1340 /* Determine width and height scale factors for texture.
1341 * Remember, Glide is limited to 8:1 aspect ratios.
1342 */
1343 tdfxTexGetInfo(ctx,
1344 texImage->Width, texImage->Height,
1345 NULL, /* lod level */
1346 NULL, /* aspect ratio */
1347 NULL, NULL, /* sscale, tscale */
1348 &mml->wScale, &mml->hScale);
1349
1350 /* rescaled size: */
1351 mml->width = width * mml->wScale;
1352 mml->height = height * mml->hScale;
1353
1354 #if FX_COMPRESS_S3TC_AS_FXT1_HACK
1355 /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
1356 /* [dBorca] we should update texture's attribute, then,
1357 * because if the application asks us to decompress, we
1358 * have to know the REAL format! Also, DXT3/5 might not
1359 * be correct, since it would mess with "compressedSize".
1360 * Ditto for GL_RGBA[4]_S3TC, which is always mapped to DXT3.
1361 */
1362 if (texImage->IsCompressed) {
1363 switch (internalFormat) {
1364 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1365 case GL_RGB_S3TC:
1366 case GL_RGB4_S3TC:
1367 internalFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
1368 break;
1369 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1370 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
1371 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
1372 case GL_RGBA_S3TC:
1373 case GL_RGBA4_S3TC:
1374 internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
1375 }
1376 texImage->InternalFormat = internalFormat;
1377 }
1378 #endif
1379 #if FX_TC_NAPALM
1380 if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
1381 GLenum texNapalm = 0;
1382 if (internalFormat == GL_COMPRESSED_RGB) {
1383 texNapalm = GL_COMPRESSED_RGB_FXT1_3DFX;
1384 } else if (internalFormat == GL_COMPRESSED_RGBA) {
1385 texNapalm = GL_COMPRESSED_RGBA_FXT1_3DFX;
1386 }
1387 if (texNapalm) {
1388 texImage->InternalFormat = internalFormat = texNapalm;
1389 texImage->IsCompressed = GL_TRUE;
1390 }
1391 }
1392 #endif
1393
1394 /* choose the texture format */
1395 assert(ctx->Driver.ChooseTextureFormat);
1396 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1397 internalFormat, format, type);
1398 assert(texImage->TexFormat);
1399 mesaFormat = texImage->TexFormat->MesaFormat;
1400 mml->glideFormat = fxGlideFormat(mesaFormat);
1401 ti->info.format = mml->glideFormat;
1402 texImage->FetchTexelc = fxFetchFunction(mesaFormat);
1403 texelBytes = _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
1404
1405 if (texImage->IsCompressed) {
1406 texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
1407 mml->width,
1408 mml->height,
1409 1,
1410 mesaFormat);
1411 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, mml->width);
1412 texImage->Data = _mesa_alloc_texmemory(texImage->CompressedSize);
1413 } else {
1414 dstRowStride = mml->width * texelBytes;
1415 texImage->Data = _mesa_alloc_texmemory(mml->width * mml->height * texelBytes);
1416 }
1417 if (!texImage->Data) {
1418 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1419 return;
1420 }
1421
1422 if (pixels != NULL) {
1423 if (mml->wScale != 1 || mml->hScale != 1) {
1424 /* rescale image to overcome 1:8 aspect limitation */
1425 if (!adjust2DRatio(ctx,
1426 0, 0,
1427 width, height,
1428 format, type, pixels,
1429 packing,
1430 mml,
1431 texImage,
1432 texelBytes,
1433 dstRowStride)
1434 ) {
1435 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1436 return;
1437 }
1438 }
1439 else {
1440 /* no rescaling needed */
1441 /* unpack image, apply transfer ops and store in texImage->Data */
1442 _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1443 texImage->TexFormat, texImage->Data,
1444 0, 0, 0, /* dstX/Y/Zoffset */
1445 dstRowStride,
1446 texImage->ImageOffsets,
1447 width, height, 1,
1448 format, type, pixels, packing);
1449 }
1450 }
1451
1452 RevalidateTexture(ctx, texObj);
1453
1454 ti->reloadImages = GL_TRUE;
1455 fxMesa->new_state |= TDFX_NEW_TEXTURE;
1456 }
1457
1458
1459 static void
1460 tdfxTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
1461 GLint xoffset, GLint yoffset,
1462 GLsizei width, GLsizei height,
1463 GLenum format, GLenum type,
1464 const GLvoid *pixels,
1465 const struct gl_pixelstore_attrib *packing,
1466 struct gl_texture_object *texObj,
1467 struct gl_texture_image *texImage )
1468 {
1469 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1470 tdfxTexInfo *ti;
1471 tdfxMipMapLevel *mml;
1472 GLint texelBytes, dstRowStride;
1473
1474 if (!texObj->DriverData) {
1475 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1476 return;
1477 }
1478
1479 ti = TDFX_TEXTURE_DATA(texObj);
1480 assert(ti);
1481 mml = TDFX_TEXIMAGE_DATA(texImage);
1482 assert(mml);
1483
1484 assert(texImage->Data); /* must have an existing texture image! */
1485 assert(texImage->_BaseFormat);
1486
1487 texelBytes = _mesa_get_format_bytes(texImage->TexFormat->MesaFormat);
1488 if (texImage->IsCompressed) {
1489 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, mml->width);
1490 } else {
1491 dstRowStride = mml->width * texelBytes;
1492 }
1493
1494 if (mml->wScale != 1 || mml->hScale != 1) {
1495 /* need to rescale subimage to match mipmap level's rescale factors */
1496 if (!adjust2DRatio(ctx,
1497 xoffset, yoffset,
1498 width, height,
1499 format, type, pixels,
1500 packing,
1501 mml,
1502 texImage,
1503 texelBytes,
1504 dstRowStride)
1505 ) {
1506 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1507 return;
1508 }
1509 }
1510 else {
1511 /* no rescaling needed */
1512 _mesa_texstore(ctx, 2, texImage->_BaseFormat,
1513 texImage->TexFormat, texImage->Data,
1514 xoffset, yoffset, 0,
1515 dstRowStride,
1516 texImage->ImageOffsets,
1517 width, height, 1,
1518 format, type, pixels, packing);
1519 }
1520
1521 ti->reloadImages = GL_TRUE; /* signal the image needs to be reloaded */
1522 fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX this might be a bit much */
1523 }
1524
1525
1526 static void
1527 tdfxTexImage1D(GLcontext *ctx, GLenum target, GLint level,
1528 GLint internalFormat, GLint width, GLint border,
1529 GLenum format, GLenum type, const GLvoid *pixels,
1530 const struct gl_pixelstore_attrib *packing,
1531 struct gl_texture_object *texObj,
1532 struct gl_texture_image *texImage)
1533 {
1534 tdfxTexImage2D(ctx, target, level,
1535 internalFormat, width, 1, border,
1536 format, type, pixels,
1537 packing,
1538 texObj,
1539 texImage);
1540 }
1541
1542 static void
1543 tdfxTexSubImage1D(GLcontext *ctx, GLenum target, GLint level,
1544 GLint xoffset,
1545 GLsizei width,
1546 GLenum format, GLenum type,
1547 const GLvoid *pixels,
1548 const struct gl_pixelstore_attrib *packing,
1549 struct gl_texture_object *texObj,
1550 struct gl_texture_image *texImage )
1551 {
1552 tdfxTexSubImage2D(ctx, target, level,
1553 xoffset, 0,
1554 width, 1,
1555 format, type,
1556 pixels,
1557 packing,
1558 texObj,
1559 texImage);
1560 }
1561
1562 /**********************************************************************/
1563 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1564 /**********************************************************************/
1565
1566 static void
1567 tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target,
1568 GLint level, GLint internalFormat,
1569 GLsizei width, GLsizei height, GLint border,
1570 GLsizei imageSize, const GLvoid *data,
1571 struct gl_texture_object *texObj,
1572 struct gl_texture_image *texImage)
1573 {
1574 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1575 tdfxTexInfo *ti;
1576 tdfxMipMapLevel *mml;
1577 GLuint mesaFormat;
1578
1579 if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) {
1580 fprintf(stderr, "tdfxCompressedTexImage2D: id=%d int 0x%x %dx%d\n",
1581 texObj->Name, internalFormat,
1582 width, height);
1583 }
1584
1585 if ((target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) || texImage->Border > 0) {
1586 _mesa_problem(NULL, "tdfx: unsupported texture in tdfxCompressedTexImg()\n");
1587 return;
1588 }
1589
1590 assert(texImage->IsCompressed);
1591
1592 ti = TDFX_TEXTURE_DATA(texObj);
1593 if (!ti) {
1594 texObj->DriverData = fxAllocTexObjData(fxMesa);
1595 if (!texObj->DriverData) {
1596 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1597 return;
1598 }
1599 ti = TDFX_TEXTURE_DATA(texObj);
1600 }
1601 assert(ti);
1602
1603 mml = TDFX_TEXIMAGE_DATA(texImage);
1604 if (!mml) {
1605 texImage->DriverData = CALLOC(sizeof(tdfxMipMapLevel));
1606 if (!texImage->DriverData) {
1607 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1608 return;
1609 }
1610 mml = TDFX_TEXIMAGE_DATA(texImage);
1611 }
1612
1613 tdfxTexGetInfo(ctx, width, height, NULL, NULL, NULL, NULL,
1614 &mml->wScale, &mml->hScale);
1615
1616 mml->width = width * mml->wScale;
1617 mml->height = height * mml->hScale;
1618
1619
1620 /* choose the texture format */
1621 assert(ctx->Driver.ChooseTextureFormat);
1622 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1623 internalFormat, -1/*format*/, -1/*type*/);
1624 assert(texImage->TexFormat);
1625
1626 /* Determine the appropriate Glide texel format,
1627 * given the user's internal texture format hint.
1628 */
1629 mesaFormat = texImage->TexFormat->MesaFormat;
1630 mml->glideFormat = fxGlideFormat(mesaFormat);
1631 ti->info.format = mml->glideFormat;
1632 texImage->FetchTexelc = fxFetchFunction(mesaFormat);
1633
1634 /* allocate new storage for texture image, if needed */
1635 if (!texImage->Data) {
1636 texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
1637 mml->width,
1638 mml->height,
1639 1,
1640 mesaFormat);
1641 texImage->Data = _mesa_alloc_texmemory(texImage->CompressedSize);
1642 if (!texImage->Data) {
1643 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1644 return;
1645 }
1646 }
1647
1648 /* save the texture data */
1649 if (mml->wScale != 1 || mml->hScale != 1) {
1650 /* [dBorca] Hack alert:
1651 * now we're screwed. We can't decompress,
1652 * unless we do it in HW (via textureBuffer).
1653 * We still have some chances:
1654 * 1) we got FXT1 textures - we CAN decompress, rescale for
1655 * aspectratio, then compress back.
1656 * 2) there is a chance that MIN("s", "t") won't be overflowed.
1657 * Thus, we don't care about textureclamp and we could lower
1658 * MIN("uscale", "vscale") below 32. We still have to have
1659 * our data aligned inside a 8:1 rectangle.
1660 * 3) just in case if MIN("s", "t") gets overflowed with GL_REPEAT,
1661 * we replicate the data over the padded area.
1662 * For now, we take 2) + 3) but texelfetchers will be wrong!
1663 */
1664 const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
1665 GLuint srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
1666
1667 GLuint destRowStride = _mesa_compressed_row_stride(mesaFormat,
1668 mml->width);
1669
1670 _mesa_upscale_teximage2d(srcRowStride, (height+3) / 4,
1671 destRowStride, (mml->height+3) / 4,
1672 1, data, srcRowStride,
1673 texImage->Data);
1674 ti->padded = GL_TRUE;
1675 } else {
1676 MEMCPY(texImage->Data, data, texImage->CompressedSize);
1677 }
1678
1679 RevalidateTexture(ctx, texObj);
1680
1681 ti->reloadImages = GL_TRUE;
1682 fxMesa->new_state |= TDFX_NEW_TEXTURE;
1683 }
1684
1685
1686 static void
1687 tdfxCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
1688 GLint level, GLint xoffset,
1689 GLint yoffset, GLsizei width,
1690 GLint height, GLenum format,
1691 GLsizei imageSize, const GLvoid *data,
1692 struct gl_texture_object *texObj,
1693 struct gl_texture_image *texImage )
1694 {
1695 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1696 tdfxTexInfo *ti;
1697 tdfxMipMapLevel *mml;
1698 GLint destRowStride, srcRowStride;
1699 GLint i, rows;
1700 GLubyte *dest;
1701 const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
1702
1703 if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) {
1704 fprintf(stderr, "tdfxCompressedTexSubImage2D: id=%d\n", texObj->Name);
1705 }
1706
1707 ti = TDFX_TEXTURE_DATA(texObj);
1708 assert(ti);
1709 mml = TDFX_TEXIMAGE_DATA(texImage);
1710 assert(mml);
1711
1712 srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
1713
1714 destRowStride = _mesa_compressed_row_stride(mesaFormat, mml->width);
1715 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
1716 mesaFormat,
1717 mml->width,
1718 (GLubyte*) texImage->Data);
1719
1720 rows = height / 4; /* [dBorca] hardcoded 4, but works for FXT1/DXTC */
1721
1722 for (i = 0; i < rows; i++) {
1723 MEMCPY(dest, data, srcRowStride);
1724 dest += destRowStride;
1725 data = (GLvoid *)((intptr_t)data + (intptr_t)srcRowStride);
1726 }
1727
1728 /* [dBorca] Hack alert:
1729 * see fxDDCompressedTexImage2D for caveats
1730 */
1731 if (mml->wScale != 1 || mml->hScale != 1) {
1732 srcRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width);
1733
1734 destRowStride = _mesa_compressed_row_stride(mesaFormat, mml->width);
1735 _mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4,
1736 destRowStride, mml->height / 4,
1737 1, texImage->Data, destRowStride,
1738 texImage->Data);
1739 }
1740
1741 RevalidateTexture(ctx, texObj);
1742
1743 ti->reloadImages = GL_TRUE;
1744 fxMesa->new_state |= TDFX_NEW_TEXTURE;
1745 }
1746
1747
1748 #if 0
1749 static void
1750 PrintTexture(int w, int h, int c, const GLubyte * data)
1751 {
1752 int i, j;
1753 for (i = 0; i < h; i++) {
1754 for (j = 0; j < w; j++) {
1755 if (c == 2)
1756 printf("%02x %02x ", data[0], data[1]);
1757 else if (c == 3)
1758 printf("%02x %02x %02x ", data[0], data[1], data[2]);
1759 data += c;
1760 }
1761 printf("\n");
1762 }
1763 }
1764 #endif
1765
1766
1767 GLboolean
1768 tdfxTestProxyTexImage(GLcontext *ctx, GLenum target,
1769 GLint level, GLint internalFormat,
1770 GLenum format, GLenum type,
1771 GLint width, GLint height,
1772 GLint depth, GLint border)
1773 {
1774 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1775 struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
1776 struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
1777
1778 switch (target) {
1779 case GL_PROXY_TEXTURE_1D:
1780 /*JJJ wrong*/
1781 case GL_PROXY_TEXTURE_2D:
1782 {
1783 struct gl_texture_object *tObj;
1784 tdfxTexInfo *ti;
1785 int memNeeded;
1786
1787 tObj = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
1788 if (!tObj->DriverData)
1789 tObj->DriverData = fxAllocTexObjData(fxMesa);
1790 ti = TDFX_TEXTURE_DATA(tObj);
1791 assert(ti);
1792
1793 /* assign the parameters to test against */
1794 tObj->Image[0][level]->Width = width;
1795 tObj->Image[0][level]->Height = height;
1796 tObj->Image[0][level]->Border = border;
1797 #if 0
1798 tObj->Image[0][level]->InternalFormat = internalFormat;
1799 #endif
1800 if (level == 0) {
1801 /* don't use mipmap levels > 0 */
1802 tObj->MinFilter = tObj->MagFilter = GL_NEAREST;
1803 }
1804 else {
1805 /* test with all mipmap levels */
1806 tObj->MinFilter = GL_LINEAR_MIPMAP_LINEAR;
1807 tObj->MagFilter = GL_NEAREST;
1808 }
1809 RevalidateTexture(ctx, tObj);
1810
1811 /*
1812 printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1813 printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1814 printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1815 printf("glide format 0x%x\n", ti->info.format);
1816 printf("data %p\n", ti->info.data);
1817 printf("lodblend %d\n", (int) ti->LODblend);
1818 */
1819
1820 /* determine where texture will reside */
1821 if (ti->LODblend && !shared->umaTexMemory) {
1822 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1823 memNeeded = fxMesa->Glide.grTexTextureMemRequired(
1824 GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1825 }
1826 else {
1827 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1828 memNeeded = fxMesa->Glide.grTexTextureMemRequired(
1829 GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1830 }
1831 /*
1832 printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1833 */
1834 if (memNeeded > shared->totalTexMem[0])
1835 return GL_FALSE;
1836 else
1837 return GL_TRUE;
1838 }
1839 case GL_PROXY_TEXTURE_3D:
1840 return GL_TRUE; /* software rendering */
1841 default:
1842 return GL_TRUE; /* never happens, silence compiler */
1843 }
1844 }
1845
1846
1847 /**
1848 * Allocate a new texture object.
1849 * Called via ctx->Driver.NewTextureObject.
1850 * Note: this function will be called during context creation to
1851 * allocate the default texture objects.
1852 * Note: we could use containment here to 'derive' the driver-specific
1853 * texture object from the core mesa gl_texture_object. Not done at this time.
1854 */
1855 static struct gl_texture_object *
1856 tdfxNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
1857 {
1858 struct gl_texture_object *obj;
1859 obj = _mesa_new_texture_object(ctx, name, target);
1860 return obj;
1861 }
1862
1863
1864 void tdfxInitTextureFuncs( struct dd_function_table *functions )
1865 {
1866 functions->BindTexture = tdfxBindTexture;
1867 functions->NewTextureObject = tdfxNewTextureObject;
1868 functions->DeleteTexture = tdfxDeleteTexture;
1869 functions->TexEnv = tdfxTexEnv;
1870 functions->TexParameter = tdfxTexParameter;
1871 functions->ChooseTextureFormat = tdfxChooseTextureFormat;
1872 functions->TexImage1D = tdfxTexImage1D;
1873 functions->TexSubImage1D = tdfxTexSubImage1D;
1874 functions->TexImage2D = tdfxTexImage2D;
1875 functions->TexSubImage2D = tdfxTexSubImage2D;
1876 functions->IsTextureResident = tdfxIsTextureResident;
1877 functions->CompressedTexImage2D = tdfxCompressedTexImage2D;
1878 functions->CompressedTexSubImage2D = tdfxCompressedTexSubImage2D;
1879 functions->UpdateTexturePalette = tdfxUpdateTexturePalette;
1880 functions->GenerateMipmap = tdfxGenerateMipmap;
1881 }