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