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>
39 #include "texformat.h"
43 #include "tdfx_context.h"
45 #include "tdfx_texman.h"
73 * Compute various texture image parameters.
74 * Input: w, h - source texture width and height
75 * Output: lodlevel - Glide lod level token for the larger texture dimension
76 * aspectratio - Glide aspect ratio token
77 * sscale - S scale factor used during triangle setup
78 * tscale - T scale factor used during triangle setup
79 * wscale - OpenGL -> Glide image width scale factor
80 * hscale - OpenGL -> Glide image height scale factor
83 * w h lodlevel aspectRatio
84 * 128 128 GR_LOD_LOG2_128 (=7) GR_ASPECT_LOG2_1x1 (=0)
85 * 64 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x1 (=0)
86 * 64 32 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_2x1 (=1)
87 * 32 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x2 (=-1)
88 * 32 32 GR_LOD_LOG2_32 (=5) GR_ASPECT_LOG2_1x1 (=0)
91 tdfxTexGetInfo(const GLcontext
*ctx
, int w
, int h
,
92 GrLOD_t
*lodlevel
, GrAspectRatio_t
*aspectratio
,
93 float *sscale
, float *tscale
,
94 int *wscale
, int *hscale
)
96 int logw
, logh
, ar
, lod
, ws
, hs
;
104 ar
= logw
- logh
; /* aspect ratio = difference in log dimensions */
106 /* Hardware only allows a maximum aspect ratio of 8x1, so handle
107 |ar| > 3 by scaling the image and using an 8x1 aspect ratio */
109 ASSERT(width
>= height
);
113 if (ar
<= GR_ASPECT_LOG2_8x1
) {
118 /* have to stretch image height */
124 ASSERT(width
< height
);
128 if (ar
>= GR_ASPECT_LOG2_1x8
) {
133 /* have to stretch image width */
139 if (ar
< GR_ASPECT_LOG2_1x8
)
140 ar
= GR_ASPECT_LOG2_1x8
;
141 else if (ar
> GR_ASPECT_LOG2_8x1
)
142 ar
= GR_ASPECT_LOG2_8x1
;
145 *lodlevel
= (GrLOD_t
) lod
;
147 *aspectratio
= (GrAspectRatio_t
) ar
;
160 * We need to call this when a texture object's minification filter
161 * or texture image sizes change.
163 static void RevalidateTexture(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
165 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
171 minl
= maxl
= tObj
->BaseLevel
;
173 if (tObj
->Image
[0][minl
]) {
174 maxl
= MIN2(tObj
->MaxLevel
, tObj
->Image
[0][minl
]->MaxLog2
);
176 /* compute largeLodLog2, aspect ratio and texcoord scale factors */
177 tdfxTexGetInfo(ctx
, tObj
->Image
[0][minl
]->Width
, tObj
->Image
[0][minl
]->Height
,
178 &ti
->info
.largeLodLog2
,
179 &ti
->info
.aspectRatioLog2
,
180 &(ti
->sScale
), &(ti
->tScale
), NULL
, NULL
);
183 if (tObj
->Image
[0][maxl
] && (tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
184 /* mipmapping: need to compute smallLodLog2 */
185 tdfxTexGetInfo(ctx
, tObj
->Image
[0][maxl
]->Width
,
186 tObj
->Image
[0][maxl
]->Height
,
187 &ti
->info
.smallLodLog2
, NULL
,
188 NULL
, NULL
, NULL
, NULL
);
191 /* not mipmapping: smallLodLog2 = largeLodLog2 */
192 ti
->info
.smallLodLog2
= ti
->info
.largeLodLog2
;
198 ti
->info
.data
= NULL
;
203 fxAllocTexObjData(tdfxContextPtr fxMesa
)
207 if (!(ti
= CALLOC(sizeof(tdfxTexInfo
)))) {
208 _mesa_problem(NULL
, "tdfx driver: out of memory");
212 ti
->isInTM
= GL_FALSE
;
214 ti
->whichTMU
= TDFX_TMU_NONE
;
216 ti
->tm
[TDFX_TMU0
] = NULL
;
217 ti
->tm
[TDFX_TMU1
] = NULL
;
219 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
220 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
222 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
223 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
225 ti
->mmMode
= GR_MIPMAP_NEAREST
;
226 ti
->LODblend
= FXFALSE
;
233 * Called via glBindTexture.
236 tdfxBindTexture(GLcontext
* ctx
, GLenum target
,
237 struct gl_texture_object
*tObj
)
239 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
242 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
243 fprintf(stderr
, "fxmesa: fxDDTexBind(%d,%p)\n", tObj
->Name
,
247 if (target
!= GL_TEXTURE_2D
)
250 if (!tObj
->DriverData
) {
251 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
254 ti
= TDFX_TEXTURE_DATA(tObj
);
255 ti
->lastTimeUsed
= fxMesa
->texBindNumber
++;
257 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
262 * Called via glTexEnv.
265 tdfxTexEnv(GLcontext
* ctx
, GLenum target
, GLenum pname
,
266 const GLfloat
* param
)
268 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
270 if ( TDFX_DEBUG
& DEBUG_VERBOSE_API
) {
272 fprintf(stderr
, "fxmesa: texenv(%x,%x)\n", pname
,
275 fprintf(stderr
, "fxmesa: texenv(%x)\n", pname
);
278 /* XXX this is a bit of a hack to force the Glide texture
279 * state to be updated.
281 fxMesa
->TexState
.EnvMode
[ctx
->Texture
.CurrentUnit
] = 0;
283 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
288 * Called via glTexParameter.
291 tdfxTexParameter(GLcontext
* ctx
, GLenum target
,
292 struct gl_texture_object
*tObj
,
293 GLenum pname
, const GLfloat
* params
)
295 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
296 GLenum param
= (GLenum
) (GLint
) params
[0];
299 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
300 fprintf(stderr
, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj
->Name
,
301 tObj
->DriverData
, pname
, param
);
304 if (target
!= GL_TEXTURE_2D
)
307 if (!tObj
->DriverData
)
308 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
310 ti
= TDFX_TEXTURE_DATA(tObj
);
313 case GL_TEXTURE_MIN_FILTER
:
316 ti
->mmMode
= GR_MIPMAP_DISABLE
;
317 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
318 ti
->LODblend
= FXFALSE
;
321 ti
->mmMode
= GR_MIPMAP_DISABLE
;
322 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
323 ti
->LODblend
= FXFALSE
;
325 case GL_NEAREST_MIPMAP_LINEAR
:
326 if (TDFX_IS_NAPALM(fxMesa
)) {
327 if (fxMesa
->haveTwoTMUs
) {
328 ti
->mmMode
= GR_MIPMAP_NEAREST
;
329 ti
->LODblend
= FXTRUE
;
332 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
333 ti
->LODblend
= FXFALSE
;
335 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
338 /* XXX Voodoo3/Banshee mipmap blending seems to produce
339 * incorrectly filtered colors for the smallest mipmap levels.
340 * To work-around we fall-through here and use a different filter.
342 case GL_NEAREST_MIPMAP_NEAREST
:
343 ti
->mmMode
= GR_MIPMAP_NEAREST
;
344 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
345 ti
->LODblend
= FXFALSE
;
347 case GL_LINEAR_MIPMAP_LINEAR
:
348 if (TDFX_IS_NAPALM(fxMesa
)) {
349 if (fxMesa
->haveTwoTMUs
) {
350 ti
->mmMode
= GR_MIPMAP_NEAREST
;
351 ti
->LODblend
= FXTRUE
;
354 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
355 ti
->LODblend
= FXFALSE
;
357 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
360 /* XXX Voodoo3/Banshee mipmap blending seems to produce
361 * incorrectly filtered colors for the smallest mipmap levels.
362 * To work-around we fall-through here and use a different filter.
364 case GL_LINEAR_MIPMAP_NEAREST
:
365 ti
->mmMode
= GR_MIPMAP_NEAREST
;
366 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
367 ti
->LODblend
= FXFALSE
;
372 RevalidateTexture(ctx
, tObj
);
373 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
376 case GL_TEXTURE_MAG_FILTER
:
379 ti
->magFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
382 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
387 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
390 case GL_TEXTURE_WRAP_S
:
393 ti
->sClamp
= GR_TEXTURECLAMP_CLAMP
;
396 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
401 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
404 case GL_TEXTURE_WRAP_T
:
407 ti
->tClamp
= GR_TEXTURECLAMP_CLAMP
;
410 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
415 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
418 case GL_TEXTURE_BORDER_COLOR
:
421 case GL_TEXTURE_MIN_LOD
:
424 case GL_TEXTURE_MAX_LOD
:
427 case GL_TEXTURE_BASE_LEVEL
:
428 RevalidateTexture(ctx
, tObj
);
430 case GL_TEXTURE_MAX_LEVEL
:
431 RevalidateTexture(ctx
, tObj
);
441 * Called via glDeleteTextures to delete a texture object.
442 * Here, we delete the Glide data associated with the texture.
445 tdfxDeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
447 if (ctx
&& ctx
->DriverCtx
) {
448 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
449 tdfxTMFreeTexture(fxMesa
, tObj
);
450 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
451 /* Free mipmap images and the texture object itself */
452 _mesa_delete_texture_object(ctx
, tObj
);
458 * Return true if texture is resident, false otherwise.
461 tdfxIsTextureResident(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
463 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
464 return (GLboolean
) (ti
&& ti
->isInTM
);
470 * Convert a gl_color_table texture palette to Glide's format.
473 convertPalette(FxU32 data
[256], const struct gl_color_table
*table
)
475 const GLubyte
*tableUB
= (const GLubyte
*) table
->Table
;
476 GLint width
= table
->Size
;
480 ASSERT(table
->TableType
== GL_UNSIGNED_BYTE
);
482 switch (table
->Format
) {
484 for (i
= 0; i
< width
; i
++) {
489 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
493 for (i
= 0; i
< width
; i
++) {
498 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
502 for (i
= 0; i
< width
; i
++) {
505 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
508 case GL_LUMINANCE_ALPHA
:
509 for (i
= 0; i
< width
; i
++) {
510 r
= g
= b
= tableUB
[i
* 2 + 0];
511 a
= tableUB
[i
* 2 + 1];
512 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
516 for (i
= 0; i
< width
; i
++) {
517 r
= tableUB
[i
* 3 + 0];
518 g
= tableUB
[i
* 3 + 1];
519 b
= tableUB
[i
* 3 + 2];
521 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
525 for (i
= 0; i
< width
; i
++) {
526 r
= tableUB
[i
* 4 + 0];
527 g
= tableUB
[i
* 4 + 1];
528 b
= tableUB
[i
* 4 + 2];
529 a
= tableUB
[i
* 4 + 3];
530 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
539 tdfxUpdateTexturePalette(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
541 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
544 /* per-texture palette */
547 /* This might be a proxy texture. */
548 if (!tObj
->Palette
.Table
)
551 if (!tObj
->DriverData
)
552 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
553 ti
= TDFX_TEXTURE_DATA(tObj
);
555 convertPalette(ti
->palette
.data
, &tObj
->Palette
);
556 /*tdfxTexInvalidate(ctx, tObj);*/
559 /* global texture palette */
560 convertPalette(fxMesa
->glbPalette
.data
, &ctx
->Texture
.Palette
);
562 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX too heavy-handed */
566 /**********************************************************************/
567 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
568 /**********************************************************************/
571 static FxBool TexusFatalError
= FXFALSE
;
572 static FxBool TexusError
= FXFALSE
;
574 #define TX_DITHER_NONE 0x00000000
577 fxTexusError(const char *string
, FxBool fatal
)
579 _mesa_problem(NULL
, string
);
581 * Just propagate the fatal value up.
584 TexusFatalError
= fatal
;
589 static const struct gl_texture_format
*
590 tdfxChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
591 GLenum srcFormat
, GLenum srcType
)
593 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
594 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
596 switch (internalFormat
) {
602 return &_mesa_texformat_a8
;
609 return &_mesa_texformat_l8
;
611 case GL_LUMINANCE_ALPHA
:
612 case GL_LUMINANCE4_ALPHA4
:
613 case GL_LUMINANCE6_ALPHA2
:
614 case GL_LUMINANCE8_ALPHA8
:
615 case GL_LUMINANCE12_ALPHA4
:
616 case GL_LUMINANCE12_ALPHA12
:
617 case GL_LUMINANCE16_ALPHA16
:
618 return &_mesa_texformat_al88
;
624 return &_mesa_texformat_i8
;
628 return &_mesa_texformat_rgb565
;
635 return (allow32bpt
) ? &_mesa_texformat_argb8888
636 : &_mesa_texformat_rgb565
;
640 return &_mesa_texformat_argb4444
;
647 return allow32bpt
? &_mesa_texformat_argb8888
648 : &_mesa_texformat_argb4444
;
650 return &_mesa_texformat_argb1555
;
652 case GL_COLOR_INDEX1_EXT
:
653 case GL_COLOR_INDEX2_EXT
:
654 case GL_COLOR_INDEX4_EXT
:
655 case GL_COLOR_INDEX8_EXT
:
656 case GL_COLOR_INDEX12_EXT
:
657 case GL_COLOR_INDEX16_EXT
:
658 return &_mesa_texformat_ci8
;
660 _mesa_problem(ctx
, "unexpected format in tdfxChooseTextureFormat");
667 * Return the Glide format for the given mesa texture format.
669 static GrTextureFormat_t
670 fxGlideFormat(GLint mesaFormat
)
672 switch (mesaFormat
) {
674 return GR_TEXFMT_ALPHA_8
;
676 return GR_TEXFMT_ALPHA_8
;
678 return GR_TEXFMT_INTENSITY_8
;
679 case MESA_FORMAT_CI8
:
680 return GR_TEXFMT_P_8
;
681 case MESA_FORMAT_AL88
:
682 return GR_TEXFMT_ALPHA_INTENSITY_88
;
683 case MESA_FORMAT_RGB565
:
684 return GR_TEXFMT_RGB_565
;
685 case MESA_FORMAT_ARGB4444
:
686 return GR_TEXFMT_ARGB_4444
;
687 case MESA_FORMAT_ARGB1555
:
688 return GR_TEXFMT_ARGB_1555
;
689 case MESA_FORMAT_ARGB8888
:
690 return GR_TEXFMT_ARGB_8888
;
692 _mesa_problem(NULL
, "Unexpected format in fxGlideFormat");
698 /* Texel-fetch functions for software texturing and glGetTexImage().
699 * We should have been able to use some "standard" fetch functions (which
700 * may get defined in texutil.c) but we have to account for scaled texture
701 * images on tdfx hardware (the 8:1 aspect ratio limit).
702 * Hence, we need special functions here.
706 fetch_intensity8(const struct gl_texture_image
*texImage
,
707 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
709 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
710 const GLubyte
*texel
;
715 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
716 rgba
[RCOMP
] = *texel
;
717 rgba
[GCOMP
] = *texel
;
718 rgba
[BCOMP
] = *texel
;
719 rgba
[ACOMP
] = *texel
;
724 fetch_luminance8(const struct gl_texture_image
*texImage
,
725 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
727 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
728 const GLubyte
*texel
;
733 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
734 rgba
[RCOMP
] = *texel
;
735 rgba
[GCOMP
] = *texel
;
736 rgba
[BCOMP
] = *texel
;
742 fetch_alpha8(const struct gl_texture_image
*texImage
,
743 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
745 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
746 const GLubyte
*texel
;
750 i
= i
* mml
->width
/ texImage
->Width
;
751 j
= j
* mml
->height
/ texImage
->Height
;
753 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
757 rgba
[ACOMP
] = *texel
;
762 fetch_index8(const struct gl_texture_image
*texImage
,
763 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
765 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
772 fetch_luminance8_alpha8(const struct gl_texture_image
*texImage
,
773 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
775 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
776 const GLubyte
*texel
;
781 texel
= ((GLubyte
*) texImage
->Data
) + (j
* mml
->width
+ i
) * 2;
782 rgba
[RCOMP
] = texel
[0];
783 rgba
[GCOMP
] = texel
[0];
784 rgba
[BCOMP
] = texel
[0];
785 rgba
[ACOMP
] = texel
[1];
790 fetch_r5g6b5(const struct gl_texture_image
*texImage
,
791 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
793 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
794 const GLushort
*texel
;
799 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
800 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
801 rgba
[GCOMP
] = (((*texel
) >> 5) & 0x3f) * 255 / 63;
802 rgba
[BCOMP
] = (((*texel
) >> 0) & 0x1f) * 255 / 31;
808 fetch_r4g4b4a4(const struct gl_texture_image
*texImage
,
809 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
811 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
812 const GLushort
*texel
;
817 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
818 rgba
[RCOMP
] = (((*texel
) >> 12) & 0xf) * 255 / 15;
819 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xf) * 255 / 15;
820 rgba
[BCOMP
] = (((*texel
) >> 4) & 0xf) * 255 / 15;
821 rgba
[ACOMP
] = (((*texel
) >> 0) & 0xf) * 255 / 15;
826 fetch_r5g5b5a1(const struct gl_texture_image
*texImage
,
827 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
829 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
830 const GLushort
*texel
;
835 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
836 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
837 rgba
[GCOMP
] = (((*texel
) >> 6) & 0x1f) * 255 / 31;
838 rgba
[BCOMP
] = (((*texel
) >> 1) & 0x1f) * 255 / 31;
839 rgba
[ACOMP
] = (((*texel
) >> 0) & 0x01) * 255;
844 fetch_a8r8g8b8(const struct gl_texture_image
*texImage
,
845 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
847 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
853 texel
= ((GLuint
*) texImage
->Data
) + j
* mml
->width
+ i
;
854 rgba
[RCOMP
] = (((*texel
) >> 16) & 0xff);
855 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xff);
856 rgba
[BCOMP
] = (((*texel
) ) & 0xff);
857 rgba
[ACOMP
] = (((*texel
) >> 24) & 0xff);
861 static FetchTexelFuncC
862 fxFetchFunction(GLint mesaFormat
)
864 switch (mesaFormat
) {
866 return fetch_intensity8
;
870 return fetch_luminance8
;
871 case MESA_FORMAT_CI8
:
873 case MESA_FORMAT_AL88
:
874 return fetch_luminance8_alpha8
;
875 case MESA_FORMAT_RGB565
:
877 case MESA_FORMAT_ARGB4444
:
878 return fetch_r4g4b4a4
;
879 case MESA_FORMAT_ARGB1555
:
880 return fetch_r5g5b5a1
;
881 case MESA_FORMAT_ARGB8888
:
882 return fetch_a8r8g8b8
;
884 _mesa_problem(NULL
, "Unexpected format in fxFetchFunction");
885 printf("%d\n", mesaFormat
);
892 tdfxTexImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
893 GLint internalFormat
, GLint width
, GLint height
, GLint border
,
894 GLenum format
, GLenum type
, const GLvoid
*pixels
,
895 const struct gl_pixelstore_attrib
*packing
,
896 struct gl_texture_object
*texObj
,
897 struct gl_texture_image
*texImage
)
899 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
901 tdfxMipMapLevel
*mml
;
905 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
906 texObj->Name, texImage->IntFormat, format, type,
907 texImage->Width, texImage->Height);
910 ti
= TDFX_TEXTURE_DATA(texObj
);
912 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
913 if (!texObj
->DriverData
) {
914 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
917 ti
= TDFX_TEXTURE_DATA(texObj
);
921 mml
= TDFX_TEXIMAGE_DATA(texImage
);
923 texImage
->DriverData
= CALLOC(sizeof(tdfxMipMapLevel
));
924 if (!texImage
->DriverData
) {
925 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
928 mml
= TDFX_TEXIMAGE_DATA(texImage
);
931 /* Determine width and height scale factors for texture.
932 * Remember, Glide is limited to 8:1 aspect ratios.
935 texImage
->Width
, texImage
->Height
,
936 NULL
, /* lod level */
937 NULL
, /* aspect ratio */
938 NULL
, NULL
, /* sscale, tscale */
939 &mml
->wScale
, &mml
->hScale
);
942 mml
->width
= width
* mml
->wScale
;
943 mml
->height
= height
* mml
->hScale
;
946 /* choose the texture format */
947 assert(ctx
->Driver
.ChooseTextureFormat
);
948 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
949 internalFormat
, format
, type
);
950 assert(texImage
->TexFormat
);
951 mml
->glideFormat
= fxGlideFormat(texImage
->TexFormat
->MesaFormat
);
952 ti
->info
.format
= mml
->glideFormat
;
953 texImage
->FetchTexelc
= fxFetchFunction(texImage
->TexFormat
->MesaFormat
);
954 texelBytes
= texImage
->TexFormat
->TexelBytes
;
956 if (mml
->width
!= width
|| mml
->height
!= height
) {
957 /* rescale the image to overcome 1:8 aspect limitation */
959 /* allocate temporary image */
960 tempImage
= MALLOC(width
* height
* texelBytes
);
962 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
965 /* allocate texture memory */
966 assert(!texImage
->Data
);
967 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
968 if (!texImage
->Data
) {
969 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
974 /* unpack image, apply transfer ops and store in tempImage */
975 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
976 texImage
->TexFormat
, tempImage
,
977 0, 0, 0, /* dstX/Y/Zoffset */
978 width
* texelBytes
, /* dstRowStride */
979 0, /* dstImageStride */
981 format
, type
, pixels
, packing
);
983 _mesa_rescale_teximage2d(texelBytes
,
984 mml
->width
* texelBytes
, /* dst stride */
986 mml
->width
, mml
->height
,
987 tempImage
/*src*/, texImage
->Data
/*dst*/ );
992 /* no rescaling needed */
993 assert(!texImage
->Data
);
994 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
995 if (!texImage
->Data
) {
996 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
999 /* unpack image, apply transfer ops and store in texImage->Data */
1001 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1002 texImage
->TexFormat
, texImage
->Data
,
1003 0, 0, 0, /* dstX/Y/Zoffset */
1004 width
* texelBytes
, /* dstRowStride */
1005 0, /* dstImageStride */
1007 format
, type
, pixels
, packing
);
1011 RevalidateTexture(ctx
, texObj
);
1013 ti
->reloadImages
= GL_TRUE
;
1014 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1019 tdfxTexSubImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
1020 GLint xoffset
, GLint yoffset
,
1021 GLsizei width
, GLsizei height
,
1022 GLenum format
, GLenum type
,
1023 const GLvoid
*pixels
,
1024 const struct gl_pixelstore_attrib
*packing
,
1025 struct gl_texture_object
*texObj
,
1026 struct gl_texture_image
*texImage
)
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 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1061 texImage
->TexFormat
, texImage
->Data
,
1062 0, 0, 0, /* dstX/Y/Zoffset */
1063 width
* texelBytes
, /* dstRowStride */
1064 0, /* dstImageStride */
1066 format
, type
, pixels
, packing
);
1069 scaledImage
= MALLOC(newWidth
* newHeight
* texelBytes
);
1071 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1076 /* compute address of dest subimage within the overal tex image */
1077 destAddr
= (GLubyte
*) texImage
->Data
1078 + (yoffset
* mml
->hScale
* mml
->width
1079 + xoffset
* mml
->wScale
) * texelBytes
;
1081 _mesa_rescale_teximage2d(texelBytes
,
1082 mml
->width
* texelBytes
, /* dst stride */
1084 newWidth
, newHeight
,
1085 tempImage
, destAddr
);
1091 /* no rescaling needed */
1092 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->Format
,
1093 texImage
->TexFormat
, texImage
->Data
,
1094 xoffset
, yoffset
, 0,
1095 mml
->width
* texelBytes
, /* dstRowStride */
1096 0, /* dstImageStride */
1098 format
, type
, pixels
, packing
);
1101 ti
->reloadImages
= GL_TRUE
; /* signal the image needs to be reloaded */
1102 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX this might be a bit much */
1107 /**********************************************************************/
1108 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1109 /**********************************************************************/
1113 tdfxCompressedTexImage2D( GLcontext
*ctx
, GLenum target
,
1114 GLint level
, GLsizei imageSize
,
1116 struct gl_texture_object
*texObj
,
1117 struct gl_texture_image
*texImage
,
1118 GLboolean
*retainInternalCopy
)
1120 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1121 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
1122 GrTextureFormat_t gldformat
;
1124 tdfxMipMapLevel
*mml
;
1125 GLint dstWidth
, dstHeight
, wScale
, hScale
, texelSize
;
1126 MesaIntTexFormat intFormat
;
1127 GLboolean isCompressedFormat
;
1130 if (target
!= GL_TEXTURE_2D
|| texImage
->Border
> 0)
1133 ti
= TDFX_TEXTURE_DATA(texObj
);
1135 mml
= &ti
->mipmapLevel
[level
];
1137 isCompressedFormat
= tdfxDDIsCompressedGlideFormatMacro(texImage
->IntFormat
);
1138 if (!isCompressedFormat
) {
1139 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(format)");
1142 /* Determine the apporpriate GL internal texel format, Mesa internal
1143 * texel format, and texelSize (bytes) given the user's internal
1144 * texture format hint.
1146 tdfxTexGetFormat(texImage
->IntFormat
, allow32bpt
,
1147 &gldformat
, &intFormat
, &texelSize
);
1149 /* Determine width and height scale factors for texture.
1150 * Remember, Glide is limited to 8:1 aspect ratios.
1153 texImage
->Width
, texImage
->Height
,
1154 NULL
, /* lod level */
1155 NULL
, /* aspect ratio */
1156 NULL
, NULL
, /* sscale, tscale */
1158 dstWidth
= texImage
->Width
* wScale
;
1159 dstHeight
= texImage
->Height
* hScale
;
1161 _mesa_set_teximage_component_sizes(intFormat
, texImage
);
1163 texSize
= tdfxDDCompressedImageSize(ctx
,
1164 texImage
->IntFormat
,
1169 if (texSize
!= imageSize
) {
1170 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage2D(texSize)");
1174 /* allocate new storage for texture image, if needed */
1175 if (!mml
->data
|| mml
->glideFormat
!= gldformat
||
1176 mml
->width
!= dstWidth
|| mml
->height
!= dstHeight
||
1177 texSize
!= mml
->dataSize
) {
1181 mml
->data
= MALLOC(texSize
);
1185 mml
->texelSize
= texelSize
;
1186 mml
->glideFormat
= gldformat
;
1187 mml
->width
= dstWidth
;
1188 mml
->height
= dstHeight
;
1189 tdfxTMMoveOutTM(fxMesa
, texObj
);
1190 /*tdfxTexInvalidate(ctx, texObj);*/
1193 /* save the texture data */
1194 MEMCPY(mml
->data
, data
, imageSize
);
1196 RevalidateTexture(ctx
, texObj
);
1198 ti
->reloadImages
= GL_TRUE
;
1199 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1201 *retainInternalCopy
= GL_FALSE
;
1206 tdfxCompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
,
1207 GLint level
, GLint xoffset
,
1208 GLint yoffset
, GLsizei width
,
1209 GLint height
, GLenum format
,
1210 GLsizei imageSize
, const GLvoid
*data
,
1211 struct gl_texture_object
*texObj
,
1212 struct gl_texture_image
*texImage
)
1214 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1216 tdfxMipMapLevel
*mml
;
1219 * We punt if we are not replacing the entire image. This
1220 * is allowed by the spec.
1222 if ((xoffset
!= 0) && (yoffset
!= 0)
1223 && (width
!= texImage
->Width
)
1224 && (height
!= texImage
->Height
)) {
1228 ti
= TDFX_TEXTURE_DATA(texObj
);
1229 mml
= &ti
->mipmapLevel
[level
];
1230 if (imageSize
!= mml
->dataSize
) {
1233 MEMCPY(data
, mml
->data
, imageSize
);
1235 ti
->reloadImages
= GL_TRUE
;
1236 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1246 PrintTexture(int w
, int h
, int c
, const GLubyte
* data
)
1249 for (i
= 0; i
< h
; i
++) {
1250 for (j
= 0; j
< w
; j
++) {
1252 printf("%02x %02x ", data
[0], data
[1]);
1254 printf("%02x %02x %02x ", data
[0], data
[1], data
[2]);
1264 tdfxTestProxyTexImage(GLcontext
*ctx
, GLenum target
,
1265 GLint level
, GLint internalFormat
,
1266 GLenum format
, GLenum type
,
1267 GLint width
, GLint height
,
1268 GLint depth
, GLint border
)
1270 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1271 struct gl_shared_state
*mesaShared
= fxMesa
->glCtx
->Shared
;
1272 struct tdfxSharedState
*shared
= (struct tdfxSharedState
*) mesaShared
->DriverData
;
1275 case GL_PROXY_TEXTURE_1D
:
1276 return GL_TRUE
; /* software rendering */
1277 case GL_PROXY_TEXTURE_2D
:
1279 struct gl_texture_object
*tObj
;
1283 tObj
= ctx
->Texture
.Proxy2D
;
1284 if (!tObj
->DriverData
)
1285 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1286 ti
= TDFX_TEXTURE_DATA(tObj
);
1289 /* assign the parameters to test against */
1290 tObj
->Image
[0][level
]->Width
= width
;
1291 tObj
->Image
[0][level
]->Height
= height
;
1292 tObj
->Image
[0][level
]->Border
= border
;
1294 tObj
->Image
[0][level
]->IntFormat
= internalFormat
;
1297 /* don't use mipmap levels > 0 */
1298 tObj
->MinFilter
= tObj
->MagFilter
= GL_NEAREST
;
1301 /* test with all mipmap levels */
1302 tObj
->MinFilter
= GL_LINEAR_MIPMAP_LINEAR
;
1303 tObj
->MagFilter
= GL_NEAREST
;
1305 RevalidateTexture(ctx
, tObj
);
1308 printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1309 printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1310 printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1311 printf("glide format 0x%x\n", ti->info.format);
1312 printf("data %p\n", ti->info.data);
1313 printf("lodblend %d\n", (int) ti->LODblend);
1316 /* determine where texture will reside */
1317 if (ti
->LODblend
&& !shared
->umaTexMemory
) {
1318 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1319 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1320 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1323 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1324 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1325 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1328 printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1330 if (memNeeded
> shared
->totalTexMem
[0])
1335 case GL_PROXY_TEXTURE_3D
:
1336 return GL_TRUE
; /* software rendering */
1338 return GL_TRUE
; /* never happens, silence compiler */
1345 * This is called from _mesa_GetCompressedTexImage. We just
1346 * copy out the compressed data.
1349 tdfxGetCompressedTexImage( GLcontext
*ctx
, GLenum target
,
1350 GLint lod
, void *image
,
1351 const struct gl_texture_object
*texObj
,
1352 struct gl_texture_image
*texImage
)
1355 tdfxMipMapLevel
*mml
;
1357 if (target
!= GL_TEXTURE_2D
)
1360 if (!texObj
->DriverData
)
1363 ti
= TDFX_TEXTURE_DATA(texObj
);
1365 mml
= &ti
->mipmapLevel
[lod
];
1367 MEMCPY(image
, mml
->data
, mml
->dataSize
);
1373 * Calculate a specific texture format given a generic
1377 tdfxSpecificCompressedTexFormat(GLcontext
*ctx
,
1378 GLint internalFormat
,
1379 GLint numDimensions
)
1381 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1383 if (numDimensions
!= 2) {
1384 return internalFormat
;
1387 * If we don't have pointers to the functions, then
1388 * we drop back to uncompressed format. The logic
1389 * in Mesa proper handles this for us.
1391 * This is just to ease the transition to a Glide with
1392 * the texus2 library.
1394 if (!fxMesa
->Glide
.txImgQuantize
|| !fxMesa
->Glide
.txImgDequantizeFXT1
) {
1395 return internalFormat
;
1397 switch (internalFormat
) {
1398 case GL_COMPRESSED_RGB_ARB
:
1399 return GL_COMPRESSED_RGB_FXT1_3DFX
;
1400 case GL_COMPRESSED_RGBA_ARB
:
1401 return GL_COMPRESSED_RGBA_FXT1_3DFX
;
1403 return internalFormat
;
1407 * Calculate a specific texture format given a generic
1411 tdfxBaseCompressedTexFormat(GLcontext
*ctx
,
1412 GLint internalFormat
)
1414 switch (internalFormat
) {
1415 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1417 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1424 * Tell us if an image is compressed. The real work is done
1425 * in a macro, but we need to have a function to create a
1429 tdfxDDIsCompressedFormat(GLcontext
*ctx
, GLint internalFormat
)
1431 return tdfxDDIsCompressedFormatMacro(internalFormat
);
1436 * Calculate the image size of a compressed texture.
1438 * The current compressed format, the FXT1 family, all
1439 * map 8x32 texel blocks into 128 bits.
1441 * We return 0 if we can't calculate the size.
1443 * Glide would report this out to us, but we don't have
1444 * exactly the right parameters.
1447 tdfxDDCompressedImageSize(GLcontext
*ctx
,
1449 GLuint numDimensions
,
1454 if (numDimensions
!= 2) {
1457 switch (intFormat
) {
1458 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1459 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1461 * Round height and width to multiples of 4 and 8,
1462 * divide the resulting product by 32 to get the number
1463 * of blocks, and multiply by 32 = 128/8 to get the.
1464 * number of bytes required. That is to say, just
1465 * return the product. Remember that we are returning
1466 * bytes, not texels, so we have shrunk the texture
1467 * by a factor of the texel size.
1469 width
= (width
+ 0x7) &~ 0x7;
1470 height
= (height
+ 0x3) &~ 0x3;
1471 return width
* height
;
1479 * Allocate a new texture object.
1480 * Called via ctx->Driver.NewTextureObject.
1481 * Note: this function will be called during context creation to
1482 * allocate the default texture objects.
1483 * Note: we could use containment here to 'derive' the driver-specific
1484 * texture object from the core mesa gl_texture_object. Not done at this time.
1486 static struct gl_texture_object
*
1487 tdfxNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1489 struct gl_texture_object
*obj
;
1490 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1495 void tdfxInitTextureFuncs( struct dd_function_table
*functions
)
1497 functions
->BindTexture
= tdfxBindTexture
;
1498 functions
->NewTextureObject
= tdfxNewTextureObject
;
1499 functions
->DeleteTexture
= tdfxDeleteTexture
;
1500 functions
->TexEnv
= tdfxTexEnv
;
1501 functions
->TexParameter
= tdfxTexParameter
;
1502 functions
->ChooseTextureFormat
= tdfxChooseTextureFormat
;
1503 functions
->TexImage2D
= tdfxTexImage2D
;
1504 functions
->TexSubImage2D
= tdfxTexSubImage2D
;
1505 functions
->IsTextureResident
= tdfxIsTextureResident
;
1506 functions
->UpdateTexturePalette
= tdfxUpdateTexturePalette
;