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 * Called via glBindTexture.
207 tdfxBindTexture(GLcontext
* ctx
, GLenum target
,
208 struct gl_texture_object
*tObj
)
210 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
213 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
214 fprintf(stderr
, "fxmesa: fxDDTexBind(%d,%p)\n", tObj
->Name
,
218 if (target
!= GL_TEXTURE_2D
)
221 ti
= TDFX_TEXTURE_DATA(tObj
);
223 ti
->lastTimeUsed
= fxMesa
->texBindNumber
++;
225 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
230 * Called via glTexEnv.
233 tdfxTexEnv(GLcontext
* ctx
, GLenum target
, GLenum pname
,
234 const GLfloat
* param
)
236 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
238 if ( TDFX_DEBUG
& DEBUG_VERBOSE_API
) {
240 fprintf(stderr
, "fxmesa: texenv(%x,%x)\n", pname
,
243 fprintf(stderr
, "fxmesa: texenv(%x)\n", pname
);
246 /* XXX this is a bit of a hack to force the Glide texture
247 * state to be updated.
249 fxMesa
->TexState
.EnvMode
[ctx
->Texture
.CurrentUnit
] = 0;
251 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
256 * Called via glTexParameter.
259 tdfxTexParameter(GLcontext
* ctx
, GLenum target
,
260 struct gl_texture_object
*tObj
,
261 GLenum pname
, const GLfloat
* params
)
263 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
264 GLenum param
= (GLenum
) (GLint
) params
[0];
267 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
268 fprintf(stderr
, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj
->Name
,
269 tObj
->DriverData
, pname
, param
);
272 if (target
!= GL_TEXTURE_2D
)
275 ti
= TDFX_TEXTURE_DATA(tObj
);
279 case GL_TEXTURE_MIN_FILTER
:
282 ti
->mmMode
= GR_MIPMAP_DISABLE
;
283 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
284 ti
->LODblend
= FXFALSE
;
287 ti
->mmMode
= GR_MIPMAP_DISABLE
;
288 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
289 ti
->LODblend
= FXFALSE
;
291 case GL_NEAREST_MIPMAP_LINEAR
:
292 if (TDFX_IS_NAPALM(fxMesa
)) {
293 if (fxMesa
->haveTwoTMUs
) {
294 ti
->mmMode
= GR_MIPMAP_NEAREST
;
295 ti
->LODblend
= FXTRUE
;
298 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
299 ti
->LODblend
= FXFALSE
;
301 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
304 /* XXX Voodoo3/Banshee mipmap blending seems to produce
305 * incorrectly filtered colors for the smallest mipmap levels.
306 * To work-around we fall-through here and use a different filter.
308 case GL_NEAREST_MIPMAP_NEAREST
:
309 ti
->mmMode
= GR_MIPMAP_NEAREST
;
310 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
311 ti
->LODblend
= FXFALSE
;
313 case GL_LINEAR_MIPMAP_LINEAR
:
314 if (TDFX_IS_NAPALM(fxMesa
)) {
315 if (fxMesa
->haveTwoTMUs
) {
316 ti
->mmMode
= GR_MIPMAP_NEAREST
;
317 ti
->LODblend
= FXTRUE
;
320 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
321 ti
->LODblend
= FXFALSE
;
323 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
326 /* XXX Voodoo3/Banshee mipmap blending seems to produce
327 * incorrectly filtered colors for the smallest mipmap levels.
328 * To work-around we fall-through here and use a different filter.
330 case GL_LINEAR_MIPMAP_NEAREST
:
331 ti
->mmMode
= GR_MIPMAP_NEAREST
;
332 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
333 ti
->LODblend
= FXFALSE
;
338 RevalidateTexture(ctx
, tObj
);
339 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
342 case GL_TEXTURE_MAG_FILTER
:
345 ti
->magFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
348 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
353 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
356 case GL_TEXTURE_WRAP_S
:
359 ti
->sClamp
= GR_TEXTURECLAMP_CLAMP
;
362 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
367 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
370 case GL_TEXTURE_WRAP_T
:
373 ti
->tClamp
= GR_TEXTURECLAMP_CLAMP
;
376 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
381 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
384 case GL_TEXTURE_BORDER_COLOR
:
387 case GL_TEXTURE_MIN_LOD
:
390 case GL_TEXTURE_MAX_LOD
:
393 case GL_TEXTURE_BASE_LEVEL
:
394 RevalidateTexture(ctx
, tObj
);
396 case GL_TEXTURE_MAX_LEVEL
:
397 RevalidateTexture(ctx
, tObj
);
407 * Called via glDeleteTextures to delete a texture object.
408 * Here, we delete the Glide data associated with the texture.
411 tdfxDeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
413 if (ctx
&& ctx
->DriverCtx
) {
414 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
415 tdfxTMFreeTexture(fxMesa
, tObj
);
416 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
417 /* Free mipmap images and the texture object itself */
418 _mesa_delete_texture_object(ctx
, tObj
);
424 * Return true if texture is resident, false otherwise.
427 tdfxIsTextureResident(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
429 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
430 return (GLboolean
) (ti
&& ti
->isInTM
);
436 * Convert a gl_color_table texture palette to Glide's format.
439 convertPalette(FxU32 data
[256], const struct gl_color_table
*table
)
441 const GLubyte
*tableUB
= (const GLubyte
*) table
->Table
;
442 GLint width
= table
->Size
;
446 ASSERT(table
->TableType
== GL_UNSIGNED_BYTE
);
448 switch (table
->Format
) {
450 for (i
= 0; i
< width
; i
++) {
455 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
459 for (i
= 0; i
< width
; i
++) {
464 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
468 for (i
= 0; i
< width
; i
++) {
471 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
474 case GL_LUMINANCE_ALPHA
:
475 for (i
= 0; i
< width
; i
++) {
476 r
= g
= b
= tableUB
[i
* 2 + 0];
477 a
= tableUB
[i
* 2 + 1];
478 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
482 for (i
= 0; i
< width
; i
++) {
483 r
= tableUB
[i
* 3 + 0];
484 g
= tableUB
[i
* 3 + 1];
485 b
= tableUB
[i
* 3 + 2];
487 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
491 for (i
= 0; i
< width
; i
++) {
492 r
= tableUB
[i
* 4 + 0];
493 g
= tableUB
[i
* 4 + 1];
494 b
= tableUB
[i
* 4 + 2];
495 a
= tableUB
[i
* 4 + 3];
496 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
505 tdfxTexturePalette(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
507 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
510 /* per-texture palette */
513 /* This might be a proxy texture. */
514 if (!tObj
->Palette
.Table
)
517 ti
= TDFX_TEXTURE_DATA(tObj
);
519 convertPalette(ti
->palette
.data
, &tObj
->Palette
);
520 /*tdfxTexInvalidate(ctx, tObj);*/
523 /* global texture palette */
524 convertPalette(fxMesa
->glbPalette
.data
, &ctx
->Texture
.Palette
);
526 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX too heavy-handed */
530 /**********************************************************************/
531 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
532 /**********************************************************************/
535 static FxBool TexusFatalError
= FXFALSE
;
536 static FxBool TexusError
= FXFALSE
;
538 #define TX_DITHER_NONE 0x00000000
541 fxTexusError(const char *string
, FxBool fatal
)
543 _mesa_problem(NULL
, string
);
545 * Just propagate the fatal value up.
548 TexusFatalError
= fatal
;
553 static const struct gl_texture_format
*
554 tdfxChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
555 GLenum srcFormat
, GLenum srcType
)
557 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
558 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
560 switch (internalFormat
) {
566 return &_mesa_texformat_a8
;
573 return &_mesa_texformat_l8
;
575 case GL_LUMINANCE_ALPHA
:
576 case GL_LUMINANCE4_ALPHA4
:
577 case GL_LUMINANCE6_ALPHA2
:
578 case GL_LUMINANCE8_ALPHA8
:
579 case GL_LUMINANCE12_ALPHA4
:
580 case GL_LUMINANCE12_ALPHA12
:
581 case GL_LUMINANCE16_ALPHA16
:
582 return &_mesa_texformat_al88
;
588 return &_mesa_texformat_i8
;
592 return &_mesa_texformat_rgb565
;
599 return (allow32bpt
) ? &_mesa_texformat_argb8888
600 : &_mesa_texformat_rgb565
;
604 return &_mesa_texformat_argb4444
;
611 return allow32bpt
? &_mesa_texformat_argb8888
612 : &_mesa_texformat_argb4444
;
614 return &_mesa_texformat_argb1555
;
616 case GL_COLOR_INDEX1_EXT
:
617 case GL_COLOR_INDEX2_EXT
:
618 case GL_COLOR_INDEX4_EXT
:
619 case GL_COLOR_INDEX8_EXT
:
620 case GL_COLOR_INDEX12_EXT
:
621 case GL_COLOR_INDEX16_EXT
:
622 return &_mesa_texformat_ci8
;
624 _mesa_problem(ctx
, "unexpected format in tdfxChooseTextureFormat");
631 * Return the Glide format for the given mesa texture format.
633 static GrTextureFormat_t
634 fxGlideFormat(GLint mesaFormat
)
636 switch (mesaFormat
) {
638 return GR_TEXFMT_ALPHA_8
;
640 return GR_TEXFMT_ALPHA_8
;
642 return GR_TEXFMT_INTENSITY_8
;
643 case MESA_FORMAT_CI8
:
644 return GR_TEXFMT_P_8
;
645 case MESA_FORMAT_AL88
:
646 return GR_TEXFMT_ALPHA_INTENSITY_88
;
647 case MESA_FORMAT_RGB565
:
648 return GR_TEXFMT_RGB_565
;
649 case MESA_FORMAT_ARGB4444
:
650 return GR_TEXFMT_ARGB_4444
;
651 case MESA_FORMAT_ARGB1555
:
652 return GR_TEXFMT_ARGB_1555
;
653 case MESA_FORMAT_ARGB8888
:
654 return GR_TEXFMT_ARGB_8888
;
656 _mesa_problem(NULL
, "Unexpected format in fxGlideFormat");
662 /* Texel-fetch functions for software texturing and glGetTexImage().
663 * We should have been able to use some "standard" fetch functions (which
664 * may get defined in texutil.c) but we have to account for scaled texture
665 * images on tdfx hardware (the 8:1 aspect ratio limit).
666 * Hence, we need special functions here.
670 fetch_intensity8(const struct gl_texture_image
*texImage
,
671 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
673 GLchan
*rgba
= (GLchan
*) texelOut
;
674 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
675 const GLubyte
*texel
;
680 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
681 rgba
[RCOMP
] = *texel
;
682 rgba
[GCOMP
] = *texel
;
683 rgba
[BCOMP
] = *texel
;
684 rgba
[ACOMP
] = *texel
;
689 fetch_luminance8(const struct gl_texture_image
*texImage
,
690 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
692 GLchan
*rgba
= (GLchan
*) texelOut
;
693 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
694 const GLubyte
*texel
;
699 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
700 rgba
[RCOMP
] = *texel
;
701 rgba
[GCOMP
] = *texel
;
702 rgba
[BCOMP
] = *texel
;
708 fetch_alpha8(const struct gl_texture_image
*texImage
,
709 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
711 GLchan
*rgba
= (GLchan
*) texelOut
;
712 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
713 const GLubyte
*texel
;
717 i
= i
* mml
->width
/ texImage
->Width
;
718 j
= j
* mml
->height
/ texImage
->Height
;
720 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
724 rgba
[ACOMP
] = *texel
;
729 fetch_index8(const struct gl_texture_image
*texImage
,
730 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
732 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
739 fetch_luminance8_alpha8(const struct gl_texture_image
*texImage
,
740 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
742 GLchan
*rgba
= (GLchan
*) texelOut
;
743 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
744 const GLubyte
*texel
;
749 texel
= ((GLubyte
*) texImage
->Data
) + (j
* mml
->width
+ i
) * 2;
750 rgba
[RCOMP
] = texel
[0];
751 rgba
[GCOMP
] = texel
[0];
752 rgba
[BCOMP
] = texel
[0];
753 rgba
[ACOMP
] = texel
[1];
758 fetch_r5g6b5(const struct gl_texture_image
*texImage
,
759 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
761 GLchan
*rgba
= (GLchan
*) texelOut
;
762 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
763 const GLushort
*texel
;
768 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
769 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
770 rgba
[GCOMP
] = (((*texel
) >> 5) & 0x3f) * 255 / 63;
771 rgba
[BCOMP
] = (((*texel
) >> 0) & 0x1f) * 255 / 31;
777 fetch_r4g4b4a4(const struct gl_texture_image
*texImage
,
778 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
780 GLchan
*rgba
= (GLchan
*) texelOut
;
781 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
782 const GLushort
*texel
;
787 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
788 rgba
[RCOMP
] = (((*texel
) >> 12) & 0xf) * 255 / 15;
789 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xf) * 255 / 15;
790 rgba
[BCOMP
] = (((*texel
) >> 4) & 0xf) * 255 / 15;
791 rgba
[ACOMP
] = (((*texel
) >> 0) & 0xf) * 255 / 15;
796 fetch_r5g5b5a1(const struct gl_texture_image
*texImage
,
797 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
799 GLchan
*rgba
= (GLchan
*) texelOut
;
800 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
801 const GLushort
*texel
;
806 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
807 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
808 rgba
[GCOMP
] = (((*texel
) >> 6) & 0x1f) * 255 / 31;
809 rgba
[BCOMP
] = (((*texel
) >> 1) & 0x1f) * 255 / 31;
810 rgba
[ACOMP
] = (((*texel
) >> 0) & 0x01) * 255;
815 fetch_a8r8g8b8(const struct gl_texture_image
*texImage
,
816 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
818 GLchan
*rgba
= (GLchan
*) texelOut
;
819 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
825 texel
= ((GLuint
*) texImage
->Data
) + j
* mml
->width
+ i
;
826 rgba
[RCOMP
] = (((*texel
) >> 16) & 0xff);
827 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xff);
828 rgba
[BCOMP
] = (((*texel
) ) & 0xff);
829 rgba
[ACOMP
] = (((*texel
) >> 24) & 0xff);
833 static FetchTexelFunc
834 fxFetchFunction(GLint mesaFormat
)
836 switch (mesaFormat
) {
838 return fetch_intensity8
;
842 return fetch_luminance8
;
843 case MESA_FORMAT_CI8
:
845 case MESA_FORMAT_AL88
:
846 return fetch_luminance8_alpha8
;
847 case MESA_FORMAT_RGB565
:
849 case MESA_FORMAT_ARGB4444
:
850 return fetch_r4g4b4a4
;
851 case MESA_FORMAT_ARGB1555
:
852 return fetch_r5g5b5a1
;
853 case MESA_FORMAT_ARGB8888
:
854 return fetch_a8r8g8b8
;
856 _mesa_problem(NULL
, "Unexpected format in fxFetchFunction");
857 printf("%d\n", mesaFormat
);
864 tdfxTexImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
865 GLint internalFormat
, GLint width
, GLint height
, GLint border
,
866 GLenum format
, GLenum type
, const GLvoid
*pixels
,
867 const struct gl_pixelstore_attrib
*packing
,
868 struct gl_texture_object
*texObj
,
869 struct gl_texture_image
*texImage
)
871 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
873 tdfxMipMapLevel
*mml
;
877 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
878 texObj->Name, texImage->IntFormat, format, type,
879 texImage->Width, texImage->Height);
882 ti
= TDFX_TEXTURE_DATA(texObj
);
885 mml
= TDFX_TEXIMAGE_DATA(texImage
);
887 texImage
->DriverData
= CALLOC(sizeof(tdfxMipMapLevel
));
888 if (!texImage
->DriverData
) {
889 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
892 mml
= TDFX_TEXIMAGE_DATA(texImage
);
895 /* Determine width and height scale factors for texture.
896 * Remember, Glide is limited to 8:1 aspect ratios.
899 texImage
->Width
, texImage
->Height
,
900 NULL
, /* lod level */
901 NULL
, /* aspect ratio */
902 NULL
, NULL
, /* sscale, tscale */
903 &mml
->wScale
, &mml
->hScale
);
906 mml
->width
= width
* mml
->wScale
;
907 mml
->height
= height
* mml
->hScale
;
910 /* choose the texture format */
911 assert(ctx
->Driver
.ChooseTextureFormat
);
912 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
913 internalFormat
, format
, type
);
914 assert(texImage
->TexFormat
);
915 mml
->glideFormat
= fxGlideFormat(texImage
->TexFormat
->MesaFormat
);
916 ti
->info
.format
= mml
->glideFormat
;
917 texImage
->FetchTexel
= fxFetchFunction(texImage
->TexFormat
->MesaFormat
);
918 texelBytes
= texImage
->TexFormat
->TexelBytes
;
920 if (mml
->width
!= width
|| mml
->height
!= height
) {
921 /* rescale the image to overcome 1:8 aspect limitation */
923 tempImage
= MALLOC(width
* height
* texelBytes
);
925 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
928 /* unpack image, apply transfer ops and store in tempImage */
929 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
932 width
, height
, 1, 0, 0, 0,
934 0, /* dstImageStride */
935 format
, type
, pixels
, packing
);
936 assert(!texImage
->Data
);
937 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
938 if (!texImage
->Data
) {
939 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
943 _mesa_rescale_teximage2d(texelBytes
,
944 mml
->width
* texelBytes
, /* dst stride */
946 mml
->width
, mml
->height
,
947 tempImage
/*src*/, texImage
->Data
/*dst*/ );
951 /* no rescaling needed */
952 assert(!texImage
->Data
);
953 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
954 if (!texImage
->Data
) {
955 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
958 /* unpack image, apply transfer ops and store in texImage->Data */
959 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
960 texImage
->TexFormat
, texImage
->Data
,
961 width
, height
, 1, 0, 0, 0,
962 texImage
->Width
* texelBytes
,
963 0, /* dstImageStride */
964 format
, type
, pixels
, packing
);
967 RevalidateTexture(ctx
, texObj
);
969 ti
->reloadImages
= GL_TRUE
;
970 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
975 tdfxTexSubImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
976 GLint xoffset
, GLint yoffset
,
977 GLsizei width
, GLsizei height
,
978 GLenum format
, GLenum type
,
979 const GLvoid
*pixels
,
980 const struct gl_pixelstore_attrib
*packing
,
981 struct gl_texture_object
*texObj
,
982 struct gl_texture_image
*texImage
)
984 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
986 tdfxMipMapLevel
*mml
;
989 ti
= TDFX_TEXTURE_DATA(texObj
);
991 mml
= TDFX_TEXIMAGE_DATA(texImage
);
994 assert(texImage
->Data
); /* must have an existing texture image! */
995 assert(texImage
->Format
);
997 texelBytes
= texImage
->TexFormat
->TexelBytes
;
999 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
1000 /* need to rescale subimage to match mipmap level's rescale factors */
1001 const GLint newWidth
= width
* mml
->wScale
;
1002 const GLint newHeight
= height
* mml
->hScale
;
1003 GLvoid
*scaledImage
, *tempImage
;
1005 tempImage
= MALLOC(width
* height
* texelBytes
);
1007 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1011 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,/* Tex int format */
1012 texImage
->TexFormat
, /* dest format */
1013 (GLubyte
*) tempImage
, /* dest */
1014 width
, height
, 1, /* subimage size */
1015 0, 0, 0, /* subimage pos */
1016 width
* texelBytes
, /* dest row stride */
1017 0, /* dst image stride */
1018 format
, type
, pixels
, packing
);
1021 scaledImage
= MALLOC(newWidth
* newHeight
* texelBytes
);
1023 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1028 /* compute address of dest subimage within the overal tex image */
1029 destAddr
= (GLubyte
*) texImage
->Data
1030 + (yoffset
* mml
->hScale
* mml
->width
1031 + xoffset
* mml
->wScale
) * texelBytes
;
1033 _mesa_rescale_teximage2d(texelBytes
,
1034 mml
->width
* texelBytes
, /* dst stride */
1036 newWidth
, newHeight
,
1037 tempImage
, destAddr
);
1043 /* no rescaling needed */
1044 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, /* Tex int format */
1045 texImage
->TexFormat
, /* dest format */
1046 (GLubyte
*) texImage
->Data
,/* dest */
1047 width
, height
, 1, /* subimage size */
1048 xoffset
, yoffset
, 0, /* subimage pos */
1049 mml
->width
* texelBytes
, /* dest row stride */
1050 0, /* dst image stride */
1051 format
, type
, pixels
, packing
);
1054 ti
->reloadImages
= GL_TRUE
; /* signal the image needs to be reloaded */
1055 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX this might be a bit much */
1060 /**********************************************************************/
1061 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1062 /**********************************************************************/
1066 tdfxCompressedTexImage2D( GLcontext
*ctx
, GLenum target
,
1067 GLint level
, GLsizei imageSize
,
1069 struct gl_texture_object
*texObj
,
1070 struct gl_texture_image
*texImage
,
1071 GLboolean
*retainInternalCopy
)
1073 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1074 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
1075 GrTextureFormat_t gldformat
;
1077 tdfxMipMapLevel
*mml
;
1078 GLint dstWidth
, dstHeight
, wScale
, hScale
, texelSize
;
1079 MesaIntTexFormat intFormat
;
1080 GLboolean isCompressedFormat
;
1083 if (target
!= GL_TEXTURE_2D
|| texImage
->Border
> 0)
1086 ti
= TDFX_TEXTURE_DATA(texObj
);
1088 mml
= &ti
->mipmapLevel
[level
];
1090 isCompressedFormat
= tdfxDDIsCompressedGlideFormatMacro(texImage
->IntFormat
);
1091 if (!isCompressedFormat
) {
1092 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(format)");
1095 /* Determine the apporpriate GL internal texel format, Mesa internal
1096 * texel format, and texelSize (bytes) given the user's internal
1097 * texture format hint.
1099 tdfxTexGetFormat(texImage
->IntFormat
, allow32bpt
,
1100 &gldformat
, &intFormat
, &texelSize
);
1102 /* Determine width and height scale factors for texture.
1103 * Remember, Glide is limited to 8:1 aspect ratios.
1106 texImage
->Width
, texImage
->Height
,
1107 NULL
, /* lod level */
1108 NULL
, /* aspect ratio */
1109 NULL
, NULL
, /* sscale, tscale */
1111 dstWidth
= texImage
->Width
* wScale
;
1112 dstHeight
= texImage
->Height
* hScale
;
1114 _mesa_set_teximage_component_sizes(intFormat
, texImage
);
1116 texSize
= tdfxDDCompressedImageSize(ctx
,
1117 texImage
->IntFormat
,
1122 if (texSize
!= imageSize
) {
1123 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage2D(texSize)");
1127 /* allocate new storage for texture image, if needed */
1128 if (!mml
->data
|| mml
->glideFormat
!= gldformat
||
1129 mml
->width
!= dstWidth
|| mml
->height
!= dstHeight
||
1130 texSize
!= mml
->dataSize
) {
1134 mml
->data
= MALLOC(texSize
);
1138 mml
->texelSize
= texelSize
;
1139 mml
->glideFormat
= gldformat
;
1140 mml
->width
= dstWidth
;
1141 mml
->height
= dstHeight
;
1142 tdfxTMMoveOutTM(fxMesa
, texObj
);
1143 /*tdfxTexInvalidate(ctx, texObj);*/
1146 /* save the texture data */
1147 MEMCPY(mml
->data
, data
, imageSize
);
1149 RevalidateTexture(ctx
, texObj
);
1151 ti
->reloadImages
= GL_TRUE
;
1152 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1154 *retainInternalCopy
= GL_FALSE
;
1159 tdfxCompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
,
1160 GLint level
, GLint xoffset
,
1161 GLint yoffset
, GLsizei width
,
1162 GLint height
, GLenum format
,
1163 GLsizei imageSize
, const GLvoid
*data
,
1164 struct gl_texture_object
*texObj
,
1165 struct gl_texture_image
*texImage
)
1167 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1169 tdfxMipMapLevel
*mml
;
1172 * We punt if we are not replacing the entire image. This
1173 * is allowed by the spec.
1175 if ((xoffset
!= 0) && (yoffset
!= 0)
1176 && (width
!= texImage
->Width
)
1177 && (height
!= texImage
->Height
)) {
1181 ti
= TDFX_TEXTURE_DATA(texObj
);
1182 mml
= &ti
->mipmapLevel
[level
];
1183 if (imageSize
!= mml
->dataSize
) {
1186 MEMCPY(data
, mml
->data
, imageSize
);
1188 ti
->reloadImages
= GL_TRUE
;
1189 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1199 PrintTexture(int w
, int h
, int c
, const GLubyte
* data
)
1202 for (i
= 0; i
< h
; i
++) {
1203 for (j
= 0; j
< w
; j
++) {
1205 printf("%02x %02x ", data
[0], data
[1]);
1207 printf("%02x %02x %02x ", data
[0], data
[1], data
[2]);
1217 tdfxTestProxyTexImage(GLcontext
*ctx
, GLenum target
,
1218 GLint level
, GLint internalFormat
,
1219 GLenum format
, GLenum type
,
1220 GLint width
, GLint height
,
1221 GLint depth
, GLint border
)
1223 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1224 struct gl_shared_state
*mesaShared
= fxMesa
->glCtx
->Shared
;
1225 struct tdfxSharedState
*shared
= (struct tdfxSharedState
*) mesaShared
->DriverData
;
1228 case GL_PROXY_TEXTURE_1D
:
1229 return GL_TRUE
; /* software rendering */
1230 case GL_PROXY_TEXTURE_2D
:
1232 struct gl_texture_object
*tObj
;
1236 tObj
= ctx
->Texture
.Proxy2D
;
1237 ti
= TDFX_TEXTURE_DATA(tObj
);
1240 /* assign the parameters to test against */
1241 tObj
->Image
[level
]->Width
= width
;
1242 tObj
->Image
[level
]->Height
= height
;
1243 tObj
->Image
[level
]->Border
= border
;
1245 tObj
->Image
[level
]->IntFormat
= internalFormat
;
1248 /* don't use mipmap levels > 0 */
1249 tObj
->MinFilter
= tObj
->MagFilter
= GL_NEAREST
;
1252 /* test with all mipmap levels */
1253 tObj
->MinFilter
= GL_LINEAR_MIPMAP_LINEAR
;
1254 tObj
->MagFilter
= GL_NEAREST
;
1256 RevalidateTexture(ctx
, tObj
);
1259 printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1260 printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1261 printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1262 printf("glide format 0x%x\n", ti->info.format);
1263 printf("data %p\n", ti->info.data);
1264 printf("lodblend %d\n", (int) ti->LODblend);
1267 /* determine where texture will reside */
1268 if (ti
->LODblend
&& !shared
->umaTexMemory
) {
1269 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1270 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1271 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1274 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1275 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1276 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1279 printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1281 if (memNeeded
> shared
->totalTexMem
[0])
1286 case GL_PROXY_TEXTURE_3D
:
1287 return GL_TRUE
; /* software rendering */
1289 return GL_TRUE
; /* never happens, silence compiler */
1296 * This is called from _mesa_GetCompressedTexImage. We just
1297 * copy out the compressed data.
1300 tdfxGetCompressedTexImage( GLcontext
*ctx
, GLenum target
,
1301 GLint lod
, void *image
,
1302 const struct gl_texture_object
*texObj
,
1303 struct gl_texture_image
*texImage
)
1306 tdfxMipMapLevel
*mml
;
1308 if (target
!= GL_TEXTURE_2D
)
1311 ti
= TDFX_TEXTURE_DATA(texObj
);
1313 mml
= &ti
->mipmapLevel
[lod
];
1315 MEMCPY(image
, mml
->data
, mml
->dataSize
);
1321 * Calculate a specific texture format given a generic
1325 tdfxSpecificCompressedTexFormat(GLcontext
*ctx
,
1326 GLint internalFormat
,
1327 GLint numDimensions
)
1329 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1331 if (numDimensions
!= 2) {
1332 return internalFormat
;
1335 * If we don't have pointers to the functions, then
1336 * we drop back to uncompressed format. The logic
1337 * in Mesa proper handles this for us.
1339 * This is just to ease the transition to a Glide with
1340 * the texus2 library.
1342 if (!fxMesa
->Glide
.txImgQuantize
|| !fxMesa
->Glide
.txImgDequantizeFXT1
) {
1343 return internalFormat
;
1345 switch (internalFormat
) {
1346 case GL_COMPRESSED_RGB_ARB
:
1347 return GL_COMPRESSED_RGB_FXT1_3DFX
;
1348 case GL_COMPRESSED_RGBA_ARB
:
1349 return GL_COMPRESSED_RGBA_FXT1_3DFX
;
1351 return internalFormat
;
1355 * Calculate a specific texture format given a generic
1359 tdfxBaseCompressedTexFormat(GLcontext
*ctx
,
1360 GLint internalFormat
)
1362 switch (internalFormat
) {
1363 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1365 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1372 * Tell us if an image is compressed. The real work is done
1373 * in a macro, but we need to have a function to create a
1377 tdfxDDIsCompressedFormat(GLcontext
*ctx
, GLint internalFormat
)
1379 return tdfxDDIsCompressedFormatMacro(internalFormat
);
1384 * Calculate the image size of a compressed texture.
1386 * The current compressed format, the FXT1 family, all
1387 * map 8x32 texel blocks into 128 bits.
1389 * We return 0 if we can't calculate the size.
1391 * Glide would report this out to us, but we don't have
1392 * exactly the right parameters.
1395 tdfxDDCompressedImageSize(GLcontext
*ctx
,
1397 GLuint numDimensions
,
1402 if (numDimensions
!= 2) {
1405 switch (intFormat
) {
1406 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1407 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1409 * Round height and width to multiples of 4 and 8,
1410 * divide the resulting product by 32 to get the number
1411 * of blocks, and multiply by 32 = 128/8 to get the.
1412 * number of bytes required. That is to say, just
1413 * return the product. Remember that we are returning
1414 * bytes, not texels, so we have shrunk the texture
1415 * by a factor of the texel size.
1417 width
= (width
+ 0x7) &~ 0x7;
1418 height
= (height
+ 0x3) &~ 0x3;
1419 return width
* height
;
1427 * Allocate a new texture object.
1428 * Called via ctx->Driver.NewTextureObject.
1429 * Note: this function will be called during context creation to
1430 * allocate the default texture objects.
1432 static struct gl_texture_object
*
1433 tdfxNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1435 struct gl_texture_object
*obj
;
1437 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1441 if (!(ti
= CALLOC(sizeof(tdfxTexInfo
)))) {
1442 _mesa_delete_texture_object(ctx
, obj
);
1446 ti
->isInTM
= GL_FALSE
;
1448 ti
->whichTMU
= TDFX_TMU_NONE
;
1450 ti
->tm
[TDFX_TMU0
] = NULL
;
1451 ti
->tm
[TDFX_TMU1
] = NULL
;
1453 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
1454 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
1456 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
1457 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
1459 ti
->mmMode
= GR_MIPMAP_NEAREST
;
1460 ti
->LODblend
= FXFALSE
;
1462 obj
->DriverData
= ti
;
1468 void tdfxInitTextureFuncs( struct dd_function_table
*functions
)
1470 functions
->BindTexture
= tdfxBindTexture
;
1471 functions
->NewTextureObject
= tdfxNewTextureObject
;
1472 functions
->DeleteTexture
= tdfxDeleteTexture
;
1473 functions
->TexEnv
= tdfxTexEnv
;
1474 functions
->TexParameter
= tdfxTexParameter
;
1475 functions
->ChooseTextureFormat
= tdfxChooseTextureFormat
;
1476 functions
->TexImage2D
= tdfxTexImage2D
;
1477 functions
->TexSubImage2D
= tdfxTexSubImage2D
;