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
[0][minl
]) {
175 maxl
= MIN2(tObj
->MaxLevel
, tObj
->Image
[0][minl
]->MaxLog2
);
177 /* compute largeLodLog2, aspect ratio and texcoord scale factors */
178 tdfxTexGetInfo(ctx
, tObj
->Image
[0][minl
]->Width
, tObj
->Image
[0][minl
]->Height
,
179 &ti
->info
.largeLodLog2
,
180 &ti
->info
.aspectRatioLog2
,
181 &(ti
->sScale
), &(ti
->tScale
), NULL
, NULL
);
184 if (tObj
->Image
[0][maxl
] && (tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
185 /* mipmapping: need to compute smallLodLog2 */
186 tdfxTexGetInfo(ctx
, tObj
->Image
[0][maxl
]->Width
,
187 tObj
->Image
[0][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.
237 tdfxBindTexture(GLcontext
* ctx
, GLenum target
,
238 struct gl_texture_object
*tObj
)
240 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
243 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
244 fprintf(stderr
, "fxmesa: fxDDTexBind(%d,%p)\n", tObj
->Name
,
248 if (target
!= GL_TEXTURE_2D
)
251 if (!tObj
->DriverData
) {
252 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
255 ti
= TDFX_TEXTURE_DATA(tObj
);
256 ti
->lastTimeUsed
= fxMesa
->texBindNumber
++;
258 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
263 * Called via glTexEnv.
266 tdfxTexEnv(GLcontext
* ctx
, GLenum target
, GLenum pname
,
267 const GLfloat
* param
)
269 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
271 if ( TDFX_DEBUG
& DEBUG_VERBOSE_API
) {
273 fprintf(stderr
, "fxmesa: texenv(%x,%x)\n", pname
,
276 fprintf(stderr
, "fxmesa: texenv(%x)\n", pname
);
279 /* XXX this is a bit of a hack to force the Glide texture
280 * state to be updated.
282 fxMesa
->TexState
.EnvMode
[ctx
->Texture
.CurrentUnit
] = 0;
284 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
289 * Called via glTexParameter.
292 tdfxTexParameter(GLcontext
* ctx
, GLenum target
,
293 struct gl_texture_object
*tObj
,
294 GLenum pname
, const GLfloat
* params
)
296 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
297 GLenum param
= (GLenum
) (GLint
) params
[0];
300 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
301 fprintf(stderr
, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj
->Name
,
302 tObj
->DriverData
, pname
, param
);
305 if (target
!= GL_TEXTURE_2D
)
308 if (!tObj
->DriverData
)
309 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
311 ti
= TDFX_TEXTURE_DATA(tObj
);
314 case GL_TEXTURE_MIN_FILTER
:
317 ti
->mmMode
= GR_MIPMAP_DISABLE
;
318 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
319 ti
->LODblend
= FXFALSE
;
322 ti
->mmMode
= GR_MIPMAP_DISABLE
;
323 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
324 ti
->LODblend
= FXFALSE
;
326 case GL_NEAREST_MIPMAP_LINEAR
:
327 if (TDFX_IS_NAPALM(fxMesa
)) {
328 if (fxMesa
->haveTwoTMUs
) {
329 ti
->mmMode
= GR_MIPMAP_NEAREST
;
330 ti
->LODblend
= FXTRUE
;
333 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
334 ti
->LODblend
= FXFALSE
;
336 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
339 /* XXX Voodoo3/Banshee mipmap blending seems to produce
340 * incorrectly filtered colors for the smallest mipmap levels.
341 * To work-around we fall-through here and use a different filter.
343 case GL_NEAREST_MIPMAP_NEAREST
:
344 ti
->mmMode
= GR_MIPMAP_NEAREST
;
345 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
346 ti
->LODblend
= FXFALSE
;
348 case GL_LINEAR_MIPMAP_LINEAR
:
349 if (TDFX_IS_NAPALM(fxMesa
)) {
350 if (fxMesa
->haveTwoTMUs
) {
351 ti
->mmMode
= GR_MIPMAP_NEAREST
;
352 ti
->LODblend
= FXTRUE
;
355 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
356 ti
->LODblend
= FXFALSE
;
358 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
361 /* XXX Voodoo3/Banshee mipmap blending seems to produce
362 * incorrectly filtered colors for the smallest mipmap levels.
363 * To work-around we fall-through here and use a different filter.
365 case GL_LINEAR_MIPMAP_NEAREST
:
366 ti
->mmMode
= GR_MIPMAP_NEAREST
;
367 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
368 ti
->LODblend
= FXFALSE
;
373 RevalidateTexture(ctx
, tObj
);
374 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
377 case GL_TEXTURE_MAG_FILTER
:
380 ti
->magFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
383 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
388 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
391 case GL_TEXTURE_WRAP_S
:
394 ti
->sClamp
= GR_TEXTURECLAMP_CLAMP
;
397 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
402 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
405 case GL_TEXTURE_WRAP_T
:
408 ti
->tClamp
= GR_TEXTURECLAMP_CLAMP
;
411 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
416 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
419 case GL_TEXTURE_BORDER_COLOR
:
422 case GL_TEXTURE_MIN_LOD
:
425 case GL_TEXTURE_MAX_LOD
:
428 case GL_TEXTURE_BASE_LEVEL
:
429 RevalidateTexture(ctx
, tObj
);
431 case GL_TEXTURE_MAX_LEVEL
:
432 RevalidateTexture(ctx
, tObj
);
442 * Called via glDeleteTextures to delete a texture object.
443 * Here, we delete the Glide data associated with the texture.
446 tdfxDeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
448 if (ctx
&& ctx
->DriverCtx
) {
449 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
450 tdfxTMFreeTexture(fxMesa
, tObj
);
451 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
452 /* Free mipmap images and the texture object itself */
453 _mesa_delete_texture_object(ctx
, tObj
);
459 * Return true if texture is resident, false otherwise.
462 tdfxIsTextureResident(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
464 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
465 return (GLboolean
) (ti
&& ti
->isInTM
);
471 * Convert a gl_color_table texture palette to Glide's format.
474 convertPalette(FxU32 data
[256], const struct gl_color_table
*table
)
476 const GLubyte
*tableUB
= (const GLubyte
*) table
->Table
;
477 GLint width
= table
->Size
;
481 ASSERT(table
->TableType
== GL_UNSIGNED_BYTE
);
483 switch (table
->Format
) {
485 for (i
= 0; i
< width
; i
++) {
490 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
494 for (i
= 0; i
< width
; i
++) {
499 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
503 for (i
= 0; i
< width
; i
++) {
506 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
509 case GL_LUMINANCE_ALPHA
:
510 for (i
= 0; i
< width
; i
++) {
511 r
= g
= b
= tableUB
[i
* 2 + 0];
512 a
= tableUB
[i
* 2 + 1];
513 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
517 for (i
= 0; i
< width
; i
++) {
518 r
= tableUB
[i
* 3 + 0];
519 g
= tableUB
[i
* 3 + 1];
520 b
= tableUB
[i
* 3 + 2];
522 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
526 for (i
= 0; i
< width
; i
++) {
527 r
= tableUB
[i
* 4 + 0];
528 g
= tableUB
[i
* 4 + 1];
529 b
= tableUB
[i
* 4 + 2];
530 a
= tableUB
[i
* 4 + 3];
531 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
540 tdfxUpdateTexturePalette(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
542 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
545 /* per-texture palette */
548 /* This might be a proxy texture. */
549 if (!tObj
->Palette
.Table
)
552 if (!tObj
->DriverData
)
553 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
554 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 static const struct gl_texture_format
*
591 tdfxChooseTextureFormat( 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 tdfxChooseTextureFormat");
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
, GLchan
* rgba
)
710 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
711 const GLubyte
*texel
;
716 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
717 rgba
[RCOMP
] = *texel
;
718 rgba
[GCOMP
] = *texel
;
719 rgba
[BCOMP
] = *texel
;
720 rgba
[ACOMP
] = *texel
;
725 fetch_luminance8(const struct gl_texture_image
*texImage
,
726 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
728 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
729 const GLubyte
*texel
;
734 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
735 rgba
[RCOMP
] = *texel
;
736 rgba
[GCOMP
] = *texel
;
737 rgba
[BCOMP
] = *texel
;
743 fetch_alpha8(const struct gl_texture_image
*texImage
,
744 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
746 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
747 const GLubyte
*texel
;
751 i
= i
* mml
->width
/ texImage
->Width
;
752 j
= j
* mml
->height
/ texImage
->Height
;
754 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
758 rgba
[ACOMP
] = *texel
;
763 fetch_index8(const struct gl_texture_image
*texImage
,
764 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
766 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
773 fetch_luminance8_alpha8(const struct gl_texture_image
*texImage
,
774 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
776 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
777 const GLubyte
*texel
;
782 texel
= ((GLubyte
*) texImage
->Data
) + (j
* mml
->width
+ i
) * 2;
783 rgba
[RCOMP
] = texel
[0];
784 rgba
[GCOMP
] = texel
[0];
785 rgba
[BCOMP
] = texel
[0];
786 rgba
[ACOMP
] = texel
[1];
791 fetch_r5g6b5(const struct gl_texture_image
*texImage
,
792 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
794 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
795 const GLushort
*texel
;
800 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
801 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
802 rgba
[GCOMP
] = (((*texel
) >> 5) & 0x3f) * 255 / 63;
803 rgba
[BCOMP
] = (((*texel
) >> 0) & 0x1f) * 255 / 31;
809 fetch_r4g4b4a4(const struct gl_texture_image
*texImage
,
810 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
812 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
813 const GLushort
*texel
;
818 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
819 rgba
[RCOMP
] = (((*texel
) >> 12) & 0xf) * 255 / 15;
820 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xf) * 255 / 15;
821 rgba
[BCOMP
] = (((*texel
) >> 4) & 0xf) * 255 / 15;
822 rgba
[ACOMP
] = (((*texel
) >> 0) & 0xf) * 255 / 15;
827 fetch_r5g5b5a1(const struct gl_texture_image
*texImage
,
828 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
830 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
831 const GLushort
*texel
;
836 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
837 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
838 rgba
[GCOMP
] = (((*texel
) >> 6) & 0x1f) * 255 / 31;
839 rgba
[BCOMP
] = (((*texel
) >> 1) & 0x1f) * 255 / 31;
840 rgba
[ACOMP
] = (((*texel
) >> 0) & 0x01) * 255;
845 fetch_a8r8g8b8(const struct gl_texture_image
*texImage
,
846 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
848 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
854 texel
= ((GLuint
*) texImage
->Data
) + j
* mml
->width
+ i
;
855 rgba
[RCOMP
] = (((*texel
) >> 16) & 0xff);
856 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xff);
857 rgba
[BCOMP
] = (((*texel
) ) & 0xff);
858 rgba
[ACOMP
] = (((*texel
) >> 24) & 0xff);
862 static FetchTexelFuncC
863 fxFetchFunction(GLint mesaFormat
)
865 switch (mesaFormat
) {
867 return fetch_intensity8
;
871 return fetch_luminance8
;
872 case MESA_FORMAT_CI8
:
874 case MESA_FORMAT_AL88
:
875 return fetch_luminance8_alpha8
;
876 case MESA_FORMAT_RGB565
:
878 case MESA_FORMAT_ARGB4444
:
879 return fetch_r4g4b4a4
;
880 case MESA_FORMAT_ARGB1555
:
881 return fetch_r5g5b5a1
;
882 case MESA_FORMAT_ARGB8888
:
883 return fetch_a8r8g8b8
;
885 _mesa_problem(NULL
, "Unexpected format in fxFetchFunction");
886 printf("%d\n", mesaFormat
);
893 tdfxTexImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
894 GLint internalFormat
, GLint width
, GLint height
, GLint border
,
895 GLenum format
, GLenum type
, const GLvoid
*pixels
,
896 const struct gl_pixelstore_attrib
*packing
,
897 struct gl_texture_object
*texObj
,
898 struct gl_texture_image
*texImage
)
900 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
902 tdfxMipMapLevel
*mml
;
906 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
907 texObj->Name, texImage->IntFormat, format, type,
908 texImage->Width, texImage->Height);
911 ti
= TDFX_TEXTURE_DATA(texObj
);
913 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
914 if (!texObj
->DriverData
) {
915 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
918 ti
= TDFX_TEXTURE_DATA(texObj
);
922 mml
= TDFX_TEXIMAGE_DATA(texImage
);
924 texImage
->DriverData
= CALLOC(sizeof(tdfxMipMapLevel
));
925 if (!texImage
->DriverData
) {
926 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
929 mml
= TDFX_TEXIMAGE_DATA(texImage
);
932 /* Determine width and height scale factors for texture.
933 * Remember, Glide is limited to 8:1 aspect ratios.
936 texImage
->Width
, texImage
->Height
,
937 NULL
, /* lod level */
938 NULL
, /* aspect ratio */
939 NULL
, NULL
, /* sscale, tscale */
940 &mml
->wScale
, &mml
->hScale
);
943 mml
->width
= width
* mml
->wScale
;
944 mml
->height
= height
* mml
->hScale
;
947 /* choose the texture format */
948 assert(ctx
->Driver
.ChooseTextureFormat
);
949 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
950 internalFormat
, format
, type
);
951 assert(texImage
->TexFormat
);
952 mml
->glideFormat
= fxGlideFormat(texImage
->TexFormat
->MesaFormat
);
953 ti
->info
.format
= mml
->glideFormat
;
954 texImage
->FetchTexelc
= fxFetchFunction(texImage
->TexFormat
->MesaFormat
);
955 texelBytes
= texImage
->TexFormat
->TexelBytes
;
957 if (mml
->width
!= width
|| mml
->height
!= height
) {
958 /* rescale the image to overcome 1:8 aspect limitation */
960 tempImage
= MALLOC(width
* height
* texelBytes
);
962 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
965 /* unpack image, apply transfer ops and store in tempImage */
967 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
970 width
, height
, 1, 0, 0, 0,
972 0, /* dstImageStride */
973 format
, type
, pixels
, packing
);
975 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
976 texImage
->Format
, tempImage
,
977 0, 0, 0, /* dstX/Y/Zoffset */
978 width
* texelBytes
, /* dstRowStride */
979 0, /* dstImageStride */
981 format
, type
, pixels
, packing
);
983 assert(!texImage
->Data
);
984 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
985 if (!texImage
->Data
) {
986 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
990 _mesa_rescale_teximage2d(texelBytes
,
991 mml
->width
* texelBytes
, /* dst stride */
993 mml
->width
, mml
->height
,
994 tempImage
/*src*/, texImage
->Data
/*dst*/ );
998 /* no rescaling needed */
999 assert(!texImage
->Data
);
1000 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
1001 if (!texImage
->Data
) {
1002 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1005 /* unpack image, apply transfer ops and store in texImage->Data */
1007 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
1008 texImage
->TexFormat
, texImage
->Data
,
1009 width
, height
, 1, 0, 0, 0,
1010 texImage
->Width
* texelBytes
,
1011 0, /* dstImageStride */
1012 format
, type
, pixels
, packing
);
1015 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1016 texImage
->Format
, texImage
->Data
,
1017 0, 0, 0, /* dstX/Y/Zoffset */
1018 width
* texelBytes
, /* dstRowStride */
1019 0, /* dstImageStride */
1021 format
, type
, pixels
, packing
);
1024 RevalidateTexture(ctx
, texObj
);
1026 ti
->reloadImages
= GL_TRUE
;
1027 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1032 tdfxTexSubImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
1033 GLint xoffset
, GLint yoffset
,
1034 GLsizei width
, GLsizei height
,
1035 GLenum format
, GLenum type
,
1036 const GLvoid
*pixels
,
1037 const struct gl_pixelstore_attrib
*packing
,
1038 struct gl_texture_object
*texObj
,
1039 struct gl_texture_image
*texImage
)
1041 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1043 tdfxMipMapLevel
*mml
;
1046 if (!texObj
->DriverData
) {
1047 _mesa_problem(ctx
, "problem in fxDDTexSubImage2D");
1051 ti
= TDFX_TEXTURE_DATA(texObj
);
1053 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1056 assert(texImage
->Data
); /* must have an existing texture image! */
1057 assert(texImage
->Format
);
1059 texelBytes
= texImage
->TexFormat
->TexelBytes
;
1061 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
1062 /* need to rescale subimage to match mipmap level's rescale factors */
1063 const GLint newWidth
= width
* mml
->wScale
;
1064 const GLint newHeight
= height
* mml
->hScale
;
1065 GLvoid
*scaledImage
, *tempImage
;
1067 tempImage
= MALLOC(width
* height
* texelBytes
);
1069 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1074 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,/* Tex int format */
1075 texImage
->TexFormat
, /* dest format */
1076 (GLubyte
*) tempImage
, /* dest */
1077 width
, height
, 1, /* subimage size */
1078 0, 0, 0, /* subimage pos */
1079 width
* texelBytes
, /* dest row stride */
1080 0, /* dst image stride */
1081 format
, type
, pixels
, packing
);
1083 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1084 texImage
->Format
, texImage
->Data
,
1085 0, 0, 0, /* dstX/Y/Zoffset */
1086 width
* texelBytes
, /* dstRowStride */
1087 0, /* dstImageStride */
1089 format
, type
, pixels
, packing
);
1093 scaledImage
= MALLOC(newWidth
* newHeight
* texelBytes
);
1095 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1100 /* compute address of dest subimage within the overal tex image */
1101 destAddr
= (GLubyte
*) texImage
->Data
1102 + (yoffset
* mml
->hScale
* mml
->width
1103 + xoffset
* mml
->wScale
) * texelBytes
;
1105 _mesa_rescale_teximage2d(texelBytes
,
1106 mml
->width
* texelBytes
, /* dst stride */
1108 newWidth
, newHeight
,
1109 tempImage
, destAddr
);
1115 /* no rescaling needed */
1117 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, /* Tex int format */
1118 texImage
->TexFormat
, /* dest format */
1119 (GLubyte
*) texImage
->Data
,/* dest */
1120 width
, height
, 1, /* subimage size */
1121 xoffset
, yoffset
, 0, /* subimage pos */
1122 mml
->width
* texelBytes
, /* dest row stride */
1123 0, /* dst image stride */
1124 format
, type
, pixels
, packing
);
1126 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1127 texImage
->Format
, texImage
->Data
,
1128 xoffset
, yoffset
, 0,
1129 mml
->width
* texelBytes
, /* dstRowStride */
1130 0, /* dstImageStride */
1132 format
, type
, pixels
, packing
);
1136 ti
->reloadImages
= GL_TRUE
; /* signal the image needs to be reloaded */
1137 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX this might be a bit much */
1142 /**********************************************************************/
1143 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1144 /**********************************************************************/
1148 tdfxCompressedTexImage2D( GLcontext
*ctx
, GLenum target
,
1149 GLint level
, GLsizei imageSize
,
1151 struct gl_texture_object
*texObj
,
1152 struct gl_texture_image
*texImage
,
1153 GLboolean
*retainInternalCopy
)
1155 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1156 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
1157 GrTextureFormat_t gldformat
;
1159 tdfxMipMapLevel
*mml
;
1160 GLint dstWidth
, dstHeight
, wScale
, hScale
, texelSize
;
1161 MesaIntTexFormat intFormat
;
1162 GLboolean isCompressedFormat
;
1165 if (target
!= GL_TEXTURE_2D
|| texImage
->Border
> 0)
1168 ti
= TDFX_TEXTURE_DATA(texObj
);
1170 mml
= &ti
->mipmapLevel
[level
];
1172 isCompressedFormat
= tdfxDDIsCompressedGlideFormatMacro(texImage
->IntFormat
);
1173 if (!isCompressedFormat
) {
1174 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(format)");
1177 /* Determine the apporpriate GL internal texel format, Mesa internal
1178 * texel format, and texelSize (bytes) given the user's internal
1179 * texture format hint.
1181 tdfxTexGetFormat(texImage
->IntFormat
, allow32bpt
,
1182 &gldformat
, &intFormat
, &texelSize
);
1184 /* Determine width and height scale factors for texture.
1185 * Remember, Glide is limited to 8:1 aspect ratios.
1188 texImage
->Width
, texImage
->Height
,
1189 NULL
, /* lod level */
1190 NULL
, /* aspect ratio */
1191 NULL
, NULL
, /* sscale, tscale */
1193 dstWidth
= texImage
->Width
* wScale
;
1194 dstHeight
= texImage
->Height
* hScale
;
1196 _mesa_set_teximage_component_sizes(intFormat
, texImage
);
1198 texSize
= tdfxDDCompressedImageSize(ctx
,
1199 texImage
->IntFormat
,
1204 if (texSize
!= imageSize
) {
1205 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage2D(texSize)");
1209 /* allocate new storage for texture image, if needed */
1210 if (!mml
->data
|| mml
->glideFormat
!= gldformat
||
1211 mml
->width
!= dstWidth
|| mml
->height
!= dstHeight
||
1212 texSize
!= mml
->dataSize
) {
1216 mml
->data
= MALLOC(texSize
);
1220 mml
->texelSize
= texelSize
;
1221 mml
->glideFormat
= gldformat
;
1222 mml
->width
= dstWidth
;
1223 mml
->height
= dstHeight
;
1224 tdfxTMMoveOutTM(fxMesa
, texObj
);
1225 /*tdfxTexInvalidate(ctx, texObj);*/
1228 /* save the texture data */
1229 MEMCPY(mml
->data
, data
, imageSize
);
1231 RevalidateTexture(ctx
, texObj
);
1233 ti
->reloadImages
= GL_TRUE
;
1234 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1236 *retainInternalCopy
= GL_FALSE
;
1241 tdfxCompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
,
1242 GLint level
, GLint xoffset
,
1243 GLint yoffset
, GLsizei width
,
1244 GLint height
, GLenum format
,
1245 GLsizei imageSize
, const GLvoid
*data
,
1246 struct gl_texture_object
*texObj
,
1247 struct gl_texture_image
*texImage
)
1249 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1251 tdfxMipMapLevel
*mml
;
1254 * We punt if we are not replacing the entire image. This
1255 * is allowed by the spec.
1257 if ((xoffset
!= 0) && (yoffset
!= 0)
1258 && (width
!= texImage
->Width
)
1259 && (height
!= texImage
->Height
)) {
1263 ti
= TDFX_TEXTURE_DATA(texObj
);
1264 mml
= &ti
->mipmapLevel
[level
];
1265 if (imageSize
!= mml
->dataSize
) {
1268 MEMCPY(data
, mml
->data
, imageSize
);
1270 ti
->reloadImages
= GL_TRUE
;
1271 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1281 PrintTexture(int w
, int h
, int c
, const GLubyte
* data
)
1284 for (i
= 0; i
< h
; i
++) {
1285 for (j
= 0; j
< w
; j
++) {
1287 printf("%02x %02x ", data
[0], data
[1]);
1289 printf("%02x %02x %02x ", data
[0], data
[1], data
[2]);
1299 tdfxTestProxyTexImage(GLcontext
*ctx
, GLenum target
,
1300 GLint level
, GLint internalFormat
,
1301 GLenum format
, GLenum type
,
1302 GLint width
, GLint height
,
1303 GLint depth
, GLint border
)
1305 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1306 struct gl_shared_state
*mesaShared
= fxMesa
->glCtx
->Shared
;
1307 struct tdfxSharedState
*shared
= (struct tdfxSharedState
*) mesaShared
->DriverData
;
1310 case GL_PROXY_TEXTURE_1D
:
1311 return GL_TRUE
; /* software rendering */
1312 case GL_PROXY_TEXTURE_2D
:
1314 struct gl_texture_object
*tObj
;
1318 tObj
= ctx
->Texture
.Proxy2D
;
1319 if (!tObj
->DriverData
)
1320 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1321 ti
= TDFX_TEXTURE_DATA(tObj
);
1324 /* assign the parameters to test against */
1325 tObj
->Image
[0][level
]->Width
= width
;
1326 tObj
->Image
[0][level
]->Height
= height
;
1327 tObj
->Image
[0][level
]->Border
= border
;
1329 tObj
->Image
[0][level
]->IntFormat
= internalFormat
;
1332 /* don't use mipmap levels > 0 */
1333 tObj
->MinFilter
= tObj
->MagFilter
= GL_NEAREST
;
1336 /* test with all mipmap levels */
1337 tObj
->MinFilter
= GL_LINEAR_MIPMAP_LINEAR
;
1338 tObj
->MagFilter
= GL_NEAREST
;
1340 RevalidateTexture(ctx
, tObj
);
1343 printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1344 printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1345 printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1346 printf("glide format 0x%x\n", ti->info.format);
1347 printf("data %p\n", ti->info.data);
1348 printf("lodblend %d\n", (int) ti->LODblend);
1351 /* determine where texture will reside */
1352 if (ti
->LODblend
&& !shared
->umaTexMemory
) {
1353 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1354 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1355 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1358 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1359 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1360 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1363 printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1365 if (memNeeded
> shared
->totalTexMem
[0])
1370 case GL_PROXY_TEXTURE_3D
:
1371 return GL_TRUE
; /* software rendering */
1373 return GL_TRUE
; /* never happens, silence compiler */
1380 * This is called from _mesa_GetCompressedTexImage. We just
1381 * copy out the compressed data.
1384 tdfxGetCompressedTexImage( GLcontext
*ctx
, GLenum target
,
1385 GLint lod
, void *image
,
1386 const struct gl_texture_object
*texObj
,
1387 struct gl_texture_image
*texImage
)
1390 tdfxMipMapLevel
*mml
;
1392 if (target
!= GL_TEXTURE_2D
)
1395 if (!texObj
->DriverData
)
1398 ti
= TDFX_TEXTURE_DATA(texObj
);
1400 mml
= &ti
->mipmapLevel
[lod
];
1402 MEMCPY(image
, mml
->data
, mml
->dataSize
);
1408 * Calculate a specific texture format given a generic
1412 tdfxSpecificCompressedTexFormat(GLcontext
*ctx
,
1413 GLint internalFormat
,
1414 GLint numDimensions
)
1416 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1418 if (numDimensions
!= 2) {
1419 return internalFormat
;
1422 * If we don't have pointers to the functions, then
1423 * we drop back to uncompressed format. The logic
1424 * in Mesa proper handles this for us.
1426 * This is just to ease the transition to a Glide with
1427 * the texus2 library.
1429 if (!fxMesa
->Glide
.txImgQuantize
|| !fxMesa
->Glide
.txImgDequantizeFXT1
) {
1430 return internalFormat
;
1432 switch (internalFormat
) {
1433 case GL_COMPRESSED_RGB_ARB
:
1434 return GL_COMPRESSED_RGB_FXT1_3DFX
;
1435 case GL_COMPRESSED_RGBA_ARB
:
1436 return GL_COMPRESSED_RGBA_FXT1_3DFX
;
1438 return internalFormat
;
1442 * Calculate a specific texture format given a generic
1446 tdfxBaseCompressedTexFormat(GLcontext
*ctx
,
1447 GLint internalFormat
)
1449 switch (internalFormat
) {
1450 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1452 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1459 * Tell us if an image is compressed. The real work is done
1460 * in a macro, but we need to have a function to create a
1464 tdfxDDIsCompressedFormat(GLcontext
*ctx
, GLint internalFormat
)
1466 return tdfxDDIsCompressedFormatMacro(internalFormat
);
1471 * Calculate the image size of a compressed texture.
1473 * The current compressed format, the FXT1 family, all
1474 * map 8x32 texel blocks into 128 bits.
1476 * We return 0 if we can't calculate the size.
1478 * Glide would report this out to us, but we don't have
1479 * exactly the right parameters.
1482 tdfxDDCompressedImageSize(GLcontext
*ctx
,
1484 GLuint numDimensions
,
1489 if (numDimensions
!= 2) {
1492 switch (intFormat
) {
1493 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1494 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1496 * Round height and width to multiples of 4 and 8,
1497 * divide the resulting product by 32 to get the number
1498 * of blocks, and multiply by 32 = 128/8 to get the.
1499 * number of bytes required. That is to say, just
1500 * return the product. Remember that we are returning
1501 * bytes, not texels, so we have shrunk the texture
1502 * by a factor of the texel size.
1504 width
= (width
+ 0x7) &~ 0x7;
1505 height
= (height
+ 0x3) &~ 0x3;
1506 return width
* height
;
1514 * Allocate a new texture object.
1515 * Called via ctx->Driver.NewTextureObject.
1516 * Note: this function will be called during context creation to
1517 * allocate the default texture objects.
1518 * Note: we could use containment here to 'derive' the driver-specific
1519 * texture object from the core mesa gl_texture_object. Not done at this time.
1521 static struct gl_texture_object
*
1522 tdfxNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1524 struct gl_texture_object
*obj
;
1525 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1530 void tdfxInitTextureFuncs( struct dd_function_table
*functions
)
1532 functions
->BindTexture
= tdfxBindTexture
;
1533 functions
->NewTextureObject
= tdfxNewTextureObject
;
1534 functions
->DeleteTexture
= tdfxDeleteTexture
;
1535 functions
->TexEnv
= tdfxTexEnv
;
1536 functions
->TexParameter
= tdfxTexParameter
;
1537 functions
->ChooseTextureFormat
= tdfxChooseTextureFormat
;
1538 functions
->TexImage2D
= tdfxTexImage2D
;
1539 functions
->TexSubImage2D
= tdfxTexSubImage2D
;
1540 functions
->IsTextureResident
= tdfxIsTextureResident
;
1541 functions
->UpdateTexturePalette
= tdfxUpdateTexturePalette
;