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