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 * Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
33 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
36 * Gareth Hughes <gareth@valinux.com>
37 * Brian Paul <brianp@valinux.com>
45 #include "texcompress.h"
46 #include "texformat.h"
50 #include "tdfx_context.h"
52 #include "tdfx_texman.h"
55 /* no borders! can't halve 1x1! (stride > width * comp) not allowed */
57 _mesa_halve2x2_teximage2d ( GLcontext
*ctx
,
58 struct gl_texture_image
*texImage
,
60 GLint srcWidth
, GLint srcHeight
,
61 const GLvoid
*srcImage
, GLvoid
*dstImage
)
64 GLint dstWidth
= srcWidth
/ 2;
65 GLint dstHeight
= srcHeight
/ 2;
66 GLint srcRowStride
= srcWidth
* bytesPerPixel
;
67 GLubyte
*src
= (GLubyte
*)srcImage
;
68 GLubyte
*dst
= dstImage
;
69 GLuint dstImageOffsets
= 0;
76 if (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_RGB565
) {
77 _t
= GL_UNSIGNED_SHORT_5_6_5_REV
;
79 } else if (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_ARGB4444
) {
80 _t
= GL_UNSIGNED_SHORT_4_4_4_4_REV
;
82 } else if (texImage
->TexFormat
->MesaFormat
== MESA_FORMAT_ARGB1555
) {
83 _t
= GL_UNSIGNED_SHORT_1_5_5_5_REV
;
88 srcRowStride
= srcWidth
* bytesPerPixel
;
95 _s
= src
= MALLOC(srcRowStride
* srcHeight
);
96 _d
= dst
= MALLOC(dstWidth
* bytesPerPixel
* dstHeight
);
97 _mesa_texstore_rgba8888(ctx
, 2, GL_RGBA
,
98 &_mesa_texformat_rgba8888_rev
, src
,
99 0, 0, 0, /* dstX/Y/Zoffset */
100 srcRowStride
, /* dstRowStride */
102 srcWidth
, srcHeight
, 1,
103 texImage
->_BaseFormat
, _t
, srcImage
, &ctx
->DefaultPacking
);
106 if (srcHeight
== 1) {
107 for (i
= 0; i
< dstWidth
; i
++) {
108 for (k
= 0; k
< bytesPerPixel
; k
++) {
109 dst
[0] = (src
[0] + src
[bytesPerPixel
] + 1) / 2;
113 src
+= bytesPerPixel
;
115 } else if (srcWidth
== 1) {
116 for (j
= 0; j
< dstHeight
; j
++) {
117 for (k
= 0; k
< bytesPerPixel
; k
++) {
118 dst
[0] = (src
[0] + src
[srcRowStride
] + 1) / 2;
125 for (j
= 0; j
< dstHeight
; j
++) {
126 for (i
= 0; i
< dstWidth
; i
++) {
127 for (k
= 0; k
< bytesPerPixel
; k
++) {
131 src
[srcRowStride
+ bytesPerPixel
] + 2) / 4;
135 src
+= bytesPerPixel
;
144 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
145 texImage
->TexFormat
, dstImage
,
146 0, 0, 0, /* dstX/Y/Zoffset */
149 dstWidth
, dstHeight
, 1,
150 GL_BGRA
, CHAN_TYPE
, dst
, &ctx
->DefaultPacking
);
181 * Compute various texture image parameters.
182 * Input: w, h - source texture width and height
183 * Output: lodlevel - Glide lod level token for the larger texture dimension
184 * aspectratio - Glide aspect ratio token
185 * sscale - S scale factor used during triangle setup
186 * tscale - T scale factor used during triangle setup
187 * wscale - OpenGL -> Glide image width scale factor
188 * hscale - OpenGL -> Glide image height scale factor
191 * w h lodlevel aspectRatio
192 * 128 128 GR_LOD_LOG2_128 (=7) GR_ASPECT_LOG2_1x1 (=0)
193 * 64 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x1 (=0)
194 * 64 32 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_2x1 (=1)
195 * 32 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x2 (=-1)
196 * 32 32 GR_LOD_LOG2_32 (=5) GR_ASPECT_LOG2_1x1 (=0)
199 tdfxTexGetInfo(const GLcontext
*ctx
, int w
, int h
,
200 GrLOD_t
*lodlevel
, GrAspectRatio_t
*aspectratio
,
201 float *sscale
, float *tscale
,
202 int *wscale
, int *hscale
)
204 int logw
, logh
, ar
, lod
, ws
, hs
;
212 ar
= logw
- logh
; /* aspect ratio = difference in log dimensions */
216 /* Hardware only allows a maximum aspect ratio of 8x1, so handle
217 |ar| > 3 by scaling the image and using an 8x1 aspect ratio */
221 if (ar
<= GR_ASPECT_LOG2_8x1
) {
225 /* have to stretch image height */
228 ar
= GR_ASPECT_LOG2_8x1
;
234 if (ar
>= GR_ASPECT_LOG2_1x8
) {
238 /* have to stretch image width */
241 ar
= GR_ASPECT_LOG2_1x8
;
246 *lodlevel
= (GrLOD_t
) lod
;
248 *aspectratio
= (GrAspectRatio_t
) ar
;
261 * We need to call this when a texture object's minification filter
262 * or texture image sizes change.
264 static void RevalidateTexture(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
266 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
272 minl
= maxl
= tObj
->BaseLevel
;
274 if (tObj
->Image
[0][minl
]) {
275 maxl
= MIN2(tObj
->MaxLevel
, tObj
->Image
[0][minl
]->MaxLog2
);
277 /* compute largeLodLog2, aspect ratio and texcoord scale factors */
278 tdfxTexGetInfo(ctx
, tObj
->Image
[0][minl
]->Width
, tObj
->Image
[0][minl
]->Height
,
279 &ti
->info
.largeLodLog2
,
280 &ti
->info
.aspectRatioLog2
,
281 &(ti
->sScale
), &(ti
->tScale
), NULL
, NULL
);
284 if (tObj
->Image
[0][maxl
] && (tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
285 /* mipmapping: need to compute smallLodLog2 */
286 tdfxTexGetInfo(ctx
, tObj
->Image
[0][maxl
]->Width
,
287 tObj
->Image
[0][maxl
]->Height
,
288 &ti
->info
.smallLodLog2
, NULL
,
289 NULL
, NULL
, NULL
, NULL
);
292 /* not mipmapping: smallLodLog2 = largeLodLog2 */
293 ti
->info
.smallLodLog2
= ti
->info
.largeLodLog2
;
299 ti
->info
.data
= NULL
;
301 /* this is necessary because of fxDDCompressedTexImage2D */
303 struct gl_texture_image
*texImage
= tObj
->Image
[0][minl
];
304 tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
305 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
306 ti
->sScale
/= mml
->wScale
;
307 ti
->tScale
/= mml
->hScale
;
314 fxAllocTexObjData(tdfxContextPtr fxMesa
)
318 if (!(ti
= CALLOC(sizeof(tdfxTexInfo
)))) {
319 _mesa_problem(NULL
, "tdfx driver: out of memory");
323 ti
->isInTM
= GL_FALSE
;
325 ti
->whichTMU
= TDFX_TMU_NONE
;
327 ti
->tm
[TDFX_TMU0
] = NULL
;
328 ti
->tm
[TDFX_TMU1
] = NULL
;
330 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
331 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
333 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
334 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
336 ti
->mmMode
= GR_MIPMAP_NEAREST
;
337 ti
->LODblend
= FXFALSE
;
344 * Called via glBindTexture.
347 tdfxBindTexture(GLcontext
* ctx
, GLenum target
,
348 struct gl_texture_object
*tObj
)
350 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
353 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
354 fprintf(stderr
, "fxmesa: fxDDTexBind(%d,%p)\n", tObj
->Name
,
358 if ((target
!= GL_TEXTURE_1D
) && (target
!= GL_TEXTURE_2D
))
361 if (!tObj
->DriverData
) {
362 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
365 ti
= TDFX_TEXTURE_DATA(tObj
);
366 ti
->lastTimeUsed
= fxMesa
->texBindNumber
++;
368 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
373 * Called via glTexEnv.
376 tdfxTexEnv(GLcontext
* ctx
, GLenum target
, GLenum pname
,
377 const GLfloat
* param
)
379 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
381 if ( TDFX_DEBUG
& DEBUG_VERBOSE_API
) {
383 fprintf(stderr
, "fxmesa: texenv(%x,%x)\n", pname
,
386 fprintf(stderr
, "fxmesa: texenv(%x)\n", pname
);
389 /* XXX this is a bit of a hack to force the Glide texture
390 * state to be updated.
392 fxMesa
->TexState
.EnvMode
[ctx
->Texture
.CurrentUnit
] = 0;
394 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
399 * Called via glTexParameter.
402 tdfxTexParameter(GLcontext
* ctx
, GLenum target
,
403 struct gl_texture_object
*tObj
,
404 GLenum pname
, const GLfloat
* params
)
406 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
407 GLenum param
= (GLenum
) (GLint
) params
[0];
410 if (MESA_VERBOSE
& VERBOSE_DRIVER
) {
411 fprintf(stderr
, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj
->Name
,
412 tObj
->DriverData
, pname
, param
);
415 if ((target
!= GL_TEXTURE_1D
) && (target
!= GL_TEXTURE_2D
))
418 if (!tObj
->DriverData
)
419 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
421 ti
= TDFX_TEXTURE_DATA(tObj
);
424 case GL_TEXTURE_MIN_FILTER
:
427 ti
->mmMode
= GR_MIPMAP_DISABLE
;
428 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
429 ti
->LODblend
= FXFALSE
;
432 ti
->mmMode
= GR_MIPMAP_DISABLE
;
433 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
434 ti
->LODblend
= FXFALSE
;
436 case GL_NEAREST_MIPMAP_LINEAR
:
437 if (!fxMesa
->Glide
.HaveCombineExt
) {
438 if (fxMesa
->haveTwoTMUs
) {
439 ti
->mmMode
= GR_MIPMAP_NEAREST
;
440 ti
->LODblend
= FXTRUE
;
443 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
444 ti
->LODblend
= FXFALSE
;
446 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
449 /* XXX Voodoo3/Banshee mipmap blending seems to produce
450 * incorrectly filtered colors for the smallest mipmap levels.
451 * To work-around we fall-through here and use a different filter.
453 case GL_NEAREST_MIPMAP_NEAREST
:
454 ti
->mmMode
= GR_MIPMAP_NEAREST
;
455 ti
->minFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
456 ti
->LODblend
= FXFALSE
;
458 case GL_LINEAR_MIPMAP_LINEAR
:
459 if (!fxMesa
->Glide
.HaveCombineExt
) {
460 if (fxMesa
->haveTwoTMUs
) {
461 ti
->mmMode
= GR_MIPMAP_NEAREST
;
462 ti
->LODblend
= FXTRUE
;
465 ti
->mmMode
= GR_MIPMAP_NEAREST_DITHER
;
466 ti
->LODblend
= FXFALSE
;
468 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
471 /* XXX Voodoo3/Banshee mipmap blending seems to produce
472 * incorrectly filtered colors for the smallest mipmap levels.
473 * To work-around we fall-through here and use a different filter.
475 case GL_LINEAR_MIPMAP_NEAREST
:
476 ti
->mmMode
= GR_MIPMAP_NEAREST
;
477 ti
->minFilt
= GR_TEXTUREFILTER_BILINEAR
;
478 ti
->LODblend
= FXFALSE
;
483 ti
->reloadImages
= GL_TRUE
;
484 RevalidateTexture(ctx
, tObj
);
485 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
488 case GL_TEXTURE_MAG_FILTER
:
491 ti
->magFilt
= GR_TEXTUREFILTER_POINT_SAMPLED
;
494 ti
->magFilt
= GR_TEXTUREFILTER_BILINEAR
;
499 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
502 case GL_TEXTURE_WRAP_S
:
504 case GL_CLAMP_TO_BORDER
:
505 case GL_CLAMP_TO_EDGE
:
507 ti
->sClamp
= GR_TEXTURECLAMP_CLAMP
;
510 ti
->sClamp
= GR_TEXTURECLAMP_WRAP
;
512 case GL_MIRRORED_REPEAT
:
513 ti
->sClamp
= GR_TEXTURECLAMP_MIRROR_EXT
;
518 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
521 case GL_TEXTURE_WRAP_T
:
523 case GL_CLAMP_TO_BORDER
:
524 case GL_CLAMP_TO_EDGE
:
526 ti
->tClamp
= GR_TEXTURECLAMP_CLAMP
;
529 ti
->tClamp
= GR_TEXTURECLAMP_WRAP
;
531 case GL_MIRRORED_REPEAT
:
532 ti
->tClamp
= GR_TEXTURECLAMP_MIRROR_EXT
;
537 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
540 case GL_TEXTURE_BORDER_COLOR
:
543 case GL_TEXTURE_MIN_LOD
:
546 case GL_TEXTURE_MAX_LOD
:
549 case GL_TEXTURE_BASE_LEVEL
:
550 RevalidateTexture(ctx
, tObj
);
552 case GL_TEXTURE_MAX_LEVEL
:
553 RevalidateTexture(ctx
, tObj
);
563 * Called via glDeleteTextures to delete a texture object.
564 * Here, we delete the Glide data associated with the texture.
567 tdfxDeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
569 if (ctx
&& ctx
->DriverCtx
) {
570 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
571 tdfxTMFreeTexture(fxMesa
, tObj
);
572 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
573 /* Free mipmap images and the texture object itself */
574 _mesa_delete_texture_object(ctx
, tObj
);
580 * Return true if texture is resident, false otherwise.
583 tdfxIsTextureResident(GLcontext
*ctx
, struct gl_texture_object
*tObj
)
585 tdfxTexInfo
*ti
= TDFX_TEXTURE_DATA(tObj
);
586 return (GLboolean
) (ti
&& ti
->isInTM
);
592 * Convert a gl_color_table texture palette to Glide's format.
595 convertPalette(FxU32 data
[256], const struct gl_color_table
*table
)
597 const GLubyte
*tableUB
= table
->TableUB
;
598 GLint width
= table
->Size
;
602 switch (table
->_BaseFormat
) {
604 for (i
= 0; i
< width
; i
++) {
609 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
611 return GR_TEXTABLE_PALETTE_6666_EXT
;
613 for (i
= 0; i
< width
; i
++) {
618 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
620 return GR_TEXTABLE_PALETTE
;
622 for (i
= 0; i
< width
; i
++) {
625 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
627 return GR_TEXTABLE_PALETTE_6666_EXT
;
628 case GL_LUMINANCE_ALPHA
:
629 for (i
= 0; i
< width
; i
++) {
630 r
= g
= b
= tableUB
[i
* 2 + 0];
631 a
= tableUB
[i
* 2 + 1];
632 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
634 return GR_TEXTABLE_PALETTE_6666_EXT
;
636 for (i
= 0; i
< width
; i
++) {
637 r
= tableUB
[i
* 3 + 0];
638 g
= tableUB
[i
* 3 + 1];
639 b
= tableUB
[i
* 3 + 2];
641 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
643 return GR_TEXTABLE_PALETTE
;
645 for (i
= 0; i
< width
; i
++) {
646 r
= tableUB
[i
* 4 + 0];
647 g
= tableUB
[i
* 4 + 1];
648 b
= tableUB
[i
* 4 + 2];
649 a
= tableUB
[i
* 4 + 3];
650 data
[i
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
652 return GR_TEXTABLE_PALETTE_6666_EXT
;
654 /* XXX fixme: how can this happen? */
655 _mesa_error(NULL
, GL_INVALID_ENUM
, "convertPalette: table->Format == %s",
656 _mesa_lookup_enum_by_nr(table
->Format
));
657 return GR_TEXTABLE_PALETTE
;
664 tdfxUpdateTexturePalette(GLcontext
* ctx
, struct gl_texture_object
*tObj
)
666 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
669 /* per-texture palette */
672 /* This might be a proxy texture. */
673 if (!tObj
->Palette
.TableUB
)
676 if (!tObj
->DriverData
)
677 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
678 ti
= TDFX_TEXTURE_DATA(tObj
);
680 ti
->paltype
= convertPalette(ti
->palette
.data
, &tObj
->Palette
);
681 /*tdfxTexInvalidate(ctx, tObj);*/
684 /* global texture palette */
685 fxMesa
->TexPalette
.Type
= convertPalette(fxMesa
->glbPalette
.data
, &ctx
->Texture
.Palette
);
686 fxMesa
->TexPalette
.Data
= &(fxMesa
->glbPalette
.data
);
687 fxMesa
->dirty
|= TDFX_UPLOAD_TEXTURE_PALETTE
;
689 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX too heavy-handed */
693 /**********************************************************************/
694 /**** NEW TEXTURE IMAGE FUNCTIONS ****/
695 /**********************************************************************/
698 static FxBool TexusFatalError
= FXFALSE
;
699 static FxBool TexusError
= FXFALSE
;
701 #define TX_DITHER_NONE 0x00000000
704 fxTexusError(const char *string
, FxBool fatal
)
706 _mesa_problem(NULL
, string
);
708 * Just propagate the fatal value up.
711 TexusFatalError
= fatal
;
716 static const struct gl_texture_format
*
717 tdfxChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
718 GLenum srcFormat
, GLenum srcType
)
720 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
721 const GLboolean allow32bpt
= TDFX_IS_NAPALM(fxMesa
);
723 switch (internalFormat
) {
729 case GL_COMPRESSED_ALPHA
:
730 return &_mesa_texformat_a8
;
737 case GL_COMPRESSED_LUMINANCE
:
738 return &_mesa_texformat_l8
;
740 case GL_LUMINANCE_ALPHA
:
741 case GL_LUMINANCE4_ALPHA4
:
742 case GL_LUMINANCE6_ALPHA2
:
743 case GL_LUMINANCE8_ALPHA8
:
744 case GL_LUMINANCE12_ALPHA4
:
745 case GL_LUMINANCE12_ALPHA12
:
746 case GL_LUMINANCE16_ALPHA16
:
747 case GL_COMPRESSED_LUMINANCE_ALPHA
:
748 return &_mesa_texformat_al88
;
754 case GL_COMPRESSED_INTENSITY
:
755 return &_mesa_texformat_i8
;
759 return &_mesa_texformat_rgb565
;
760 case GL_COMPRESSED_RGB
:
761 /* intentional fall-through */
764 if ( srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
765 return &_mesa_texformat_rgb565
;
767 /* intentional fall through */
772 return (allow32bpt
) ? &_mesa_texformat_argb8888
773 : &_mesa_texformat_rgb565
;
776 return &_mesa_texformat_argb4444
;
777 case GL_COMPRESSED_RGBA
:
778 /* intentional fall-through */
781 if ( srcFormat
== GL_BGRA
) {
782 if ( srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
783 return &_mesa_texformat_argb8888
;
785 else if ( srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
786 return &_mesa_texformat_argb4444
;
788 else if ( srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
789 return &_mesa_texformat_argb1555
;
792 /* intentional fall through */
797 return allow32bpt
? &_mesa_texformat_argb8888
798 : &_mesa_texformat_argb4444
;
800 return &_mesa_texformat_argb1555
;
802 case GL_COLOR_INDEX1_EXT
:
803 case GL_COLOR_INDEX2_EXT
:
804 case GL_COLOR_INDEX4_EXT
:
805 case GL_COLOR_INDEX8_EXT
:
806 case GL_COLOR_INDEX12_EXT
:
807 case GL_COLOR_INDEX16_EXT
:
808 return &_mesa_texformat_ci8
;
809 /* GL_EXT_texture_compression_s3tc */
811 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
814 return &_mesa_texformat_rgb_dxt1
;
815 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
816 return &_mesa_texformat_rgba_dxt1
;
817 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
820 return &_mesa_texformat_rgba_dxt3
;
821 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
822 return &_mesa_texformat_rgba_dxt5
;
823 /* GL_3DFX_texture_compression_FXT1 */
824 case GL_COMPRESSED_RGB_FXT1_3DFX
:
825 return &_mesa_texformat_rgb_fxt1
;
826 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
827 return &_mesa_texformat_rgba_fxt1
;
829 _mesa_problem(ctx
, "unexpected format in tdfxChooseTextureFormat");
836 * Return the Glide format for the given mesa texture format.
838 static GrTextureFormat_t
839 fxGlideFormat(GLint mesaFormat
)
841 switch (mesaFormat
) {
843 return GR_TEXFMT_ALPHA_8
;
845 return GR_TEXFMT_ALPHA_8
;
847 return GR_TEXFMT_INTENSITY_8
;
848 case MESA_FORMAT_CI8
:
849 return GR_TEXFMT_P_8
;
850 case MESA_FORMAT_AL88
:
851 return GR_TEXFMT_ALPHA_INTENSITY_88
;
852 case MESA_FORMAT_RGB565
:
853 return GR_TEXFMT_RGB_565
;
854 case MESA_FORMAT_ARGB4444
:
855 return GR_TEXFMT_ARGB_4444
;
856 case MESA_FORMAT_ARGB1555
:
857 return GR_TEXFMT_ARGB_1555
;
858 case MESA_FORMAT_ARGB8888
:
859 return GR_TEXFMT_ARGB_8888
;
860 case MESA_FORMAT_RGB_FXT1
:
861 case MESA_FORMAT_RGBA_FXT1
:
862 return GR_TEXFMT_ARGB_CMP_FXT1
;
863 case MESA_FORMAT_RGB_DXT1
:
864 case MESA_FORMAT_RGBA_DXT1
:
865 return GR_TEXFMT_ARGB_CMP_DXT1
;
866 case MESA_FORMAT_RGBA_DXT3
:
867 return GR_TEXFMT_ARGB_CMP_DXT3
;
868 case MESA_FORMAT_RGBA_DXT5
:
869 return GR_TEXFMT_ARGB_CMP_DXT5
;
871 _mesa_problem(NULL
, "Unexpected format in fxGlideFormat");
877 /* Texel-fetch functions for software texturing and glGetTexImage().
878 * We should have been able to use some "standard" fetch functions (which
879 * may get defined in texutil.c) but we have to account for scaled texture
880 * images on tdfx hardware (the 8:1 aspect ratio limit).
881 * Hence, we need special functions here.
884 fxt1_decode_1 (const void *texture
, int width
,
885 int i
, int j
, unsigned char *rgba
);
888 fetch_intensity8(const struct gl_texture_image
*texImage
,
889 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
891 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
892 const GLubyte
*texel
;
897 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
898 rgba
[RCOMP
] = *texel
;
899 rgba
[GCOMP
] = *texel
;
900 rgba
[BCOMP
] = *texel
;
901 rgba
[ACOMP
] = *texel
;
906 fetch_luminance8(const struct gl_texture_image
*texImage
,
907 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
909 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
910 const GLubyte
*texel
;
915 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
916 rgba
[RCOMP
] = *texel
;
917 rgba
[GCOMP
] = *texel
;
918 rgba
[BCOMP
] = *texel
;
924 fetch_alpha8(const struct gl_texture_image
*texImage
,
925 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
927 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
928 const GLubyte
*texel
;
933 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
937 rgba
[ACOMP
] = *texel
;
942 fetch_index8(const struct gl_texture_image
*texImage
,
943 GLint i
, GLint j
, GLint k
, GLchan
* indexOut
)
945 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
946 const GLubyte
*texel
;
951 texel
= ((GLubyte
*) texImage
->Data
) + j
* mml
->width
+ i
;
957 fetch_luminance8_alpha8(const struct gl_texture_image
*texImage
,
958 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
960 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
961 const GLubyte
*texel
;
966 texel
= ((GLubyte
*) texImage
->Data
) + (j
* mml
->width
+ i
) * 2;
967 rgba
[RCOMP
] = texel
[0];
968 rgba
[GCOMP
] = texel
[0];
969 rgba
[BCOMP
] = texel
[0];
970 rgba
[ACOMP
] = texel
[1];
975 fetch_r5g6b5(const struct gl_texture_image
*texImage
,
976 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
978 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
979 const GLushort
*texel
;
984 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
985 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
986 rgba
[GCOMP
] = (((*texel
) >> 5) & 0x3f) * 255 / 63;
987 rgba
[BCOMP
] = (((*texel
) >> 0) & 0x1f) * 255 / 31;
993 fetch_r4g4b4a4(const struct gl_texture_image
*texImage
,
994 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
996 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
997 const GLushort
*texel
;
1000 j
= j
* mml
->hScale
;
1002 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
1003 rgba
[RCOMP
] = (((*texel
) >> 12) & 0xf) * 255 / 15;
1004 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xf) * 255 / 15;
1005 rgba
[BCOMP
] = (((*texel
) >> 4) & 0xf) * 255 / 15;
1006 rgba
[ACOMP
] = (((*texel
) >> 0) & 0xf) * 255 / 15;
1011 fetch_r5g5b5a1(const struct gl_texture_image
*texImage
,
1012 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
1014 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1015 const GLushort
*texel
;
1017 i
= i
* mml
->wScale
;
1018 j
= j
* mml
->hScale
;
1020 texel
= ((GLushort
*) texImage
->Data
) + j
* mml
->width
+ i
;
1021 rgba
[RCOMP
] = (((*texel
) >> 11) & 0x1f) * 255 / 31;
1022 rgba
[GCOMP
] = (((*texel
) >> 6) & 0x1f) * 255 / 31;
1023 rgba
[BCOMP
] = (((*texel
) >> 1) & 0x1f) * 255 / 31;
1024 rgba
[ACOMP
] = (((*texel
) >> 0) & 0x01) * 255;
1029 fetch_a8r8g8b8(const struct gl_texture_image
*texImage
,
1030 GLint i
, GLint j
, GLint k
, GLchan
* rgba
)
1032 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1033 const GLuint
*texel
;
1035 i
= i
* mml
->wScale
;
1036 j
= j
* mml
->hScale
;
1038 texel
= ((GLuint
*) texImage
->Data
) + j
* mml
->width
+ i
;
1039 rgba
[RCOMP
] = (((*texel
) >> 16) & 0xff);
1040 rgba
[GCOMP
] = (((*texel
) >> 8) & 0xff);
1041 rgba
[BCOMP
] = (((*texel
) ) & 0xff);
1042 rgba
[ACOMP
] = (((*texel
) >> 24) & 0xff);
1047 fetch_rgb_fxt1(const struct gl_texture_image
*texImage
,
1048 GLint i
, GLint j
, GLint k
, GLchan
*rgba
)
1050 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1052 i
= i
* mml
->wScale
;
1053 j
= j
* mml
->hScale
;
1055 fxt1_decode_1(texImage
->Data
, mml
->width
, i
, j
, rgba
);
1061 fetch_rgba_fxt1(const struct gl_texture_image
*texImage
,
1062 GLint i
, GLint j
, GLint k
, GLchan
*rgba
)
1064 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1066 i
= i
* mml
->wScale
;
1067 j
= j
* mml
->hScale
;
1069 fxt1_decode_1(texImage
->Data
, mml
->width
, i
, j
, rgba
);
1074 fetch_rgb_dxt1(const struct gl_texture_image
*texImage
,
1075 GLint i
, GLint j
, GLint k
, GLchan
*rgba
)
1077 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1079 i
= i
* mml
->wScale
;
1080 j
= j
* mml
->hScale
;
1082 _mesa_texformat_rgb_dxt1
.FetchTexel2D(texImage
, i
, j
, k
, rgba
);
1087 fetch_rgba_dxt1(const struct gl_texture_image
*texImage
,
1088 GLint i
, GLint j
, GLint k
, GLchan
*rgba
)
1090 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1092 i
= i
* mml
->wScale
;
1093 j
= j
* mml
->hScale
;
1095 _mesa_texformat_rgba_dxt1
.FetchTexel2D(texImage
, i
, j
, k
, rgba
);
1100 fetch_rgba_dxt3(const struct gl_texture_image
*texImage
,
1101 GLint i
, GLint j
, GLint k
, GLchan
*rgba
)
1103 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1105 i
= i
* mml
->wScale
;
1106 j
= j
* mml
->hScale
;
1108 _mesa_texformat_rgba_dxt3
.FetchTexel2D(texImage
, i
, j
, k
, rgba
);
1113 fetch_rgba_dxt5(const struct gl_texture_image
*texImage
,
1114 GLint i
, GLint j
, GLint k
, GLchan
*rgba
)
1116 const tdfxMipMapLevel
*mml
= TDFX_TEXIMAGE_DATA(texImage
);
1118 i
= i
* mml
->wScale
;
1119 j
= j
* mml
->hScale
;
1121 _mesa_texformat_rgba_dxt5
.FetchTexel2D(texImage
, i
, j
, k
, rgba
);
1125 static FetchTexelFuncC
1126 fxFetchFunction(GLint mesaFormat
)
1128 switch (mesaFormat
) {
1129 case MESA_FORMAT_I8
:
1130 return &fetch_intensity8
;
1131 case MESA_FORMAT_A8
:
1132 return &fetch_alpha8
;
1133 case MESA_FORMAT_L8
:
1134 return &fetch_luminance8
;
1135 case MESA_FORMAT_CI8
:
1136 return &fetch_index8
;
1137 case MESA_FORMAT_AL88
:
1138 return &fetch_luminance8_alpha8
;
1139 case MESA_FORMAT_RGB565
:
1140 return &fetch_r5g6b5
;
1141 case MESA_FORMAT_ARGB4444
:
1142 return &fetch_r4g4b4a4
;
1143 case MESA_FORMAT_ARGB1555
:
1144 return &fetch_r5g5b5a1
;
1145 case MESA_FORMAT_ARGB8888
:
1146 return &fetch_a8r8g8b8
;
1147 case MESA_FORMAT_RGB_FXT1
:
1148 return &fetch_rgb_fxt1
;
1149 case MESA_FORMAT_RGBA_FXT1
:
1150 return &fetch_rgba_fxt1
;
1151 case MESA_FORMAT_RGB_DXT1
:
1152 return &fetch_rgb_dxt1
;
1153 case MESA_FORMAT_RGBA_DXT1
:
1154 return &fetch_rgba_dxt1
;
1155 case MESA_FORMAT_RGBA_DXT3
:
1156 return &fetch_rgba_dxt3
;
1157 case MESA_FORMAT_RGBA_DXT5
:
1158 return &fetch_rgba_dxt5
;
1160 _mesa_problem(NULL
, "Unexpected format in fxFetchFunction");
1167 adjust2DRatio (GLcontext
*ctx
,
1168 GLint xoffset
, GLint yoffset
,
1169 GLint width
, GLint height
,
1170 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1171 const struct gl_pixelstore_attrib
*packing
,
1172 tdfxMipMapLevel
*mml
,
1173 struct gl_texture_image
*texImage
,
1177 const GLint newWidth
= width
* mml
->wScale
;
1178 const GLint newHeight
= height
* mml
->hScale
;
1180 GLuint dstImageOffsets
= 0;
1182 if (!texImage
->IsCompressed
) {
1184 tempImage
= MALLOC(width
* height
* texelBytes
);
1189 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
1190 texImage
->TexFormat
, tempImage
,
1191 0, 0, 0, /* dstX/Y/Zoffset */
1192 width
* texelBytes
, /* dstRowStride */
1195 format
, type
, pixels
, packing
);
1198 /* compute address of dest subimage within the overal tex image */
1199 destAddr
= (GLubyte
*) texImage
->Data
1200 + (yoffset
* mml
->hScale
* mml
->width
1201 + xoffset
* mml
->wScale
) * texelBytes
;
1203 _mesa_rescale_teximage2d(texelBytes
,
1205 dstRowStride
, /* dst stride */
1207 newWidth
, newHeight
,
1208 tempImage
, destAddr
);
1210 const GLint rawBytes
= 4;
1211 GLvoid
*rawImage
= MALLOC(width
* height
* rawBytes
);
1215 tempImage
= MALLOC(newWidth
* newHeight
* rawBytes
);
1220 /* unpack image, apply transfer ops and store in rawImage */
1221 _mesa_texstore_rgba8888(ctx
, 2, GL_RGBA
,
1222 &_mesa_texformat_rgba8888_rev
, rawImage
,
1223 0, 0, 0, /* dstX/Y/Zoffset */
1224 width
* rawBytes
, /* dstRowStride */
1227 format
, type
, pixels
, packing
);
1228 _mesa_rescale_teximage2d(rawBytes
,
1230 newWidth
* rawBytes
, /* dst stride */
1231 width
, height
, /* src */
1232 newWidth
, newHeight
, /* dst */
1233 rawImage
/*src*/, tempImage
/*dst*/ );
1234 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
1235 texImage
->TexFormat
, texImage
->Data
,
1236 xoffset
* mml
->wScale
, yoffset
* mml
->hScale
, 0, /* dstX/Y/Zoffset */
1239 newWidth
, newHeight
, 1,
1240 GL_RGBA
, CHAN_TYPE
, tempImage
, &ctx
->DefaultPacking
);
1251 tdfxTexImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
1252 GLint internalFormat
, GLint width
, GLint height
, GLint border
,
1253 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1254 const struct gl_pixelstore_attrib
*packing
,
1255 struct gl_texture_object
*texObj
,
1256 struct gl_texture_image
*texImage
)
1258 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1260 tdfxMipMapLevel
*mml
;
1261 GLint texelBytes
, dstRowStride
;
1265 printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
1266 texObj->Name, texImage->InternalFormat, format, type,
1267 texImage->Width, texImage->Height);
1270 ti
= TDFX_TEXTURE_DATA(texObj
);
1272 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1273 if (!texObj
->DriverData
) {
1274 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1277 ti
= TDFX_TEXTURE_DATA(texObj
);
1281 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1283 texImage
->DriverData
= CALLOC(sizeof(tdfxMipMapLevel
));
1284 if (!texImage
->DriverData
) {
1285 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1288 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1291 /* Determine width and height scale factors for texture.
1292 * Remember, Glide is limited to 8:1 aspect ratios.
1295 texImage
->Width
, texImage
->Height
,
1296 NULL
, /* lod level */
1297 NULL
, /* aspect ratio */
1298 NULL
, NULL
, /* sscale, tscale */
1299 &mml
->wScale
, &mml
->hScale
);
1301 /* rescaled size: */
1302 mml
->width
= width
* mml
->wScale
;
1303 mml
->height
= height
* mml
->hScale
;
1305 #if FX_COMPRESS_S3TC_AS_FXT1_HACK
1306 /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
1307 /* [dBorca] we should update texture's attribute, then,
1308 * because if the application asks us to decompress, we
1309 * have to know the REAL format! Also, DXT3/5 might not
1310 * be correct, since it would mess with "compressedSize".
1311 * Ditto for GL_RGBA[4]_S3TC, which is always mapped to DXT3.
1313 if (texImage
->IsCompressed
) {
1314 switch (internalFormat
) {
1315 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
1318 internalFormat
= GL_COMPRESSED_RGB_FXT1_3DFX
;
1320 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
1321 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
1322 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
1325 internalFormat
= GL_COMPRESSED_RGBA_FXT1_3DFX
;
1327 texImage
->InternalFormat
= internalFormat
;
1331 if (fxMesa
->type
>= GR_SSTTYPE_Voodoo4
) {
1332 GLenum texNapalm
= 0;
1333 if (internalFormat
== GL_COMPRESSED_RGB
) {
1334 texNapalm
= GL_COMPRESSED_RGB_FXT1_3DFX
;
1335 } else if (internalFormat
== GL_COMPRESSED_RGBA
) {
1336 texNapalm
= GL_COMPRESSED_RGBA_FXT1_3DFX
;
1339 texImage
->InternalFormat
= internalFormat
= texNapalm
;
1340 texImage
->IsCompressed
= GL_TRUE
;
1345 /* choose the texture format */
1346 assert(ctx
->Driver
.ChooseTextureFormat
);
1347 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
1348 internalFormat
, format
, type
);
1349 assert(texImage
->TexFormat
);
1350 mesaFormat
= texImage
->TexFormat
->MesaFormat
;
1351 mml
->glideFormat
= fxGlideFormat(mesaFormat
);
1352 ti
->info
.format
= mml
->glideFormat
;
1353 texImage
->FetchTexelc
= fxFetchFunction(mesaFormat
);
1354 texelBytes
= texImage
->TexFormat
->TexelBytes
;
1356 if (texImage
->IsCompressed
) {
1357 texImage
->CompressedSize
= _mesa_compressed_texture_size(ctx
,
1362 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, mml
->width
);
1363 texImage
->Data
= _mesa_alloc_texmemory(texImage
->CompressedSize
);
1365 dstRowStride
= mml
->width
* texelBytes
;
1366 texImage
->Data
= _mesa_alloc_texmemory(mml
->width
* mml
->height
* texelBytes
);
1368 if (!texImage
->Data
) {
1369 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1373 if (pixels
!= NULL
) {
1374 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
1375 /* rescale image to overcome 1:8 aspect limitation */
1376 if (!adjust2DRatio(ctx
,
1379 format
, type
, pixels
,
1386 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
1391 /* no rescaling needed */
1392 /* unpack image, apply transfer ops and store in texImage->Data */
1393 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
1394 texImage
->TexFormat
, texImage
->Data
,
1395 0, 0, 0, /* dstX/Y/Zoffset */
1397 texImage
->ImageOffsets
,
1399 format
, type
, pixels
, packing
);
1402 /* GL_SGIS_generate_mipmap */
1403 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1404 GLint mipWidth
, mipHeight
;
1405 tdfxMipMapLevel
*mip
;
1406 struct gl_texture_image
*mipImage
;
1407 const GLint maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
1409 assert(!texImage
->IsCompressed
);
1411 while (level
< texObj
->MaxLevel
&& level
< maxLevels
- 1) {
1412 mipWidth
= width
/ 2;
1416 mipHeight
= height
/ 2;
1420 if ((mipWidth
== width
) && (mipHeight
== height
)) {
1423 _mesa_TexImage2D(target
, ++level
, internalFormat
,
1424 mipWidth
, mipHeight
, border
,
1427 mipImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
1428 mip
= TDFX_TEXIMAGE_DATA(mipImage
);
1429 _mesa_halve2x2_teximage2d(ctx
,
1432 mml
->width
, mml
->height
,
1433 texImage
->Data
, mipImage
->Data
);
1434 texImage
= mipImage
;
1442 RevalidateTexture(ctx
, texObj
);
1444 ti
->reloadImages
= GL_TRUE
;
1445 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1450 tdfxTexSubImage2D(GLcontext
*ctx
, GLenum target
, GLint level
,
1451 GLint xoffset
, GLint yoffset
,
1452 GLsizei width
, GLsizei height
,
1453 GLenum format
, GLenum type
,
1454 const GLvoid
*pixels
,
1455 const struct gl_pixelstore_attrib
*packing
,
1456 struct gl_texture_object
*texObj
,
1457 struct gl_texture_image
*texImage
)
1459 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1461 tdfxMipMapLevel
*mml
;
1462 GLint texelBytes
, dstRowStride
;
1464 if (!texObj
->DriverData
) {
1465 _mesa_problem(ctx
, "problem in fxDDTexSubImage2D");
1469 ti
= TDFX_TEXTURE_DATA(texObj
);
1471 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1474 assert(texImage
->Data
); /* must have an existing texture image! */
1475 assert(texImage
->_BaseFormat
);
1477 texelBytes
= texImage
->TexFormat
->TexelBytes
;
1478 if (texImage
->IsCompressed
) {
1479 dstRowStride
= _mesa_compressed_row_stride(texImage
->TexFormat
->MesaFormat
, mml
->width
);
1481 dstRowStride
= mml
->width
* texelBytes
;
1484 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
1485 /* need to rescale subimage to match mipmap level's rescale factors */
1486 if (!adjust2DRatio(ctx
,
1489 format
, type
, pixels
,
1496 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
1501 /* no rescaling needed */
1502 texImage
->TexFormat
->StoreImage(ctx
, 2, texImage
->_BaseFormat
,
1503 texImage
->TexFormat
, texImage
->Data
,
1504 xoffset
, yoffset
, 0,
1506 texImage
->ImageOffsets
,
1508 format
, type
, pixels
, packing
);
1511 /* GL_SGIS_generate_mipmap */
1512 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1513 GLint mipWidth
, mipHeight
;
1514 tdfxMipMapLevel
*mip
;
1515 struct gl_texture_image
*mipImage
;
1516 const GLint maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
1518 assert(!texImage
->IsCompressed
);
1520 width
= texImage
->Width
;
1521 height
= texImage
->Height
;
1522 while (level
< texObj
->MaxLevel
&& level
< maxLevels
- 1) {
1523 mipWidth
= width
/ 2;
1527 mipHeight
= height
/ 2;
1531 if ((mipWidth
== width
) && (mipHeight
== height
)) {
1535 mipImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
1536 mip
= TDFX_TEXIMAGE_DATA(mipImage
);
1537 _mesa_halve2x2_teximage2d(ctx
,
1540 mml
->width
, mml
->height
,
1541 texImage
->Data
, mipImage
->Data
);
1542 texImage
= mipImage
;
1549 ti
->reloadImages
= GL_TRUE
; /* signal the image needs to be reloaded */
1550 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
; /* XXX this might be a bit much */
1555 tdfxTexImage1D(GLcontext
*ctx
, GLenum target
, GLint level
,
1556 GLint internalFormat
, GLint width
, GLint border
,
1557 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1558 const struct gl_pixelstore_attrib
*packing
,
1559 struct gl_texture_object
*texObj
,
1560 struct gl_texture_image
*texImage
)
1562 tdfxTexImage2D(ctx
, target
, level
,
1563 internalFormat
, width
, 1, border
,
1564 format
, type
, pixels
,
1571 tdfxTexSubImage1D(GLcontext
*ctx
, GLenum target
, GLint level
,
1574 GLenum format
, GLenum type
,
1575 const GLvoid
*pixels
,
1576 const struct gl_pixelstore_attrib
*packing
,
1577 struct gl_texture_object
*texObj
,
1578 struct gl_texture_image
*texImage
)
1580 tdfxTexSubImage2D(ctx
, target
, level
,
1590 /**********************************************************************/
1591 /**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
1592 /**********************************************************************/
1595 tdfxCompressedTexImage2D (GLcontext
*ctx
, GLenum target
,
1596 GLint level
, GLint internalFormat
,
1597 GLsizei width
, GLsizei height
, GLint border
,
1598 GLsizei imageSize
, const GLvoid
*data
,
1599 struct gl_texture_object
*texObj
,
1600 struct gl_texture_image
*texImage
)
1602 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1604 tdfxMipMapLevel
*mml
;
1607 if (TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
1608 fprintf(stderr
, "tdfxCompressedTexImage2D: id=%d int 0x%x %dx%d\n",
1609 texObj
->Name
, internalFormat
,
1613 if ((target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) || texImage
->Border
> 0) {
1614 _mesa_problem(NULL
, "tdfx: unsupported texture in tdfxCompressedTexImg()\n");
1618 assert(texImage
->IsCompressed
);
1620 ti
= TDFX_TEXTURE_DATA(texObj
);
1622 texObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1623 if (!texObj
->DriverData
) {
1624 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
1627 ti
= TDFX_TEXTURE_DATA(texObj
);
1631 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1633 texImage
->DriverData
= CALLOC(sizeof(tdfxMipMapLevel
));
1634 if (!texImage
->DriverData
) {
1635 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
1638 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1641 tdfxTexGetInfo(ctx
, width
, height
, NULL
, NULL
, NULL
, NULL
,
1642 &mml
->wScale
, &mml
->hScale
);
1644 mml
->width
= width
* mml
->wScale
;
1645 mml
->height
= height
* mml
->hScale
;
1648 /* choose the texture format */
1649 assert(ctx
->Driver
.ChooseTextureFormat
);
1650 texImage
->TexFormat
= (*ctx
->Driver
.ChooseTextureFormat
)(ctx
,
1651 internalFormat
, -1/*format*/, -1/*type*/);
1652 assert(texImage
->TexFormat
);
1654 /* Determine the appropriate Glide texel format,
1655 * given the user's internal texture format hint.
1657 mesaFormat
= texImage
->TexFormat
->MesaFormat
;
1658 mml
->glideFormat
= fxGlideFormat(mesaFormat
);
1659 ti
->info
.format
= mml
->glideFormat
;
1660 texImage
->FetchTexelc
= fxFetchFunction(mesaFormat
);
1662 /* allocate new storage for texture image, if needed */
1663 if (!texImage
->Data
) {
1664 texImage
->CompressedSize
= _mesa_compressed_texture_size(ctx
,
1669 texImage
->Data
= _mesa_alloc_texmemory(texImage
->CompressedSize
);
1670 if (!texImage
->Data
) {
1671 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
1676 /* save the texture data */
1677 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
1678 /* [dBorca] Hack alert:
1679 * now we're screwed. We can't decompress,
1680 * unless we do it in HW (via textureBuffer).
1681 * We still have some chances:
1682 * 1) we got FXT1 textures - we CAN decompress, rescale for
1683 * aspectratio, then compress back.
1684 * 2) there is a chance that MIN("s", "t") won't be overflowed.
1685 * Thus, we don't care about textureclamp and we could lower
1686 * MIN("uscale", "vscale") below 32. We still have to have
1687 * our data aligned inside a 8:1 rectangle.
1688 * 3) just in case if MIN("s", "t") gets overflowed with GL_REPEAT,
1689 * we replicate the data over the padded area.
1690 * For now, we take 2) + 3) but texelfetchers will be wrong!
1692 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
1693 GLuint srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
1695 GLuint destRowStride
= _mesa_compressed_row_stride(mesaFormat
,
1698 _mesa_upscale_teximage2d(srcRowStride
, (height
+3) / 4,
1699 destRowStride
, (mml
->height
+3) / 4,
1700 1, data
, srcRowStride
,
1702 ti
->padded
= GL_TRUE
;
1704 MEMCPY(texImage
->Data
, data
, texImage
->CompressedSize
);
1707 /* GL_SGIS_generate_mipmap */
1708 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1709 assert(!texImage
->IsCompressed
);
1712 RevalidateTexture(ctx
, texObj
);
1714 ti
->reloadImages
= GL_TRUE
;
1715 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1720 tdfxCompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
,
1721 GLint level
, GLint xoffset
,
1722 GLint yoffset
, GLsizei width
,
1723 GLint height
, GLenum format
,
1724 GLsizei imageSize
, const GLvoid
*data
,
1725 struct gl_texture_object
*texObj
,
1726 struct gl_texture_image
*texImage
)
1728 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1730 tdfxMipMapLevel
*mml
;
1731 GLint destRowStride
, srcRowStride
;
1734 const GLuint mesaFormat
= texImage
->TexFormat
->MesaFormat
;
1736 if (TDFX_DEBUG
& DEBUG_VERBOSE_DRI
) {
1737 fprintf(stderr
, "tdfxCompressedTexSubImage2D: id=%d\n", texObj
->Name
);
1740 ti
= TDFX_TEXTURE_DATA(texObj
);
1742 mml
= TDFX_TEXIMAGE_DATA(texImage
);
1745 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, width
);
1747 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, mml
->width
);
1748 dest
= _mesa_compressed_image_address(xoffset
, yoffset
, 0,
1751 (GLubyte
*) texImage
->Data
);
1753 rows
= height
/ 4; /* [dBorca] hardcoded 4, but works for FXT1/DXTC */
1755 for (i
= 0; i
< rows
; i
++) {
1756 MEMCPY(dest
, data
, srcRowStride
);
1757 dest
+= destRowStride
;
1758 data
= (GLvoid
*)((intptr_t)data
+ (intptr_t)srcRowStride
);
1761 /* [dBorca] Hack alert:
1762 * see fxDDCompressedTexImage2D for caveats
1764 if (mml
->wScale
!= 1 || mml
->hScale
!= 1) {
1765 srcRowStride
= _mesa_compressed_row_stride(mesaFormat
, texImage
->Width
);
1767 destRowStride
= _mesa_compressed_row_stride(mesaFormat
, mml
->width
);
1768 _mesa_upscale_teximage2d(srcRowStride
, texImage
->Height
/ 4,
1769 destRowStride
, mml
->height
/ 4,
1770 1, texImage
->Data
, destRowStride
,
1774 /* GL_SGIS_generate_mipmap */
1775 if (level
== texObj
->BaseLevel
&& texObj
->GenerateMipmap
) {
1776 assert(!texImage
->IsCompressed
);
1779 RevalidateTexture(ctx
, texObj
);
1781 ti
->reloadImages
= GL_TRUE
;
1782 fxMesa
->new_state
|= TDFX_NEW_TEXTURE
;
1788 PrintTexture(int w
, int h
, int c
, const GLubyte
* data
)
1791 for (i
= 0; i
< h
; i
++) {
1792 for (j
= 0; j
< w
; j
++) {
1794 printf("%02x %02x ", data
[0], data
[1]);
1796 printf("%02x %02x %02x ", data
[0], data
[1], data
[2]);
1806 tdfxTestProxyTexImage(GLcontext
*ctx
, GLenum target
,
1807 GLint level
, GLint internalFormat
,
1808 GLenum format
, GLenum type
,
1809 GLint width
, GLint height
,
1810 GLint depth
, GLint border
)
1812 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
1813 struct gl_shared_state
*mesaShared
= fxMesa
->glCtx
->Shared
;
1814 struct tdfxSharedState
*shared
= (struct tdfxSharedState
*) mesaShared
->DriverData
;
1817 case GL_PROXY_TEXTURE_1D
:
1819 case GL_PROXY_TEXTURE_2D
:
1821 struct gl_texture_object
*tObj
;
1825 tObj
= ctx
->Texture
.ProxyTex
[TEXTURE_2D_INDEX
];
1826 if (!tObj
->DriverData
)
1827 tObj
->DriverData
= fxAllocTexObjData(fxMesa
);
1828 ti
= TDFX_TEXTURE_DATA(tObj
);
1831 /* assign the parameters to test against */
1832 tObj
->Image
[0][level
]->Width
= width
;
1833 tObj
->Image
[0][level
]->Height
= height
;
1834 tObj
->Image
[0][level
]->Border
= border
;
1836 tObj
->Image
[0][level
]->InternalFormat
= internalFormat
;
1839 /* don't use mipmap levels > 0 */
1840 tObj
->MinFilter
= tObj
->MagFilter
= GL_NEAREST
;
1843 /* test with all mipmap levels */
1844 tObj
->MinFilter
= GL_LINEAR_MIPMAP_LINEAR
;
1845 tObj
->MagFilter
= GL_NEAREST
;
1847 RevalidateTexture(ctx
, tObj
);
1850 printf("small lodlog2 0x%x\n", ti->info.smallLodLog2);
1851 printf("large lodlog2 0x%x\n", ti->info.largeLodLog2);
1852 printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2);
1853 printf("glide format 0x%x\n", ti->info.format);
1854 printf("data %p\n", ti->info.data);
1855 printf("lodblend %d\n", (int) ti->LODblend);
1858 /* determine where texture will reside */
1859 if (ti
->LODblend
&& !shared
->umaTexMemory
) {
1860 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1861 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1862 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1865 /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */
1866 memNeeded
= fxMesa
->Glide
.grTexTextureMemRequired(
1867 GR_MIPMAPLEVELMASK_BOTH
, &(ti
->info
));
1870 printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]);
1872 if (memNeeded
> shared
->totalTexMem
[0])
1877 case GL_PROXY_TEXTURE_3D
:
1878 return GL_TRUE
; /* software rendering */
1880 return GL_TRUE
; /* never happens, silence compiler */
1886 * Allocate a new texture object.
1887 * Called via ctx->Driver.NewTextureObject.
1888 * Note: this function will be called during context creation to
1889 * allocate the default texture objects.
1890 * Note: we could use containment here to 'derive' the driver-specific
1891 * texture object from the core mesa gl_texture_object. Not done at this time.
1893 static struct gl_texture_object
*
1894 tdfxNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
1896 struct gl_texture_object
*obj
;
1897 obj
= _mesa_new_texture_object(ctx
, name
, target
);
1902 void tdfxInitTextureFuncs( struct dd_function_table
*functions
)
1904 functions
->BindTexture
= tdfxBindTexture
;
1905 functions
->NewTextureObject
= tdfxNewTextureObject
;
1906 functions
->DeleteTexture
= tdfxDeleteTexture
;
1907 functions
->TexEnv
= tdfxTexEnv
;
1908 functions
->TexParameter
= tdfxTexParameter
;
1909 functions
->ChooseTextureFormat
= tdfxChooseTextureFormat
;
1910 functions
->TexImage1D
= tdfxTexImage1D
;
1911 functions
->TexSubImage1D
= tdfxTexSubImage1D
;
1912 functions
->TexImage2D
= tdfxTexImage2D
;
1913 functions
->TexSubImage2D
= tdfxTexSubImage2D
;
1914 functions
->IsTextureResident
= tdfxIsTextureResident
;
1915 functions
->CompressedTexImage2D
= tdfxCompressedTexImage2D
;
1916 functions
->CompressedTexSubImage2D
= tdfxCompressedTexSubImage2D
;
1917 functions
->UpdateTexturePalette
= tdfxUpdateTexturePalette
;