1 /* -*- mode: c; c-basic-offset: 3 -*-
3 * Copyright 2000 VA Linux Systems Inc., Fremont, California.
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:
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
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
26 /* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.c,v 1.7 2002/11/05 17:46:10 tsi Exp $ */
30 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
33 * Gareth Hughes <gareth@valinux.com>
34 * Brian Paul <brianp@valinux.com>
40 #include "texformat.h"
44 #include "tdfx_context.h"
46 #include "tdfx_texman.h"
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
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)
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
)
97 int logw
, logh
, ar
, lod
, ws
, hs
;
105 ar
= logw
- logh
; /* aspect ratio = difference in log dimensions */
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 */
110 ASSERT(width
>= height
);
114 if (ar
<= GR_ASPECT_LOG2_8x1
) {
119 /* have to stretch image height */
125 ASSERT(width
< height
);
129 if (ar
>= GR_ASPECT_LOG2_1x8
) {
134 /* have to stretch image width */
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
;
146 *lodlevel
= (GrLOD_t
) lod
;
148 *aspectratio
= (GrAspectRatio_t
) ar
;
161 * We need to call this when a texture object's minification filter
162 * or texture image sizes change.
164 static void RevalidateTexture(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
166 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
172 minl
= maxl
= tObj
->BaseLevel
;
174 if (tObj
->Image
[minl
]) {
175 maxl
= MIN2(tObj
->MaxLevel
, tObj
->Image
[minl
]->MaxLog2
);
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
);
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
);
192 /* not mipmapping: smallLodLog2 = largeLodLog2 */
193 ti
->info
.smallLodLog2
= ti
->info
.largeLodLog2
;
199 ti
->info
.data
= NULL
;
204 fxAllocTexObjData(tdfxContextPtr fxMesa
)
208 if (!(ti
= CALLOC(sizeof(tdfxTexInfo
)))) {
209 _mesa_problem(NULL
, "tdfx driver: out of memory");
213 ti
->isInTM
= GL_FALSE
;
215 ti
->whichTMU
= TDFX_TMU_NONE
;
217 ti
->tm
[TDFX_TMU0
] = NULL
;
218 ti
->tm
[TDFX_TMU1
] = NULL
;
220 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
221 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
223 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
224 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
226 ti
->mmMode
= GR_MIPMAP_NEAREST
;
227 ti
->LODblend
= FXFALSE
;
234 * Called via glBindTexture.
238 tdfxDDBindTexture(GLcontext
* ctx
, GLenum target
,
239 struct gl_texture_object
*tObj
)
241 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
244 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
245 fprintf(stderr
, "fxmesa: fxDDTexBind(%d,%p)\n", tObj
->Name
,
249 if (target
!= GL_TEXTURE_2D
)
252 if (!tObj
->DriverData
) {
253 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
256 ti
= TDFX_TEXTURE_DATA(tObj
);
257 ti
->lastTimeUsed
= fxMesa
->texBindNumber
++;
259 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
264 * Called via glTexEnv.
267 tdfxDDTexEnv(GLcontext
* ctx
, GLenum target
, GLenum pname
,
268 const GLfloat
* param
)
270 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
272 if ( TDFX_DEBUG
& DEBUG_VERBOSE_API
) {
274 fprintf(stderr
, "fxmesa: texenv(%x,%x)\n", pname
,
277 fprintf(stderr
, "fxmesa: texenv(%x)\n", pname
);
280 /* XXX this is a bit of a hack to force the Glide texture
281 * state to be updated.
283 fxMesa
->TexState
.EnvMode
[ctx
->Texture
.CurrentUnit
] = 0;
285 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
290 * Called via glTexParameter.
293 tdfxDDTexParameter(GLcontext
* ctx
, GLenum target
,
294 struct gl_texture_object
*tObj
,
295 GLenum pname
, const GLfloat
* params
)
297 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
298 GLenum param
= (GLenum
) (GLint
) params
[0];
301 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
302 fprintf(stderr
, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj
->Name
,
303 tObj
->DriverData
, pname
, param
);
306 if (target
!= GL_TEXTURE_2D
)
309 if (!tObj
->DriverData
)
310 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
312 ti
= TDFX_TEXTURE_DATA(tObj
);
315 case GL_TEXTURE_MIN_FILTER
:
318 ti
->mmMode
= GR_MIPMAP_DISABLE
;
319 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
320 ti
->LODblend
= FXFALSE
;
323 ti
->mmMode
= GR_MIPMAP_DISABLE
;
324 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
325 ti
->LODblend
= FXFALSE
;
327 case GL_NEAREST_MIPMAP_LINEAR
:
328 if (TDFX_IS_NAPALM(fxMesa
)) {
329 if (fxMesa
->haveTwoTMUs
) {
330 ti
->mmMode
= GR_MIPMAP_NEAREST
;
331 ti
->LODblend
= FXTRUE
;
334 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
335 ti
->LODblend
= FXFALSE
;
337 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
340 /* XXX Voodoo3/Banshee mipmap blending seems to produce
341 * incorrectly filtered colors for the smallest mipmap levels.
342 * To work-around we fall-through here and use a different filter.
344 case GL_NEAREST_MIPMAP_NEAREST
:
345 ti
->mmMode
= GR_MIPMAP_NEAREST
;
346 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
347 ti
->LODblend
= FXFALSE
;
349 case GL_LINEAR_MIPMAP_LINEAR
:
350 if (TDFX_IS_NAPALM(fxMesa
)) {
351 if (fxMesa
->haveTwoTMUs
) {
352 ti
->mmMode
= GR_MIPMAP_NEAREST
;
353 ti
->LODblend
= FXTRUE
;
356 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
357 ti
->LODblend
= FXFALSE
;
359 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
362 /* XXX Voodoo3/Banshee mipmap blending seems to produce
363 * incorrectly filtered colors for the smallest mipmap levels.
364 * To work-around we fall-through here and use a different filter.
366 case GL_LINEAR_MIPMAP_NEAREST
:
367 ti
->mmMode
= GR_MIPMAP_NEAREST
;
368 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
369 ti
->LODblend
= FXFALSE
;
374 RevalidateTexture(ctx
, tObj
);
375 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
378 case GL_TEXTURE_MAG_FILTER
:
381 ti
->magFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
384 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
389 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
392 case GL_TEXTURE_WRAP_S
:
395 ti
->sClamp
= GR_TEXTURECLAMP_CLAMP
;
398 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
403 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
406 case GL_TEXTURE_WRAP_T
:
409 ti
->tClamp
= GR_TEXTURECLAMP_CLAMP
;
412 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
417 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
420 case GL_TEXTURE_BORDER_COLOR
:
423 case GL_TEXTURE_MIN_LOD
:
426 case GL_TEXTURE_MAX_LOD
:
429 case GL_TEXTURE_BASE_LEVEL
:
430 RevalidateTexture(ctx
, tObj
);
432 case GL_TEXTURE_MAX_LEVEL
:
433 RevalidateTexture(ctx
, tObj
);
443 * Called via glDeleteTextures to delete a texture object.
444 * Here, we delete the Glide data associated with the texture.
447 tdfxDDDeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
449 if (ctx
&& ctx
->DriverCtx
) {
450 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
451 tdfxTMFreeTexture(fxMesa
, tObj
);
452 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
453 /* Free mipmap images and the texture object itself */
454 _mesa_delete_texture_object(ctx
, tObj
);
460 * Return true if texture is resident, false otherwise.
463 tdfxDDIsTextureResident(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
465 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
466 return (GLboolean
) (ti
&& ti
->isInTM
);
472 * Convert a gl_color_table texture palette to Glide's format.
475 convertPalette(FxU32 data
[256], const struct gl_color_table
*table
)
477 const GLubyte
*tableUB
= (const GLubyte
*) table
->Table
;
478 GLint width
= table
->Size
;
482 ASSERT(table
->TableType
== GL_UNSIGNED_BYTE
);
484 switch (table
->Format
) {
486 for (i
= 0; i
< width
; i
++) {
491 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
495 for (i
= 0; i
< width
; i
++) {
500 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
504 for (i
= 0; i
< width
; i
++) {
507 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
510 case GL_LUMINANCE_ALPHA
:
511 for (i
= 0; i
< width
; i
++) {
512 r
= g
= b
= tableUB
[i
* 2 + 0];
513 a
= tableUB
[i
* 2 + 1];
514 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
518 for (i
= 0; i
< width
; i
++) {
519 r
= tableUB
[i
* 3 + 0];
520 g
= tableUB
[i
* 3 + 1];
521 b
= tableUB
[i
* 3 + 2];
523 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
527 for (i
= 0; i
< width
; i
++) {
528 r
= tableUB
[i
* 4 + 0];
529 g
= tableUB
[i
* 4 + 1];
530 b
= tableUB
[i
* 4 + 2];
531 a
= tableUB
[i
* 4 + 3];
532 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
541 tdfxDDTexturePalette(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
543 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
546 /* per-texture palette */
549 /* This might be a proxy texture. */
550 if (!tObj
->Palette
.Table
)
553 if (!tObj
->DriverData
)
554 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
555 ti
= TDFX_TEXTURE_DATA(tObj
);
556 convertPalette(ti
->palette
.data
, &tObj
->Palette
);
557 /*tdfxTexInvalidate(ctx, tObj);*/
560 /* global texture palette */
561 convertPalette(fxMesa
->glbPalette
.data
, &ctx
->Texture
.Palette
);
563 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX too heavy-handed */
567 /**********************************************************************/
568 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
569 /**********************************************************************/
572 static FxBool TexusFatalError
= FXFALSE
;
573 static FxBool TexusError
= FXFALSE
;
575 #define TX_DITHER_NONE 0x00000000
578 fxTexusError(const char *string
, FxBool fatal
)
580 _mesa_problem(NULL
, string
);
582 * Just propagate the fatal value up.
585 TexusFatalError
= fatal
;
590 const struct gl_texture_format
*
591 tdfxDDChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
592 GLenum srcFormat
, GLenum srcType
)
594 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
595 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
597 switch (internalFormat
) {
603 return &_mesa_texformat_a8
;
610 return &_mesa_texformat_l8
;
612 case GL_LUMINANCE_ALPHA
:
613 case GL_LUMINANCE4_ALPHA4
:
614 case GL_LUMINANCE6_ALPHA2
:
615 case GL_LUMINANCE8_ALPHA8
:
616 case GL_LUMINANCE12_ALPHA4
:
617 case GL_LUMINANCE12_ALPHA12
:
618 case GL_LUMINANCE16_ALPHA16
:
619 return &_mesa_texformat_al88
;
625 return &_mesa_texformat_i8
;
629 return &_mesa_texformat_rgb565
;
636 return (allow32bpt
) ? &_mesa_texformat_argb8888
637 : &_mesa_texformat_rgb565
;
641 return &_mesa_texformat_argb4444
;
648 return allow32bpt
? &_mesa_texformat_argb8888
649 : &_mesa_texformat_argb4444
;
651 return &_mesa_texformat_argb1555
;
653 case GL_COLOR_INDEX1_EXT
:
654 case GL_COLOR_INDEX2_EXT
:
655 case GL_COLOR_INDEX4_EXT
:
656 case GL_COLOR_INDEX8_EXT
:
657 case GL_COLOR_INDEX12_EXT
:
658 case GL_COLOR_INDEX16_EXT
:
659 return &_mesa_texformat_ci8
;
661 _mesa_problem(ctx
, "unexpected format in tdfxDDChooseTextureFormat");
668 * Return the Glide format for the given mesa texture format.
670 static GrTextureFormat_t
671 fxGlideFormat(GLint mesaFormat
)
673 switch (mesaFormat
) {
675 return GR_TEXFMT_ALPHA_8
;
677 return GR_TEXFMT_ALPHA_8
;
679 return GR_TEXFMT_INTENSITY_8
;
680 case MESA_FORMAT_CI8
:
681 return GR_TEXFMT_P_8
;
682 case MESA_FORMAT_AL88
:
683 return GR_TEXFMT_ALPHA_INTENSITY_88
;
684 case MESA_FORMAT_RGB565
:
685 return GR_TEXFMT_RGB_565
;
686 case MESA_FORMAT_ARGB4444
:
687 return GR_TEXFMT_ARGB_4444
;
688 case MESA_FORMAT_ARGB1555
:
689 return GR_TEXFMT_ARGB_1555
;
690 case MESA_FORMAT_ARGB8888
:
691 return GR_TEXFMT_ARGB_8888
;
693 _mesa_problem(NULL
, "Unexpected format in fxGlideFormat");
699 /* Texel-fetch functions for software texturing and glGetTexImage().
700 * We should have been able to use some "standard" fetch functions (which
701 * may get defined in texutil.c) but we have to account for scaled texture
702 * images on tdfx hardware (the 8:1 aspect ratio limit).
703 * Hence, we need special functions here.
707 fetch_intensity8(const struct gl_texture_image
*texImage
,
708 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
710 GLchan
*rgba
= (GLchan
*) texelOut
;
711 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
712 const GLubyte
*texel
;
717 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
718 rgba
[RCOMP
] = *texel
;
719 rgba
[GCOMP
] = *texel
;
720 rgba
[BCOMP
] = *texel
;
721 rgba
[ACOMP
] = *texel
;
726 fetch_luminance8(const struct gl_texture_image
*texImage
,
727 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
729 GLchan
*rgba
= (GLchan
*) texelOut
;
730 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
731 const GLubyte
*texel
;
736 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
737 rgba
[RCOMP
] = *texel
;
738 rgba
[GCOMP
] = *texel
;
739 rgba
[BCOMP
] = *texel
;
745 fetch_alpha8(const struct gl_texture_image
*texImage
,
746 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
748 GLchan
*rgba
= (GLchan
*) texelOut
;
749 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
750 const GLubyte
*texel
;
754 i
= i
* mml
->width
/ texImage
->Width
;
755 j
= j
* mml
->height
/ texImage
->Height
;
757 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
761 rgba
[ACOMP
] = *texel
;
766 fetch_index8(const struct gl_texture_image
*texImage
,
767 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
769 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
776 fetch_luminance8_alpha8(const struct gl_texture_image
*texImage
,
777 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
779 GLchan
*rgba
= (GLchan
*) texelOut
;
780 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
781 const GLubyte
*texel
;
786 texel
= ((GLubyte
*) texImage
->Data
) + (j
* mml
->width
+ i
) * 2;
787 rgba
[RCOMP
] = texel
[0];
788 rgba
[GCOMP
] = texel
[0];
789 rgba
[BCOMP
] = texel
[0];
790 rgba
[ACOMP
] = texel
[1];
795 fetch_r5g6b5(const struct gl_texture_image
*texImage
,
796 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
798 GLchan
*rgba
= (GLchan
*) texelOut
;
799 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
800 const GLushort
*texel
;
805 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
806 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
807 rgba
[GCOMP
] = (((*texel
) >> 5) & 0x3f) * 255 / 63;
808 rgba
[BCOMP
] = (((*texel
) >> 0) & 0x1f) * 255 / 31;
814 fetch_r4g4b4a4(const struct gl_texture_image
*texImage
,
815 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
817 GLchan
*rgba
= (GLchan
*) texelOut
;
818 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
819 const GLushort
*texel
;
824 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
825 rgba
[RCOMP
] = (((*texel
) >> 12) & 0xf) * 255 / 15;
826 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xf) * 255 / 15;
827 rgba
[BCOMP
] = (((*texel
) >> 4) & 0xf) * 255 / 15;
828 rgba
[ACOMP
] = (((*texel
) >> 0) & 0xf) * 255 / 15;
833 fetch_r5g5b5a1(const struct gl_texture_image
*texImage
,
834 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
836 GLchan
*rgba
= (GLchan
*) texelOut
;
837 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
838 const GLushort
*texel
;
843 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
844 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
845 rgba
[GCOMP
] = (((*texel
) >> 6) & 0x1f) * 255 / 31;
846 rgba
[BCOMP
] = (((*texel
) >> 1) & 0x1f) * 255 / 31;
847 rgba
[ACOMP
] = (((*texel
) >> 0) & 0x01) * 255;
852 fetch_a8r8g8b8(const struct gl_texture_image
*texImage
,
853 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
855 GLchan
*rgba
= (GLchan
*) texelOut
;
856 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
862 texel
= ((GLuint
*) texImage
->Data
) + j
* mml
->width
+ i
;
863 rgba
[RCOMP
] = (((*texel
) >> 16) & 0xff);
864 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xff);
865 rgba
[BCOMP
] = (((*texel
) ) & 0xff);
866 rgba
[ACOMP
] = (((*texel
) >> 24) & 0xff);
870 static FetchTexelFunc
871 fxFetchFunction(GLint mesaFormat
)
873 switch (mesaFormat
) {
875 return fetch_intensity8
;
879 return fetch_luminance8
;
880 case MESA_FORMAT_CI8
:
882 case MESA_FORMAT_AL88
:
883 return fetch_luminance8_alpha8
;
884 case MESA_FORMAT_RGB565
:
886 case MESA_FORMAT_ARGB4444
:
887 return fetch_r4g4b4a4
;
888 case MESA_FORMAT_ARGB1555
:
889 return fetch_r5g5b5a1
;
890 case MESA_FORMAT_ARGB8888
:
891 return fetch_a8r8g8b8
;
893 _mesa_problem(NULL
, "Unexpected format in fxFetchFunction");
894 printf("%d\n", mesaFormat
);
901 tdfxDDTexImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
902 GLint internalFormat
, GLint width
, GLint height
, GLint border
,
903 GLenum format
, GLenum type
, const GLvoid
*pixels
,
904 const struct gl_pixelstore_attrib
*packing
,
905 struct gl_texture_object
*texObj
,
906 struct gl_texture_image
*texImage
)
908 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
910 tdfxMipMapLevel
*mml
;
914 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
915 texObj->Name, texImage->IntFormat, format, type,
916 texImage->Width, texImage->Height);
919 ti
= TDFX_TEXTURE_DATA(texObj
);
921 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
922 if (!texObj
->DriverData
) {
923 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
926 ti
= TDFX_TEXTURE_DATA(texObj
);
929 mml
= TDFX_TEXIMAGE_DATA(texImage
);
931 texImage
->DriverData
= CALLOC(sizeof(tdfxMipMapLevel
));
932 if (!texImage
->DriverData
) {
933 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
936 mml
= TDFX_TEXIMAGE_DATA(texImage
);
939 /* Determine width and height scale factors for texture.
940 * Remember, Glide is limited to 8:1 aspect ratios.
943 texImage
->Width
, texImage
->Height
,
944 NULL
, /* lod level */
945 NULL
, /* aspect ratio */
946 NULL
, NULL
, /* sscale, tscale */
947 &mml
->wScale
, &mml
->hScale
);
950 mml
->width
= width
* mml
->wScale
;
951 mml
->height
= height
* mml
->hScale
;
954 /* choose the texture format */
955 assert(ctx
->Driver
.ChooseTextureFormat
);
956 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
957 internalFormat
, format
, type
);
958 assert(texImage
->TexFormat
);
959 mml
->glideFormat
= fxGlideFormat(texImage
->TexFormat
->MesaFormat
);
960 ti
->info
.format
= mml
->glideFormat
;
961 texImage
->FetchTexel
= fxFetchFunction(texImage
->TexFormat
->MesaFormat
);
962 texelBytes
= texImage
->TexFormat
->TexelBytes
;
964 if (mml
->width
!= width
|| mml
->height
!= height
) {
965 /* rescale the image to overcome 1:8 aspect limitation */
967 tempImage
= MALLOC(width
* height
* texelBytes
);
969 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
972 /* unpack image, apply transfer ops and store in tempImage */
973 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
976 width
, height
, 1, 0, 0, 0,
978 0, /* dstImageStride */
979 format
, type
, pixels
, packing
);
980 assert(!texImage
->Data
);
981 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
982 if (!texImage
->Data
) {
983 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
987 _mesa_rescale_teximage2d(texelBytes
,
988 mml
->width
* texelBytes
, /* dst stride */
990 mml
->width
, mml
->height
,
991 tempImage
/*src*/, texImage
->Data
/*dst*/ );
995 /* no rescaling needed */
996 assert(!texImage
->Data
);
997 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
998 if (!texImage
->Data
) {
999 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1002 /* unpack image, apply transfer ops and store in texImage->Data */
1003 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
1004 texImage
->TexFormat
, texImage
->Data
,
1005 width
, height
, 1, 0, 0, 0,
1006 texImage
->Width
* texelBytes
,
1007 0, /* dstImageStride */
1008 format
, type
, pixels
, packing
);
1011 RevalidateTexture(ctx
, texObj
);
1013 ti
->reloadImages
= GL_TRUE
;
1014 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1019 tdfxDDTexSubImage2D(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
)
1028 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1030 tdfxMipMapLevel
*mml
;
1033 if (!texObj
->DriverData
) {
1034 _mesa_problem(ctx
, "problem in fxDDTexSubImage2D");
1038 ti
= TDFX_TEXTURE_DATA(texObj
);
1040 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1043 assert(texImage
->Data
); /* must have an existing texture image! */
1044 assert(texImage
->Format
);
1046 texelBytes
= texImage
->TexFormat
->TexelBytes
;
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
;
1054 tempImage
= MALLOC(width
* height
* texelBytes
);
1056 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1060 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,/* Tex int format */
1061 texImage
->TexFormat
, /* dest format */
1062 (GLubyte
*) tempImage
, /* dest */
1063 width
, height
, 1, /* subimage size */
1064 0, 0, 0, /* subimage pos */
1065 width
* texelBytes
, /* dest row stride */
1066 0, /* dst image stride */
1067 format
, type
, pixels
, packing
);
1070 scaledImage
= MALLOC(newWidth
* newHeight
* texelBytes
);
1072 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1077 /* compute address of dest subimage within the overal tex image */
1078 destAddr
= (GLubyte
*) texImage
->Data
1079 + (yoffset
* mml
->hScale
* mml
->width
1080 + xoffset
* mml
->wScale
) * texelBytes
;
1082 _mesa_rescale_teximage2d(texelBytes
,
1083 mml
->width
* texelBytes
, /* dst stride */
1085 newWidth
, newHeight
,
1086 tempImage
, destAddr
);
1092 /* no rescaling needed */
1093 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, /* Tex int format */
1094 texImage
->TexFormat
, /* dest format */
1095 (GLubyte
*) texImage
->Data
,/* dest */
1096 width
, height
, 1, /* subimage size */
1097 xoffset
, yoffset
, 0, /* subimage pos */
1098 mml
->width
* texelBytes
, /* dest row stride */
1099 0, /* dst image stride */
1100 format
, type
, pixels
, packing
);
1103 ti
->reloadImages
= GL_TRUE
; /* signal the image needs to be reloaded */
1104 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX this might be a bit much */
1109 /**********************************************************************/
1110 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1111 /**********************************************************************/
1115 tdfxDDCompressedTexImage2D( GLcontext
*ctx
, GLenum target
,
1116 GLint level
, GLsizei imageSize
,
1118 struct gl_texture_object
*texObj
,
1119 struct gl_texture_image
*texImage
,
1120 GLboolean
*retainInternalCopy
)
1122 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1123 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
1124 GrTextureFormat_t gldformat
;
1126 tdfxMipMapLevel
*mml
;
1127 GLint dstWidth
, dstHeight
, wScale
, hScale
, texelSize
;
1128 MesaIntTexFormat intFormat
;
1129 GLboolean isCompressedFormat
;
1132 if (target
!= GL_TEXTURE_2D
|| texImage
->Border
> 0)
1135 if (!texObj
->DriverData
)
1136 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1138 ti
= TDFX_TEXTURE_DATA(texObj
);
1139 mml
= &ti
->mipmapLevel
[level
];
1141 isCompressedFormat
= tdfxDDIsCompressedGlideFormatMacro(texImage
->IntFormat
);
1142 if (!isCompressedFormat
) {
1143 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(format)");
1146 /* Determine the apporpriate GL internal texel format, Mesa internal
1147 * texel format, and texelSize (bytes) given the user's internal
1148 * texture format hint.
1150 tdfxTexGetFormat(texImage
->IntFormat
, allow32bpt
,
1151 &gldformat
, &intFormat
, &texelSize
);
1153 /* Determine width and height scale factors for texture.
1154 * Remember, Glide is limited to 8:1 aspect ratios.
1157 texImage
->Width
, texImage
->Height
,
1158 NULL
, /* lod level */
1159 NULL
, /* aspect ratio */
1160 NULL
, NULL
, /* sscale, tscale */
1162 dstWidth
= texImage
->Width
* wScale
;
1163 dstHeight
= texImage
->Height
* hScale
;
1165 _mesa_set_teximage_component_sizes(intFormat
, texImage
);
1167 texSize
= tdfxDDCompressedImageSize(ctx
,
1168 texImage
->IntFormat
,
1173 if (texSize
!= imageSize
) {
1174 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage2D(texSize)");
1178 /* allocate new storage for texture image, if needed */
1179 if (!mml
->data
|| mml
->glideFormat
!= gldformat
||
1180 mml
->width
!= dstWidth
|| mml
->height
!= dstHeight
||
1181 texSize
!= mml
->dataSize
) {
1185 mml
->data
= MALLOC(texSize
);
1189 mml
->texelSize
= texelSize
;
1190 mml
->glideFormat
= gldformat
;
1191 mml
->width
= dstWidth
;
1192 mml
->height
= dstHeight
;
1193 tdfxTMMoveOutTM(fxMesa
, texObj
);
1194 /*tdfxTexInvalidate(ctx, texObj);*/
1197 /* save the texture data */
1198 MEMCPY(mml
->data
, data
, imageSize
);
1200 RevalidateTexture(ctx
, texObj
);
1202 ti
->reloadImages
= GL_TRUE
;
1203 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1205 *retainInternalCopy
= GL_FALSE
;
1210 tdfxDDCompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
,
1211 GLint level
, GLint xoffset
,
1212 GLint yoffset
, GLsizei width
,
1213 GLint height
, GLenum format
,
1214 GLsizei imageSize
, const GLvoid
*data
,
1215 struct gl_texture_object
*texObj
,
1216 struct gl_texture_image
*texImage
)
1218 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1220 tdfxMipMapLevel
*mml
;
1223 * We punt if we are not replacing the entire image. This
1224 * is allowed by the spec.
1226 if ((xoffset
!= 0) && (yoffset
!= 0)
1227 && (width
!= texImage
->Width
)
1228 && (height
!= texImage
->Height
)) {
1232 ti
= TDFX_TEXTURE_DATA(texObj
);
1233 mml
= &ti
->mipmapLevel
[level
];
1234 if (imageSize
!= mml
->dataSize
) {
1237 MEMCPY(data
, mml
->data
, imageSize
);
1239 ti
->reloadImages
= GL_TRUE
;
1240 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1250 PrintTexture(int w
, int h
, int c
, const GLubyte
* data
)
1253 for (i
= 0; i
< h
; i
++) {
1254 for (j
= 0; j
< w
; j
++) {
1256 printf("%02x %02x ", data
[0], data
[1]);
1258 printf("%02x %02x %02x ", data
[0], data
[1], data
[2]);
1268 tdfxDDTestProxyTexImage(GLcontext
*ctx
, GLenum target
,
1269 GLint level
, GLint internalFormat
,
1270 GLenum format
, GLenum type
,
1271 GLint width
, GLint height
,
1272 GLint depth
, GLint border
)
1274 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1275 struct gl_shared_state
*mesaShared
= fxMesa
->glCtx
->Shared
;
1276 struct tdfxSharedState
*shared
= (struct tdfxSharedState
*) mesaShared
->DriverData
;
1279 case GL_PROXY_TEXTURE_1D
:
1280 return GL_TRUE
; /* software rendering */
1281 case GL_PROXY_TEXTURE_2D
:
1283 struct gl_texture_object
*tObj
;
1287 tObj
= ctx
->Texture
.Proxy2D
;
1288 if (!tObj
->DriverData
)
1289 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1290 ti
= TDFX_TEXTURE_DATA(tObj
);
1292 /* assign the parameters to test against */
1293 tObj
->Image
[level
]->Width
= width
;
1294 tObj
->Image
[level
]->Height
= height
;
1295 tObj
->Image
[level
]->Border
= border
;
1297 tObj
->Image
[level
]->IntFormat
= internalFormat
;
1300 /* don't use mipmap levels > 0 */
1301 tObj
->MinFilter
= tObj
->MagFilter
= GL_NEAREST
;
1304 /* test with all mipmap levels */
1305 tObj
->MinFilter
= GL_LINEAR_MIPMAP_LINEAR
;
1306 tObj
->MagFilter
= GL_NEAREST
;
1308 RevalidateTexture(ctx
, tObj
);
1311 printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1312 printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1313 printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1314 printf("glide format 0x%x\n", ti->info.format);
1315 printf("data %p\n", ti->info.data);
1316 printf("lodblend %d\n", (int) ti->LODblend);
1319 /* determine where texture will reside */
1320 if (ti
->LODblend
&& !shared
->umaTexMemory
) {
1321 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1322 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1323 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1326 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1327 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1328 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1331 printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1333 if (memNeeded
> shared
->totalTexMem
[0])
1338 case GL_PROXY_TEXTURE_3D
:
1339 return GL_TRUE
; /* software rendering */
1341 return GL_TRUE
; /* never happens, silence compiler */
1348 * This is called from _mesa_GetCompressedTexImage. We just
1349 * copy out the compressed data.
1352 tdfxDDGetCompressedTexImage( GLcontext
*ctx
, GLenum target
,
1353 GLint lod
, void *image
,
1354 const struct gl_texture_object
*texObj
,
1355 struct gl_texture_image
*texImage
)
1358 tdfxMipMapLevel
*mml
;
1360 if (target
!= GL_TEXTURE_2D
)
1363 if (!texObj
->DriverData
)
1366 ti
= TDFX_TEXTURE_DATA(texObj
);
1367 mml
= &ti
->mipmapLevel
[lod
];
1369 MEMCPY(image
, mml
->data
, mml
->dataSize
);
1375 * Calculate a specific texture format given a generic
1379 tdfxDDSpecificCompressedTexFormat(GLcontext
*ctx
,
1380 GLint internalFormat
,
1381 GLint numDimensions
)
1383 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1385 if (numDimensions
!= 2) {
1386 return internalFormat
;
1389 * If we don't have pointers to the functions, then
1390 * we drop back to uncompressed format. The logic
1391 * in Mesa proper handles this for us.
1393 * This is just to ease the transition to a Glide with
1394 * the texus2 library.
1396 if (!fxMesa
->Glide
.txImgQuantize
|| !fxMesa
->Glide
.txImgDequantizeFXT1
) {
1397 return internalFormat
;
1399 switch (internalFormat
) {
1400 case GL_COMPRESSED_RGB_ARB
:
1401 return GL_COMPRESSED_RGB_FXT1_3DFX
;
1402 case GL_COMPRESSED_RGBA_ARB
:
1403 return GL_COMPRESSED_RGBA_FXT1_3DFX
;
1405 return internalFormat
;
1409 * Calculate a specific texture format given a generic
1413 tdfxDDBaseCompressedTexFormat(GLcontext
*ctx
,
1414 GLint internalFormat
)
1416 switch (internalFormat
) {
1417 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1419 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1426 * Tell us if an image is compressed. The real work is done
1427 * in a macro, but we need to have a function to create a
1431 tdfxDDIsCompressedFormat(GLcontext
*ctx
, GLint internalFormat
)
1433 return tdfxDDIsCompressedFormatMacro(internalFormat
);
1438 * Calculate the image size of a compressed texture.
1440 * The current compressed format, the FXT1 family, all
1441 * map 8x32 texel blocks into 128 bits.
1443 * We return 0 if we can't calculate the size.
1445 * Glide would report this out to us, but we don't have
1446 * exactly the right parameters.
1449 tdfxDDCompressedImageSize(GLcontext
*ctx
,
1451 GLuint numDimensions
,
1456 if (numDimensions
!= 2) {
1459 switch (intFormat
) {
1460 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1461 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1463 * Round height and width to multiples of 4 and 8,
1464 * divide the resulting product by 32 to get the number
1465 * of blocks, and multiply by 32 = 128/8 to get the.
1466 * number of bytes required. That is to say, just
1467 * return the product. Remember that we are returning
1468 * bytes, not texels, so we have shrunk the texture
1469 * by a factor of the texel size.
1471 width
= (width
+ 0x7) &~ 0x7;
1472 height
= (height
+ 0x3) &~ 0x3;
1473 return width
* height
;