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