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"
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
[minl
]) {
174 maxl
= MIN2(tObj
->MaxLevel
, tObj
->Image
[minl
]->MaxLog2
);
176 /* compute largeLodLog2, aspect ratio and texcoord scale factors */
177 tdfxTexGetInfo(ctx
, tObj
->Image
[minl
]->Width
, tObj
->Image
[minl
]->Height
,
178 &ti
->info
.largeLodLog2
,
179 &ti
->info
.aspectRatioLog2
,
180 &(ti
->sScale
), &(ti
->tScale
), NULL
, NULL
);
183 if (tObj
->Image
[maxl
] && (tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
184 /* mipmapping: need to compute smallLodLog2 */
185 tdfxTexGetInfo(ctx
, tObj
->Image
[maxl
]->Width
,
186 tObj
->Image
[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.
237 tdfxDDBindTexture(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 tdfxDDTexEnv(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 tdfxDDTexParameter(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 tdfxDDDeleteTexture(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
;
457 * Return true if texture is resident, false otherwise.
460 tdfxDDIsTextureResident(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
462 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
463 return (GLboolean
) (ti
&& ti
->isInTM
);
469 * Convert a gl_color_table texture palette to Glide's format.
472 convertPalette(FxU32 data
[256], const struct gl_color_table
*table
)
474 const GLubyte
*tableUB
= (const GLubyte
*) table
->Table
;
475 GLint width
= table
->Size
;
479 ASSERT(table
->TableType
== GL_UNSIGNED_BYTE
);
481 switch (table
->Format
) {
483 for (i
= 0; i
< width
; i
++) {
488 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
492 for (i
= 0; i
< width
; i
++) {
497 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
501 for (i
= 0; i
< width
; i
++) {
504 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
507 case GL_LUMINANCE_ALPHA
:
508 for (i
= 0; i
< width
; i
++) {
509 r
= g
= b
= tableUB
[i
* 2 + 0];
510 a
= tableUB
[i
* 2 + 1];
511 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
515 for (i
= 0; i
< width
; i
++) {
516 r
= tableUB
[i
* 3 + 0];
517 g
= tableUB
[i
* 3 + 1];
518 b
= tableUB
[i
* 3 + 2];
520 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
524 for (i
= 0; i
< width
; i
++) {
525 r
= tableUB
[i
* 4 + 0];
526 g
= tableUB
[i
* 4 + 1];
527 b
= tableUB
[i
* 4 + 2];
528 a
= tableUB
[i
* 4 + 3];
529 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
538 tdfxDDTexturePalette(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
540 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
543 /* per-texture palette */
546 /* This might be a proxy texture. */
547 if (!tObj
->Palette
.Table
)
550 if (!tObj
->DriverData
)
551 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
552 ti
= TDFX_TEXTURE_DATA(tObj
);
553 convertPalette(ti
->palette
.data
, &tObj
->Palette
);
554 /*tdfxTexInvalidate(ctx, tObj);*/
557 /* global texture palette */
558 convertPalette(fxMesa
->glbPalette
.data
, &ctx
->Texture
.Palette
);
560 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX too heavy-handed */
564 /**********************************************************************/
565 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
566 /**********************************************************************/
569 static FxBool TexusFatalError
= FXFALSE
;
570 static FxBool TexusError
= FXFALSE
;
572 #define TX_DITHER_NONE 0x00000000
575 fxTexusError(const char *string
, FxBool fatal
)
577 _mesa_problem(NULL
, string
);
579 * Just propagate the fatal value up.
582 TexusFatalError
= fatal
;
587 const struct gl_texture_format
*
588 tdfxDDChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
589 GLenum srcFormat
, GLenum srcType
)
591 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
592 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
594 switch (internalFormat
) {
600 return &_mesa_texformat_a8
;
607 return &_mesa_texformat_l8
;
609 case GL_LUMINANCE_ALPHA
:
610 case GL_LUMINANCE4_ALPHA4
:
611 case GL_LUMINANCE6_ALPHA2
:
612 case GL_LUMINANCE8_ALPHA8
:
613 case GL_LUMINANCE12_ALPHA4
:
614 case GL_LUMINANCE12_ALPHA12
:
615 case GL_LUMINANCE16_ALPHA16
:
616 return &_mesa_texformat_al88
;
622 return &_mesa_texformat_i8
;
626 return &_mesa_texformat_rgb565
;
633 return (allow32bpt
) ? &_mesa_texformat_argb8888
634 : &_mesa_texformat_rgb565
;
638 return &_mesa_texformat_argb4444
;
645 return allow32bpt
? &_mesa_texformat_argb8888
646 : &_mesa_texformat_argb4444
;
648 return &_mesa_texformat_argb1555
;
650 case GL_COLOR_INDEX1_EXT
:
651 case GL_COLOR_INDEX2_EXT
:
652 case GL_COLOR_INDEX4_EXT
:
653 case GL_COLOR_INDEX8_EXT
:
654 case GL_COLOR_INDEX12_EXT
:
655 case GL_COLOR_INDEX16_EXT
:
656 return &_mesa_texformat_ci8
;
658 _mesa_problem(ctx
, "unexpected format in tdfxDDChooseTextureFormat");
665 * Return the Glide format for the given mesa texture format.
667 static GrTextureFormat_t
668 fxGlideFormat(GLint mesaFormat
)
670 switch (mesaFormat
) {
672 return GR_TEXFMT_ALPHA_8
;
674 return GR_TEXFMT_ALPHA_8
;
676 return GR_TEXFMT_INTENSITY_8
;
677 case MESA_FORMAT_CI8
:
678 return GR_TEXFMT_P_8
;
679 case MESA_FORMAT_AL88
:
680 return GR_TEXFMT_ALPHA_INTENSITY_88
;
681 case MESA_FORMAT_RGB565
:
682 return GR_TEXFMT_RGB_565
;
683 case MESA_FORMAT_ARGB4444
:
684 return GR_TEXFMT_ARGB_4444
;
685 case MESA_FORMAT_ARGB1555
:
686 return GR_TEXFMT_ARGB_1555
;
687 case MESA_FORMAT_ARGB8888
:
688 return GR_TEXFMT_ARGB_8888
;
690 _mesa_problem(NULL
, "Unexpected format in fxGlideFormat");
696 /* Texel-fetch functions for software texturing and glGetTexImage().
697 * We should have been able to use some "standard" fetch functions (which
698 * may get defined in texutil.c) but we have to account for scaled texture
699 * images on tdfx hardware (the 8:1 aspect ratio limit).
700 * Hence, we need special functions here.
704 fetch_intensity8(const struct gl_texture_image
*texImage
,
705 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
707 GLchan
*rgba
= (GLchan
*) texelOut
;
708 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
709 const GLubyte
*texel
;
714 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
715 rgba
[RCOMP
] = *texel
;
716 rgba
[GCOMP
] = *texel
;
717 rgba
[BCOMP
] = *texel
;
718 rgba
[ACOMP
] = *texel
;
723 fetch_luminance8(const struct gl_texture_image
*texImage
,
724 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
726 GLchan
*rgba
= (GLchan
*) texelOut
;
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
, GLvoid
* texelOut
)
745 GLchan
*rgba
= (GLchan
*) texelOut
;
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
, GLvoid
* texelOut
)
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
, GLvoid
* texelOut
)
776 GLchan
*rgba
= (GLchan
*) texelOut
;
777 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
778 const GLubyte
*texel
;
783 texel
= ((GLubyte
*) texImage
->Data
) + (j
* mml
->width
+ i
) * 2;
784 rgba
[RCOMP
] = texel
[0];
785 rgba
[GCOMP
] = texel
[0];
786 rgba
[BCOMP
] = texel
[0];
787 rgba
[ACOMP
] = texel
[1];
792 fetch_r5g6b5(const struct gl_texture_image
*texImage
,
793 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
795 GLchan
*rgba
= (GLchan
*) texelOut
;
796 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
797 const GLushort
*texel
;
802 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
803 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
804 rgba
[GCOMP
] = (((*texel
) >> 5) & 0x3f) * 255 / 63;
805 rgba
[BCOMP
] = (((*texel
) >> 0) & 0x1f) * 255 / 31;
811 fetch_r4g4b4a4(const struct gl_texture_image
*texImage
,
812 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
814 GLchan
*rgba
= (GLchan
*) texelOut
;
815 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
816 const GLushort
*texel
;
821 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
822 rgba
[RCOMP
] = (((*texel
) >> 12) & 0xf) * 255 / 15;
823 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xf) * 255 / 15;
824 rgba
[BCOMP
] = (((*texel
) >> 4) & 0xf) * 255 / 15;
825 rgba
[ACOMP
] = (((*texel
) >> 0) & 0xf) * 255 / 15;
830 fetch_r5g5b5a1(const struct gl_texture_image
*texImage
,
831 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
833 GLchan
*rgba
= (GLchan
*) texelOut
;
834 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
835 const GLushort
*texel
;
840 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
841 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
842 rgba
[GCOMP
] = (((*texel
) >> 6) & 0x1f) * 255 / 31;
843 rgba
[BCOMP
] = (((*texel
) >> 1) & 0x1f) * 255 / 31;
844 rgba
[ACOMP
] = (((*texel
) >> 0) & 0x01) * 255;
849 fetch_a8r8g8b8(const struct gl_texture_image
*texImage
,
850 GLint i
, GLint j
, GLint k
, GLvoid
* texelOut
)
852 GLchan
*rgba
= (GLchan
*) texelOut
;
853 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
859 texel
= ((GLuint
*) texImage
->Data
) + j
* mml
->width
+ i
;
860 rgba
[RCOMP
] = (((*texel
) >> 16) & 0xff);
861 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xff);
862 rgba
[BCOMP
] = (((*texel
) ) & 0xff);
863 rgba
[ACOMP
] = (((*texel
) >> 24) & 0xff);
867 static FetchTexelFunc
868 fxFetchFunction(GLint mesaFormat
)
870 switch (mesaFormat
) {
872 return fetch_intensity8
;
876 return fetch_luminance8
;
877 case MESA_FORMAT_CI8
:
879 case MESA_FORMAT_AL88
:
880 return fetch_luminance8_alpha8
;
881 case MESA_FORMAT_RGB565
:
883 case MESA_FORMAT_ARGB4444
:
884 return fetch_r4g4b4a4
;
885 case MESA_FORMAT_ARGB1555
:
886 return fetch_r5g5b5a1
;
887 case MESA_FORMAT_ARGB8888
:
888 return fetch_a8r8g8b8
;
890 _mesa_problem(NULL
, "Unexpected format in fxFetchFunction");
891 printf("%d\n", mesaFormat
);
898 tdfxDDTexImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
899 GLint internalFormat
, GLint width
, GLint height
, GLint border
,
900 GLenum format
, GLenum type
, const GLvoid
*pixels
,
901 const struct gl_pixelstore_attrib
*packing
,
902 struct gl_texture_object
*texObj
,
903 struct gl_texture_image
*texImage
)
905 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
907 tdfxMipMapLevel
*mml
;
911 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
912 texObj->Name, texImage->IntFormat, format, type,
913 texImage->Width, texImage->Height);
916 ti
= TDFX_TEXTURE_DATA(texObj
);
918 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
919 if (!texObj
->DriverData
) {
920 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
923 ti
= TDFX_TEXTURE_DATA(texObj
);
926 mml
= TDFX_TEXIMAGE_DATA(texImage
);
928 texImage
->DriverData
= CALLOC(sizeof(tdfxMipMapLevel
));
929 if (!texImage
->DriverData
) {
930 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
933 mml
= TDFX_TEXIMAGE_DATA(texImage
);
936 /* Determine width and height scale factors for texture.
937 * Remember, Glide is limited to 8:1 aspect ratios.
940 texImage
->Width
, texImage
->Height
,
941 NULL
, /* lod level */
942 NULL
, /* aspect ratio */
943 NULL
, NULL
, /* sscale, tscale */
944 &mml
->wScale
, &mml
->hScale
);
947 mml
->width
= width
* mml
->wScale
;
948 mml
->height
= height
* mml
->hScale
;
951 /* choose the texture format */
952 assert(ctx
->Driver
.ChooseTextureFormat
);
953 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
954 internalFormat
, format
, type
);
955 assert(texImage
->TexFormat
);
956 mml
->glideFormat
= fxGlideFormat(texImage
->TexFormat
->MesaFormat
);
957 ti
->info
.format
= mml
->glideFormat
;
958 texImage
->FetchTexel
= fxFetchFunction(texImage
->TexFormat
->MesaFormat
);
959 texelBytes
= texImage
->TexFormat
->TexelBytes
;
961 if (mml
->width
!= width
|| mml
->height
!= height
) {
962 /* rescale the image to overcome 1:8 aspect limitation */
964 tempImage
= MALLOC(width
* height
* texelBytes
);
966 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
969 /* unpack image, apply transfer ops and store in tempImage */
970 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
973 width
, height
, 1, 0, 0, 0,
975 0, /* dstImageStride */
976 format
, type
, pixels
, packing
);
977 assert(!texImage
->Data
);
978 texImage
->Data
= MESA_PBUFFER_ALLOC(mml
->width
* mml
->height
* texelBytes
);
979 if (!texImage
->Data
) {
980 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
984 _mesa_rescale_teximage2d(texelBytes
,
985 mml
->width
* texelBytes
, /* dst stride */
987 mml
->width
, mml
->height
,
988 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 */
1000 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,
1001 texImage
->TexFormat
, texImage
->Data
,
1002 width
, height
, 1, 0, 0, 0,
1003 texImage
->Width
* texelBytes
,
1004 0, /* dstImageStride */
1005 format
, type
, pixels
, packing
);
1008 RevalidateTexture(ctx
, texObj
);
1010 ti
->reloadImages
= GL_TRUE
;
1011 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1016 tdfxDDTexSubImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
1017 GLint xoffset
, GLint yoffset
,
1018 GLsizei width
, GLsizei height
,
1019 GLenum format
, GLenum type
,
1020 const GLvoid
*pixels
,
1021 const struct gl_pixelstore_attrib
*packing
,
1022 struct gl_texture_object
*texObj
,
1023 struct gl_texture_image
*texImage
)
1025 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1027 tdfxMipMapLevel
*mml
;
1030 if (!texObj
->DriverData
) {
1031 _mesa_problem(ctx
, "problem in fxDDTexSubImage2D");
1035 ti
= TDFX_TEXTURE_DATA(texObj
);
1037 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1040 assert(texImage
->Data
); /* must have an existing texture image! */
1041 assert(texImage
->Format
);
1043 texelBytes
= texImage
->TexFormat
->TexelBytes
;
1045 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
1046 /* need to rescale subimage to match mipmap level's rescale factors */
1047 const GLint newWidth
= width
* mml
->wScale
;
1048 const GLint newHeight
= height
* mml
->hScale
;
1049 GLvoid
*scaledImage
, *tempImage
;
1051 tempImage
= MALLOC(width
* height
* texelBytes
);
1053 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1057 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
,/* Tex int format */
1058 texImage
->TexFormat
, /* dest format */
1059 (GLubyte
*) tempImage
, /* dest */
1060 width
, height
, 1, /* subimage size */
1061 0, 0, 0, /* subimage pos */
1062 width
* texelBytes
, /* dest row stride */
1063 0, /* dst image stride */
1064 format
, type
, pixels
, packing
);
1067 scaledImage
= MALLOC(newWidth
* newHeight
* texelBytes
);
1069 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1074 /* compute address of dest subimage within the overal tex image */
1075 destAddr
= (GLubyte
*) texImage
->Data
1076 + (yoffset
* mml
->hScale
* mml
->width
1077 + xoffset
* mml
->wScale
) * texelBytes
;
1079 _mesa_rescale_teximage2d(texelBytes
,
1080 mml
->width
* texelBytes
, /* dst stride */
1082 newWidth
, newHeight
,
1083 tempImage
, destAddr
);
1089 /* no rescaling needed */
1090 _mesa_transfer_teximage(ctx
, 2, texImage
->Format
, /* Tex int format */
1091 texImage
->TexFormat
, /* dest format */
1092 (GLubyte
*) texImage
->Data
,/* dest */
1093 width
, height
, 1, /* subimage size */
1094 xoffset
, yoffset
, 0, /* subimage pos */
1095 mml
->width
* texelBytes
, /* dest row stride */
1096 0, /* dst image stride */
1097 format
, type
, pixels
, packing
);
1100 ti
->reloadImages
= GL_TRUE
; /* signal the image needs to be reloaded */
1101 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX this might be a bit much */
1106 /**********************************************************************/
1107 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1108 /**********************************************************************/
1112 tdfxDDCompressedTexImage2D( GLcontext
*ctx
, GLenum target
,
1113 GLint level
, GLsizei imageSize
,
1115 struct gl_texture_object
*texObj
,
1116 struct gl_texture_image
*texImage
,
1117 GLboolean
*retainInternalCopy
)
1119 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1120 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
1121 GrTextureFormat_t gldformat
;
1123 tdfxMipMapLevel
*mml
;
1124 GLint dstWidth
, dstHeight
, wScale
, hScale
, texelSize
;
1125 MesaIntTexFormat intFormat
;
1126 GLboolean isCompressedFormat
;
1129 if (target
!= GL_TEXTURE_2D
|| texImage
->Border
> 0)
1132 if (!texObj
->DriverData
)
1133 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1135 ti
= TDFX_TEXTURE_DATA(texObj
);
1136 mml
= &ti
->mipmapLevel
[level
];
1138 isCompressedFormat
= tdfxDDIsCompressedGlideFormatMacro(texImage
->IntFormat
);
1139 if (!isCompressedFormat
) {
1140 _mesa_error(ctx
, GL_INVALID_ENUM
, "glCompressedTexImage2D(format)");
1143 /* Determine the apporpriate GL internal texel format, Mesa internal
1144 * texel format, and texelSize (bytes) given the user's internal
1145 * texture format hint.
1147 tdfxTexGetFormat(texImage
->IntFormat
, allow32bpt
,
1148 &gldformat
, &intFormat
, &texelSize
);
1150 /* Determine width and height scale factors for texture.
1151 * Remember, Glide is limited to 8:1 aspect ratios.
1154 texImage
->Width
, texImage
->Height
,
1155 NULL
, /* lod level */
1156 NULL
, /* aspect ratio */
1157 NULL
, NULL
, /* sscale, tscale */
1159 dstWidth
= texImage
->Width
* wScale
;
1160 dstHeight
= texImage
->Height
* hScale
;
1162 _mesa_set_teximage_component_sizes(intFormat
, texImage
);
1164 texSize
= tdfxDDCompressedImageSize(ctx
,
1165 texImage
->IntFormat
,
1170 if (texSize
!= imageSize
) {
1171 _mesa_error(ctx
, GL_INVALID_VALUE
, "glCompressedTexImage2D(texSize)");
1175 /* allocate new storage for texture image, if needed */
1176 if (!mml
->data
|| mml
->glideFormat
!= gldformat
||
1177 mml
->width
!= dstWidth
|| mml
->height
!= dstHeight
||
1178 texSize
!= mml
->dataSize
) {
1182 mml
->data
= MALLOC(texSize
);
1186 mml
->texelSize
= texelSize
;
1187 mml
->glideFormat
= gldformat
;
1188 mml
->width
= dstWidth
;
1189 mml
->height
= dstHeight
;
1190 tdfxTMMoveOutTM(fxMesa
, texObj
);
1191 /*tdfxTexInvalidate(ctx, texObj);*/
1194 /* save the texture data */
1195 MEMCPY(mml
->data
, data
, imageSize
);
1197 RevalidateTexture(ctx
, texObj
);
1199 ti
->reloadImages
= GL_TRUE
;
1200 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1202 *retainInternalCopy
= GL_FALSE
;
1207 tdfxDDCompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
,
1208 GLint level
, GLint xoffset
,
1209 GLint yoffset
, GLsizei width
,
1210 GLint height
, GLenum format
,
1211 GLsizei imageSize
, const GLvoid
*data
,
1212 struct gl_texture_object
*texObj
,
1213 struct gl_texture_image
*texImage
)
1215 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1217 tdfxMipMapLevel
*mml
;
1220 * We punt if we are not replacing the entire image. This
1221 * is allowed by the spec.
1223 if ((xoffset
!= 0) && (yoffset
!= 0)
1224 && (width
!= texImage
->Width
)
1225 && (height
!= texImage
->Height
)) {
1229 ti
= TDFX_TEXTURE_DATA(texObj
);
1230 mml
= &ti
->mipmapLevel
[level
];
1231 if (imageSize
!= mml
->dataSize
) {
1234 MEMCPY(data
, mml
->data
, imageSize
);
1236 ti
->reloadImages
= GL_TRUE
;
1237 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1247 PrintTexture(int w
, int h
, int c
, const GLubyte
* data
)
1250 for (i
= 0; i
< h
; i
++) {
1251 for (j
= 0; j
< w
; j
++) {
1253 printf("%02x %02x ", data
[0], data
[1]);
1255 printf("%02x %02x %02x ", data
[0], data
[1], data
[2]);
1265 tdfxDDTestProxyTexImage(GLcontext
*ctx
, GLenum target
,
1266 GLint level
, GLint internalFormat
,
1267 GLenum format
, GLenum type
,
1268 GLint width
, GLint height
,
1269 GLint depth
, GLint border
)
1271 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1272 struct gl_shared_state
*mesaShared
= fxMesa
->glCtx
->Shared
;
1273 struct tdfxSharedState
*shared
= (struct tdfxSharedState
*) mesaShared
->DriverData
;
1276 case GL_PROXY_TEXTURE_1D
:
1277 return GL_TRUE
; /* software rendering */
1278 case GL_PROXY_TEXTURE_2D
:
1280 struct gl_texture_object
*tObj
;
1284 tObj
= ctx
->Texture
.Proxy2D
;
1285 if (!tObj
->DriverData
)
1286 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1287 ti
= TDFX_TEXTURE_DATA(tObj
);
1289 /* assign the parameters to test against */
1290 tObj
->Image
[level
]->Width
= width
;
1291 tObj
->Image
[level
]->Height
= height
;
1292 tObj
->Image
[level
]->Border
= border
;
1294 tObj
->Image
[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 tdfxDDGetCompressedTexImage( 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
);
1364 mml
= &ti
->mipmapLevel
[lod
];
1366 MEMCPY(image
, mml
->data
, mml
->dataSize
);
1372 * Calculate a specific texture format given a generic
1376 tdfxDDSpecificCompressedTexFormat(GLcontext
*ctx
,
1377 GLint internalFormat
,
1378 GLint numDimensions
)
1380 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1382 if (numDimensions
!= 2) {
1383 return internalFormat
;
1386 * If we don't have pointers to the functions, then
1387 * we drop back to uncompressed format. The logic
1388 * in Mesa proper handles this for us.
1390 * This is just to ease the transition to a Glide with
1391 * the texus2 library.
1393 if (!fxMesa
->Glide
.txImgQuantize
|| !fxMesa
->Glide
.txImgDequantizeFXT1
) {
1394 return internalFormat
;
1396 switch (internalFormat
) {
1397 case GL_COMPRESSED_RGB_ARB
:
1398 return GL_COMPRESSED_RGB_FXT1_3DFX
;
1399 case GL_COMPRESSED_RGBA_ARB
:
1400 return GL_COMPRESSED_RGBA_FXT1_3DFX
;
1402 return internalFormat
;
1406 * Calculate a specific texture format given a generic
1410 tdfxDDBaseCompressedTexFormat(GLcontext
*ctx
,
1411 GLint internalFormat
)
1413 switch (internalFormat
) {
1414 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1416 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1423 * Tell us if an image is compressed. The real work is done
1424 * in a macro, but we need to have a function to create a
1428 tdfxDDIsCompressedFormat(GLcontext
*ctx
, GLint internalFormat
)
1430 return tdfxDDIsCompressedFormatMacro(internalFormat
);
1435 * Calculate the image size of a compressed texture.
1437 * The current compressed format, the FXT1 family, all
1438 * map 8x32 texel blocks into 128 bits.
1440 * We return 0 if we can't calculate the size.
1442 * Glide would report this out to us, but we don't have
1443 * exactly the right parameters.
1446 tdfxDDCompressedImageSize(GLcontext
*ctx
,
1448 GLuint numDimensions
,
1453 if (numDimensions
!= 2) {
1456 switch (intFormat
) {
1457 case GL_COMPRESSED_RGB_FXT1_3DFX
:
1458 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
1460 * Round height and width to multiples of 4 and 8,
1461 * divide the resulting product by 32 to get the number
1462 * of blocks, and multiply by 32 = 128/8 to get the.
1463 * number of bytes required. That is to say, just
1464 * return the product. Remember that we are returning
1465 * bytes, not texels, so we have shrunk the texture
1466 * by a factor of the texel size.
1468 width
= (width
+ 0x7) &~ 0x7;
1469 height
= (height
+ 0x3) &~ 0x3;
1470 return width
* height
;