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