add tdfx DRI driver
[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 * Original rewrite:
30 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
31 *
32 * Authors:
33 * Gareth Hughes <gareth@valinux.com>
34 * Brian Paul <brianp@valinux.com>
35 *
36 */
37
38 #include "image.h"
39 #include "texutil.h"
40 #include "texformat.h"
41 #include "teximage.h"
42 #include "texstore.h"
43 #include "tdfx_context.h"
44 #include "tdfx_tex.h"
45 #include "tdfx_texman.h"
46
47
48
49 static int
50 logbase2(int n)
51 {
52 GLint i = 1;
53 GLint log2 = 0;
54
55 if (n < 0) {
56 return -1;
57 }
58
59 while (n > i) {
60 i *= 2;
61 log2++;
62 }
63 if (i != n) {
64 return -1;
65 }
66 else {
67 return log2;
68 }
69 }
70
71
72 /*
73 * Compute various texture image parameters.
74 * Input: w, h - source texture width and height
75 * Output: lodlevel - Glide lod level token for the larger texture dimension
76 * aspectratio - Glide aspect ratio token
77 * sscale - S scale factor used during triangle setup
78 * tscale - T scale factor used during triangle setup
79 * wscale - OpenGL -> Glide image width scale factor
80 * hscale - OpenGL -> Glide image height scale factor
81 *
82 * Sample results:
83 * w h lodlevel aspectRatio
84 * 128 128 GR_LOD_LOG2_128 (=7) GR_ASPECT_LOG2_1x1 (=0)
85 * 64 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x1 (=0)
86 * 64 32 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_2x1 (=1)
87 * 32 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x2 (=-1)
88 * 32 32 GR_LOD_LOG2_32 (=5) GR_ASPECT_LOG2_1x1 (=0)
89 */
90 static void
91 tdfxTexGetInfo(const GLcontext *ctx, int w, int h,
92 GrLOD_t *lodlevel, GrAspectRatio_t *aspectratio,
93 float *sscale, float *tscale,
94 int *wscale, int *hscale)
95 {
96 int logw, logh, ar, lod, ws, hs;
97 float s, t;
98
99 ASSERT(w >= 1);
100 ASSERT(h >= 1);
101
102 logw = logbase2(w);
103 logh = logbase2(h);
104 ar = logw - logh; /* aspect ratio = difference in log dimensions */
105
106 /* Hardware only allows a maximum aspect ratio of 8x1, so handle
107 |ar| > 3 by scaling the image and using an 8x1 aspect ratio */
108 if (ar >= 0) {
109 ASSERT(width >= height);
110 lod = logw;
111 s = 256.0;
112 ws = 1;
113 if (ar <= GR_ASPECT_LOG2_8x1) {
114 t = 256 >> ar;
115 hs = 1;
116 }
117 else {
118 /* have to stretch image height */
119 t = 32.0;
120 hs = 1 << (ar - 3);
121 }
122 }
123 else {
124 ASSERT(width < height);
125 lod = logh;
126 t = 256.0;
127 hs = 1;
128 if (ar >= GR_ASPECT_LOG2_1x8) {
129 s = 256 >> -ar;
130 ws = 1;
131 }
132 else {
133 /* have to stretch image width */
134 s = 32.0;
135 ws = 1 << (-ar - 3);
136 }
137 }
138
139 if (ar < GR_ASPECT_LOG2_1x8)
140 ar = GR_ASPECT_LOG2_1x8;
141 else if (ar > GR_ASPECT_LOG2_8x1)
142 ar = GR_ASPECT_LOG2_8x1;
143
144 if (lodlevel)
145 *lodlevel = (GrLOD_t) lod;
146 if (aspectratio)
147 *aspectratio = (GrAspectRatio_t) ar;
148 if (sscale)
149 *sscale = s;
150 if (tscale)
151 *tscale = t;
152 if (wscale)
153 *wscale = ws;
154 if (hscale)
155 *hscale = hs;
156 }
157
158
159 /*
160 * We need to call this when a texture object's minification filter
161 * or texture image sizes change.
162 */
163 static void RevalidateTexture(GLcontext *ctx, struct gl_texture_object *tObj)
164 {
165 tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
166 GLint minl, maxl;
167
168 if (!ti)
169 return;
170
171 minl = maxl = tObj->BaseLevel;
172
173 if (tObj->Image[minl]) {
174 maxl = MIN2(tObj->MaxLevel, tObj->Image[minl]->MaxLog2);
175
176 /* compute largeLodLog2, aspect ratio and texcoord scale factors */
177 tdfxTexGetInfo(ctx, tObj->Image[minl]->Width, tObj->Image[minl]->Height,
178 &ti->info.largeLodLog2,
179 &ti->info.aspectRatioLog2,
180 &(ti->sScale), &(ti->tScale), NULL, NULL);
181 }
182
183 if (tObj->Image[maxl] && (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) {
184 /* mipmapping: need to compute smallLodLog2 */
185 tdfxTexGetInfo(ctx, tObj->Image[maxl]->Width,
186 tObj->Image[maxl]->Height,
187 &ti->info.smallLodLog2, NULL,
188 NULL, NULL, NULL, NULL);
189 }
190 else {
191 /* not mipmapping: smallLodLog2 = largeLodLog2 */
192 ti->info.smallLodLog2 = ti->info.largeLodLog2;
193 maxl = minl;
194 }
195
196 ti->minLevel = minl;
197 ti->maxLevel = maxl;
198 ti->info.data = NULL;
199 }
200
201
202 static tdfxTexInfo *
203 fxAllocTexObjData(tdfxContextPtr fxMesa)
204 {
205 tdfxTexInfo *ti;
206
207 if (!(ti = CALLOC(sizeof(tdfxTexInfo)))) {
208 _mesa_problem(NULL, "tdfx driver: out of memory");
209 return NULL;
210 }
211
212 ti->isInTM = GL_FALSE;
213
214 ti->whichTMU = TDFX_TMU_NONE;
215
216 ti->tm[TDFX_TMU0] = NULL;
217 ti->tm[TDFX_TMU1] = NULL;
218
219 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
220 ti->magFilt = GR_TEXTUREFILTER_BILINEAR;
221
222 ti->sClamp = GR_TEXTURECLAMP_WRAP;
223 ti->tClamp = GR_TEXTURECLAMP_WRAP;
224
225 ti->mmMode = GR_MIPMAP_NEAREST;
226 ti->LODblend = FXFALSE;
227
228 return ti;
229 }
230
231
232 /*
233 * Called via glBindTexture.
234 */
235
236 void
237 tdfxDDBindTexture(GLcontext * ctx, GLenum target,
238 struct gl_texture_object *tObj)
239 {
240 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
241 tdfxTexInfo *ti;
242
243 if (MESA_VERBOSE & VERBOSE_DRIVER) {
244 fprintf(stderr, "fxmesa: fxDDTexBind(%d,%p)\n", tObj->Name,
245 tObj->DriverData);
246 }
247
248 if (target != GL_TEXTURE_2D)
249 return;
250
251 if (!tObj->DriverData) {
252 tObj->DriverData = fxAllocTexObjData(fxMesa);
253 }
254
255 ti = TDFX_TEXTURE_DATA(tObj);
256 ti->lastTimeUsed = fxMesa->texBindNumber++;
257
258 fxMesa->new_state |= TDFX_NEW_TEXTURE;
259 }
260
261
262 /*
263 * Called via glTexEnv.
264 */
265 void
266 tdfxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
267 const GLfloat * param)
268 {
269 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
270
271 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
272 if (param)
273 fprintf(stderr, "fxmesa: texenv(%x,%x)\n", pname,
274 (GLint) (*param));
275 else
276 fprintf(stderr, "fxmesa: texenv(%x)\n", pname);
277 }
278
279 /* XXX this is a bit of a hack to force the Glide texture
280 * state to be updated.
281 */
282 fxMesa->TexState.EnvMode[ctx->Texture.CurrentUnit] = 0;
283
284 fxMesa->new_state |= TDFX_NEW_TEXTURE;
285 }
286
287
288 /*
289 * Called via glTexParameter.
290 */
291 void
292 tdfxDDTexParameter(GLcontext * ctx, GLenum target,
293 struct gl_texture_object *tObj,
294 GLenum pname, const GLfloat * params)
295 {
296 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
297 GLenum param = (GLenum) (GLint) params[0];
298 tdfxTexInfo *ti;
299
300 if (MESA_VERBOSE & VERBOSE_DRIVER) {
301 fprintf(stderr, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj->Name,
302 tObj->DriverData, pname, param);
303 }
304
305 if (target != GL_TEXTURE_2D)
306 return;
307
308 if (!tObj->DriverData)
309 tObj->DriverData = fxAllocTexObjData(fxMesa);
310
311 ti = TDFX_TEXTURE_DATA(tObj);
312
313 switch (pname) {
314 case GL_TEXTURE_MIN_FILTER:
315 switch (param) {
316 case GL_NEAREST:
317 ti->mmMode = GR_MIPMAP_DISABLE;
318 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
319 ti->LODblend = FXFALSE;
320 break;
321 case GL_LINEAR:
322 ti->mmMode = GR_MIPMAP_DISABLE;
323 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
324 ti->LODblend = FXFALSE;
325 break;
326 case GL_NEAREST_MIPMAP_LINEAR:
327 if (TDFX_IS_NAPALM(fxMesa)) {
328 if (fxMesa->haveTwoTMUs) {
329 ti->mmMode = GR_MIPMAP_NEAREST;
330 ti->LODblend = FXTRUE;
331 }
332 else {
333 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
334 ti->LODblend = FXFALSE;
335 }
336 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
337 break;
338 }
339 /* XXX Voodoo3/Banshee mipmap blending seems to produce
340 * incorrectly filtered colors for the smallest mipmap levels.
341 * To work-around we fall-through here and use a different filter.
342 */
343 case GL_NEAREST_MIPMAP_NEAREST:
344 ti->mmMode = GR_MIPMAP_NEAREST;
345 ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
346 ti->LODblend = FXFALSE;
347 break;
348 case GL_LINEAR_MIPMAP_LINEAR:
349 if (TDFX_IS_NAPALM(fxMesa)) {
350 if (fxMesa->haveTwoTMUs) {
351 ti->mmMode = GR_MIPMAP_NEAREST;
352 ti->LODblend = FXTRUE;
353 }
354 else {
355 ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
356 ti->LODblend = FXFALSE;
357 }
358 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
359 break;
360 }
361 /* XXX Voodoo3/Banshee mipmap blending seems to produce
362 * incorrectly filtered colors for the smallest mipmap levels.
363 * To work-around we fall-through here and use a different filter.
364 */
365 case GL_LINEAR_MIPMAP_NEAREST:
366 ti->mmMode = GR_MIPMAP_NEAREST;
367 ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
368 ti->LODblend = FXFALSE;
369 break;
370 default:
371 break;
372 }
373 RevalidateTexture(ctx, tObj);
374 fxMesa->new_state |= TDFX_NEW_TEXTURE;
375 break;
376
377 case GL_TEXTURE_MAG_FILTER:
378 switch (param) {
379 case GL_NEAREST:
380 ti->magFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
381 break;
382 case GL_LINEAR:
383 ti->magFilt = GR_TEXTUREFILTER_BILINEAR;
384 break;
385 default:
386 break;
387 }
388 fxMesa->new_state |= TDFX_NEW_TEXTURE;
389 break;
390
391 case GL_TEXTURE_WRAP_S:
392 switch (param) {
393 case GL_CLAMP:
394 ti->sClamp = GR_TEXTURECLAMP_CLAMP;
395 break;
396 case GL_REPEAT:
397 ti->sClamp = GR_TEXTURECLAMP_WRAP;
398 break;
399 default:
400 break;
401 }
402 fxMesa->new_state |= TDFX_NEW_TEXTURE;
403 break;
404
405 case GL_TEXTURE_WRAP_T:
406 switch (param) {
407 case GL_CLAMP:
408 ti->tClamp = GR_TEXTURECLAMP_CLAMP;
409 break;
410 case GL_REPEAT:
411 ti->tClamp = GR_TEXTURECLAMP_WRAP;
412 break;
413 default:
414 break;
415 }
416 fxMesa->new_state |= TDFX_NEW_TEXTURE;
417 break;
418
419 case GL_TEXTURE_BORDER_COLOR:
420 /* TO DO */
421 break;
422 case GL_TEXTURE_MIN_LOD:
423 /* TO DO */
424 break;
425 case GL_TEXTURE_MAX_LOD:
426 /* TO DO */
427 break;
428 case GL_TEXTURE_BASE_LEVEL:
429 RevalidateTexture(ctx, tObj);
430 break;
431 case GL_TEXTURE_MAX_LEVEL:
432 RevalidateTexture(ctx, tObj);
433 break;
434
435 default:
436 break;
437 }
438 }
439
440
441 /*
442 * Called via glDeleteTextures to delete a texture object.
443 * Here, we delete the Glide data associated with the texture.
444 */
445 void
446 tdfxDDDeleteTexture(GLcontext * ctx, struct gl_texture_object *tObj)
447 {
448 if (ctx && ctx->DriverCtx) {
449 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
450 tdfxTMFreeTexture(fxMesa, tObj);
451 fxMesa->new_state |= TDFX_NEW_TEXTURE;
452 }
453 }
454
455
456 /*
457 * Return true if texture is resident, false otherwise.
458 */
459 GLboolean
460 tdfxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
461 {
462 tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
463 return (GLboolean) (ti && ti->isInTM);
464 }
465
466
467
468 /*
469 * Convert a gl_color_table texture palette to Glide's format.
470 */
471 static void
472 convertPalette(FxU32 data[256], const struct gl_color_table *table)
473 {
474 const GLubyte *tableUB = (const GLubyte *) table->Table;
475 GLint width = table->Size;
476 FxU32 r, g, b, a;
477 GLint i;
478
479 ASSERT(table->TableType == GL_UNSIGNED_BYTE);
480
481 switch (table->Format) {
482 case GL_INTENSITY:
483 for (i = 0; i < width; i++) {
484 r = tableUB[i];
485 g = tableUB[i];
486 b = tableUB[i];
487 a = tableUB[i];
488 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
489 }
490 break;
491 case GL_LUMINANCE:
492 for (i = 0; i < width; i++) {
493 r = tableUB[i];
494 g = tableUB[i];
495 b = tableUB[i];
496 a = 255;
497 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
498 }
499 break;
500 case GL_ALPHA:
501 for (i = 0; i < width; i++) {
502 r = g = b = 255;
503 a = tableUB[i];
504 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
505 }
506 break;
507 case GL_LUMINANCE_ALPHA:
508 for (i = 0; i < width; i++) {
509 r = g = b = tableUB[i * 2 + 0];
510 a = tableUB[i * 2 + 1];
511 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
512 }
513 break;
514 case GL_RGB:
515 for (i = 0; i < width; i++) {
516 r = tableUB[i * 3 + 0];
517 g = tableUB[i * 3 + 1];
518 b = tableUB[i * 3 + 2];
519 a = 255;
520 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
521 }
522 break;
523 case GL_RGBA:
524 for (i = 0; i < width; i++) {
525 r = tableUB[i * 4 + 0];
526 g = tableUB[i * 4 + 1];
527 b = tableUB[i * 4 + 2];
528 a = tableUB[i * 4 + 3];
529 data[i] = (a << 24) | (r << 16) | (g << 8) | b;
530 }
531 break;
532 }
533 }
534
535
536
537 void
538 tdfxDDTexturePalette(GLcontext * ctx, struct gl_texture_object *tObj)
539 {
540 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
541
542 if (tObj) {
543 /* per-texture palette */
544 tdfxTexInfo *ti;
545
546 /* This might be a proxy texture. */
547 if (!tObj->Palette.Table)
548 return;
549
550 if (!tObj->DriverData)
551 tObj->DriverData = fxAllocTexObjData(fxMesa);
552 ti = TDFX_TEXTURE_DATA(tObj);
553 convertPalette(ti->palette.data, &tObj->Palette);
554 /*tdfxTexInvalidate(ctx, tObj);*/
555 }
556 else {
557 /* global texture palette */
558 convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
559 }
560 fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX too heavy-handed */
561 }
562
563
564 /**********************************************************************/
565 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
566 /**********************************************************************/
567
568 #if 000
569 static FxBool TexusFatalError = FXFALSE;
570 static FxBool TexusError = FXFALSE;
571
572 #define TX_DITHER_NONE 0x00000000
573
574 static void
575 fxTexusError(const char *string, FxBool fatal)
576 {
577 _mesa_problem(NULL, string);
578 /*
579 * Just propagate the fatal value up.
580 */
581 TexusError = FXTRUE;
582 TexusFatalError = fatal;
583 }
584 #endif
585
586
587 const struct gl_texture_format *
588 tdfxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
589 GLenum srcFormat, GLenum srcType )
590 {
591 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
592 const GLboolean allow32bpt = TDFX_IS_NAPALM(fxMesa);
593
594 switch (internalFormat) {
595 case GL_ALPHA:
596 case GL_ALPHA4:
597 case GL_ALPHA8:
598 case GL_ALPHA12:
599 case GL_ALPHA16:
600 return &_mesa_texformat_a8;
601 case 1:
602 case GL_LUMINANCE:
603 case GL_LUMINANCE4:
604 case GL_LUMINANCE8:
605 case GL_LUMINANCE12:
606 case GL_LUMINANCE16:
607 return &_mesa_texformat_l8;
608 case 2:
609 case GL_LUMINANCE_ALPHA:
610 case GL_LUMINANCE4_ALPHA4:
611 case GL_LUMINANCE6_ALPHA2:
612 case GL_LUMINANCE8_ALPHA8:
613 case GL_LUMINANCE12_ALPHA4:
614 case GL_LUMINANCE12_ALPHA12:
615 case GL_LUMINANCE16_ALPHA16:
616 return &_mesa_texformat_al88;
617 case GL_INTENSITY:
618 case GL_INTENSITY4:
619 case GL_INTENSITY8:
620 case GL_INTENSITY12:
621 case GL_INTENSITY16:
622 return &_mesa_texformat_i8;
623 case GL_R3_G3_B2:
624 case GL_RGB4:
625 case GL_RGB5:
626 return &_mesa_texformat_rgb565;
627 case 3:
628 case GL_RGB:
629 case GL_RGB8:
630 case GL_RGB10:
631 case GL_RGB12:
632 case GL_RGB16:
633 return (allow32bpt) ? &_mesa_texformat_argb8888
634 : &_mesa_texformat_rgb565;
635 break;
636 case GL_RGBA2:
637 case GL_RGBA4:
638 return &_mesa_texformat_argb4444;
639 case 4:
640 case GL_RGBA:
641 case GL_RGBA8:
642 case GL_RGB10_A2:
643 case GL_RGBA12:
644 case GL_RGBA16:
645 return allow32bpt ? &_mesa_texformat_argb8888
646 : &_mesa_texformat_argb4444;
647 case GL_RGB5_A1:
648 return &_mesa_texformat_argb1555;
649 case GL_COLOR_INDEX:
650 case GL_COLOR_INDEX1_EXT:
651 case GL_COLOR_INDEX2_EXT:
652 case GL_COLOR_INDEX4_EXT:
653 case GL_COLOR_INDEX8_EXT:
654 case GL_COLOR_INDEX12_EXT:
655 case GL_COLOR_INDEX16_EXT:
656 return &_mesa_texformat_ci8;
657 default:
658 _mesa_problem(ctx, "unexpected format in tdfxDDChooseTextureFormat");
659 return NULL;
660 }
661 }
662
663
664 /*
665 * Return the Glide format for the given mesa texture format.
666 */
667 static GrTextureFormat_t
668 fxGlideFormat(GLint mesaFormat)
669 {
670 switch (mesaFormat) {
671 case MESA_FORMAT_I8:
672 return GR_TEXFMT_ALPHA_8;
673 case MESA_FORMAT_A8:
674 return GR_TEXFMT_ALPHA_8;
675 case MESA_FORMAT_L8:
676 return GR_TEXFMT_INTENSITY_8;
677 case MESA_FORMAT_CI8:
678 return GR_TEXFMT_P_8;
679 case MESA_FORMAT_AL88:
680 return GR_TEXFMT_ALPHA_INTENSITY_88;
681 case MESA_FORMAT_RGB565:
682 return GR_TEXFMT_RGB_565;
683 case MESA_FORMAT_ARGB4444:
684 return GR_TEXFMT_ARGB_4444;
685 case MESA_FORMAT_ARGB1555:
686 return GR_TEXFMT_ARGB_1555;
687 case MESA_FORMAT_ARGB8888:
688 return GR_TEXFMT_ARGB_8888;
689 default:
690 _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
691 return 0;
692 }
693 }
694
695
696 /* Texel-fetch functions for software texturing and glGetTexImage().
697 * We should have been able to use some "standard" fetch functions (which
698 * may get defined in texutil.c) but we have to account for scaled texture
699 * images on tdfx hardware (the 8:1 aspect ratio limit).
700 * Hence, we need special functions here.
701 */
702
703 static void
704 fetch_intensity8(const struct gl_texture_image *texImage,
705 GLint i, GLint j, GLint k, GLvoid * texelOut)
706 {
707 GLchan *rgba = (GLchan *) texelOut;
708 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
709 const GLubyte *texel;
710
711 i = i * mml->wScale;
712 j = j * mml->hScale;
713
714 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
715 rgba[RCOMP] = *texel;
716 rgba[GCOMP] = *texel;
717 rgba[BCOMP] = *texel;
718 rgba[ACOMP] = *texel;
719 }
720
721
722 static void
723 fetch_luminance8(const struct gl_texture_image *texImage,
724 GLint i, GLint j, GLint k, GLvoid * texelOut)
725 {
726 GLchan *rgba = (GLchan *) texelOut;
727 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
728 const GLubyte *texel;
729
730 i = i * mml->wScale;
731 j = j * mml->hScale;
732
733 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
734 rgba[RCOMP] = *texel;
735 rgba[GCOMP] = *texel;
736 rgba[BCOMP] = *texel;
737 rgba[ACOMP] = 255;
738 }
739
740
741 static void
742 fetch_alpha8(const struct gl_texture_image *texImage,
743 GLint i, GLint j, GLint k, GLvoid * texelOut)
744 {
745 GLchan *rgba = (GLchan *) texelOut;
746 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
747 const GLubyte *texel;
748
749 i = i * mml->wScale;
750 j = j * mml->hScale;
751 i = i * mml->width / texImage->Width;
752 j = j * mml->height / texImage->Height;
753
754 texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
755 rgba[RCOMP] = 255;
756 rgba[GCOMP] = 255;
757 rgba[BCOMP] = 255;
758 rgba[ACOMP] = *texel;
759 }
760
761
762 static void
763 fetch_index8(const struct gl_texture_image *texImage,
764 GLint i, GLint j, GLint k, GLvoid * texelOut)
765 {
766 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
767 (void) mml;
768 /* XXX todo */
769 }
770
771
772 static void
773 fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
774 GLint i, GLint j, GLint k, GLvoid * texelOut)
775 {
776 GLchan *rgba = (GLchan *) texelOut;
777 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
778 const GLubyte *texel;
779
780 i = i * mml->wScale;
781 j = j * mml->hScale;
782
783 texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
784 rgba[RCOMP] = texel[0];
785 rgba[GCOMP] = texel[0];
786 rgba[BCOMP] = texel[0];
787 rgba[ACOMP] = texel[1];
788 }
789
790
791 static void
792 fetch_r5g6b5(const struct gl_texture_image *texImage,
793 GLint i, GLint j, GLint k, GLvoid * texelOut)
794 {
795 GLchan *rgba = (GLchan *) texelOut;
796 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
797 const GLushort *texel;
798
799 i = i * mml->wScale;
800 j = j * mml->hScale;
801
802 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
803 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
804 rgba[GCOMP] = (((*texel) >> 5) & 0x3f) * 255 / 63;
805 rgba[BCOMP] = (((*texel) >> 0) & 0x1f) * 255 / 31;
806 rgba[ACOMP] = 255;
807 }
808
809
810 static void
811 fetch_r4g4b4a4(const struct gl_texture_image *texImage,
812 GLint i, GLint j, GLint k, GLvoid * texelOut)
813 {
814 GLchan *rgba = (GLchan *) texelOut;
815 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
816 const GLushort *texel;
817
818 i = i * mml->wScale;
819 j = j * mml->hScale;
820
821 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
822 rgba[RCOMP] = (((*texel) >> 12) & 0xf) * 255 / 15;
823 rgba[GCOMP] = (((*texel) >> 8) & 0xf) * 255 / 15;
824 rgba[BCOMP] = (((*texel) >> 4) & 0xf) * 255 / 15;
825 rgba[ACOMP] = (((*texel) >> 0) & 0xf) * 255 / 15;
826 }
827
828
829 static void
830 fetch_r5g5b5a1(const struct gl_texture_image *texImage,
831 GLint i, GLint j, GLint k, GLvoid * texelOut)
832 {
833 GLchan *rgba = (GLchan *) texelOut;
834 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
835 const GLushort *texel;
836
837 i = i * mml->wScale;
838 j = j * mml->hScale;
839
840 texel = ((GLushort *) texImage->Data) + j * mml->width + i;
841 rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
842 rgba[GCOMP] = (((*texel) >> 6) & 0x1f) * 255 / 31;
843 rgba[BCOMP] = (((*texel) >> 1) & 0x1f) * 255 / 31;
844 rgba[ACOMP] = (((*texel) >> 0) & 0x01) * 255;
845 }
846
847
848 static void
849 fetch_a8r8g8b8(const struct gl_texture_image *texImage,
850 GLint i, GLint j, GLint k, GLvoid * texelOut)
851 {
852 GLchan *rgba = (GLchan *) texelOut;
853 const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
854 const GLuint *texel;
855
856 i = i * mml->wScale;
857 j = j * mml->hScale;
858
859 texel = ((GLuint *) texImage->Data) + j * mml->width + i;
860 rgba[RCOMP] = (((*texel) >> 16) & 0xff);
861 rgba[GCOMP] = (((*texel) >> 8) & 0xff);
862 rgba[BCOMP] = (((*texel) ) & 0xff);
863 rgba[ACOMP] = (((*texel) >> 24) & 0xff);
864 }
865
866
867 static FetchTexelFunc
868 fxFetchFunction(GLint mesaFormat)
869 {
870 switch (mesaFormat) {
871 case MESA_FORMAT_I8:
872 return fetch_intensity8;
873 case MESA_FORMAT_A8:
874 return fetch_alpha8;
875 case MESA_FORMAT_L8:
876 return fetch_luminance8;
877 case MESA_FORMAT_CI8:
878 return fetch_index8;
879 case MESA_FORMAT_AL88:
880 return fetch_luminance8_alpha8;
881 case MESA_FORMAT_RGB565:
882 return fetch_r5g6b5;
883 case MESA_FORMAT_ARGB4444:
884 return fetch_r4g4b4a4;
885 case MESA_FORMAT_ARGB1555:
886 return fetch_r5g5b5a1;
887 case MESA_FORMAT_ARGB8888:
888 return fetch_a8r8g8b8;
889 default:
890 _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
891 printf("%d\n", mesaFormat);
892 return NULL;
893 }
894 }
895
896
897 void
898 tdfxDDTexImage2D(GLcontext *ctx, GLenum target, GLint level,
899 GLint internalFormat, GLint width, GLint height, GLint border,
900 GLenum format, GLenum type, const GLvoid *pixels,
901 const struct gl_pixelstore_attrib *packing,
902 struct gl_texture_object *texObj,
903 struct gl_texture_image *texImage)
904 {
905 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
906 tdfxTexInfo *ti;
907 tdfxMipMapLevel *mml;
908 GLint texelBytes;
909
910 /*
911 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
912 texObj->Name, texImage->IntFormat, format, type,
913 texImage->Width, texImage->Height);
914 */
915
916 ti = TDFX_TEXTURE_DATA(texObj);
917 if (!ti) {
918 texObj->DriverData = fxAllocTexObjData(fxMesa);
919 if (!texObj->DriverData) {
920 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
921 return;
922 }
923 ti = TDFX_TEXTURE_DATA(texObj);
924 }
925
926 mml = TDFX_TEXIMAGE_DATA(texImage);
927 if (!mml) {
928 texImage->DriverData = CALLOC(sizeof(tdfxMipMapLevel));
929 if (!texImage->DriverData) {
930 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
931 return;
932 }
933 mml = TDFX_TEXIMAGE_DATA(texImage);
934 }
935
936 /* Determine width and height scale factors for texture.
937 * Remember, Glide is limited to 8:1 aspect ratios.
938 */
939 tdfxTexGetInfo(ctx,
940 texImage->Width, texImage->Height,
941 NULL, /* lod level */
942 NULL, /* aspect ratio */
943 NULL, NULL, /* sscale, tscale */
944 &mml->wScale, &mml->hScale);
945
946 /* rescaled size: */
947 mml->width = width * mml->wScale;
948 mml->height = height * mml->hScale;
949
950
951 /* choose the texture format */
952 assert(ctx->Driver.ChooseTextureFormat);
953 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
954 internalFormat, format, type);
955 assert(texImage->TexFormat);
956 mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
957 ti->info.format = mml->glideFormat;
958 texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
959 texelBytes = texImage->TexFormat->TexelBytes;
960
961 if (mml->width != width || mml->height != height) {
962 /* rescale the image to overcome 1:8 aspect limitation */
963 GLvoid *tempImage;
964 tempImage = MALLOC(width * height * texelBytes);
965 if (!tempImage) {
966 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
967 return;
968 }
969 /* unpack image, apply transfer ops and store in tempImage */
970 _mesa_transfer_teximage(ctx, 2, texImage->Format,
971 texImage->TexFormat,
972 tempImage,
973 width, height, 1, 0, 0, 0,
974 width * texelBytes,
975 0, /* dstImageStride */
976 format, type, pixels, packing);
977 assert(!texImage->Data);
978 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
979 if (!texImage->Data) {
980 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
981 FREE(tempImage);
982 return;
983 }
984 _mesa_rescale_teximage2d(texelBytes,
985 mml->width * texelBytes, /* dst stride */
986 width, height,
987 mml->width, mml->height,
988 tempImage /*src*/, texImage->Data /*dst*/ );
989 FREE(tempImage);
990 }
991 else {
992 /* no rescaling needed */
993 assert(!texImage->Data);
994 texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
995 if (!texImage->Data) {
996 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
997 return;
998 }
999 /* unpack image, apply transfer ops and store in texImage->Data */
1000 _mesa_transfer_teximage(ctx, 2, texImage->Format,
1001 texImage->TexFormat, texImage->Data,
1002 width, height, 1, 0, 0, 0,
1003 texImage->Width * texelBytes,
1004 0, /* dstImageStride */
1005 format, type, pixels, packing);
1006 }
1007
1008 RevalidateTexture(ctx, texObj);
1009
1010 ti->reloadImages = GL_TRUE;
1011 fxMesa->new_state |= TDFX_NEW_TEXTURE;
1012 }
1013
1014
1015 void
1016 tdfxDDTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
1017 GLint xoffset, GLint yoffset,
1018 GLsizei width, GLsizei height,
1019 GLenum format, GLenum type,
1020 const GLvoid *pixels,
1021 const struct gl_pixelstore_attrib *packing,
1022 struct gl_texture_object *texObj,
1023 struct gl_texture_image *texImage )
1024 {
1025 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1026 tdfxTexInfo *ti;
1027 tdfxMipMapLevel *mml;
1028 GLint texelBytes;
1029
1030 if (!texObj->DriverData) {
1031 _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
1032 return;
1033 }
1034
1035 ti = TDFX_TEXTURE_DATA(texObj);
1036 assert(ti);
1037 mml = TDFX_TEXIMAGE_DATA(texImage);
1038 assert(mml);
1039
1040 assert(texImage->Data); /* must have an existing texture image! */
1041 assert(texImage->Format);
1042
1043 texelBytes = texImage->TexFormat->TexelBytes;
1044
1045 if (mml->wScale != 1 || mml->hScale != 1) {
1046 /* need to rescale subimage to match mipmap level's rescale factors */
1047 const GLint newWidth = width * mml->wScale;
1048 const GLint newHeight = height * mml->hScale;
1049 GLvoid *scaledImage, *tempImage;
1050 GLubyte *destAddr;
1051 tempImage = MALLOC(width * height * texelBytes);
1052 if (!tempImage) {
1053 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1054 return;
1055 }
1056
1057 _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */
1058 texImage->TexFormat, /* dest format */
1059 (GLubyte *) tempImage, /* dest */
1060 width, height, 1, /* subimage size */
1061 0, 0, 0, /* subimage pos */
1062 width * texelBytes, /* dest row stride */
1063 0, /* dst image stride */
1064 format, type, pixels, packing);
1065
1066 /* now rescale */
1067 scaledImage = MALLOC(newWidth * newHeight * texelBytes);
1068 if (!scaledImage) {
1069 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1070 FREE(tempImage);
1071 return;
1072 }
1073
1074 /* compute address of dest subimage within the overal tex image */
1075 destAddr = (GLubyte *) texImage->Data
1076 + (yoffset * mml->hScale * mml->width
1077 + xoffset * mml->wScale) * texelBytes;
1078
1079 _mesa_rescale_teximage2d(texelBytes,
1080 mml->width * texelBytes, /* dst stride */
1081 width, height,
1082 newWidth, newHeight,
1083 tempImage, destAddr);
1084
1085 FREE(tempImage);
1086 FREE(scaledImage);
1087 }
1088 else {
1089 /* no rescaling needed */
1090 _mesa_transfer_teximage(ctx, 2, texImage->Format, /* Tex int format */
1091 texImage->TexFormat, /* dest format */
1092 (GLubyte *) texImage->Data,/* dest */
1093 width, height, 1, /* subimage size */
1094 xoffset, yoffset, 0, /* subimage pos */
1095 mml->width * texelBytes, /* dest row stride */
1096 0, /* dst image stride */
1097 format, type, pixels, packing);
1098 }
1099
1100 ti->reloadImages = GL_TRUE; /* signal the image needs to be reloaded */
1101 fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX this might be a bit much */
1102 }
1103
1104
1105
1106 /**********************************************************************/
1107 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1108 /**********************************************************************/
1109
1110 #if 0000
1111 GLboolean
1112 tdfxDDCompressedTexImage2D( GLcontext *ctx, GLenum target,
1113 GLint level, GLsizei imageSize,
1114 const GLvoid *data,
1115 struct gl_texture_object *texObj,
1116 struct gl_texture_image *texImage,
1117 GLboolean *retainInternalCopy)
1118 {
1119 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1120 const GLboolean allow32bpt = TDFX_IS_NAPALM(fxMesa);
1121 GrTextureFormat_t gldformat;
1122 tdfxTexInfo *ti;
1123 tdfxMipMapLevel *mml;
1124 GLint dstWidth, dstHeight, wScale, hScale, texelSize;
1125 MesaIntTexFormat intFormat;
1126 GLboolean isCompressedFormat;
1127 GLsizei texSize;
1128
1129 if (target != GL_TEXTURE_2D || texImage->Border > 0)
1130 return GL_FALSE;
1131
1132 if (!texObj->DriverData)
1133 texObj->DriverData = fxAllocTexObjData(fxMesa);
1134
1135 ti = TDFX_TEXTURE_DATA(texObj);
1136 mml = &ti->mipmapLevel[level];
1137
1138 isCompressedFormat = tdfxDDIsCompressedGlideFormatMacro(texImage->IntFormat);
1139 if (!isCompressedFormat) {
1140 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(format)");
1141 return GL_FALSE;
1142 }
1143 /* Determine the apporpriate GL internal texel format, Mesa internal
1144 * texel format, and texelSize (bytes) given the user's internal
1145 * texture format hint.
1146 */
1147 tdfxTexGetFormat(texImage->IntFormat, allow32bpt,
1148 &gldformat, &intFormat, &texelSize);
1149
1150 /* Determine width and height scale factors for texture.
1151 * Remember, Glide is limited to 8:1 aspect ratios.
1152 */
1153 tdfxTexGetInfo(ctx,
1154 texImage->Width, texImage->Height,
1155 NULL, /* lod level */
1156 NULL, /* aspect ratio */
1157 NULL, NULL, /* sscale, tscale */
1158 &wScale, &hScale);
1159 dstWidth = texImage->Width * wScale;
1160 dstHeight = texImage->Height * hScale;
1161 /* housekeeping */
1162 _mesa_set_teximage_component_sizes(intFormat, texImage);
1163
1164 texSize = tdfxDDCompressedImageSize(ctx,
1165 texImage->IntFormat,
1166 2,
1167 texImage->Width,
1168 texImage->Height,
1169 1);
1170 if (texSize != imageSize) {
1171 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2D(texSize)");
1172 return GL_FALSE;
1173 }
1174
1175 /* allocate new storage for texture image, if needed */
1176 if (!mml->data || mml->glideFormat != gldformat ||
1177 mml->width != dstWidth || mml->height != dstHeight ||
1178 texSize != mml->dataSize) {
1179 if (mml->data) {
1180 FREE(mml->data);
1181 }
1182 mml->data = MALLOC(texSize);
1183 if (!mml->data) {
1184 return GL_FALSE;
1185 }
1186 mml->texelSize = texelSize;
1187 mml->glideFormat = gldformat;
1188 mml->width = dstWidth;
1189 mml->height = dstHeight;
1190 tdfxTMMoveOutTM(fxMesa, texObj);
1191 /*tdfxTexInvalidate(ctx, texObj);*/
1192 }
1193
1194 /* save the texture data */
1195 MEMCPY(mml->data, data, imageSize);
1196
1197 RevalidateTexture(ctx, texObj);
1198
1199 ti->reloadImages = GL_TRUE;
1200 fxMesa->new_state |= TDFX_NEW_TEXTURE;
1201
1202 *retainInternalCopy = GL_FALSE;
1203 return GL_TRUE;
1204 }
1205
1206 GLboolean
1207 tdfxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
1208 GLint level, GLint xoffset,
1209 GLint yoffset, GLsizei width,
1210 GLint height, GLenum format,
1211 GLsizei imageSize, const GLvoid *data,
1212 struct gl_texture_object *texObj,
1213 struct gl_texture_image *texImage )
1214 {
1215 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1216 tdfxTexInfo *ti;
1217 tdfxMipMapLevel *mml;
1218
1219 /*
1220 * We punt if we are not replacing the entire image. This
1221 * is allowed by the spec.
1222 */
1223 if ((xoffset != 0) && (yoffset != 0)
1224 && (width != texImage->Width)
1225 && (height != texImage->Height)) {
1226 return GL_FALSE;
1227 }
1228
1229 ti = TDFX_TEXTURE_DATA(texObj);
1230 mml = &ti->mipmapLevel[level];
1231 if (imageSize != mml->dataSize) {
1232 return GL_FALSE;
1233 }
1234 MEMCPY(data, mml->data, imageSize);
1235
1236 ti->reloadImages = GL_TRUE;
1237 fxMesa->new_state |= TDFX_NEW_TEXTURE;
1238
1239 return GL_TRUE;
1240 }
1241 #endif
1242
1243
1244
1245 #if 0
1246 static void
1247 PrintTexture(int w, int h, int c, const GLubyte * data)
1248 {
1249 int i, j;
1250 for (i = 0; i < h; i++) {
1251 for (j = 0; j < w; j++) {
1252 if (c == 2)
1253 printf("%02x %02x ", data[0], data[1]);
1254 else if (c == 3)
1255 printf("%02x %02x %02x ", data[0], data[1], data[2]);
1256 data += c;
1257 }
1258 printf("\n");
1259 }
1260 }
1261 #endif
1262
1263
1264 GLboolean
1265 tdfxDDTestProxyTexImage(GLcontext *ctx, GLenum target,
1266 GLint level, GLint internalFormat,
1267 GLenum format, GLenum type,
1268 GLint width, GLint height,
1269 GLint depth, GLint border)
1270 {
1271 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1272 struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
1273 struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
1274
1275 switch (target) {
1276 case GL_PROXY_TEXTURE_1D:
1277 return GL_TRUE; /* software rendering */
1278 case GL_PROXY_TEXTURE_2D:
1279 {
1280 struct gl_texture_object *tObj;
1281 tdfxTexInfo *ti;
1282 int memNeeded;
1283
1284 tObj = ctx->Texture.Proxy2D;
1285 if (!tObj->DriverData)
1286 tObj->DriverData = fxAllocTexObjData(fxMesa);
1287 ti = TDFX_TEXTURE_DATA(tObj);
1288
1289 /* assign the parameters to test against */
1290 tObj->Image[level]->Width = width;
1291 tObj->Image[level]->Height = height;
1292 tObj->Image[level]->Border = border;
1293 #if 0
1294 tObj->Image[level]->IntFormat = internalFormat;
1295 #endif
1296 if (level == 0) {
1297 /* don't use mipmap levels > 0 */
1298 tObj->MinFilter = tObj->MagFilter = GL_NEAREST;
1299 }
1300 else {
1301 /* test with all mipmap levels */
1302 tObj->MinFilter = GL_LINEAR_MIPMAP_LINEAR;
1303 tObj->MagFilter = GL_NEAREST;
1304 }
1305 RevalidateTexture(ctx, tObj);
1306
1307 /*
1308 printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1309 printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1310 printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1311 printf("glide format 0x%x\n", ti->info.format);
1312 printf("data %p\n", ti->info.data);
1313 printf("lodblend %d\n", (int) ti->LODblend);
1314 */
1315
1316 /* determine where texture will reside */
1317 if (ti->LODblend && !shared->umaTexMemory) {
1318 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1319 memNeeded = fxMesa->Glide.grTexTextureMemRequired(
1320 GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1321 }
1322 else {
1323 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1324 memNeeded = fxMesa->Glide.grTexTextureMemRequired(
1325 GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1326 }
1327 /*
1328 printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1329 */
1330 if (memNeeded > shared->totalTexMem[0])
1331 return GL_FALSE;
1332 else
1333 return GL_TRUE;
1334 }
1335 case GL_PROXY_TEXTURE_3D:
1336 return GL_TRUE; /* software rendering */
1337 default:
1338 return GL_TRUE; /* never happens, silence compiler */
1339 }
1340 }
1341
1342
1343 #if 000
1344 /*
1345 * This is called from _mesa_GetCompressedTexImage. We just
1346 * copy out the compressed data.
1347 */
1348 void
1349 tdfxDDGetCompressedTexImage( GLcontext *ctx, GLenum target,
1350 GLint lod, void *image,
1351 const struct gl_texture_object *texObj,
1352 struct gl_texture_image *texImage )
1353 {
1354 tdfxTexInfo *ti;
1355 tdfxMipMapLevel *mml;
1356
1357 if (target != GL_TEXTURE_2D)
1358 return;
1359
1360 if (!texObj->DriverData)
1361 return;
1362
1363 ti = TDFX_TEXTURE_DATA(texObj);
1364 mml = &ti->mipmapLevel[lod];
1365 if (mml->data) {
1366 MEMCPY(image, mml->data, mml->dataSize);
1367 }
1368 }
1369 #endif
1370
1371 /*
1372 * Calculate a specific texture format given a generic
1373 * texture format.
1374 */
1375 GLint
1376 tdfxDDSpecificCompressedTexFormat(GLcontext *ctx,
1377 GLint internalFormat,
1378 GLint numDimensions)
1379 {
1380 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1381
1382 if (numDimensions != 2) {
1383 return internalFormat;
1384 }
1385 /*
1386 * If we don't have pointers to the functions, then
1387 * we drop back to uncompressed format. The logic
1388 * in Mesa proper handles this for us.
1389 *
1390 * This is just to ease the transition to a Glide with
1391 * the texus2 library.
1392 */
1393 if (!fxMesa->Glide.txImgQuantize || !fxMesa->Glide.txImgDequantizeFXT1) {
1394 return internalFormat;
1395 }
1396 switch (internalFormat) {
1397 case GL_COMPRESSED_RGB_ARB:
1398 return GL_COMPRESSED_RGB_FXT1_3DFX;
1399 case GL_COMPRESSED_RGBA_ARB:
1400 return GL_COMPRESSED_RGBA_FXT1_3DFX;
1401 }
1402 return internalFormat;
1403 }
1404
1405 /*
1406 * Calculate a specific texture format given a generic
1407 * texture format.
1408 */
1409 GLint
1410 tdfxDDBaseCompressedTexFormat(GLcontext *ctx,
1411 GLint internalFormat)
1412 {
1413 switch (internalFormat) {
1414 case GL_COMPRESSED_RGB_FXT1_3DFX:
1415 return GL_RGB;
1416 case GL_COMPRESSED_RGBA_FXT1_3DFX:
1417 return GL_RGBA;
1418 }
1419 return -1;
1420 }
1421
1422 /*
1423 * Tell us if an image is compressed. The real work is done
1424 * in a macro, but we need to have a function to create a
1425 * function pointer.
1426 */
1427 GLboolean
1428 tdfxDDIsCompressedFormat(GLcontext *ctx, GLint internalFormat)
1429 {
1430 return tdfxDDIsCompressedFormatMacro(internalFormat);
1431 }
1432
1433
1434 /*
1435 * Calculate the image size of a compressed texture.
1436 *
1437 * The current compressed format, the FXT1 family, all
1438 * map 8x32 texel blocks into 128 bits.
1439 *
1440 * We return 0 if we can't calculate the size.
1441 *
1442 * Glide would report this out to us, but we don't have
1443 * exactly the right parameters.
1444 */
1445 GLsizei
1446 tdfxDDCompressedImageSize(GLcontext *ctx,
1447 GLenum intFormat,
1448 GLuint numDimensions,
1449 GLuint width,
1450 GLuint height,
1451 GLuint depth)
1452 {
1453 if (numDimensions != 2) {
1454 return 0;
1455 }
1456 switch (intFormat) {
1457 case GL_COMPRESSED_RGB_FXT1_3DFX:
1458 case GL_COMPRESSED_RGBA_FXT1_3DFX:
1459 /*
1460 * Round height and width to multiples of 4 and 8,
1461 * divide the resulting product by 32 to get the number
1462 * of blocks, and multiply by 32 = 128/8 to get the.
1463 * number of bytes required. That is to say, just
1464 * return the product. Remember that we are returning
1465 * bytes, not texels, so we have shrunk the texture
1466 * by a factor of the texel size.
1467 */
1468 width = (width + 0x7) &~ 0x7;
1469 height = (height + 0x3) &~ 0x3;
1470 return width * height;
1471 }
1472 return 0;
1473 }