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