diff options
53 files changed, 6781 insertions, 6747 deletions
diff --git a/xc/extras/Mesa/src/image.c b/xc/extras/Mesa/src/image.c index c0f463c39..5ffb84dce 100644 --- a/xc/extras/Mesa/src/image.c +++ b/xc/extras/Mesa/src/image.c @@ -2,19 +2,19 @@ /* * Mesa 3-D graphics library * Version: 3.4.1 - * + * * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -1545,7 +1545,6 @@ _mesa_pack_rgba_span( GLcontext *ctx, _mesa_pack_float_rgba_span(ctx, n, (const GLfloat (*)[4]) rgba, format, type, destination, packing, applyTransferOps); - } } @@ -1811,7 +1810,7 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], alphaIndex = 0; stride = 1; break; - case GL_LUMINANCE: + case GL_LUMINANCE: redIndex = greenIndex = blueIndex = 0; alphaIndex = -1; stride = 1; @@ -2159,7 +2158,7 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], GLuint i; for (i = 0; i < n; i ++) { GLuint p = uisrc[i]; - rgba[i][rComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + rgba[i][rComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); rgba[i][gComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); rgba[i][bComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); rgba[i][aComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); @@ -2173,7 +2172,7 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], rgba[i][rComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff); rgba[i][gComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff); rgba[i][bComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff); - rgba[i][aComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); + rgba[i][aComp] = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) ); } } break; @@ -2262,7 +2261,7 @@ _mesa_unpack_ubyte_color_span( GLcontext *ctx, GLboolean applyTransferOps ) { ASSERT(dstFormat == GL_ALPHA || - dstFormat == GL_LUMINANCE || + dstFormat == GL_LUMINANCE || dstFormat == GL_LUMINANCE_ALPHA || dstFormat == GL_INTENSITY || dstFormat == GL_RGB || @@ -2474,7 +2473,7 @@ _mesa_unpack_ubyte_color_span( GLcontext *ctx, dstRedIndex = dstGreenIndex = dstBlueIndex = -1; dstLuminanceIndex = dstIntensityIndex = -1; break; - case GL_LUMINANCE: + case GL_LUMINANCE: dstLuminanceIndex = 0; dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; dstIntensityIndex = -1; @@ -2581,7 +2580,7 @@ _mesa_unpack_float_color_span( GLcontext *ctx, GLboolean applyTransferOps, GLboolean clamp ) { ASSERT(dstFormat == GL_ALPHA || - dstFormat == GL_LUMINANCE || + dstFormat == GL_LUMINANCE || dstFormat == GL_LUMINANCE_ALPHA || dstFormat == GL_INTENSITY || dstFormat == GL_RGB || @@ -2743,7 +2742,7 @@ _mesa_unpack_float_color_span( GLcontext *ctx, dstRedIndex = dstGreenIndex = dstBlueIndex = -1; dstLuminanceIndex = dstIntensityIndex = -1; break; - case GL_LUMINANCE: + case GL_LUMINANCE: dstLuminanceIndex = 0; dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; dstIntensityIndex = -1; diff --git a/xc/extras/Mesa/src/macros.h b/xc/extras/Mesa/src/macros.h index 16038d3b1..8010e28bd 100644 --- a/xc/extras/Mesa/src/macros.h +++ b/xc/extras/Mesa/src/macros.h @@ -2,19 +2,19 @@ /* * Mesa 3-D graphics library * Version: 3.3 - * + * * Copyright (C) 1999 Brian Paul All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -89,7 +89,7 @@ #define TEST_BITS(WORD, BITS) ((WORD) & (BITS)) -/* Stepping a GLfloat pointer by a byte stride +/* Stepping a GLfloat pointer by a byte stride */ #define STRIDE_F(p, i) (p = (GLfloat *)((GLubyte *)p + i)) #define STRIDE_UI(p, i) (p = (GLuint *)((GLubyte *)p + i)) @@ -160,7 +160,7 @@ do { \ case 2: (DST)[1] = (SRC)[1]; \ case 1: (DST)[0] = (SRC)[0]; \ } \ -} while(0) +} while(0) #define SUB_4V( DST, SRCA, SRCB ) \ do { \ @@ -496,4 +496,31 @@ do { \ #define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) ) + +/* Generic color packing macros + */ + +#define PACK_COLOR_8888( a, b, c, d ) \ + (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) + +#define PACK_COLOR_888( a, b, c ) \ + (((a) << 16) | ((b) << 8) | (c)) + +#define PACK_COLOR_565( a, b, c ) \ + ((((a) & 0xf8) << 8) | (((b) & 0xfc) << 3) | (((c) & 0xf8) >> 3)) + +#define PACK_COLOR_1555( a, b, c, d ) \ + ((((b) & 0xf8) << 7) | (((c) & 0xf8) << 2) | (((d) & 0xf8) >> 3) | \ + ((a) ? 0x8000 : 0)) + +#define PACK_COLOR_4444( a, b, c, d ) \ + ((((a) & 0xf0) << 8) | (((b) & 0xf0) << 4) | ((c) & 0xf0) | ((d) >> 4)) + +#define PACK_COLOR_88( a, b ) \ + (((a) << 8) | (b)) + +#define PACK_COLOR_332( a, b, c ) \ + (((a) & 0xe0) | (((b) & 0xe0) >> 3) | (((c) & 0xc0) >> 6)) + + #endif /*MACROS_H*/ diff --git a/xc/extras/Mesa/src/texformat.c b/xc/extras/Mesa/src/texformat.c new file mode 100644 index 000000000..f85725843 --- /dev/null +++ b/xc/extras/Mesa/src/texformat.c @@ -0,0 +1,351 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.4 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: + * Gareth Hughes <gareth@valinux.com> + */ + +#ifdef PC_HEADER +#include "all.h" +#else +#include "glheader.h" +#include "context.h" +#include "image.h" +#include "mem.h" +#include "mmath.h" +#include "span.h" +#include "texformat.h" +#include "teximage.h" +#include "texstate.h" +#include "types.h" +#endif + + +/* ================================================================ + * Texture internal formats: + */ + +const struct gl_texture_format _mesa_texformat_rgba8888 = { + MESA_FORMAT_RGBA8888, /* IntFormat */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 4, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_abgr8888 = { + MESA_FORMAT_ABGR8888, /* IntFormat */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 4, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_argb8888 = { + MESA_FORMAT_ARGB8888, /* IntFormat */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 4, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_rgb888 = { + MESA_FORMAT_RGB888, /* IntFormat */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 3, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_bgr888 = { + MESA_FORMAT_BGR888, /* IntFormat */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 3, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_rgb565 = { + MESA_FORMAT_RGB565, /* IntFormat */ + 5, /* RedBits */ + 6, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 2, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_argb4444 = { + MESA_FORMAT_ARGB4444, /* IntFormat */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 4, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 2, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_argb1555 = { + MESA_FORMAT_ARGB1555, /* IntFormat */ + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 1, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 2, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_al88 = { + MESA_FORMAT_AL88, /* IntFormat */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8, /* AlphaBits */ + 8, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 2, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_rgb332 = { + MESA_FORMAT_RGB332, /* IntFormat */ + 3, /* RedBits */ + 3, /* GreenBits */ + 2, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 1, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_a8 = { + MESA_FORMAT_A8, /* IntFormat */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 1, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_l8 = { + MESA_FORMAT_L8, /* IntFormat */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 8, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 1, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_i8 = { + MESA_FORMAT_I8, /* IntFormat */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 8, /* IntensityBits */ + 0, /* IndexBits */ + 1, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_texformat_ci8 = { + MESA_FORMAT_CI8, /* IntFormat */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 8, /* IndexBits */ + 1, /* TexelBytes */ +}; + +const struct gl_texture_format _mesa_null_texformat = { + -1, /* IntFormat */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* TexelBytes */ +}; + + + +/* + * Given an internal texture format enum or 1, 2, 3, 4 return the + * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, + * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. + * Return -1 if invalid enum. + */ +void _mesa_init_texture_format( GLcontext *ctx, + struct gl_texture_image *texImage, + GLenum internalFormat ) +{ + texImage->IntFormat = internalFormat; + + /* Ask the driver for the base format, if it doesn't know, it will + * return -1; + */ + if ( ctx->Driver.BaseCompressedTexFormat ) { + GLint format = 0; /* Silence compiler warning */ + format = (*ctx->Driver.BaseCompressedTexFormat)( ctx, format ); + if ( format >= 0 ) { + internalFormat = format; + } + } + + switch ( internalFormat ) { + /* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has + * got to be better than sticking them way down the end of this + * huge list. + */ + case 4: /* Quake3 uses this... */ + case GL_RGBA: + texImage->Format = GL_RGBA; + texImage->TexFormat = &_mesa_texformat_abgr8888; + break; + + case 3: /* ... and this. */ + case GL_RGB: + texImage->Format = GL_RGB; + texImage->TexFormat = &_mesa_texformat_bgr888; + break; + + /* GH: Okay, keep checking as normal. Still test for GL_RGB, + * GL_RGBA formats first. + */ + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + texImage->Format = GL_RGBA; + texImage->TexFormat = &_mesa_texformat_abgr8888; + break; + + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + texImage->Format = GL_RGB; + texImage->TexFormat = &_mesa_texformat_bgr888; + break; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + texImage->Format = GL_ALPHA; + texImage->TexFormat = &_mesa_texformat_a8; + break; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + texImage->Format = GL_LUMINANCE; + texImage->TexFormat = &_mesa_texformat_l8; + break; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + texImage->Format = GL_LUMINANCE_ALPHA; + texImage->TexFormat = &_mesa_texformat_al88; + break; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + texImage->Format = GL_INTENSITY; + texImage->TexFormat = &_mesa_texformat_i8; + break; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + texImage->Format = GL_COLOR_INDEX; + texImage->TexFormat = &_mesa_texformat_ci8; + break; + + default: + gl_problem( ctx, "unexpected format in _mesa_init_texture_format" ); + return; + } +} diff --git a/xc/extras/Mesa/src/texformat.h b/xc/extras/Mesa/src/texformat.h new file mode 100644 index 000000000..8f5e7de75 --- /dev/null +++ b/xc/extras/Mesa/src/texformat.h @@ -0,0 +1,80 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.4 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: + * Gareth Hughes <gareth@valinux.com> + */ + +#ifndef TEXFORMAT_H +#define TEXFORMAT_H + +#include "types.h" + + +/* The Mesa internal texture image types. These will be set to their + * default value, but may be changed by drivers as required. + */ + /* msb <------ TEXEL BITS -----------> lsb */ +enum _format { /* ---- ---- ---- ---- ---- ---- ---- ---- */ + MESA_FORMAT_RGBA8888, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_ABGR8888, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_ARGB8888, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_RGB888, /* RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_BGR888, /* BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_RGB565, /* RRRR RGGG GGGB BBBB */ + MESA_FORMAT_ARGB4444, /* AAAA RRRR GGGG BBBB */ + MESA_FORMAT_ARGB1555, /* ARRR RRGG GGGB BBBB */ + MESA_FORMAT_AL88, /* AAAA AAAA LLLL LLLL */ + MESA_FORMAT_RGB332, /* RRRG GGBB */ + MESA_FORMAT_A8, /* AAAA AAAA */ + MESA_FORMAT_L8, /* LLLL LLLL */ + MESA_FORMAT_I8, /* IIII IIII */ + MESA_FORMAT_CI8 /* CCCC CCCC */ +}; + + +extern void +_mesa_init_texture_format( GLcontext *ctx, + struct gl_texture_image *texImage, + GLenum internalFormat ); + + +extern const struct gl_texture_format _mesa_texformat_rgba8888; +extern const struct gl_texture_format _mesa_texformat_abgr8888; +extern const struct gl_texture_format _mesa_texformat_argb8888; +extern const struct gl_texture_format _mesa_texformat_rgb888; +extern const struct gl_texture_format _mesa_texformat_bgr888; +extern const struct gl_texture_format _mesa_texformat_rgb565; +extern const struct gl_texture_format _mesa_texformat_argb4444; +extern const struct gl_texture_format _mesa_texformat_argb1555; +extern const struct gl_texture_format _mesa_texformat_al88; +extern const struct gl_texture_format _mesa_texformat_rgb332; +extern const struct gl_texture_format _mesa_texformat_a8; +extern const struct gl_texture_format _mesa_texformat_l8; +extern const struct gl_texture_format _mesa_texformat_i8; +extern const struct gl_texture_format _mesa_texformat_ci8; + +extern const struct gl_texture_format _mesa_null_texformat; + +#endif diff --git a/xc/extras/Mesa/src/teximage.c b/xc/extras/Mesa/src/teximage.c index 4b71d5178..fc610cb0b 100644 --- a/xc/extras/Mesa/src/teximage.c +++ b/xc/extras/Mesa/src/teximage.c @@ -2,19 +2,19 @@ /* * Mesa 3-D graphics library * Version: 3.4 - * + * * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -33,6 +33,7 @@ #include "mem.h" #include "mmath.h" #include "span.h" +#include "texformat.h" #include "teximage.h" #include "texstate.h" #include "types.h" @@ -300,115 +301,6 @@ is_compressed_format(GLcontext *ctx, GLenum internalFormat) -/* - * Examine the texImage->Format field and set the Red, Green, Blue, etc - * texel component sizes to default values. - * These fields are set only here by core Mesa but device drivers may - * overwritting these fields to indicate true texel resolution. - */ -static void -set_teximage_component_sizes( struct gl_texture_image *texImage ) -{ - switch (texImage->Format) { - case GL_ALPHA: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 8; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_LUMINANCE: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 8; - texImage->IndexBits = 0; - break; - case GL_LUMINANCE_ALPHA: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 8; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 8; - texImage->IndexBits = 0; - break; - case GL_INTENSITY: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 8; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_RED: - texImage->RedBits = 8; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_GREEN: - texImage->RedBits = 0; - texImage->GreenBits = 8; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_BLUE: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 8; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_RGB: - case GL_BGR: - texImage->RedBits = 8; - texImage->GreenBits = 8; - texImage->BlueBits = 8; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_RGBA: - case GL_BGRA: - case GL_ABGR_EXT: - texImage->RedBits = 8; - texImage->GreenBits = 8; - texImage->BlueBits = 8; - texImage->AlphaBits = 8; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 0; - break; - case GL_COLOR_INDEX: - texImage->RedBits = 0; - texImage->GreenBits = 0; - texImage->BlueBits = 0; - texImage->AlphaBits = 0; - texImage->IntensityBits = 0; - texImage->LuminanceBits = 0; - texImage->IndexBits = 8; - break; - default: - gl_problem(NULL, "unexpected format in set_teximage_component_sizes"); - } -} - - static void set_tex_image(struct gl_texture_object *tObj, GLenum target, GLint level, @@ -467,9 +359,7 @@ init_texture_image( GLcontext *ctx, { ASSERT(img); ASSERT(!img->Data); - img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat); - set_teximage_component_sizes( img ); - img->IntFormat = (GLenum) internalFormat; + _mesa_init_texture_format( ctx, img, internalFormat ); img->Border = border; img->Width = width; img->Height = height; @@ -745,7 +635,7 @@ make_texture_image( GLcontext *ctx, } return; /* all done */ } - } + } /* @@ -851,13 +741,6 @@ clear_proxy_teximage(struct gl_texture_image *img) ASSERT(img); img->Format = 0; img->IntFormat = 0; - img->RedBits = 0; - img->GreenBits = 0; - img->BlueBits = 0; - img->AlphaBits = 0; - img->IntensityBits = 0; - img->LuminanceBits = 0; - img->IndexBits = 0; img->Border = 0; img->Width = 0; img->Height = 0; @@ -871,6 +754,7 @@ clear_proxy_teximage(struct gl_texture_image *img) img->Data = NULL; img->IsCompressed = 0; img->CompressedSize = 0; + img->TexFormat = &_mesa_null_texformat; } @@ -2521,7 +2405,7 @@ _mesa_CopyTexImage1D( GLenum target, GLint level, return; if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA - || !ctx->Driver.CopyTexImage1D + || !ctx->Driver.CopyTexImage1D || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, x, y, width, border)) { @@ -2616,7 +2500,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level, gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" ); return; } - + /* now call glTexSubImage1D to do the real work */ unpackSave = ctx->Unpack; ctx->Unpack = _mesa_native_packing; @@ -2668,7 +2552,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image); ctx->Unpack = unpackSave; - + FREE(image); } } @@ -2713,7 +2597,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level, _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image); ctx->Unpack = unpackSave; - + FREE(image); } } diff --git a/xc/extras/Mesa/src/teximage.h b/xc/extras/Mesa/src/teximage.h index ebc45e690..45ce79a1b 100644 --- a/xc/extras/Mesa/src/teximage.h +++ b/xc/extras/Mesa/src/teximage.h @@ -2,19 +2,19 @@ /* * Mesa 3-D graphics library * Version: 3.4 - * + * * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -142,7 +142,7 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, extern void -_mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, +_mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ); @@ -152,7 +152,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level, GLint x, GLint y, GLsizei width, GLsizei height ); -extern void +extern void _mesa_CopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ); @@ -204,4 +204,3 @@ _mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img); #endif - diff --git a/xc/extras/Mesa/src/texstate.c b/xc/extras/Mesa/src/texstate.c index 08204bd88..d74feb578 100644 --- a/xc/extras/Mesa/src/texstate.c +++ b/xc/extras/Mesa/src/texstate.c @@ -890,25 +890,25 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, *params = img->Border; return; case GL_TEXTURE_RED_SIZE: - *params = img->RedBits; + *params = img->TexFormat->RedBits; return; case GL_TEXTURE_GREEN_SIZE: - *params = img->GreenBits; + *params = img->TexFormat->GreenBits; return; case GL_TEXTURE_BLUE_SIZE: - *params = img->BlueBits; + *params = img->TexFormat->BlueBits; return; case GL_TEXTURE_ALPHA_SIZE: - *params = img->AlphaBits; + *params = img->TexFormat->AlphaBits; return; case GL_TEXTURE_INTENSITY_SIZE: - *params = img->IntensityBits; + *params = img->TexFormat->IntensityBits; return; case GL_TEXTURE_LUMINANCE_SIZE: - *params = img->LuminanceBits; + *params = img->TexFormat->LuminanceBits; return; case GL_TEXTURE_INDEX_SIZE_EXT: - *params = img->IndexBits; + *params = img->TexFormat->IndexBits; return; /* GL_ARB_texture_compression */ diff --git a/xc/extras/Mesa/src/texutil.c b/xc/extras/Mesa/src/texutil.c index 313ef1455..4143830c1 100644 --- a/xc/extras/Mesa/src/texutil.c +++ b/xc/extras/Mesa/src/texutil.c @@ -2,1687 +2,1304 @@ /* * Mesa 3-D graphics library * Version: 3.4 - * + * * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes <gareth@valinux.com> */ - #ifdef PC_HEADER #include "all.h" #else #include "glheader.h" #include "context.h" +#include "enums.h" #include "image.h" #include "mem.h" +#include "texformat.h" #include "texutil.h" #include "types.h" #endif +#define DBG 0 -/* - * Texture utilities which may be useful to device drivers. - * See the texutil.h for the list of supported internal formats. - * It's expected that new formats will be added for new hardware. - */ +struct gl_texture_convert { + GLint xoffset, yoffset, zoffset; /* Subimage offset */ + GLint width, height, depth; /* Subimage region */ -/* - * If the system is little endian and can do 4-byte word stores on - * non 4-byte-aligned addresses then we can use this optimization. - */ -#if defined(__i386__) -#define DO_32BIT_STORES000 + GLint imageWidth, imageHeight; /* Full image dimensions */ + GLenum format, type; + + const struct gl_pixelstore_attrib *packing; + + const GLvoid *srcImage; + GLvoid *dstImage; + + GLint index; +}; + +typedef GLboolean (*convert_func)( struct gl_texture_convert *convert ); +typedef void (*unconvert_func)( struct gl_texture_convert *convert ); + +#define CONVERT_STRIDE_BIT 0x1 +#define CONVERT_PACKING_BIT 0x2 + +#ifdef __GNUC__ +#define ERROR_STRING __FUNCTION__ +#else +#define ERROR_STRING __FILE__ ":" __LINE__ #endif +#define UNCONVERT_ERROR( format ) \ +do { \ + static char buffer[128]; \ + sprintf( buffer, "illegal format %s in " ERROR_STRING "\n", \ + gl_lookup_enum_by_nr( format ) ); \ + gl_problem( NULL, buffer ); \ +} while (0) -/* - * Convert texture image data into one a specific internal format. - * Input: - * dstFormat - the destination internal format - * dstWidth, dstHeight - the destination image size - * dstImage - pointer to destination image buffer - * dstRowStride - bytes to jump between image rows - * srcWidth, srcHeight - size of texture image - * srcFormat, srcType - format and datatype of source image - * srcImage - pointer to user's texture image - * packing - describes how user's texture image is packed. - * Return: pointer to resulting image data or NULL if error or out of memory - * or NULL if we can't process the given image format/type/internalFormat - * combination. - * - * Supported type conversions: - * srcFormat srcType dstFormat - * GL_INTENSITY GL_UNSIGNED_BYTE MESA_I8 - * GL_LUMINANCE GL_UNSIGNED_BYTE MESA_L8 - * GL_ALPHA GL_UNSIGNED_BYTE MESA_A8 - * GL_COLOR_INDEX GL_UNSIGNED_BYTE MESA_C8 - * GL_LUMINANCE_ALPHA GL_UNSIGNED_BYTE MESA_A8_L8 - * GL_RGB GL_UNSIGNED_BYTE MESA_R5_G6_B5 - * GL_RGB GL_UNSIGNED_SHORT_5_6_5 MESA_R5_G6_B5 - * GL_RGBA GL_UNSIGNED_BYTE MESA_A4_R4_G4_B4 - * GL_BGRA GL_UNSIGNED_SHORT_4_4_4_4_REV MESA_A4_R4_G4_B4 - * GL_BGRA GL_UNSIGHED_SHORT_1_5_5_5_REV MESA_A1_R5_G5_B5 - * GL_RGBA GL_UNSIGNED_BYTE MESA_A1_R5_G5_B5 - * GL_BGRA GL_UNSIGNED_INT_8_8_8_8_REV MESA_A8_R8_G8_B8 - * GL_RGBA GL_UNSIGNED_BYTE MESA_A8_R8_G8_B8 - * GL_RGB GL_UNSIGNED_BYTE MESA_A8_R8_G8_B8 - * more to be added for new drivers... - * - * Notes: - * Some hardware only supports texture images of specific aspect ratios. - * This code will do power-of-two image up-scaling if that's needed. - * - * +/* ================================================================ + * RGBA8888 textures: */ -GLboolean -_mesa_convert_teximage(MesaIntTexFormat dstFormat, - GLint dstWidth, GLint dstHeight, GLvoid *dstImage, - GLint dstRowStride, - GLint srcWidth, GLint srcHeight, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcImage, - const struct gl_pixelstore_attrib *packing) + +#define DST_TYPE GLuint +#define DST_TEXELS_PER_DWORD 1 + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( src[3], src[2], src[1], src[0] ) + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_rgba8888_direct +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( src[0], src[1], src[2], src[3] ) + +#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src ) + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_abgr8888_to_rgba8888 +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( src[0], src[1], src[2], 0xff ) + +#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src ) + +#define SRC_TEXEL_BYTES 3 + +#define TAG(x) x##_bgr888_to_rgba8888 +#include "texutil_tmp.h" + + +#define CONVERT_RGBA8888( name ) \ +static GLboolean \ +convert_##name##_rgba8888( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( convert->format == GL_ABGR_EXT && \ + convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \ + { \ + tab = name##_tab_rgba8888_direct; \ + } \ + else if ( convert->format == GL_RGBA && \ + ( convert->type == GL_UNSIGNED_BYTE || \ + convert->type == GL_UNSIGNED_INT_8_8_8_8 ) ) \ + { \ + tab = name##_tab_abgr8888_to_rgba8888; \ + } \ + else if ( convert->format == GL_RGB && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_bgr888_to_rgba8888; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_RGBA8888( texsubimage2d ) +CONVERT_RGBA8888( texsubimage3d ) + + +static void +unconvert_teximage_rgba8888( struct gl_texture_convert *convert ) { - const GLint wScale = dstWidth / srcWidth; /* must be power of two */ - const GLint hScale = dstHeight / srcHeight; /* must be power of two */ - ASSERT(dstWidth >= srcWidth); - ASSERT(dstHeight >= srcHeight); - ASSERT(dstImage); - ASSERT(srcImage); - ASSERT(packing); - - switch (dstFormat) { - case MESA_I8: - case MESA_L8: - case MESA_A8: - case MESA_C8: - if (srcType != GL_UNSIGNED_BYTE || - ((srcFormat != GL_INTENSITY) && - (srcFormat != GL_LUMINANCE) && - (srcFormat != GL_ALPHA) && - (srcFormat != GL_COLOR_INDEX))) { - /* bad internal format / srcFormat combination */ - return GL_FALSE; - } - else { - /* store as 8-bit texels */ - if (wScale == 1 && hScale == 1) { - /* no scaling needed - fast case */ - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLubyte *dst = (GLubyte *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - MEMCPY(dst, src, dstWidth * sizeof(GLubyte)); - dst += dstRowStride; - src += srcStride; - } - } - else { - /* must rescale image */ - GLubyte *dst = (GLubyte *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - dst[col] = src[col / wScale]; - } - dst += dstRowStride; - } - } - } - break; - - case MESA_A8_L8: - if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) { - return GL_FALSE; - } - else { - /* store as 16-bit texels */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLushort *dst = (GLushort *) dstImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - for (col = 0; col < dstWidth; col++) { - GLubyte luminance = src[col * 2 + 0]; - GLubyte alpha = src[col * 2 + 1]; - dst[col] = ((GLushort) alpha << 8) | luminance; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - src += srcStride; - } - } - else { - /* must rescale */ - GLushort *dst = (GLushort *) dstImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - for (col = 0; col < dstWidth; col++) { - GLint srcCol = col / wScale; - GLubyte luminance = src[srcCol * 2 + 0]; - GLubyte alpha = src[srcCol * 2 + 1]; - dst[col] = ((GLushort) alpha << 8) | luminance; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - src += srcStride; - } - } - } - break; - - case MESA_R5_G6_B5: - if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) { - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - MEMCPY(dst, src, dstWidth * sizeof(GLushort)); - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLushort *src = (const GLushort *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); -#ifdef DO_32BIT_STORES - GLuint *dst = (GLuint *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col3; - GLint halfDstWidth = dstWidth >> 1; - for (col = col3 = 0; col < halfDstWidth; col++, col3 += 6) { - GLubyte r0 = src[col3 + 0]; - GLubyte g0 = src[col3 + 1]; - GLubyte b0 = src[col3 + 2]; - GLubyte r1 = src[col3 + 3]; - GLubyte g1 = src[col3 + 4]; - GLubyte b1 = src[col3 + 5]; - GLuint d0 = ((r0 & 0xf8) << 8) - | ((g0 & 0xfc) << 3) - | ((b0 & 0xf8) >> 3); - GLuint d1 = ((r1 & 0xf8) << 8) - | ((g1 & 0xfc) << 3) - | ((b1 & 0xf8) >> 3); - dst[col] = (d1 << 16) | d0; - } - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } -#else /* 16-bit stores */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col3; - for (col = col3 = 0; col < dstWidth; col++, col3 += 3) { - GLubyte r = src[col3 + 0]; - GLubyte g = src[col3 + 1]; - GLubyte b = src[col3 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } -#endif - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - GLint col3 = (col / wScale) * 3; - GLubyte r = src[col3 + 0]; - GLubyte g = src[col3 + 1]; - GLubyte b = src[col3 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case (used by Quake3) */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); -#ifdef DO_32BIT_STORES - GLuint *dst = dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col4; - GLint halfDstWidth = dstWidth >> 1; - for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) { - GLubyte r0 = src[col4 + 0]; - GLubyte g0 = src[col4 + 1]; - GLubyte b0 = src[col4 + 2]; - GLubyte r1 = src[col4 + 4]; - GLubyte g1 = src[col4 + 5]; - GLubyte b1 = src[col4 + 6]; - GLuint d0 = ((r0 & 0xf8) << 8) - | ((g0 & 0xfc) << 3) - | ((b0 & 0xf8) >> 3); - GLuint d1 = ((r1 & 0xf8) << 8) - | ((g1 & 0xfc) << 3) - | ((b1 & 0xf8) >> 3); - dst[col] = (d1 << 16) | d0; - } - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } -#else /* 16-bit stores */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col4; - for (col = col4 = 0; col < dstWidth; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } -#endif - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this srcFormat/srcType combination */ - return GL_FALSE; - } - break; - - case MESA_A4_R4_G4_B4: - /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */ - if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV){ - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - MEMCPY(dst, src, dstWidth * sizeof(GLushort)); - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLushort *src = (const GLushort *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); -#ifdef DO_32BIT_STORES - GLuint *dst = dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col4; - GLint halfDstWidth = dstWidth >> 1; - for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) { - GLubyte r0 = src[col4 + 0]; - GLubyte g0 = src[col4 + 1]; - GLubyte b0 = src[col4 + 2]; - GLubyte a0 = src[col4 + 3]; - GLubyte r1 = src[col4 + 4]; - GLubyte g1 = src[col4 + 5]; - GLubyte b1 = src[col4 + 6]; - GLubyte a1 = src[col4 + 7]; - GLuint d0 = ((a0 & 0xf0) << 8) - | ((r0 & 0xf0) << 4) - | ((g0 & 0xf0) ) - | ((b0 & 0xf0) >> 4); - GLuint d1 = ((a1 & 0xf0) << 8) - | ((r1 & 0xf0) << 4) - | ((g1 & 0xf0) ) - | ((b1 & 0xf0) >> 4); - dst[col] = (d1 << 16) | d0; - } - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } -#else /* 16-bit stores */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col4; - for (col = col4 = 0; col < dstWidth; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0xf0) << 8) - | ((r & 0xf0) << 4) - | ((g & 0xf0) ) - | ((b & 0xf0) >> 4); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } -#endif - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0xf0) << 8) - | ((r & 0xf0) << 4) - | ((g & 0xf0) ) - | ((b & 0xf0) >> 4); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this format/srcType combination */ - return GL_FALSE; - } - break; - - case MESA_A1_R5_G5_B5: - /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */ - if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV){ - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - MEMCPY(dst, src, dstWidth * sizeof(GLushort)); - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLushort *src = (const GLushort *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col4; - for (col = col4 = 0; col < dstWidth; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0x80) << 8) - | ((r & 0xf8) << 7) - | ((g & 0xf8) << 2) - | ((b & 0xf8) >> 3); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0x80) << 8) - | ((r & 0xf8) << 7) - | ((g & 0xf8) << 2) - | ((b & 0xf8) >> 3); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this source format/type combination */ - return GL_FALSE; - } - break; - - case MESA_A8_R8_G8_B8: - case MESA_FF_R8_G8_B8: - /* 32-bit texels */ - if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV){ - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLuint *dst = (GLuint *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - MEMCPY(dst, src, dstWidth * sizeof(GLuint)); - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLuint *dst = (GLuint *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLuint *src = (const GLuint *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLuint *dst = (GLuint *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col4; - for (col = col4 = 0; col < dstWidth; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = (a << 24) | (r << 16) | (g << 8) | b; - } - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLuint *dst = (GLuint *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = (a << 24) | (r << 16) | (g << 8) | b; - } - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - srcWidth, srcFormat, srcType); - GLuint *dst = (GLuint *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint col, col3; - for (col = col3 = 0; col < dstWidth; col++, col3 += 3) { - GLubyte r = src[col3 + 0]; - GLubyte g = src[col3 + 1]; - GLubyte b = src[col3 + 2]; - GLubyte a = 255; - dst[col] = (a << 24) | (r << 16) | (g << 8) | b; - } - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLuint *dst = (GLuint *) dstImage; - GLint row; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < dstWidth; col++) { - GLint col3 = (col / wScale) * 3; - GLubyte r = src[col3 + 0]; - GLubyte g = src[col3 + 1]; - GLubyte b = src[col3 + 2]; - GLubyte a = 255; - dst[col] = (a << 24) | (r << 16) | (g << 8) | b; - } - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this source format/type combination */ - return GL_FALSE; - } - if (dstFormat == MESA_FF_R8_G8_B8) { - /* set alpha bytes to 0xff */ - GLint i; - GLubyte *dst = (GLubyte *) dstImage; - for (i = 0; i < dstWidth * dstHeight; i++) { - dst[i * 4 + 3] = 0xff; - } - } - break; - - default: - /* unexpected internal format! */ - return GL_FALSE; + const GLubyte *src = (const GLubyte *)convert->srcImage; + GLint texels, i; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_RGBA: { + GLuint *dst = (GLuint *)convert->dstImage; + for ( i = 0 ; i < texels ; i++ ) { + *dst++ = PACK_COLOR_8888( src[0], src[1], src[2], src[3] ); + src += 4; + } + break; + } + case GL_RGB: { + GLubyte *dst = (GLubyte *)convert->dstImage; + for ( i = 0 ; i < texels ; i++ ) { + *dst++ = src[3]; + *dst++ = src[2]; + *dst++ = src[1]; + src += 4; + } + break; + } + default: + UNCONVERT_ERROR( convert->format ); + break; } - return GL_TRUE; } -/* - * Replace a subregion of a texture image with new data. - * Input: - * dstFormat - destination image format - * dstXoffset, dstYoffset - destination for new subregion (in texels) - * dstWidth, dstHeight - total size of dest image (in texels) - * dstImage - pointer to dest image - * dstRowStride - bytes to jump between image rows (in bytes) - * width, height - size of region to copy/replace (in texels) - * srcWidth, srcHeight - size of the corresponding gl_texture_image - * srcFormat, srcType - source image format and datatype - * srcImage - source image - * packing - source image packing information. - * Return: GL_TRUE or GL_FALSE for success, failure - * - * Notes: - * Like _mesa_convert_teximage(), we can do power-of-two image scaling - * to accomodate hardware with texture image aspect ratio constraints. - * dstWidth / srcWidth is used to compute the horizontal scaling factor and - * dstHeight / srcHeight is used to compute the vertical scaling factor. +/* ================================================================ + * ABGR8888 textures: */ -GLboolean -_mesa_convert_texsubimage(MesaIntTexFormat dstFormat, - GLint dstXoffset, GLint dstYoffset, - GLint dstWidth, GLint dstHeight, GLvoid *dstImage, - GLint dstRowStride, - GLint width, GLint height, - GLint srcWidth, GLint srcHeight, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcImage, - const struct gl_pixelstore_attrib *packing) + +#define DST_TYPE GLuint +#define DST_TEXELS_PER_DWORD 1 + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( src[3], src[2], src[1], src[0] ) + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_abgr8888_direct +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( 0xff, src[2], src[1], src[0] ) + +#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src ) + +#define SRC_TEXEL_BYTES 3 + +#define TAG(x) x##_bgr888_to_abgr8888 +#include "texutil_tmp.h" + + +#define CONVERT_ABGR8888( name ) \ +static GLboolean \ +convert_##name##_abgr8888( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( convert->format == GL_RGBA && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_abgr8888_direct; \ + } \ + else if ( convert->format == GL_RGB && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_bgr888_to_abgr8888; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_ABGR8888( texsubimage2d ) +CONVERT_ABGR8888( texsubimage3d ) + + +static void +unconvert_teximage_abgr8888( struct gl_texture_convert *convert ) { - const GLint wScale = dstWidth / srcWidth; /* must be power of two */ - const GLint hScale = dstHeight / srcHeight; /* must be power of two */ - ASSERT(dstWidth >= srcWidth); - ASSERT(dstHeight >= srcHeight); - ASSERT(dstImage); - ASSERT(srcImage); - ASSERT(packing); - - width *= wScale; - height *= hScale; - dstXoffset *= wScale; - dstYoffset *= hScale; - - /* XXX hscale != 1 and wscale != 1 not tested!!!! */ - - switch (dstFormat) { - case MESA_I8: - case MESA_L8: - case MESA_A8: - case MESA_C8: - if (srcType != GL_UNSIGNED_BYTE || - ((srcFormat != GL_INTENSITY) && - (srcFormat != GL_LUMINANCE) && - (srcFormat != GL_ALPHA) && - (srcFormat != GL_COLOR_INDEX))) { - /* bad internal format / srcFormat combination */ - return GL_FALSE; - } - else { - /* store as 8-bit texels */ - if (wScale == 1 && hScale == 1) { - /* no scaling needed - fast case */ - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcRowStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLubyte *dst = (GLubyte *) dstImage - + dstYoffset * dstRowStride + dstXoffset; - const GLint rowSize = width * sizeof(GLubyte); - GLint row; - if (dstRowStride == srcRowStride && dstRowStride == rowSize) { - MEMCPY(dst, src, rowSize * height); - } - else { - for (row = 0; row < height; row++) { - MEMCPY(dst, src, rowSize); - dst += dstRowStride; - src += srcRowStride; - } - } - } - else { - /* must rescale image */ - GLubyte *dst = (GLubyte *) dstImage - + dstYoffset * dstRowStride + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - dst[col] = src[col / wScale]; - } - dst += dstRowStride; - } - } - } - break; - - case MESA_A8_L8: - if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) { - return GL_FALSE; - } - else { - /* store as 16-bit texels */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row, col; - for (row = 0; row < height; row++) { - for (col = 0; col < width; col++) { - GLubyte luminance = src[col * 2 + 0]; - GLubyte alpha = src[col * 2 + 1]; - dst[col] = ((GLushort) alpha << 8) | luminance; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - src += srcStride; - } - } - else { - /* must rescale */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row, col; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - for (col = 0; col < width; col++) { - GLint srcCol = col / wScale; - GLubyte luminance = src[srcCol * 2 + 0]; - GLubyte alpha = src[srcCol * 2 + 1]; - dst[col] = ((GLushort) alpha << 8) | luminance; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - src += srcStride; - } - } - } - break; - - case MESA_R5_G6_B5: - if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) { - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - MEMCPY(dst, src, width * sizeof(GLushort)); - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLushort *src = (const GLushort *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint col, col3; - for (col = col3 = 0; col < width; col++, col3 += 3) { - GLubyte r = src[col3 + 0]; - GLubyte g = src[col3 + 1]; - GLubyte b = src[col3 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - GLint col3 = (col / wScale) * 3; - GLubyte r = src[col3 + 0]; - GLubyte g = src[col3 + 1]; - GLubyte b = src[col3 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case (used by Quake3) */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint col, col4; - for (col = col4 = 0; col < width; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - dst[col] = ((r & 0xf8) << 8) - | ((g & 0xfc) << 3) - | ((b & 0xf8) >> 3); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this srcFormat/srcType combination */ - return GL_FALSE; - } - break; - - case MESA_A4_R4_G4_B4: - /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */ - if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV){ - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - MEMCPY(dst, src, width * sizeof(GLushort)); - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLushort *src = (const GLushort *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint col, col4; - for (col = col4 = 0; col < width; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0xf0) << 8) - | ((r & 0xf0) << 4) - | ((g & 0xf0) ) - | ((b & 0xf0) >> 4); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0xf0) << 8) - | ((r & 0xf0) << 4) - | ((g & 0xf0) ) - | ((b & 0xf0) >> 4); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this format/srcType combination */ - return GL_FALSE; - } - break; - - case MESA_A1_R5_G5_B5: - /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */ - if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV){ - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - MEMCPY(dst, src, width * sizeof(GLushort)); - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLushort *src = (const GLushort *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint col, col4; - for (col = col4 = 0; col < width; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0x80) << 8) - | ((r & 0xf8) << 7) - | ((g & 0xf8) << 2) - | ((b & 0xf8) >> 3); - } - src += srcStride; - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLushort *dst = (GLushort *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3]; - dst[col] = ((a & 0x80) << 8) - | ((r & 0xf8) << 7) - | ((g & 0xf8) << 2) - | ((b & 0xf8) >> 3); - } - dst = (GLushort *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this source format/type combination */ - return GL_FALSE; - } - break; - - case MESA_A8_R8_G8_B8: - case MESA_FF_R8_G8_B8: - /* 32-bit texels */ - if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) { - /* special, optimized case */ - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLuint *dst = (GLuint *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - MEMCPY(dst, src, width * sizeof(GLuint)); - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLuint *dst = (GLuint *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLuint *src = (const GLuint *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - dst[col] = src[col / wScale]; - } - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - if (dstFormat == MESA_FF_R8_G8_B8) { - /* set alpha bytes to 0xff */ - GLint row, col; - GLubyte *dst = (GLubyte *) dstImage - + dstYoffset * dstRowStride + dstXoffset * 4; - assert(wScale == 1 && hScale == 1); /* XXX not done */ - for (row = 0; row < height; row++) { - for (col = 0; col < width; col++) { - dst[col * 4 + 3] = 0xff; - } - dst = dst + dstRowStride; - } - } - } - else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) { - /* general case */ - const GLubyte aMask = (dstFormat==MESA_FF_R8_G8_B8) ? 0xff : 0x00; - if (wScale == 1 && hScale == 1) { - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, srcHeight, - srcFormat, srcType, 0, 0, 0); - const GLint srcStride = _mesa_image_row_stride(packing, - width, srcFormat, srcType); - GLuint *dst = (GLuint *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint col, col4; - for (col = col4 = 0; col < width; col++, col4 += 4) { - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3] | aMask; - dst[col] = (a << 24) | (r << 16) | (g << 8) | b; - } - src += srcStride; - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - else { - /* must rescale image */ - GLuint *dst = (GLuint *) ((GLubyte *) dstImage - + dstYoffset * dstRowStride) + dstXoffset; - GLint row; - for (row = 0; row < height; row++) { - GLint srcRow = row / hScale; - const GLubyte *src = (const GLubyte *) - _mesa_image_address(packing, srcImage, srcWidth, - srcHeight, srcFormat, srcType, 0, srcRow, 0); - GLint col; - for (col = 0; col < width; col++) { - GLint col4 = (col / wScale) * 4; - GLubyte r = src[col4 + 0]; - GLubyte g = src[col4 + 1]; - GLubyte b = src[col4 + 2]; - GLubyte a = src[col4 + 3] | aMask; - dst[col] = (a << 24) | (r << 16) | (g << 8) | b; - } - dst = (GLuint *) ((GLubyte *) dst + dstRowStride); - } - } - } - else { - /* can't handle this source format/type combination */ - return GL_FALSE; - } - break; - - - default: - /* unexpected internal format! */ - return GL_FALSE; + const GLubyte *src = (const GLubyte *)convert->srcImage; + GLint texels, i; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_RGBA: + MEMCPY( convert->dstImage, src, texels * 4 ); + break; + case GL_RGB: { + GLubyte *dst = (GLubyte *)convert->dstImage; + for ( i = 0 ; i < texels ; i++ ) { + *dst++ = src[0]; + *dst++ = src[1]; + *dst++ = src[2]; + src += 4; + } + break; + } + default: + UNCONVERT_ERROR( convert->format ); + break; } - return GL_TRUE; } +/* ================================================================ + * ARGB8888 textures: + */ -/* - * Used to convert 16-bit texels into GLubyte color components. +#define DST_TYPE GLuint +#define DST_TEXELS_PER_DWORD 1 + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( src[3], src[2], src[1], src[0] ) + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_argb8888_direct +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( src[3], src[0], src[1], src[2] ) + +#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src ) + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_abgr8888_to_argb8888 +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_8888( 0xff, src[0], src[1], src[2] ) + +#define CONVERT_TEXEL_DWORD( src ) CONVERT_TEXEL( src ) + +#define SRC_TEXEL_BYTES 3 + +#define TAG(x) x##_bgr888_to_argb8888 +#include "texutil_tmp.h" + + +#define CONVERT_ARGB8888( name ) \ +static GLboolean \ +convert_##name##_argb8888( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( convert->format == GL_BGRA && \ + convert->type == GL_UNSIGNED_INT_8_8_8_8_REV ) \ + { \ + tab = name##_tab_argb8888_direct; \ + } \ + else if ( convert->format == GL_RGBA && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_abgr8888_to_argb8888; \ + } \ + else if ( convert->format == GL_RGB && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_bgr888_to_argb8888; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_ARGB8888( texsubimage2d ) +CONVERT_ARGB8888( texsubimage3d ) + + +static void +unconvert_teximage_argb8888( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *)convert->srcImage; + GLint texels, i; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_RGBA: { + GLuint *dst = (GLuint *)convert->dstImage; + for ( i = 0 ; i < texels ; i++ ) { + *dst++ = PACK_COLOR_8888( src[3], src[0], src[1], src[2] ); + src += 4; + } + break; + } + case GL_RGB: { + GLubyte *dst = (GLubyte *)convert->dstImage; + for ( i = 0 ; i < texels ; i++ ) { + *dst++ = src[2]; + *dst++ = src[1]; + *dst++ = src[0]; + src += 4; + } + break; + } + default: + UNCONVERT_ERROR( convert->format ); + break; + } +} + + + +/* ================================================================ + * RGB888 textures: + */ + +static GLboolean +convert_texsubimage2d_rgb888( struct gl_texture_convert *convert ) +{ + /* This is a placeholder for now... + */ + return GL_FALSE; +} + +static GLboolean +convert_texsubimage3d_rgb888( struct gl_texture_convert *convert ) +{ + /* This is a placeholder for now... + */ + return GL_FALSE; +} + + +static void +unconvert_teximage_rgb888( struct gl_texture_convert *convert ) +{ + UNCONVERT_ERROR( convert->format ); +} + + + +/* ================================================================ + * BGR888 textures: */ -static GLubyte R5G6B5toRed[0xffff]; -static GLubyte R5G6B5toGreen[0xffff]; -static GLubyte R5G6B5toBlue[0xffff]; -static GLubyte A4R4G4B4toRed[0xffff]; -static GLubyte A4R4G4B4toGreen[0xffff]; -static GLubyte A4R4G4B4toBlue[0xffff]; -static GLubyte A4R4G4B4toAlpha[0xffff]; +static GLboolean +convert_texsubimage2d_bgr888( struct gl_texture_convert *convert ) +{ + /* This is a placeholder for now... + */ + return GL_FALSE; +} + +static GLboolean +convert_texsubimage3d_bgr888( struct gl_texture_convert *convert ) +{ + /* This is a placeholder for now... + */ + return GL_FALSE; +} + + +static void +unconvert_teximage_bgr888( struct gl_texture_convert *convert ) +{ + UNCONVERT_ERROR( convert->format ); +} + + + +/* ================================================================ + * RGB565 textures: + */ + +#define DST_TYPE GLushort +#define DST_TEXELS_PER_DWORD 2 + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_565( src[0], src[1], src[2] ) + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 2 + +#define TAG(x) x##_rgb565_direct +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_565( src[0], src[1], src[2] ) + +#define CONVERT_TEXEL_DWORD( src ) \ + ((PACK_COLOR_565( src[0], src[1], src[2] )) | \ + (PACK_COLOR_565( src[3], src[4], src[5] ) << 16)) + +#define SRC_TEXEL_BYTES 3 + +#define TAG(x) x##_bgr888_to_rgb565 +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_565( src[0], src[1], src[2] ) + +#define CONVERT_TEXEL_DWORD( src ) \ + ((PACK_COLOR_565( src[0], src[1], src[2] )) | \ + (PACK_COLOR_565( src[4], src[5], src[6] ) << 16)) + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_abgr8888_to_rgb565 +#include "texutil_tmp.h" + + +#define CONVERT_RGB565( name ) \ +static GLboolean \ +convert_##name##_rgb565( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( convert->format == GL_RGB && \ + convert->type == GL_UNSIGNED_SHORT_5_6_5 ) \ + { \ + tab = name##_tab_rgb565_direct; \ + } \ + else if ( convert->format == GL_RGB && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_bgr888_to_rgb565; \ + } \ + else if ( convert->format == GL_RGBA && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_abgr8888_to_rgb565; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_RGB565( texsubimage2d ) +CONVERT_RGB565( texsubimage3d ) + + +static void +unconvert_teximage_rgb565( struct gl_texture_convert *convert ) +{ + const GLushort *src = (const GLushort *)convert->srcImage; + GLubyte *dst = (GLubyte *)convert->dstImage; + GLint texels, i; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_RGBA: + for ( i = 0 ; i < texels ; i++ ) { + GLushort s = *src++; + *dst++ = ((s >> 8) & 0xf8) * 255 / 0xf8; + *dst++ = ((s >> 3) & 0xfc) * 255 / 0xfc; + *dst++ = ((s << 3) & 0xf8) * 255 / 0xf8; + *dst++ = 0xff; + } + break; + case GL_RGB: + for ( i = 0 ; i < texels ; i++ ) { + GLushort s = *src++; + *dst++ = ((s >> 8) & 0xf8) * 255 / 0xf8; + *dst++ = ((s >> 3) & 0xfc) * 255 / 0xfc; + *dst++ = ((s << 3) & 0xf8) * 255 / 0xf8; + } + break; + default: + UNCONVERT_ERROR( convert->format ); + break; + } +} + + + +/* ================================================================ + * ARGB4444 textures: + */ + +#define DST_TYPE GLushort +#define DST_TEXELS_PER_DWORD 2 + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_4444( src[3], src[0], src[1], src[2] ) + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 2 + +#define TAG(x) x##_argb4444_direct +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_4444( src[3], src[0], src[1], src[2] ) + +#define CONVERT_TEXEL_DWORD( src ) \ + ((PACK_COLOR_4444( src[3], src[0], src[1], src[2] )) | \ + (PACK_COLOR_4444( src[7], src[4], src[5], src[6] ) << 16)) + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_rgba8888_to_argb4444 +#include "texutil_tmp.h" + + +#define CONVERT_ARGB4444( name ) \ +static GLboolean \ +convert_##name##_argb4444( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( convert->format == GL_BGRA && \ + convert->type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) \ + { \ + tab = name##_tab_argb4444_direct; \ + } \ + else if ( convert->format == GL_RGBA && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_rgba8888_to_argb4444; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_ARGB4444( texsubimage2d ) +CONVERT_ARGB4444( texsubimage3d ) -static GLubyte A1R5G5B5toRed[0xffff]; -static GLubyte A1R5G5B5toGreen[0xffff]; -static GLubyte A1R5G5B5toBlue[0xffff]; -static GLubyte A1R5G5B5toAlpha[0xffff]; static void -generate_lookup_tables(void) +unconvert_teximage_argb4444( struct gl_texture_convert *convert ) { - GLint i; - for (i = 0; i <= 0xffff; i++) { - GLint r = (i >> 8) & 0xf8; - GLint g = (i >> 3) & 0xfc; - GLint b = (i << 3) & 0xf8; - r = r * 255 / 0xf8; - g = g * 255 / 0xfc; - b = b * 255 / 0xf8; - R5G6B5toRed[i] = r; - R5G6B5toGreen[i] = g; - R5G6B5toBlue[i] = b; + const GLushort *src = (const GLushort *)convert->srcImage; + GLubyte *dst = (GLubyte *)convert->dstImage; + GLint texels, i; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_RGBA: + for ( i = 0 ; i < texels ; i++ ) { + GLushort s = *src++; + *dst++ = ((s >> 8) & 0xf) * 255 / 0xf; + *dst++ = ((s >> 4) & 0xf) * 255 / 0xf; + *dst++ = ((s ) & 0xf) * 255 / 0xf; + *dst++ = ((s >> 12) & 0xf) * 255 / 0xf; + } + break; + default: + UNCONVERT_ERROR( convert->format ); + break; } +} + + + +/* ================================================================ + * ARGB1555 textures: + */ + +#define DST_TYPE GLushort +#define DST_TEXELS_PER_DWORD 2 + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_1555( src[3], src[0], src[1], src[2] ) + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 2 - for (i = 0; i <= 0xffff; i++) { - GLint r = (i >> 8) & 0xf; - GLint g = (i >> 4) & 0xf; - GLint b = (i ) & 0xf; - GLint a = (i >> 12) & 0xf; - r = r * 255 / 0xf; - g = g * 255 / 0xf; - b = b * 255 / 0xf; - a = a * 255 / 0xf; - A4R4G4B4toRed[i] = r; - A4R4G4B4toGreen[i] = g; - A4R4G4B4toBlue[i] = b; - A4R4G4B4toAlpha[i] = a; +#define TAG(x) x##_argb1555_direct +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_1555( src[3], src[0], src[1], src[2] ) + +#define CONVERT_TEXEL_DWORD( src ) \ + ((PACK_COLOR_1555( src[3], src[0], src[1], src[2] )) | \ + (PACK_COLOR_1555( src[7], src[4], src[5], src[6] ) << 16)) + +#define SRC_TEXEL_BYTES 4 + +#define TAG(x) x##_rgba8888_to_argb1555 +#include "texutil_tmp.h" + + +#define CONVERT_ARGB1555( name ) \ +static GLboolean \ +convert_##name##_argb1555( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( convert->format == GL_BGRA && \ + convert->type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) \ + { \ + tab = name##_tab_argb1555_direct; \ + } \ + else if ( convert->format == GL_RGBA && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_rgba8888_to_argb1555; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_ARGB1555( texsubimage2d ) +CONVERT_ARGB1555( texsubimage3d ) + + +static void +unconvert_teximage_argb1555( struct gl_texture_convert *convert ) +{ + const GLushort *src = (const GLushort *)convert->srcImage; + GLubyte *dst = (GLubyte *)convert->dstImage; + GLint texels, i; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_RGBA: + for ( i = 0 ; i < texels ; i++ ) { + GLushort s = *src++; + *dst++ = ((s >> 10) & 0xf8) * 255 / 0xf8; + *dst++ = ((s >> 5) & 0xf8) * 255 / 0xf8; + *dst++ = ((s ) & 0xf8) * 255 / 0xf8; + *dst++ = ((s >> 15) & 0x01) * 255; + } + break; + default: + UNCONVERT_ERROR( convert->format ); + break; } +} + + + +/* ================================================================ + * AL88 textures: + */ + +#define DST_TYPE GLushort +#define DST_TEXELS_PER_DWORD 2 - for (i = 0; i <= 0xffff; i++) { - GLint r = (i >> 10) & 0xf8; - GLint g = (i >> 5) & 0xf8; - GLint b = (i ) & 0xf8; - GLint a = (i >> 15) & 0x1; - r = r * 255 / 0xf8; - g = g * 255 / 0xf8; - b = b * 255 / 0xf8; - a = a * 255; - A1R5G5B5toRed[i] = r; - A1R5G5B5toGreen[i] = g; - A1R5G5B5toBlue[i] = b; - A1R5G5B5toAlpha[i] = a; +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_88( src[0], src[1] ) + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 2 + +#define TAG(x) x##_al88_direct +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_88( src[0], 0x00 ) + +#define CONVERT_TEXEL_DWORD( src ) \ + ((PACK_COLOR_88( src[0], 0x00 )) | \ + (PACK_COLOR_88( src[1], 0x00 ) << 16)) + +#define SRC_TEXEL_BYTES 1 + +#define TAG(x) x##_a8_to_al88 +#define PRESERVE_DST_TYPE +#include "texutil_tmp.h" + + +#define CONVERT_TEXEL( src ) \ + PACK_COLOR_88( 0xff, src[0] ) + +#define CONVERT_TEXEL_DWORD( src ) \ + ((PACK_COLOR_88( 0xff, src[0] )) | \ + (PACK_COLOR_88( 0xff, src[1] ) << 16)) + +#define SRC_TEXEL_BYTES 1 + +#define TAG(x) x##_l8_to_al88 +#include "texutil_tmp.h" + + +#define CONVERT_AL88( name ) \ +static GLboolean \ +convert_##name##_al88( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( convert->format == GL_LUMINANCE_ALPHA && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_al88_direct; \ + } \ + else if ( convert->format == GL_ALPHA && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_a8_to_al88; \ + } \ + else if ( convert->format == GL_LUMINANCE && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_l8_to_al88; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_AL88( texsubimage2d ) +CONVERT_AL88( texsubimage3d ) + + +static void +unconvert_teximage_al88( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *)convert->srcImage; + GLint texels, i; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_LUMINANCE_ALPHA: + MEMCPY( convert->dstImage, src, texels * 2 ); + break; + case GL_ALPHA: { + GLubyte *dst = (GLubyte *)convert->dstImage; + for ( i = 0 ; i < texels ; i++ ) { + *dst++ = src[1]; + src += 2; + } + break; + } + case GL_LUMINANCE: { + GLubyte *dst = (GLubyte *)convert->dstImage; + for ( i = 0 ; i < texels ; i++ ) { + *dst++ = src[0]; + src += 2; + } + break; + } + default: + UNCONVERT_ERROR( convert->format ); + break; } } -/* - * Convert a texture image from an internal format to one of Mesa's - * core internal formats. This is likely to be used by glGetTexImage - * and for fetching texture images when falling back to software rendering. - * - * Input: - * srcFormat - source image format - * srcWidth, srcHeight - source image size - * srcImage - source image pointer - * srcRowStride - bytes to jump between image rows - * dstWidth, dstHeight - size of dest image - * dstFormat - format of dest image (must be one of Mesa's IntFormat values) - * dstImage - pointer to dest image - * Notes: - * This function will do power of two image down-scaling to accomodate - * drivers with limited texture image aspect ratios. - * The implicit dest data type is GL_UNSIGNED_BYTE. +/* ================================================================ + * RGB332 textures: + */ + +static GLboolean +convert_texsubimage2d_rgb332( struct gl_texture_convert *convert ) +{ + /* This is a placeholder for now... + */ + return GL_FALSE; +} + +static GLboolean +convert_texsubimage3d_rgb332( struct gl_texture_convert *convert ) +{ + /* This is a placeholder for now... + */ + return GL_FALSE; +} + + +static void +unconvert_teximage_rgb332( struct gl_texture_convert *convert ) +{ + UNCONVERT_ERROR( convert->format ); +} + + + +/* ================================================================ + * CI8 (and all other single-byte texel) textures: */ -void -_mesa_unconvert_teximage(MesaIntTexFormat srcFormat, - GLint srcWidth, GLint srcHeight, - const GLvoid *srcImage, GLint srcRowStride, - GLint dstWidth, GLint dstHeight, - GLenum dstFormat, GLubyte *dstImage) + +#define DST_TYPE GLubyte +#define DST_TEXELS_PER_DWORD 4 + +#define CONVERT_TEXEL( src ) src[0] + +#define CONVERT_DIRECT + +#define SRC_TEXEL_BYTES 1 + +#define TAG(x) x##_ci8_direct +#include "texutil_tmp.h" + + +#define CONVERT_CI8( name ) \ +static GLboolean \ +convert_##name##_ci8( struct gl_texture_convert *convert ) \ +{ \ + convert_func *tab; \ + GLint index = convert->index; \ + \ + if ( ( convert->format == GL_ALPHA || \ + convert->format == GL_LUMINANCE || \ + convert->format == GL_INTENSITY || \ + convert->format == GL_COLOR_INDEX ) && \ + convert->type == GL_UNSIGNED_BYTE ) \ + { \ + tab = name##_tab_ci8_direct; \ + } \ + else \ + { \ + /* Can't handle this source format/type combination */ \ + return GL_FALSE; \ + } \ + \ + return tab[index]( convert ); \ +} + +CONVERT_CI8( texsubimage2d ) +CONVERT_CI8( texsubimage3d ) + + +static void +unconvert_teximage_ci8( struct gl_texture_convert *convert ) { - static GLboolean firstCall = GL_TRUE; - const GLint wScale = srcWidth / dstWidth; /* must be power of two */ - const GLint hScale = srcHeight / dstHeight; /* must be power of two */ - ASSERT(srcWidth >= dstWidth); - ASSERT(srcHeight >= dstHeight); - ASSERT(dstImage); - ASSERT(srcImage); - - if (firstCall) { - generate_lookup_tables(); - firstCall = GL_FALSE; + const GLubyte *src = (const GLubyte *)convert->srcImage; + GLint texels; + + texels = convert->width * convert->height * convert->depth; + + switch ( convert->format ) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + case GL_COLOR_INDEX: + MEMCPY( convert->dstImage, src, texels ); + break; + default: + UNCONVERT_ERROR( convert->format ); + break; } +} - switch (srcFormat) { - case MESA_I8: - case MESA_L8: - case MESA_A8: - case MESA_C8: -#ifdef DEBUG - if (srcFormat == MESA_I8) { - ASSERT(dstFormat == GL_INTENSITY); - } - else if (srcFormat == MESA_L8) { - ASSERT(dstFormat == GL_LUMINANCE); - } - else if (srcFormat == MESA_A8) { - ASSERT(dstFormat == GL_ALPHA); - } - else if (srcFormat == MESA_C8) { - ASSERT(dstFormat == GL_COLOR_INDEX); - } -#endif - if (wScale == 1 && hScale == 1) { - /* easy! */ - MEMCPY(dstImage, srcImage, dstWidth * dstHeight * sizeof(GLubyte)); - } - else { - /* rescale */ - const GLubyte *src8 = (const GLubyte *) srcImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row * hScale; - for (col = 0; col < dstWidth; col++) { - GLint srcCol = col * wScale; - *dstImage++ = src8[srcRow * srcWidth + srcCol]; - } - } - } - break; - case MESA_A8_L8: - ASSERT(dstFormat == GL_LUMINANCE_ALPHA); - if (wScale == 1 && hScale == 1) { - GLint i, n = dstWidth * dstHeight; - const GLushort *texel = (const GLushort *) srcImage; - for (i = 0; i < n; i++) { - const GLushort tex = *texel++; - *dstImage++ = (tex & 0xff); /* luminance */ - *dstImage++ = (tex >> 8); /* alpha */ - } - } - else { - /* rescale */ - const GLushort *src16 = (const GLushort *) srcImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row * hScale; - for (col = 0; col < dstWidth; col++) { - GLint srcCol = col * wScale; - const GLushort tex = src16[srcRow * srcWidth + srcCol]; - *dstImage++ = (tex & 0xff); /* luminance */ - *dstImage++ = (tex >> 8); /* alpha */ - } - } - } - break; - case MESA_R5_G6_B5: - ASSERT(dstFormat == GL_RGB); - if (wScale == 1 && hScale == 1) { - GLint i, n = dstWidth * dstHeight; - const GLushort *texel = (const GLushort *) srcImage; - for (i = 0; i < n; i++) { - const GLushort tex = *texel++; - *dstImage++ = R5G6B5toRed[tex]; - *dstImage++ = R5G6B5toGreen[tex]; - *dstImage++ = R5G6B5toBlue[tex]; - } - } - else { - /* rescale */ - const GLushort *src16 = (const GLushort *) srcImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row * hScale; - for (col = 0; col < dstWidth; col++) { - GLint srcCol = col * wScale; - const GLushort tex = src16[srcRow * srcWidth + srcCol]; - *dstImage++ = R5G6B5toRed[tex]; - *dstImage++ = R5G6B5toGreen[tex]; - *dstImage++ = R5G6B5toBlue[tex]; - } - } - } - break; - case MESA_A4_R4_G4_B4: - ASSERT(dstFormat == GL_RGBA); - if (wScale == 1 && hScale == 1) { - GLint i, n = dstWidth * dstHeight; - const GLushort *texel = (const GLushort *) srcImage; - for (i = 0; i < n; i++) { - const GLushort tex = *texel++; - *dstImage++ = A4R4G4B4toRed[tex]; - *dstImage++ = A4R4G4B4toGreen[tex]; - *dstImage++ = A4R4G4B4toBlue[tex]; - *dstImage++ = A4R4G4B4toAlpha[tex]; - } - } - else { - /* rescale */ - const GLushort *src16 = (const GLushort *) srcImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row * hScale; - for (col = 0; col < dstWidth; col++) { - GLint srcCol = col * wScale; - const GLushort tex = src16[srcRow * srcWidth + srcCol]; - *dstImage++ = A4R4G4B4toRed[tex]; - *dstImage++ = A4R4G4B4toGreen[tex]; - *dstImage++ = A4R4G4B4toBlue[tex]; - *dstImage++ = A4R4G4B4toAlpha[tex]; - } - } - } - break; - case MESA_A1_R5_G5_B5: - ASSERT(dstFormat == GL_RGBA); - if (wScale == 1 && hScale == 1) { - GLint i, n = dstWidth * dstHeight; - const GLushort *texel = (const GLushort *) srcImage; - for (i = 0; i < n; i++) { - const GLushort tex = *texel++; - *dstImage++ = A1R5G5B5toRed[tex]; - *dstImage++ = A1R5G5B5toGreen[tex]; - *dstImage++ = A1R5G5B5toBlue[tex]; - *dstImage++ = A1R5G5B5toAlpha[tex]; - } - } - else { - /* rescale */ - const GLushort *src16 = (const GLushort *) srcImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row * hScale; - for (col = 0; col < dstWidth; col++) { - GLint srcCol = col * wScale; - const GLushort tex = src16[srcRow * srcWidth + srcCol]; - *dstImage++ = A1R5G5B5toRed[tex]; - *dstImage++ = A1R5G5B5toGreen[tex]; - *dstImage++ = A1R5G5B5toBlue[tex]; - *dstImage++ = A1R5G5B5toAlpha[tex]; - } - } - } - break; - case MESA_A8_R8_G8_B8: - case MESA_FF_R8_G8_B8: - ASSERT(dstFormat == GL_RGBA); - if (wScale == 1 && hScale == 1) { - GLint i, n = dstWidth * dstHeight; - const GLuint *texel = (const GLuint *) srcImage; - for (i = 0; i < n; i++) { - const GLuint tex = *texel++; - *dstImage++ = (tex >> 16) & 0xff; /* R */ - *dstImage++ = (tex >> 8) & 0xff; /* G */ - *dstImage++ = (tex ) & 0xff; /* B */ - *dstImage++ = (tex >> 24) & 0xff; /* A */ - } - } - else { - /* rescale */ - const GLuint *src = (const GLuint *) srcImage; - GLint row, col; - for (row = 0; row < dstHeight; row++) { - GLint srcRow = row * hScale; - for (col = 0; col < dstWidth; col++) { - GLint srcCol = col * wScale; - const GLuint tex = src[srcRow * srcWidth + srcCol]; - *dstImage++ = (tex >> 16) & 0xff; /* R */ - *dstImage++ = (tex >> 8) & 0xff; /* G */ - *dstImage++ = (tex ) & 0xff; /* B */ - *dstImage++ = (tex >> 24) & 0xff; /* A */ - } - } - } - break; - default: - gl_problem(NULL, "bad srcFormat in _mesa_uncovert_teximage()"); + + +/* ================================================================ + * Global entry points + */ + +static convert_func gl_convert_texsubimage2d_tab[] = { + convert_texsubimage2d_rgba8888, + convert_texsubimage2d_abgr8888, + convert_texsubimage2d_argb8888, + convert_texsubimage2d_rgb888, + convert_texsubimage2d_bgr888, + convert_texsubimage2d_rgb565, + convert_texsubimage2d_argb4444, + convert_texsubimage2d_argb1555, + convert_texsubimage2d_al88, + convert_texsubimage2d_rgb332, + convert_texsubimage2d_ci8, /* These are all the same... */ + convert_texsubimage2d_ci8, + convert_texsubimage2d_ci8, + convert_texsubimage2d_ci8, +}; + +static convert_func gl_convert_texsubimage3d_tab[] = { + convert_texsubimage3d_rgba8888, + convert_texsubimage3d_abgr8888, + convert_texsubimage3d_argb8888, + convert_texsubimage3d_rgb888, + convert_texsubimage3d_bgr888, + convert_texsubimage3d_rgb565, + convert_texsubimage3d_argb4444, + convert_texsubimage3d_argb1555, + convert_texsubimage3d_al88, + convert_texsubimage3d_rgb332, + convert_texsubimage3d_ci8, /* These are all the same... */ + convert_texsubimage3d_ci8, + convert_texsubimage3d_ci8, + convert_texsubimage3d_ci8, +}; + +static unconvert_func gl_unconvert_teximage_tab[] = { + unconvert_teximage_rgba8888, + unconvert_teximage_abgr8888, + unconvert_teximage_argb8888, + unconvert_teximage_rgb888, + unconvert_teximage_bgr888, + unconvert_teximage_rgb565, + unconvert_teximage_argb4444, + unconvert_teximage_argb1555, + unconvert_teximage_al88, + unconvert_teximage_rgb332, + unconvert_teximage_ci8, /* These are all the same... */ + unconvert_teximage_ci8, + unconvert_teximage_ci8, + unconvert_teximage_ci8, +}; + + +/* See if we need to care about the pixel store attributes when we're + * converting the texture image. This should be stored as + * packing->_SomeBoolean and updated when the values change, to avoid + * testing every time... + */ +static INLINE GLboolean +convert_needs_packing( const struct gl_pixelstore_attrib *packing, + GLenum format, GLenum type ) +{ + if ( ( packing->Alignment == 1 || + ( packing->Alignment == 4 && /* Pick up the common Q3A case... */ + format == GL_RGBA && type == GL_UNSIGNED_BYTE ) ) && + packing->RowLength == 0 && + packing->SkipPixels == 0 && + packing->SkipRows == 0 && + packing->ImageHeight == 0 && + packing->SkipImages == 0 && + packing->SwapBytes == GL_FALSE && + packing->LsbFirst == GL_FALSE ) { + return GL_FALSE; + } else { + return GL_TRUE; } } +GLboolean +_mesa_convert_texsubimage1d( GLint mesaFormat, + GLint xoffset, + GLint width, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing, + const GLvoid *srcImage, GLvoid *dstImage ) +{ + struct gl_texture_convert convert; -/* - * Given an internal Mesa driver texture format, fill in the component - * bit sizes in the given texture image struct. + ASSERT( packing ); + ASSERT( srcImage ); + ASSERT( dstImage ); + + ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 ); + ASSERT( mesaFormat <= MESA_FORMAT_CI8 ); + + /* Make it easier to pass all the parameters around. + */ + convert.xoffset = xoffset; + convert.yoffset = 0; + convert.width = width; + convert.height = 1; + convert.format = format; + convert.type = type; + convert.packing = packing; + convert.srcImage = srcImage; + convert.dstImage = dstImage; + + convert.index = 0; + + if ( convert_needs_packing( packing, format, type ) ) + convert.index |= CONVERT_PACKING_BIT; + + return gl_convert_texsubimage2d_tab[mesaFormat]( &convert ); +} + +GLboolean +_mesa_convert_texsubimage2d( GLint mesaFormat, + GLint xoffset, GLint yoffset, + GLint width, GLint height, + GLint imageWidth, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing, + const GLvoid *srcImage, GLvoid *dstImage ) +{ + struct gl_texture_convert convert; + + ASSERT( packing ); + ASSERT( srcImage ); + ASSERT( dstImage ); + + ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 ); + ASSERT( mesaFormat <= MESA_FORMAT_CI8 ); + + /* Make it easier to pass all the parameters around. + */ + convert.xoffset = xoffset; + convert.yoffset = yoffset; + convert.width = width; + convert.height = height; + convert.imageWidth = imageWidth; + convert.format = format; + convert.type = type; + convert.packing = packing; + convert.srcImage = srcImage; + convert.dstImage = dstImage; + + convert.index = 0; + + if ( convert_needs_packing( packing, format, type ) ) + convert.index |= CONVERT_PACKING_BIT; + + if ( width != imageWidth ) + convert.index |= CONVERT_STRIDE_BIT; + + return gl_convert_texsubimage2d_tab[mesaFormat]( &convert ); +} + +GLboolean +_mesa_convert_texsubimage3d( GLint mesaFormat, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLint imageWidth, GLint imageHeight, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing, + const GLvoid *srcImage, GLvoid *dstImage ) +{ + struct gl_texture_convert convert; + + ASSERT( packing ); + ASSERT( srcImage ); + ASSERT( dstImage ); + + ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 ); + ASSERT( mesaFormat <= MESA_FORMAT_CI8 ); + + /* Make it easier to pass all the parameters around. + */ + convert.xoffset = xoffset; + convert.yoffset = yoffset; + convert.zoffset = zoffset; + convert.width = width; + convert.height = height; + convert.depth = depth; + convert.imageWidth = imageWidth; + convert.imageHeight = imageHeight; + convert.format = format; + convert.type = type; + convert.packing = packing; + convert.srcImage = srcImage; + convert.dstImage = dstImage; + + convert.index = 0; + + if ( convert_needs_packing( packing, format, type ) ) + convert.index |= CONVERT_PACKING_BIT; + + if ( width != imageWidth || height != imageHeight ) + convert.index |= CONVERT_STRIDE_BIT; + + return gl_convert_texsubimage3d_tab[mesaFormat]( &convert ); +} + + + +void _mesa_unconvert_teximage1d( GLint mesaFormat, GLenum format, GLint width, + const GLvoid *srcImage, GLvoid *dstImage ) +{ + struct gl_texture_convert convert; + + ASSERT( srcImage ); + ASSERT( dstImage ); + + ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 ); + ASSERT( mesaFormat <= MESA_FORMAT_CI8 ); + + /* Make it easier to pass all the parameters around. + */ + convert.width = width; + convert.height = 1; + convert.depth = 1; + convert.format = format; + convert.srcImage = srcImage; + convert.dstImage = dstImage; + + gl_unconvert_teximage_tab[mesaFormat]( &convert ); +} + +void _mesa_unconvert_teximage2d( GLint mesaFormat, GLenum format, + GLint width, GLint height, + const GLvoid *srcImage, GLvoid *dstImage ) +{ + struct gl_texture_convert convert; + + ASSERT( srcImage ); + ASSERT( dstImage ); + + ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 ); + ASSERT( mesaFormat <= MESA_FORMAT_CI8 ); + + /* Make it easier to pass all the parameters around. + */ + convert.width = width; + convert.height = height; + convert.depth = 1; + convert.format = format; + convert.srcImage = srcImage; + convert.dstImage = dstImage; + + gl_unconvert_teximage_tab[mesaFormat]( &convert ); +} + +void _mesa_unconvert_teximage3d( GLint mesaFormat, GLenum format, + GLint width, GLint height, GLint depth, + const GLvoid *srcImage, GLvoid *dstImage ) +{ + struct gl_texture_convert convert; + + ASSERT( srcImage ); + ASSERT( dstImage ); + + ASSERT( mesaFormat >= MESA_FORMAT_RGBA8888 ); + ASSERT( mesaFormat <= MESA_FORMAT_CI8 ); + + /* Make it easier to pass all the parameters around. + */ + convert.width = width; + convert.height = height; + convert.depth = depth; + convert.format = format; + convert.srcImage = srcImage; + convert.dstImage = dstImage; + + gl_unconvert_teximage_tab[mesaFormat]( &convert ); +} + + + +/* Nearest filtering only (for broken hardware that can't support + * all aspect ratios). This can be made a lot faster, but I don't + * really care enough... */ -void -_mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat, - struct gl_texture_image *texImage) +void _mesa_rescale_teximage2d( const struct gl_texture_format *texFormat, + GLint srcWidth, GLint srcHeight, + GLint dstWidth, GLint dstHeight, + const GLvoid *srcImage, GLvoid *dstImage ) { - static const GLint bitSizes [][8] = { - /* format R G B A I L C */ - { MESA_I8, 0, 0, 0, 0, 8, 0, 0 }, - { MESA_L8, 0, 0, 0, 0, 0, 8, 0 }, - { MESA_A8, 0, 0, 0, 8, 0, 0, 0 }, - { MESA_C8, 0, 0, 0, 0, 0, 0, 8 }, - { MESA_A8_L8, 0, 0, 0, 8, 0, 8, 0 }, - { MESA_R5_G6_B5, 5, 6, 5, 0, 0, 0, 0 }, - { MESA_A4_R4_G4_B4, 4, 4, 4, 4, 0, 0, 0 }, - { MESA_A1_R5_G5_B5, 5, 5, 5, 1, 0, 0, 0 }, - { MESA_A8_R8_G8_B8, 8, 8, 8, 8, 0, 0, 0 }, - { MESA_FF_R8_G8_B8, 8, 8, 8, 8, 0, 0, 0 }, - { -1, 0, 0, 0, 0, 0, 0, 0 } - }; - GLint i; - for (i = 0; i < bitSizes[i][0] >= 0; i++) { - if (bitSizes[i][0] == mesaFormat) { - texImage->RedBits = bitSizes[i][1]; - texImage->GreenBits = bitSizes[i][2]; - texImage->BlueBits = bitSizes[i][3]; - texImage->AlphaBits = bitSizes[i][4]; - texImage->IntensityBits = bitSizes[i][5]; - texImage->LuminanceBits = bitSizes[i][6]; - texImage->IndexBits = bitSizes[i][7]; - return; - } + GLint row, col; + +#define INNER_LOOP( HOP, WOP ) \ + for ( row = 0 ; row < dstHeight ; row++ ) { \ + GLint srcRow = row HOP hScale; \ + for ( col = 0 ; col < dstWidth ; col++ ) { \ + GLint srcCol = col WOP wScale; \ + *dst++ = src[srcRow * srcWidth + srcCol]; \ + } \ + } \ + +#define RESCALE_IMAGE( TYPE ) \ +do { \ + const TYPE *src = (const TYPE *)srcImage; \ + TYPE *dst = (TYPE *)dstImage; \ + \ + if ( srcHeight <= dstHeight ) { \ + const GLint hScale = dstHeight / srcHeight; \ + if ( srcWidth <= dstWidth ) { \ + const GLint wScale = dstWidth / srcWidth; \ + INNER_LOOP( /, / ); \ + } \ + else { \ + const GLint wScale = srcWidth / dstWidth; \ + INNER_LOOP( /, * ); \ + } \ + } \ + else { \ + const GLint hScale = srcHeight / dstHeight; \ + if ( srcWidth <= dstWidth ) { \ + const GLint wScale = dstWidth / srcWidth; \ + INNER_LOOP( *, / ); \ + } \ + else { \ + const GLint wScale = srcWidth / dstWidth; \ + INNER_LOOP( *, * ); \ + } \ + } \ +} while (0) + + switch ( texFormat->TexelBytes ) { + case 4: + RESCALE_IMAGE( GLuint ); + break; + + case 2: + RESCALE_IMAGE( GLushort ); + break; + + case 1: + RESCALE_IMAGE( GLubyte ); + break; } - gl_problem(NULL, "bad format in _mesa_set_teximage_component_sizes"); } diff --git a/xc/extras/Mesa/src/texutil.h b/xc/extras/Mesa/src/texutil.h index 22e916d50..a3e842667 100644 --- a/xc/extras/Mesa/src/texutil.h +++ b/xc/extras/Mesa/src/texutil.h @@ -2,91 +2,86 @@ /* * Mesa 3-D graphics library * Version: 3.4 - * + * * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes <gareth@valinux.com> */ #ifndef TEXUTIL_H #define TEXUTIL_H - #include "types.h" - - - -/* - * NOTE: "FF" means fill with byte value 0xff - */ - /* msb <------ TEXEL BITS -----------> lsb */ -typedef enum { /* ---- ---- ---- ---- ---- ---- ---- ---- */ - MESA_I8, /* IIII IIII */ - MESA_L8, /* LLLL LLLL */ - MESA_A8, /* AAAA AAAA */ - MESA_C8, /* CCCC CCCC */ - MESA_A8_L8, /* AAAA AAAA LLLL LLLL */ - MESA_R5_G6_B5, /* RRRR RGGG GGGB BBBB */ - MESA_A4_R4_G4_B4, /* AAAA RRRR GGGG BBBB */ - MESA_A1_R5_G5_B5, /* ARRR RRGG GGGB BBBB */ - MESA_A8_R8_G8_B8, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ - MESA_FF_R8_G8_B8 /* FFFF FFFF RRRR RRRR GGGG GGGG BBBB BBBB */ -} MesaIntTexFormat; - - - +#include "texformat.h" extern GLboolean -_mesa_convert_teximage(MesaIntTexFormat dstFormat, - GLint dstWidth, GLint dstHeight, GLvoid *dstImage, - GLint dstRowStride, - GLint srcWidth, GLint srcHeight, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcImage, - const struct gl_pixelstore_attrib *packing); - - +_mesa_convert_texsubimage1d( GLint mesaFormat, + GLint xoffset, + GLint width, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing, + const GLvoid *srcImage, GLvoid *dstImage ); extern GLboolean -_mesa_convert_texsubimage(MesaIntTexFormat dstFormat, - GLint dstXoffset, GLint dstYoffset, - GLint dstWidth, GLint dstHeight, GLvoid *dstImage, - GLint dstRowStride, - GLint width, GLint height, - GLint srcWidth, GLint srcHeight, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcImage, - const struct gl_pixelstore_attrib *packing); - +_mesa_convert_texsubimage2d( GLint mesaFormat, + GLint xoffset, GLint yoffset, + GLint width, GLint height, + GLint imageWidth, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing, + const GLvoid *srcImage, GLvoid *dstImage ); +extern GLboolean +_mesa_convert_texsubimage3d( GLint mesaFormat, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLint imageWidth, GLint imageHeight, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing, + const GLvoid *srcImage, GLvoid *dstImage ); + +/* Deprecated in 3.5: + */ extern void -_mesa_unconvert_teximage(MesaIntTexFormat srcFormat, - GLint srcWidth, GLint srcHeight, - const GLvoid *srcImage, GLint srcRowStride, - GLint dstWidth, GLint dstHeight, - GLenum dstFormat, GLubyte *dstImage); +_mesa_unconvert_teximage1d( GLint mesaFormat, GLenum format, GLint width, + const GLvoid *srcImage, GLvoid *dstImage ); +extern void +_mesa_unconvert_teximage2d( GLint mesaFormat, GLenum format, + GLint width, GLint height, + const GLvoid *srcImage, GLvoid *dstImage ); extern void -_mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat, - struct gl_texture_image *texImage); +_mesa_unconvert_teximage3d( GLint mesaFormat, GLenum format, + GLint width, GLint height, GLint depth, + const GLvoid *srcImage, GLvoid *dstImage ); +/* Nearest filtering only (for broken hardware that can't support + * all aspect ratios). FIXME: Make this a subimage update as well... + */ +extern void +_mesa_rescale_teximage2d( const struct gl_texture_format *texFormat, + GLint srcWidth, GLint srcHeight, + GLint dstWidth, GLint dstHeight, + const GLvoid *srcImage, GLvoid *dstImage ); #endif - diff --git a/xc/extras/Mesa/src/texutil_tmp.h b/xc/extras/Mesa/src/texutil_tmp.h new file mode 100644 index 000000000..ea6c4ee52 --- /dev/null +++ b/xc/extras/Mesa/src/texutil_tmp.h @@ -0,0 +1,375 @@ +/* + * NOTE: All 3D code is untested and most definitely broken... + */ + +#define DST_TEXEL_BYTES (4 / DST_TEXELS_PER_DWORD) +#define DST_ROW_WIDTH (convert->width * DST_TEXEL_BYTES) +#define DST_ROW_STRIDE (convert->imageWidth * DST_TEXEL_BYTES) +#define DST_IMG_STRIDE (convert->imageWidth * \ + convert->imageHeight * DST_TEXEL_BYTES) + + +/* ================================================================ + * PRE: No pixelstore attribs, width == imageWidth. + */ +static GLboolean +TAG(texsubimage2d)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *)convert->srcImage; + GLuint *dst = (GLuint *)((GLubyte *)convert->dstImage + + (convert->yoffset * convert->imageWidth + + convert->xoffset) * DST_TEXEL_BYTES); + GLint dwords, i; + (void) dwords; (void) i; + + if ( DBG ) + fprintf( stderr, __FUNCTION__ "\n" ); + +#ifdef CONVERT_DIRECT + MEMCPY( dst, src, convert->height * DST_ROW_WIDTH ); +#else + dwords = (convert->width * convert->height + + DST_TEXELS_PER_DWORD - 1) / DST_TEXELS_PER_DWORD; + + for ( i = 0 ; i < dwords ; i++ ) { + *dst++ = CONVERT_TEXEL_DWORD( src ); + src += SRC_TEXEL_BYTES * DST_TEXELS_PER_DWORD; + } +#endif + + return GL_TRUE; +} + +/* PRE: As above, height == imageHeight also. + */ +static GLboolean +TAG(texsubimage3d)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *)convert->srcImage; + GLuint *dst = (GLuint *)((GLubyte *)convert->dstImage + + ((convert->zoffset * convert->height + + convert->yoffset) * convert->width + + convert->xoffset) * DST_TEXEL_BYTES); + GLint dwords, i; + (void) dwords; (void) i; + + if ( DBG ) + fprintf( stderr, __FUNCTION__ "\n" ); + +#ifdef CONVERT_DIRECT + MEMCPY( dst, src, convert->depth * convert->height * DST_ROW_WIDTH ); +#else + dwords = (convert->width * convert->height * convert->depth + + DST_TEXELS_PER_DWORD - 1) / DST_TEXELS_PER_DWORD; + + for ( i = 0 ; i < dwords ; i++ ) { + *dst++ = CONVERT_TEXEL_DWORD( src ); + src += SRC_TEXEL_BYTES * DST_TEXELS_PER_DWORD; + } +#endif + + return GL_TRUE; +} + + + +/* ================================================================ + * PRE: No pixelstore attribs, width != imageWidth. + */ +static GLboolean +TAG(texsubimage2d_stride)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *)convert->srcImage; + DST_TYPE *dst = (DST_TYPE *)((GLubyte *)convert->dstImage + + (convert->yoffset * convert->imageWidth + + convert->xoffset) * DST_TEXEL_BYTES); + GLint adjust; + GLint row, col; + + adjust = convert->imageWidth - convert->width; + + if ( DBG ) { + fprintf( stderr, __FUNCTION__ ":\n" ); + fprintf( stderr, " x=%d y=%d w=%d h=%d s=%d\n", + convert->xoffset, convert->yoffset, convert->width, + convert->height, convert->imageWidth ); + fprintf( stderr, " adjust=%d\n", adjust ); + } + + for ( row = 0 ; row < convert->height ; row++ ) { + for ( col = 0 ; col < convert->width ; col++ ) { + *dst++ = CONVERT_TEXEL( src ); + src += SRC_TEXEL_BYTES; + } + dst += adjust; + } + + return GL_TRUE; +} + +/* PRE: As above, or height != imageHeight also. + */ +static GLboolean +TAG(texsubimage3d_stride)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *)convert->srcImage; + DST_TYPE *dst = (DST_TYPE *)((GLubyte *)convert->dstImage + + ((convert->zoffset * convert->imageHeight + + convert->yoffset) * convert->imageWidth + + convert->xoffset) * DST_TEXEL_BYTES); + GLint adjust; + GLint row, col, img; + + adjust = convert->imageWidth - convert->width; + + if ( DBG ) { + fprintf( stderr, __FUNCTION__ ":\n" ); + fprintf( stderr, " x=%d y=%d w=%d h=%d s=%d\n", + convert->xoffset, convert->yoffset, convert->width, + convert->height, convert->imageWidth ); + fprintf( stderr, " adjust=%d\n", adjust ); + } + + for ( img = 0 ; img < convert->depth ; img++ ) { + for ( row = 0 ; row < convert->height ; row++ ) { + for ( col = 0 ; col < convert->width ; col++ ) { + *dst++ = CONVERT_TEXEL( src ); + src += SRC_TEXEL_BYTES; + } + dst += adjust; + } + /* FIXME: ... */ + } + + return GL_TRUE; +} + + + +/* ================================================================ + * PRE: Require pixelstore attribs, width == imageWidth. + */ +static GLboolean +TAG(texsubimage2d_pack)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *) + _mesa_image_address( convert->packing, convert->srcImage, + convert->width, convert->height, + convert->format, convert->type, 0, 0, 0 ); + const GLint srcRowStride = + _mesa_image_row_stride( convert->packing, convert->width, + convert->format, convert->type ); + GLuint *dst = (GLuint *)((GLubyte *)convert->dstImage + + (convert->yoffset * convert->width + + convert->xoffset) * DST_TEXEL_BYTES); + GLint width; + GLint row, col; + (void) col; + + if ( DBG ) + fprintf( stderr, __FUNCTION__ "\n" ); + + width = ((convert->width + DST_TEXELS_PER_DWORD - 1) + & ~(DST_TEXELS_PER_DWORD - 1)); + + for ( row = 0 ; row < convert->height ; row++ ) { +#ifdef CONVERT_DIRECT + MEMCPY( dst, src, DST_ROW_STRIDE ); + src += srcRowStride; + dst = (GLuint *)((GLubyte *)dst + DST_ROW_STRIDE); +#else + const GLubyte *srcRow = src; + for ( col = width / DST_TEXELS_PER_DWORD ; col ; col-- ) { + *dst++ = CONVERT_TEXEL_DWORD( src ); + src += SRC_TEXEL_BYTES * DST_TEXELS_PER_DWORD; + } + src = srcRow + srcRowStride; +#endif + } + + return GL_TRUE; +} + +/* PRE: as above, height == imageHeight also. + */ +static GLboolean +TAG(texsubimage3d_pack)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *) + _mesa_image_address( convert->packing, convert->srcImage, + convert->width, convert->height, + convert->format, convert->type, 0, 0, 0 ); + const GLint srcRowStride = + _mesa_image_row_stride( convert->packing, convert->width, + convert->format, convert->type ); + GLuint *dst = (GLuint *)((GLubyte *)convert->dstImage + + ((convert->zoffset * convert->height + + convert->yoffset) * convert->width + + convert->xoffset) * DST_TEXEL_BYTES); + GLint width; + GLint row, col, img; + (void) col; + + if ( DBG ) + fprintf( stderr, __FUNCTION__ "\n" ); + + width = ((convert->width + DST_TEXELS_PER_DWORD - 1) + & ~(DST_TEXELS_PER_DWORD - 1)); + + for ( img = 0 ; img < convert->depth ; img++ ) { + for ( row = 0 ; row < convert->height ; row++ ) { +#ifdef CONVERT_DIRECT + MEMCPY( dst, src, DST_ROW_STRIDE ); + src += srcRowStride; + dst = (GLuint *)((GLubyte *)dst + DST_ROW_STRIDE); +#else + const GLubyte *srcRow = src; + for ( col = width / DST_TEXELS_PER_DWORD ; col ; col-- ) { + *dst++ = CONVERT_TEXEL_DWORD( src ); + src += SRC_TEXEL_BYTES * DST_TEXELS_PER_DWORD; + } + src = srcRow + srcRowStride; +#endif + } + } + + return GL_TRUE; +} + + + +/* ================================================================ + * PRE: Require pixelstore attribs, width != imageWidth. + */ +static GLboolean +TAG(texsubimage2d_stride_pack)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *) + _mesa_image_address( convert->packing, convert->srcImage, + convert->width, convert->height, + convert->format, convert->type, 0, 0, 0 ); + const GLint srcRowStride = + _mesa_image_row_stride( convert->packing, convert->width, + convert->format, convert->type ); + DST_TYPE *dst = (DST_TYPE *)((GLubyte *)convert->dstImage + + (convert->yoffset * convert->imageWidth + + convert->xoffset) * DST_TEXEL_BYTES); + GLint adjust; + GLint row, col; + (void) col; + + adjust = convert->imageWidth - convert->width; + + if ( DBG ) { + fprintf( stderr, __FUNCTION__ ":\n" ); + fprintf( stderr, " x=%d y=%d w=%d h=%d s=%d\n", + convert->xoffset, convert->yoffset, convert->width, + convert->height, convert->imageWidth ); + fprintf( stderr, " adjust=%d\n", adjust ); + } + + for ( row = 0 ; row < convert->height ; row++ ) { +#ifdef CONVERT_DIRECT + MEMCPY( dst, src, DST_ROW_WIDTH ); + src += srcRowStride; + dst += convert->imageWidth; +#else + const GLubyte *srcRow = src; + for ( col = 0 ; col < convert->width ; col++ ) { + *dst++ = CONVERT_TEXEL( src ); + src += SRC_TEXEL_BYTES; + } + src = srcRow + srcRowStride; + dst += adjust; +#endif + } + + return GL_TRUE; +} + +/* PRE: As above, or height != imageHeight also. + */ +static GLboolean +TAG(texsubimage3d_stride_pack)( struct gl_texture_convert *convert ) +{ + const GLubyte *src = (const GLubyte *) + _mesa_image_address( convert->packing, convert->srcImage, + convert->width, convert->height, + convert->format, convert->type, 0, 0, 0 ); + const GLint srcRowStride = + _mesa_image_row_stride( convert->packing, convert->width, + convert->format, convert->type ); + DST_TYPE *dst = (DST_TYPE *)((GLubyte *)convert->dstImage + + ((convert->zoffset * convert->imageHeight + + convert->yoffset) * convert->imageWidth + + convert->xoffset) * DST_TEXEL_BYTES); + GLint adjust; + GLint row, col, img; + (void) col; + + adjust = convert->imageWidth - convert->width; + + if ( DBG ) { + fprintf( stderr, __FUNCTION__ ":\n" ); + fprintf( stderr, " x=%d y=%d w=%d h=%d s=%d\n", + convert->xoffset, convert->yoffset, convert->width, + convert->height, convert->imageWidth ); + fprintf( stderr, " adjust=%d\n", adjust ); + } + + for ( img = 0 ; img < convert->depth ; img++ ) { + for ( row = 0 ; row < convert->height ; row++ ) { +#ifdef CONVERT_DIRECT + MEMCPY( dst, src, DST_ROW_WIDTH ); + src += srcRowStride; + dst += convert->imageWidth; +#else + const GLubyte *srcRow = src; + for ( col = 0 ; col < convert->width ; col++ ) { + *dst++ = CONVERT_TEXEL( src ); + src += SRC_TEXEL_BYTES; + } + src = srcRow + srcRowStride; + dst += adjust; +#endif + } + /* FIXME: ... */ + } + + return GL_TRUE; +} + + + +static convert_func TAG(texsubimage2d_tab)[] = { + TAG(texsubimage2d), + TAG(texsubimage2d_stride), + TAG(texsubimage2d_pack), + TAG(texsubimage2d_stride_pack), +}; + +static convert_func TAG(texsubimage3d_tab)[] = { + TAG(texsubimage3d), + TAG(texsubimage3d_stride), + TAG(texsubimage3d_pack), + TAG(texsubimage3d_stride_pack), +}; + + +#ifndef PRESERVE_DST_TYPE +#undef DST_TYPE +#undef DST_TEXELS_PER_DWORD +#endif + +#undef SRC_TEXEL_BYTES +#undef DST_TEXEL_BYTES +#undef DST_ROW_WIDTH +#undef DST_ROW_STRIDE + +#undef CONVERT_TEXEL +#undef CONVERT_TEXEL_DWORD +#undef CONVERT_DIRECT + +#undef TAG + +#undef PRESERVE_DST_TYPE diff --git a/xc/extras/Mesa/src/tritemp.h b/xc/extras/Mesa/src/tritemp.h index 03a38852c..71e62a31a 100644 --- a/xc/extras/Mesa/src/tritemp.h +++ b/xc/extras/Mesa/src/tritemp.h @@ -1,21 +1,20 @@ -/* $Id: tritemp.h,v 1.15 2001/02/12 20:42:42 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 3.4.1 - * + * * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -57,7 +56,7 @@ * * Optionally, one may provide one-time setup code per triangle: * SETUP_CODE - code which is to be executed once per triangle - * + * * The following macro MUST be defined: * INNER_LOOP(LEFT,RIGHT,Y) - code to write a span of pixels. * Something like: @@ -227,7 +226,7 @@ * By stepping rasterization parameters along the major edge, * we can avoid recomputing them at the discontinuity where * the top and bottom edges meet. However, this forces us to - * be able to scan both left-to-right and right-to-left. + * be able to scan both left-to-right and right-to-left. * Also, we must determine whether the major edge is at the * left or right side of the triangle. We do this by * computing the magnitude of the cross-product of the major @@ -445,7 +444,7 @@ dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx); } else { dtdx = 0; - dtdy = 0; + dtdy = 0; } if (VB->TexCoordPtr[0]->size > 2) @@ -553,7 +552,7 @@ * inside the triangle. * * Next we creep down the major edge until we reach that y, - * and compute the corresponding x coordinate on the edge. + * and compute the corresponding x coordinate on the edge. * Then we find the half-integral x that lies on or just * inside the edge. This is the first pixel that might lie in * the interior of the triangle. (We won't know for sure @@ -784,7 +783,7 @@ t0 = VB->TexCoordPtr[0]->data[vLower][1] * T_SCALE; ft = (GLfixed)(t0 * FIXED_SCALE + dtdx * adjx + dtdy * adjy) + FIXED_HALF; fdtOuter = SignedFloatToFixed(dtdy + dxOuter * dtdx); - } + } else { t0 = 0; @@ -801,7 +800,7 @@ sLeft = s0 + (dsdx * adjx + dsdy * adjy) * (1.0F/FIXED_SCALE); dsOuter = dsdy + dxOuter * dsdx; if (VB->TexCoordPtr[0]->size > 1) - { + { t0 = VB->TexCoordPtr[0]->data[vLower][1] * invW; tLeft = t0 + (dtdx * adjx + dtdy * adjy) * (1.0F/FIXED_SCALE); dtOuter = dtdy + dxOuter * dtdx; @@ -809,7 +808,7 @@ tLeft = dtOuter = 0; } if (VB->TexCoordPtr[0]->size > 2) - { + { u0 = VB->TexCoordPtr[0]->data[vLower][2] * invW; uLeft = u0 + (dudx * adjx + dudy * adjy) * (1.0F/FIXED_SCALE); duOuter = dudy + dxOuter * dudx; @@ -817,7 +816,7 @@ uLeft = duOuter = 0; } if (VB->TexCoordPtr[0]->size > 3) - { + { v0 = VB->TexCoordPtr[0]->data[vLower][3] * invW; } else { v0 = invW; @@ -834,7 +833,7 @@ s1Left = s0 + (ds1dx * adjx + ds1dy * adjy) * (1.0F/FIXED_SCALE); ds1Outer = ds1dy + dxOuter * ds1dx; if (VB->TexCoordPtr[0]->size > 1) - { + { t0 = VB->TexCoordPtr[1]->data[vLower][1] * invW; t1Left = t0 + (dt1dx * adjx + dt1dy * adjy) * (1.0F/FIXED_SCALE); dt1Outer = dt1dy + dxOuter * dt1dx; @@ -842,7 +841,7 @@ t1Left = dt1Outer = 0; } if (VB->TexCoordPtr[0]->size > 2) - { + { u0 = VB->TexCoordPtr[1]->data[vLower][2] * invW; u1Left = u0 + (du1dx * adjx + du1dy * adjy) * (1.0F/FIXED_SCALE); du1Outer = du1dy + dxOuter * du1dx; @@ -850,7 +849,7 @@ u1Left = du1Outer = 0; } if (VB->TexCoordPtr[0]->size > 3) - { + { v0 = VB->TexCoordPtr[1]->data[vLower][3] * invW; } else { v0 = invW; diff --git a/xc/extras/Mesa/src/types.h b/xc/extras/Mesa/src/types.h index 804de925e..5c297eb2a 100644 --- a/xc/extras/Mesa/src/types.h +++ b/xc/extras/Mesa/src/types.h @@ -1,4 +1,4 @@ -/* -*- mode: C; tab-width:8; c-basic-offset:8 -*- */ +/* -*- mode: C; tab-width:8; c-basic-offset:3 -*- */ /* * Mesa 3-D graphics library @@ -171,7 +171,21 @@ typedef void (*TextureSampleFunc)( const struct gl_texture_object *tObj, const GLfloat u[], const GLfloat lambda[], GLubyte rgba[][4] ); +/* Texture format record */ +/* GH: This is an interim structure until 3.5 */ +struct gl_texture_format { + GLint IntFormat; /* One of the MESA_FORMAT_* values */ + GLubyte RedBits; /* Bits per texel component */ + GLubyte GreenBits; + GLubyte BlueBits; + GLubyte AlphaBits; + GLubyte LuminanceBits; + GLubyte IntensityBits; + GLubyte IndexBits; + + GLint TexelBytes; +}; /* Texture image record */ struct gl_texture_image { @@ -180,13 +194,6 @@ struct gl_texture_image { * GL_COLOR_INDEX only */ GLenum IntFormat; /* Internal format as given by the user */ - GLubyte RedBits; /* Bits per texel component */ - GLubyte GreenBits; /* These are initialized by Mesa but */ - GLubyte BlueBits; /* may be reassigned by the device */ - GLubyte AlphaBits; /* driver to indicate the true texture */ - GLubyte IntensityBits; /* color resolution. */ - GLubyte LuminanceBits; - GLubyte IndexBits; GLuint Border; /* 0 or 1 */ GLuint Width; /* = 2^WidthLog2 + 2*Border */ GLuint Height; /* = 2^HeightLog2 + 2*Border */ @@ -200,6 +207,8 @@ struct gl_texture_image { GLuint MaxLog2; /* = MAX(WidthLog2, HeightLog2) */ GLubyte *Data; /* Image data as unsigned bytes */ + const struct gl_texture_format *TexFormat; + GLboolean IsCompressed; /* GL_ARB_texture_compression */ GLuint CompressedSize; /* GL_ARB_texture_compression */ diff --git a/xc/lib/GL/mesa/src/Imakefile b/xc/lib/GL/mesa/src/Imakefile index cc88803f4..7ccc16fd7 100644 --- a/xc/lib/GL/mesa/src/Imakefile +++ b/xc/lib/GL/mesa/src/Imakefile @@ -152,6 +152,8 @@ LinkSourceFile(state.c, $(MESASRCDIR)/src) LinkSourceFile(state.h, $(MESASRCDIR)/src) LinkSourceFile(stencil.c, $(MESASRCDIR)/src) LinkSourceFile(stencil.h, $(MESASRCDIR)/src) +LinkSourceFile(texformat.c, $(MESASRCDIR)/src) +LinkSourceFile(texformat.h, $(MESASRCDIR)/src) LinkSourceFile(texgen_tmp.h, $(MESASRCDIR)/src) LinkSourceFile(teximage.c, $(MESASRCDIR)/src) LinkSourceFile(teximage.h, $(MESASRCDIR)/src) @@ -163,6 +165,7 @@ LinkSourceFile(texture.c, $(MESASRCDIR)/src) LinkSourceFile(texture.h, $(MESASRCDIR)/src) LinkSourceFile(texutil.c, $(MESASRCDIR)/src) LinkSourceFile(texutil.h, $(MESASRCDIR)/src) +LinkSourceFile(texutil_tmp.h, $(MESASRCDIR)/src) LinkSourceFile(trans_tmp.h, $(MESASRCDIR)/src) LinkSourceFile(translate.c, $(MESASRCDIR)/src) LinkSourceFile(translate.h, $(MESASRCDIR)/src) @@ -252,6 +255,7 @@ LinkSourceFile(zoom.h, $(MESASRCDIR)/src) stages.c \ state.c \ stencil.c \ + texformat.c \ teximage.c \ texobj.c \ texstate.c \ @@ -325,6 +329,7 @@ LinkSourceFile(zoom.h, $(MESASRCDIR)/src) stages.o \ state.o \ stencil.o \ + texformat.o \ teximage.o \ texobj.o \ texstate.o \ @@ -346,8 +351,8 @@ LinkSourceFile(zoom.h, $(MESASRCDIR)/src) zoom.o #ifdef i386Architecture - ASM_SRCS = - ASM_OBJS = + ASM_SRCS = + ASM_OBJS = #if MesaUseMMX MMX_DEFS = -DUSE_MMX_ASM #endif diff --git a/xc/lib/GL/mesa/src/drv/i810/i810span.c b/xc/lib/GL/mesa/src/drv/i810/i810span.c index ca9817b8a..4bf02ad13 100644 --- a/xc/lib/GL/mesa/src/drv/i810/i810span.c +++ b/xc/lib/GL/mesa/src/drv/i810/i810span.c @@ -30,7 +30,7 @@ dPriv->x * 2 + \ dPriv->y * pitch) -#define INIT_MONO_PIXEL(p) +#define INIT_MONO_PIXEL(p) #define CLIPPIXEL(_x,_y) (_x >= minx && _x < maxx && \ _y >= miny && _y < maxy) @@ -130,7 +130,7 @@ do { \ *(GLushort *)(buf + _x*2 + _y*pitch) = d; #define READ_DEPTH( d, _x, _y ) \ - d = *(GLushort *)(buf + _x*2 + _y*pitch); + d = *(GLushort *)(buf + _x*2 + _y*pitch); /* d = 0xffff; */ @@ -146,7 +146,7 @@ void i810DDInitSpanFuncs( GLcontext *ctx ) ctx->Driver.WriteRGBSpan = i810WriteRGBSpan_565; ctx->Driver.WriteMonoRGBASpan = i810WriteMonoRGBASpan_565; ctx->Driver.WriteRGBAPixels = i810WriteRGBAPixels_565; - ctx->Driver.WriteMonoRGBAPixels = i810WriteMonoRGBAPixels_565; + ctx->Driver.WriteMonoRGBAPixels = i810WriteMonoRGBAPixels_565; ctx->Driver.ReadRGBASpan = i810ReadRGBASpan_565; ctx->Driver.ReadRGBAPixels = i810ReadRGBAPixels_565; } else { diff --git a/xc/lib/GL/mesa/src/drv/mga/Imakefile b/xc/lib/GL/mesa/src/drv/mga/Imakefile index 2630d8159..e4c73ddc0 100644 --- a/xc/lib/GL/mesa/src/drv/mga/Imakefile +++ b/xc/lib/GL/mesa/src/drv/mga/Imakefile @@ -151,6 +151,7 @@ MESA_INCLUDES = -I. -I.. -I../../include \ ../../stages.c \ ../../state.c \ ../../stencil.c \ + ../../texformat.c \ ../../teximage.c \ ../../texobj.c \ ../../texstate.c \ @@ -224,6 +225,7 @@ MESA_INCLUDES = -I. -I.. -I../../include \ ../../stages.o \ ../../state.o \ ../../stencil.o \ + ../../texformat.o \ ../../teximage.o \ ../../texobj.o \ ../../texstate.o \ diff --git a/xc/lib/GL/mesa/src/drv/mga/mgapixel.c b/xc/lib/GL/mesa/src/drv/mga/mgapixel.c index d970e49b4..72903c209 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgapixel.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgapixel.c @@ -545,9 +545,9 @@ mgaDDDrawPixels( GLcontext *ctx, * negligble speedup when the buffers/images don't exactly * match: */ -#if 1 +#if 0 if (cpp == 2) { - if (!_mesa_convert_teximage( MESA_R5_G6_B5, + if (!_mesa_convert_teximage( MESA_FORMAT_RGB565, width, rows, address, bufferpitch, width, rows, @@ -558,7 +558,7 @@ mgaDDDrawPixels( GLcontext *ctx, return GL_FALSE; } } else { - if (!_mesa_convert_teximage( MESA_A8_R8_G8_B8, + if (!_mesa_convert_teximage( MESA_FORMAT_ARGB8888, width, rows, address, bufferpitch, width, rows, diff --git a/xc/lib/GL/mesa/src/drv/mga/mgatex.c b/xc/lib/GL/mesa/src/drv/mga/mgatex.c index 35549af27..0986b04be 100644 --- a/xc/lib/GL/mesa/src/drv/mga/mgatex.c +++ b/xc/lib/GL/mesa/src/drv/mga/mgatex.c @@ -41,6 +41,7 @@ #include "enums.h" #include "simple_list.h" #include "mem.h" +#include "texutil.h" #define TEX_0 1 #define TEX_1 2 @@ -145,6 +146,169 @@ static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4]) } +static GLint mgaChooseTexFormat( mgaContextPtr mmesa, + struct gl_texture_image *texImage, + GLenum format, GLenum type ) +{ + const GLboolean do32bpt = mmesa->default32BitTextures; + const struct gl_texture_format *texFormat; + GLint ret; + + if ( 0 ) + fprintf( stderr, "internal=%s format=%s type=%s\n", + texImage->IntFormat == 3 ? "GL_RGB (3)" : + texImage->IntFormat == 4 ? "GL_RGBA (4)" : + gl_lookup_enum_by_nr( texImage->IntFormat ), + gl_lookup_enum_by_nr( format ), + gl_lookup_enum_by_nr( type ) ); + +#define SET_FORMAT( r, gl ) \ + do { \ + ret = (r); \ + texFormat = &(gl); \ + } while (0) + +#define SET_FORMAT_32BPT( r32, gl32, r16, gl16 ) \ + do { \ + if ( do32bpt ) { \ + ret = (r32); \ + texFormat = &(gl32); \ + } else { \ + ret = (r16); \ + texFormat = &(gl16); \ + } \ + } while (0) + + switch ( texImage->IntFormat ) { + /* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has + * got to be better than sticking them way down the end of this + * huge list. + */ + case GL_RGBA: + case 4: + if ( format == GL_BGRA ) { + if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { + SET_FORMAT( TMC_tformat_tw32, _mesa_texformat_argb8888 ); + break; + } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { + SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 ); + break; + } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { + SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 ); + break; + } + } + SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, + TMC_tformat_tw12, _mesa_texformat_argb4444 ); + break; + + case GL_RGB: + case 3: + if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { + SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 ); + break; + } + SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, + TMC_tformat_tw16, _mesa_texformat_rgb565 ); + break; + + /* GH: Okay, keep checking as normal. Still test for GL_RGB, + * GL_RGBA formats first. + */ + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, + TMC_tformat_tw12, _mesa_texformat_argb4444 ); + break; + + case GL_RGBA4: + case GL_RGBA2: + SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 ); + break; + + case GL_RGB5_A1: + SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 ); + break; + + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, + TMC_tformat_tw16, _mesa_texformat_rgb565 ); + break; + + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 ); + break; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + /* FIXME: This breaks the G200... */ + SET_FORMAT( TMC_tformat_tw8a, _mesa_texformat_a8 ); + break; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + /* FIXME: This breaks the G200... */ + SET_FORMAT( TMC_tformat_tw8al, _mesa_texformat_al88 ); + break; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + /* FIXME: This breaks the G200... */ + SET_FORMAT( TMC_tformat_tw8al, _mesa_texformat_al88 ); + break; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + /* FIXME: This breaks the G200... */ + SET_FORMAT( TMC_tformat_tw8al, _mesa_texformat_al88 ); + break; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + SET_FORMAT( TMC_tformat_tw8, _mesa_texformat_ci8 ); + break; + + default: + fprintf( stderr, "bad texture format in mgaChooseTexFormat() %d", + texImage->IntFormat ); + return -1; + } + + texImage->TexFormat = texFormat; + + return ret; +} + + +#if 0 /* * Input: * baseFormat - base texture format @@ -270,6 +434,7 @@ static void mgaChooseTexelFormat(GLenum baseFormat, GLenum intFormat, return; } } +#endif /* @@ -282,14 +447,12 @@ static void mgaCreateTexObj(mgaContextPtr mmesa, struct gl_texture_object *tObj) { const GLint baseLevel = tObj->BaseLevel; - const struct gl_texture_image *image = tObj->Image[baseLevel]; + struct gl_texture_image *image = tObj->Image[baseLevel]; mgaTextureObjectPtr t; int i, ofs; int LastLevel; int s, s2; - int textureFormat; - GLubyte redBits, greenBits, blueBits, alphaBits; - GLubyte intensityBits, luminanceBits, indexBits; + int tformat; if (!image) return; @@ -299,11 +462,10 @@ static void mgaCreateTexObj(mgaContextPtr mmesa, return; } - mgaChooseTexelFormat(image->Format, image->IntFormat, - mmesa->default32BitTextures, - &t->texelBytes, &textureFormat, - &redBits, &greenBits, &blueBits, &alphaBits, - &luminanceBits, &intensityBits, &indexBits); + /* FIXME: Use the real DD interface... + */ + tformat = mgaChooseTexFormat( mmesa, image, image->Format, + GL_UNSIGNED_BYTE ); /* We are going to upload all levels that are present, even if * later levels wouldn't be used by the current filtering mode. This @@ -333,14 +495,13 @@ static void mgaCreateTexObj(mgaContextPtr mmesa, t->age = 0; t->bound = 0; t->MemBlock = 0; + t->texelBytes = image->TexFormat->TexelBytes; insert_at_tail(&(mmesa->SwappedOut), t); /* setup hardware register values */ - t->setup.texctl = (TMC_takey_1 | - TMC_tamask_0 | - textureFormat ); + t->setup.texctl = TMC_takey_1 | TMC_tamask_0 | tformat; if (image->WidthLog2 >= 3) t->setup.texctl |= ((image->WidthLog2 - 3) << TMC_tpitch_SHIFT); @@ -767,7 +928,7 @@ static void mgaDDTexImage( GLcontext *ctx, GLenum target, { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); mgaTextureObjectPtr t; - int texelBytes, mgaFormat; + GLint tformat; /* hack: cast-away const */ struct gl_texture_image *img = (struct gl_texture_image *) image; @@ -781,11 +942,8 @@ static void mgaDDTexImage( GLcontext *ctx, GLenum target, mmesa->new_state |= MGA_NEW_TEXTURE; } - mgaChooseTexelFormat(image->Format, image->IntFormat, GL_FALSE, - &texelBytes, &mgaFormat, - &img->RedBits, &img->GreenBits, &img->BlueBits, - &img->AlphaBits, &img->LuminanceBits, - &img->IntensityBits, &img->IndexBits); + tformat = mgaChooseTexFormat( mmesa, img, img->Format, + GL_UNSIGNED_BYTE ); if (0) fprintf(stderr, "mgaDDTexImage tObj %p, level %d, image %p\n", diff --git a/xc/lib/GL/mesa/src/drv/radeon/Imakefile b/xc/lib/GL/mesa/src/drv/radeon/Imakefile index d862565d0..2dc0b3083 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/Imakefile +++ b/xc/lib/GL/mesa/src/drv/radeon/Imakefile @@ -59,6 +59,8 @@ MESA_INCLUDES = -I. -I.. -I../../include \ radeon_span.c \ radeon_state.c \ radeon_tex.c \ + radeon_texmem.c \ + radeon_texstate.c \ radeon_tris.c \ radeon_vb.c \ radeon_xmesa.c @@ -74,6 +76,8 @@ MESA_INCLUDES = -I. -I.. -I../../include \ radeon_span.o \ radeon_state.o \ radeon_tex.o \ + radeon_texmem.o \ + radeon_texstate.o \ radeon_tris.o \ radeon_vb.o \ radeon_xmesa.o @@ -152,6 +156,7 @@ MESA_INCLUDES = -I. -I.. -I../../include \ ../../stages.c \ ../../state.c \ ../../stencil.c \ + ../../texformat.c \ ../../teximage.c \ ../../texobj.c \ ../../texstate.c \ @@ -225,6 +230,7 @@ MESA_INCLUDES = -I. -I.. -I../../include \ ../../stages.o \ ../../state.o \ ../../stencil.o \ + ../../texformat.o \ ../../teximage.o \ ../../texobj.o \ ../../texstate.o \ diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c index 2ead8e213..366f094ca 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c @@ -133,16 +133,8 @@ GLboolean radeonCreateContext( Display *dpy, GLvisual *glVisual, ctx->Const.MaxTextureSize = (1 << 10); } - /* FIXME: Support all available texture units... */ ctx->Const.MaxTextureUnits = 2; -#if ENABLE_PERF_BOXES - if (getenv("LIBGL_PERFORMANCE_BOXES")) - rmesa->boxes = 1; - else - rmesa->boxes = 0; -#endif - ctx->DriverCtx = (void *)rmesa; radeonDDInitExtensions( ctx ); diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_dd.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_dd.c index b86506a8d..4ef0ebd30 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_dd.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_dd.c @@ -46,7 +46,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "X86/common_x86_asm.h" #endif -#define RADEON_DATE "20010105" +#define RADEON_DATE "20010305" /* Return the width and height of the current color buffer. @@ -100,6 +100,11 @@ static const GLubyte *radeonDDGetString( GLcontext *ctx, GLenum name ) strncat( buffer, " x86", 4 ); } #endif +#ifdef USE_MMX_ASM + if ( cpu_has_mmx ) { + strncat( buffer, "/MMX", 4 ); + } +#endif #ifdef USE_3DNOW_ASM if ( cpu_has_3dnow ) { strncat( buffer, "/3DNow!", 7 ); diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c index a02794e49..c2cd6a203 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c @@ -321,6 +321,7 @@ void radeonFireBlitLocked( radeonContextPtr rmesa, drmBufPtr buffer, GLint offset, GLint pitch, GLint format, GLint x, GLint y, GLint width, GLint height ) { +#if 0 GLint ret; ret = drmRadeonTextureBlit( rmesa->driFd, buffer->idx, @@ -332,6 +333,7 @@ void radeonFireBlitLocked( radeonContextPtr rmesa, drmBufPtr buffer, fprintf( stderr, "drmRadeonTextureBlit: return = %d\n", ret ); exit( 1 ); } +#endif } @@ -616,12 +618,6 @@ static GLbitfield radeonDDClear( GLcontext *ctx, GLbitfield mask, } #endif -#if 0 - if ( rmesa->dirty & ~RADEON_UPLOAD_CLIPRECTS ) { - radeonEmitHwStateLocked( rmesa ); - } -#endif - for ( i = 0 ; i < rmesa->numClipRects ; ) { GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, rmesa->numClipRects ); XF86DRIClipRectPtr box = rmesa->pClipRects; diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c index 27cf00c0b..d80004dd6 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c @@ -936,29 +936,29 @@ void radeonEmitHwStateLocked( radeonContextPtr rmesa ) if ( (rmesa->dirty & RADEON_UPLOAD_TEX0) && t0 ) { radeon_texture_regs_t *tex = &sarea->TexState[0]; - tex->pp_txfilter = t0->setup.pp_txfilter | rmesa->lod_bias[0] << 8; - tex->pp_txformat = t0->setup.pp_txformat | RADEON_TXF_ST_ROUTE_STQ0; - tex->pp_txoffset = t0->setup.pp_txoffset; + tex->pp_txfilter = t0->pp_txfilter | rmesa->lod_bias[0] << 8; + tex->pp_txformat = t0->pp_txformat | RADEON_TXFORMAT_ST_ROUTE_STQ0; + tex->pp_txoffset = t0->pp_txoffset; tex->pp_txcblend = rmesa->color_combine[0]; tex->pp_txablend = rmesa->alpha_combine[0]; tex->pp_tfactor = rmesa->env_color[0]; - tex->pp_border_color = t0->setup.pp_border_color; + tex->pp_border_color = t0->pp_border_color; } if ( (rmesa->dirty & RADEON_UPLOAD_TEX1) && t1 ) { radeon_texture_regs_t *tex = &sarea->TexState[1]; - tex->pp_txfilter = t1->setup.pp_txfilter | rmesa->lod_bias[1] << 8; - tex->pp_txformat = t1->setup.pp_txformat | RADEON_TXF_ST_ROUTE_STQ1; - tex->pp_txoffset = t1->setup.pp_txoffset; + tex->pp_txfilter = t1->pp_txfilter | rmesa->lod_bias[1] << 8; + tex->pp_txformat = t1->pp_txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1; + tex->pp_txoffset = t1->pp_txoffset; tex->pp_txcblend = rmesa->color_combine[1]; tex->pp_txablend = rmesa->alpha_combine[1]; tex->pp_tfactor = rmesa->env_color[1]; - tex->pp_border_color = t1->setup.pp_border_color; + tex->pp_border_color = t1->pp_border_color; } if ( rmesa->dirty & RADEON_UPLOAD_TEX2 ) { diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c index dd9c4557b..6659f7abe 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c @@ -44,1963 +44,680 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "simple_list.h" #include "enums.h" #include "mem.h" +#include "texutil.h" static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap ) { - t->setup.pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK); + t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK); switch ( swrap ) { case GL_REPEAT: - t->setup.pp_txfilter |= RADEON_CLAMP_S_WRAP; + t->pp_txfilter |= RADEON_CLAMP_S_WRAP; break; case GL_CLAMP: - t->setup.pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST; + t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST; break; case GL_CLAMP_TO_EDGE: - t->setup.pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST; + t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST; break; } switch ( twrap ) { case GL_REPEAT: - t->setup.pp_txfilter |= RADEON_CLAMP_T_WRAP; + t->pp_txfilter |= RADEON_CLAMP_T_WRAP; break; case GL_CLAMP: - t->setup.pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST; + t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST; break; case GL_CLAMP_TO_EDGE: - t->setup.pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST; + t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST; break; } } static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf ) { - t->setup.pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK); + t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK); switch ( minf ) { case GL_NEAREST: - t->setup.pp_txfilter |= RADEON_MIN_FILTER_NEAREST; + t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST; break; case GL_LINEAR: - t->setup.pp_txfilter |= RADEON_MIN_FILTER_LINEAR; + t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR; break; case GL_NEAREST_MIPMAP_NEAREST: - t->setup.pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST; + t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: - t->setup.pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST; + t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: - t->setup.pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR; + t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: - t->setup.pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR; + t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR; break; } switch ( magf ) { case GL_NEAREST: - t->setup.pp_txfilter |= RADEON_MAG_FILTER_NEAREST; + t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST; break; case GL_LINEAR: - t->setup.pp_txfilter |= RADEON_MAG_FILTER_LINEAR; + t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR; break; } } static void radeonSetTexBorderColor( radeonTexObjPtr t, GLubyte c[4] ) { - t->setup.pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); + t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); } - -/* Allocate and initialize hardware state associated with texture `t'. - */ -static radeonTexObjPtr radeonCreateTexObj( radeonContextPtr rmesa, - struct gl_texture_object *tObj ) +static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *tObj ) { radeonTexObjPtr t; - struct gl_texture_image *image; - GLint log2Width, log2Height, log2Size, log2MinSize; - GLint totalSize; - GLint texelsPerDword = 0, blitWidth = 0, blitPitch = 0; - GLint x, y, width, height; - GLint i; - GLuint txformat, txalpha; - - image = tObj->Image[0]; - if ( !image ) - return NULL; - - t = (radeonTexObjPtr) CALLOC( sizeof(*t) ); - if ( !t ) - return NULL; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) - fprintf( stderr, "%s( %p )\n", __FUNCTION__, tObj ); - - switch ( image->Format ) { - case GL_RGBA: - if ( image->IntFormat != GL_RGBA4 && - ( image->IntFormat == GL_RGBA8 || - rmesa->radeonScreen->cpp == 4 ) ) { - t->texelBytes = 4; - txformat = RADEON_TXF_32BPP_ARGB8888; - } else { - t->texelBytes = 2; - txformat = RADEON_TXF_16BPP_ARGB4444; - } - txalpha = RADEON_TXF_ALPHA_IN_MAP; - break; - - case GL_RGB: - if ( image->IntFormat != GL_RGB5 && - ( image->IntFormat == GL_RGB8 || - rmesa->radeonScreen->cpp == 4 ) ) { - t->texelBytes = 4; - txformat = RADEON_TXF_32BPP_ARGB8888; - } else { - t->texelBytes = 2; - txformat = RADEON_TXF_16BPP_RGB565; - } - txalpha = 0; - break; - - case GL_ALPHA: - case GL_LUMINANCE_ALPHA: - t->texelBytes = 2; - txformat = RADEON_TXF_16BPP_AI88; - txalpha = RADEON_TXF_ALPHA_IN_MAP; - break; - - case GL_LUMINANCE: - t->texelBytes = 2; - txformat = RADEON_TXF_16BPP_AI88; - txalpha = 0; - break; - - case GL_INTENSITY: - t->texelBytes = 1; - txformat = RADEON_TXF_8BPP_I; - txalpha = 0; - break; - - case GL_COLOR_INDEX: - default: - fprintf( stderr, "%s: bad image->Format\n", __FUNCTION__ ); - FREE( t ); - return NULL; - } - - /* Calculate dimensions in log domain. - */ - for ( i = 1, log2Height = 0 ; i < image->Height ; i *= 2 ) { - log2Height++; - } - for ( i = 1, log2Width = 0 ; i < image->Width ; i *= 2 ) { - log2Width++; - } - if ( image->Width > image->Height ) { - log2Size = log2Width; - } else { - log2Size = log2Height; - } - - t->dirty_images = 0; - - /* The Radeon has a 64-byte minimum pitch for all blits. We - * calculate the equivalent number of texels to simplify the - * calculation of the texture image area. - */ - switch ( t->texelBytes ) { - case 1: - texelsPerDword = 4; - blitPitch = 64; - break; - case 2: - texelsPerDword = 2; - blitPitch = 32; - break; - case 4: - texelsPerDword = 1; - blitPitch = 16; - break; - } - - /* Select the larger of the two widths for our global texture image - * coordinate space. As the Radeon has very strict offset rules, we - * can't upload mipmaps directly and have to reference their location - * from the aligned start of the whole image. - */ - blitWidth = MAX2( image->Width, blitPitch ); - - /* Calculate mipmap offsets and dimensions. - */ - totalSize = 0; - x = 0; - y = 0; - - for ( i = 0 ; i <= log2Size ; i++ ) { - GLuint size; - image = tObj->Image[i]; - if ( !image ) - break; - - width = image->Width; - height = image->Height; - - /* Texture images have a minimum pitch of 32 bytes (half of the - * 64-byte minimum pitch for blits). For images that have a - * width smaller than this, we must pad each texture image - * scanline out to this amount. - */ - if ( width < blitPitch / 2 ) { - width = blitPitch / 2; - } - - size = width * height * t->texelBytes; - totalSize += size; - - t->dirty_images |= (1 << i); - - while ( width < blitWidth && height > 1 ) { - width *= 2; - height /= 2; - } - - t->image[i].x = x; - t->image[i].y = y; - - t->image[i].width = width; - t->image[i].height = height; - - t->image[i].dwords = size / sizeof(CARD32); - - /* While blits must have a pitch of at least 64 bytes, mipmaps - * must be aligned on a 32-byte boundary (just like each texture - * image scanline). - */ - if ( width >= blitWidth ) { - y += height; - } else { - x += width; - if ( x >= blitWidth ) { - x = 0; - y++; - } - } + t = CALLOC_STRUCT( radeon_tex_obj ); - if ( 0 ) - fprintf( stderr, "level=%d p=%d %dx%d -> %dx%d at (%d,%d) %d dwords\n", - i, blitWidth, image->Width, image->Height, - t->image[i].width, t->image[i].height, - t->image[i].x, t->image[i].y, - t->image[i].dwords ); + if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s( %p )\n", __FUNCTION__, t ); } - log2MinSize = log2Size - i + 1; - - /* Align the total size of texture memory block. + /* Initialize non-image-dependent parts of the state: */ - totalSize = (totalSize + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK; - - t->totalSize = totalSize; - - t->bound = 0; - t->heap = 0; t->tObj = tObj; + t->dirty_images = ~0; + t->pp_txfilter = RADEON_BORDER_MODE_OGL; + t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP | + RADEON_TXFORMAT_PERSPECTIVE_ENABLE); - t->memBlock = NULL; - t->bufAddr = 0; - - /* Hardware state: - */ - t->setup.pp_txfilter = ((log2Size << RADEON_MAX_MIP_LEVEL_SHIFT) | - RADEON_BORDER_MODE_OGL); - - t->setup.pp_txformat = (txformat | txalpha | - (log2Width << RADEON_TXF_WIDTH_SHIFT) | - (log2Height << RADEON_TXF_HEIGHT_SHIFT) | - RADEON_TXF_ENDIAN_NO_SWAP | - RADEON_TXF_PERSPECTIVE_ENABLE); - - t->setup.pp_txoffset = 0x00000000; - t->setup.pp_txcblend = 0x00000000; - t->setup.pp_txablend = 0x00000000; - t->setup.pp_tfactor = 0x00000000; - t->setup.pp_border_color = 0x00000000; + make_empty_list( t ); radeonSetTexWrap( t, tObj->WrapS, tObj->WrapT ); radeonSetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); radeonSetTexBorderColor( t, tObj->BorderColor ); - tObj->DriverData = t; - - make_empty_list( t ); - return t; } -/* Destroy hardware state associated with texture `t'. - */ -void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) -{ -#if ENABLE_PERF_BOXES - /* Bump the performace counter */ - rmesa->c_textureSwaps++; -#endif - if ( !t ) return; - - if ( t->memBlock ) { - mmFreeMem( t->memBlock ); - t->memBlock = NULL; - } - if ( t->tObj ) - t->tObj->DriverData = NULL; - if ( t->bound ) - rmesa->CurrentTexObj[t->bound-1] = NULL; - - remove_from_list( t ); - FREE( t ); -} - -/* Keep track of swapped out texture objects. - */ -static void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) +static GLint radeonChooseTexFormat( radeonContextPtr rmesa, + struct gl_texture_image *texImage, + GLenum format, GLenum type ) { -#if ENABLE_PERF_BOXES - /* Bump the performace counter */ - rmesa->c_textureSwaps++; -#endif - if ( t->memBlock ) { - mmFreeMem( t->memBlock ); - t->memBlock = NULL; - } + const GLboolean do32bpt = ( rmesa->radeonScreen->cpp == 4 ); + const struct gl_texture_format *texFormat; + GLint ret; - t->dirty_images = ~0; - move_to_tail( &rmesa->SwappedOut, t ); -} + if ( 0 ) + fprintf( stderr, "internal=%s format=%s type=%s\n", + texImage->IntFormat == 3 ? "GL_RGB (3)" : + texImage->IntFormat == 4 ? "GL_RGBA (4)" : + gl_lookup_enum_by_nr( texImage->IntFormat ), + gl_lookup_enum_by_nr( format ), + gl_lookup_enum_by_nr( type ) ); -/* Print out debugging information about texture LRU. - */ -void radeonPrintLocalLRU( radeonContextPtr rmesa, int heap ) -{ - radeonTexObjPtr t; - int sz = 1 << (rmesa->radeonScreen->logTexGranularity[heap]); - - fprintf( stderr, "\nLocal LRU, heap %d:\n", heap ); - - foreach ( t, &rmesa->TexObjList[heap] ) { - if (!t->tObj) { - fprintf( stderr, "Placeholder %d at 0x%x sz 0x%x\n", - t->memBlock->ofs / sz, - t->memBlock->ofs, - t->memBlock->size ); - } else { - fprintf( stderr, "Texture (bound %d) at 0x%x sz 0x%x\n", - t->bound, - t->memBlock->ofs, - t->memBlock->size ); - } - } - - fprintf( stderr, "\n" ); -} - -void radeonPrintGlobalLRU( radeonContextPtr rmesa, int heap ) -{ - radeon_tex_region_t *list = rmesa->sarea->texList[heap]; - int i, j; - - fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list ); - - for ( i = 0, j = RADEON_NR_TEX_REGIONS ; i < RADEON_NR_TEX_REGIONS ; i++ ) { - fprintf( stderr, "list[%d] age %d next %d prev %d\n", - j, list[j].age, list[j].next, list[j].prev ); - j = list[j].next; - if ( j == RADEON_NR_TEX_REGIONS ) break; - } - - if ( j != RADEON_NR_TEX_REGIONS ) { - fprintf( stderr, "Loop detected in global LRU\n" ); - for ( i = 0 ; i < RADEON_NR_TEX_REGIONS ; i++ ) { - fprintf( stderr, "list[%d] age %d next %d prev %d\n", - i, list[i].age, list[i].next, list[i].prev ); - } - } - - fprintf( stderr, "\n" ); -} - -/* Reset the global texture LRU. - */ -static void radeonResetGlobalLRU( radeonContextPtr rmesa, int heap ) -{ - radeon_tex_region_t *list = rmesa->sarea->texList[heap]; - int sz = 1 << rmesa->radeonScreen->logTexGranularity[heap]; - int i; - - /* - * (Re)initialize the global circular LRU list. The last element in - * the array (RADEON_NR_TEX_REGIONS) is the sentinal. Keeping it at - * the end of the array allows it to be addressed rationally when - * looking up objects at a particular location in texture memory. - */ - for ( i = 0 ; (i+1) * sz <= rmesa->radeonScreen->texSize[heap] ; i++ ) { - list[i].prev = i-1; - list[i].next = i+1; - list[i].age = 0; - } - - i--; - list[0].prev = RADEON_NR_TEX_REGIONS; - list[i].prev = i-1; - list[i].next = RADEON_NR_TEX_REGIONS; - list[RADEON_NR_TEX_REGIONS].prev = i; - list[RADEON_NR_TEX_REGIONS].next = 0; - rmesa->sarea->texAge[heap] = 0; -} - -/* Update the local and glock texture LRUs. - */ -static void radeonUpdateTexLRU(radeonContextPtr rmesa, radeonTexObjPtr t ) -{ - int heap = t->heap; - radeon_tex_region_t *list = rmesa->sarea->texList[heap]; - int sz = rmesa->radeonScreen->logTexGranularity[heap]; - int start = t->memBlock->ofs >> sz; - int end = (t->memBlock->ofs + t->memBlock->size-1) >> sz; - int i; - - rmesa->lastTexAge[heap] = ++rmesa->sarea->texAge[heap]; - - if ( !t->memBlock ) { - fprintf( stderr, "no memblock\n\n" ); - return; - } - - /* Update our local LRU */ - move_to_head( &rmesa->TexObjList[heap], t ); - - /* Update the global LRU */ - for ( i = start ; i <= end ; i++ ) { - list[i].in_use = 1; - list[i].age = rmesa->lastTexAge[heap]; - - /* remove_from_list(i) */ - list[(CARD32)list[i].next].prev = list[i].prev; - list[(CARD32)list[i].prev].next = list[i].next; - - /* insert_at_head(list, i) */ - list[i].prev = RADEON_NR_TEX_REGIONS; - list[i].next = list[RADEON_NR_TEX_REGIONS].next; - list[(CARD32)list[RADEON_NR_TEX_REGIONS].next].prev = i; - list[RADEON_NR_TEX_REGIONS].next = i; - } - - if ( 0 ) { - radeonPrintGlobalLRU( rmesa, t->heap ); - radeonPrintLocalLRU( rmesa, t->heap ); - } -} - -/* Update our notion of what textures have been changed since we last - * held the lock. This pertains to both our local textures and the - * textures belonging to other clients. Keep track of other client's - * textures by pushing a placeholder texture onto the LRU list -- these - * are denoted by (tObj == NULL). - */ -static void radeonTexturesGone( radeonContextPtr rmesa, int heap, - int offset, int size, int in_use ) -{ - radeonTexObjPtr t, tmp; - - foreach_s ( t, tmp, &rmesa->TexObjList[heap] ) { - if ( t->memBlock->ofs >= offset + size || - t->memBlock->ofs + t->memBlock->size <= offset ) - continue; - - /* It overlaps - kick it out. Need to hold onto the currently - * bound objects, however. - */ - if ( t->bound ) { - radeonSwapOutTexObj( rmesa, t ); - } else { - radeonDestroyTexObj( rmesa, t ); - } - } - - if ( in_use ) { - t = (radeonTexObjPtr) CALLOC( sizeof(*t) ); - if ( !t ) return; - - t->memBlock = mmAllocMem( rmesa->texHeap[heap], size, 0, offset ); - if ( !t->memBlock ) { - fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n", - (int)size, (int)offset ); - mmDumpMemInfo( rmesa->texHeap[heap] ); - return; - } - insert_at_head( &rmesa->TexObjList[heap], t ); - } -} - -/* Update our client's shared texture state. If another client has - * modified a region in which we have textures, then we need to figure - * out which of our textures has been removed, and update our global - * LRU. - */ -void radeonAgeTextures( radeonContextPtr rmesa, int heap ) -{ - RADEONSAREAPrivPtr sarea = rmesa->sarea; - - if ( sarea->texAge[heap] != rmesa->lastTexAge[heap] ) { - int sz = 1 << rmesa->radeonScreen->logTexGranularity[heap]; - int nr = 0; - int idx; - - for ( idx = sarea->texList[heap][RADEON_NR_TEX_REGIONS].prev ; - idx != RADEON_NR_TEX_REGIONS && nr < RADEON_NR_TEX_REGIONS ; - idx = sarea->texList[heap][idx].prev, nr++ ) - { - /* If switching texturing schemes, then the SAREA might not - * have been properly cleared, so we need to reset the - * global texture LRU. - */ - if ( idx * sz > rmesa->radeonScreen->texSize[heap] ) { - nr = RADEON_NR_TEX_REGIONS; - break; - } - - if ( sarea->texList[heap][idx].age > rmesa->lastTexAge[heap] ) { - radeonTexturesGone( rmesa, heap, idx * sz, sz, - sarea->texList[heap][idx].in_use ); - } - } - - if ( nr == RADEON_NR_TEX_REGIONS ) { - radeonTexturesGone( rmesa, heap, 0, - rmesa->radeonScreen->texSize[heap], 0 ); - radeonResetGlobalLRU( rmesa, heap ); - } - - rmesa->dirty |= (RADEON_UPLOAD_CONTEXT | - RADEON_UPLOAD_TEX0IMAGES | - RADEON_UPLOAD_TEX1IMAGES); - rmesa->lastTexAge[heap] = sarea->texAge[heap]; - } -} - - -/* ================================================================ - * Texture image conversions - */ - -/* Convert a block of Mesa-formatted texture to an 8bpp hardware format. - */ -static void radeonConvertTexture8bpp( CARD32 *dst, - struct gl_texture_image *image, - int x, int y, int width, int height, - int pitch ) -{ - CARD8 *src; - int i, j; - - if ( width < 4 ) { - width = 4; - } - -#define ALIGN_DST \ +#define SET_FORMAT( r, gl ) \ do { \ - if ( width < 32 ) { \ - dst += ((32 - width) / 4); \ - } \ + ret = (r); \ + texFormat = &(gl); \ } while (0) - switch ( image->Format ) { - case GL_INTENSITY: - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x); - for ( j = width >> 2 ; j ; j-- ) { - *dst++ = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - src += 4; - } - ALIGN_DST; - } - break; - - case GL_COLOR_INDEX: - default: - fprintf( stderr, "%s: unsupported format 0x%x\n", - __FUNCTION__, image->Format ); - break; - } -} -#undef ALIGN_DST - -/* Convert a block of Mesa-formatted texture to a 16bpp hardware format. - */ -static void radeonConvertTexture16bpp( CARD32 *dst, - struct gl_texture_image *image, - int x, int y, int width, int height, - int pitch ) -{ - CARD8 *src; - int i, j; - - if ( width < 2 ) { - width = 2; - } - -#define ALIGN_DST \ +#define SET_FORMAT_32BPT( r32, gl32, r16, gl16 ) \ do { \ - if ( width < 16 ) { \ - dst += ((16 - width) / 2); \ + if ( do32bpt ) { \ + ret = (r32); \ + texFormat = &(gl32); \ + } else { \ + ret = (r16); \ + texFormat = &(gl16); \ } \ } while (0) - switch ( image->Format ) { + switch ( texImage->IntFormat ) { + /* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has + * got to be better than sticking them way down the end of this + * huge list. + */ case GL_RGBA: - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 4; - for ( j = width >> 1 ; j ; j-- ) { - *dst++ = ((RADEONPACKCOLOR4444( src[0], src[1], src[2], src[3] )) | - (RADEONPACKCOLOR4444( src[4], src[5], src[6], src[7] ) << 16)); - src += 8; + case 4: + if ( format == GL_BGRA ) { + if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { + SET_FORMAT( RADEON_TXFORMAT_ARGB8888, _mesa_texformat_argb8888 ); + break; + } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { + SET_FORMAT( RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); + break; + } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { + SET_FORMAT( RADEON_TXFORMAT_ARGB1555, _mesa_texformat_argb1555 ); + break; } - ALIGN_DST; } + SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, + RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); break; case GL_RGB: - { - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3; - for ( j = width >> 1 ; j ; j-- ) { - *dst++ = ((RADEONPACKCOLOR565( src[0], src[1], src[2] )) | - (RADEONPACKCOLOR565( src[3], src[4], src[5] ) << 16)); - src += 6; - } - ALIGN_DST; + case 3: + if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { + SET_FORMAT( RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); + break; } - } + SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, + RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); break; - case GL_ALPHA: - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x); - for ( j = width >> 1 ; j ; j-- ) { - *dst++ = ((RADEONPACKCOLOR88( 0x00, src[0] )) | - (RADEONPACKCOLOR88( 0x00, src[1] ) << 16)); - src += 2; - } - ALIGN_DST; - } + /* GH: Okay, keep checking as normal. Still test for GL_RGB, + * GL_RGBA formats first. + */ + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, + RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); break; - case GL_LUMINANCE: - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x); - for ( j = width >> 1 ; j ; j-- ) { - *dst++ = ((RADEONPACKCOLOR88( src[0], 0xff )) | - (RADEONPACKCOLOR88( src[1], 0xff ) << 16)); - src += 2; - } - ALIGN_DST; - } + case GL_RGBA4: + case GL_RGBA2: + SET_FORMAT( RADEON_TXFORMAT_ARGB4444, _mesa_texformat_argb4444 ); break; - case GL_LUMINANCE_ALPHA: - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 2; - for ( j = width >> 1 ; j ; j-- ) { - *dst++ = ((RADEONPACKCOLOR88( src[0], src[1] )) | - (RADEONPACKCOLOR88( src[2], src[3] ) << 16)); - src += 4; - } - ALIGN_DST; - } + case GL_RGB5_A1: + SET_FORMAT( RADEON_TXFORMAT_ARGB1555, _mesa_texformat_argb1555 ); break; - default: - fprintf( stderr, "%s: unsupported format 0x%x\n", - __FUNCTION__, image->Format ); + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + SET_FORMAT_32BPT( RADEON_TXFORMAT_RGBA8888, _mesa_texformat_rgba8888, + RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); break; - } -} -#undef ALIGN_DST -/* Convert a block of Mesa-formatted texture to a 32bpp hardware format. - */ -static void radeonConvertTexture32bpp( CARD32 *dst, - struct gl_texture_image *image, - int x, int y, int width, int height, - int pitch ) -{ - CARD8 *src; - int i, j; + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + SET_FORMAT( RADEON_TXFORMAT_RGB565, _mesa_texformat_rgb565 ); + break; -#define ALIGN_DST \ - do { \ - if ( width < 8 ) { \ - dst += (8 - width); \ - } \ - } while (0) + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + SET_FORMAT( RADEON_TXFORMAT_AI88, _mesa_texformat_al88 ); + break; - switch ( image->Format ) { - case GL_RGBA: - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 4; - for ( j = width ; j ; j-- ) { - *dst++ = RADEONPACKCOLOR8888( src[0], src[1], src[2], src[3] ); - src += 4; - } - ALIGN_DST; - } + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + SET_FORMAT( RADEON_TXFORMAT_AI88, _mesa_texformat_al88 ); break; - case GL_RGB: - for ( i = 0 ; i < height ; i++ ) { - src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3; - for ( j = width ; j ; j-- ) { - *dst++ = RADEONPACKCOLOR8888( src[0], src[1], src[2], 0xff ); - src += 3; - } - ALIGN_DST; - } + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + SET_FORMAT( RADEON_TXFORMAT_AI88, _mesa_texformat_al88 ); break; - default: - fprintf( stderr, "%s: unsupported format 0x%x\n", - __FUNCTION__, image->Format ); + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + SET_FORMAT( RADEON_TXFORMAT_I8, _mesa_texformat_i8 ); break; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + default: + fprintf( stderr, "bad texture format in radeonChooseTexFormat() %d", + texImage->IntFormat ); + return -1; } + + texImage->TexFormat = texFormat; + + return ret; } -/* Upload the texture image associated with texture `t' at level `level' - * at the address relative to `start'. + +/* ================================================================ + * Texture image callbacks */ -static void radeonUploadSubImage( radeonContextPtr rmesa, - radeonTexObjPtr t, GLint level, - GLint x, GLint y, GLint width, GLint height ) -{ - struct gl_texture_image *image; - GLint texelsPerDword = 0; - GLint imageX, imageY, imageWidth, imageHeight; - GLint blitX, blitY, blitWidth, blitHeight; - GLint imageRows, blitRows; - GLint remaining ; - GLint format, dwords; - CARD32 pitch, offset; - drmBufPtr buffer; - CARD32 *dst; - - /* Ensure we have a valid texture to upload */ - if ( ( level < 0 ) || ( level >= RADEON_MAX_TEXTURE_LEVELS ) ) - return; - image = t->tObj->Image[level]; - if ( !image ) - return; +static GLboolean +radeonDDTexImage1D( GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + GLboolean *retainInternalCopy ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; + const struct gl_texture_format *texFormat; + GLuint texSize; + GLint txformat; + GLubyte *data; - switch ( t->texelBytes ) { - case 1: - texelsPerDword = 4; - break; - case 2: - texelsPerDword = 2; - break; - case 4: - texelsPerDword = 1; - break; - } + if ( target != GL_TEXTURE_1D ) + return GL_FALSE; - format = t->setup.pp_txformat & RADEON_TXF_FORMAT_MASK; - - imageX = 0; - imageY = 0; - imageWidth = image->Width; - imageHeight = image->Height; - - blitX = t->image[level].x; - blitY = t->image[level].y; - blitWidth = t->image[level].width; - blitHeight = t->image[level].height; - - dwords = t->image[level].dwords; - offset = t->bufAddr; - pitch = (t->image[0].width * t->texelBytes) / 64; - -#if ENABLE_PERF_BOXES - /* Bump the performace counter */ - rmesa->c_textureBytes += (dwords << 2); -#endif - - if ( RADEON_DEBUG & DEBUG_VERBOSE_MSG ) { - fprintf( stderr, " upload image: %d,%d at %d,%d\n", - imageWidth, imageHeight, imageX, imageY ); - fprintf( stderr, " upload blit: %d,%d at %d,%d\n", - blitWidth, blitHeight, blitX, blitY ); - fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x dwords: %d " - "level: %d format: %x\n", - (GLuint)offset, (GLuint)pitch, dwords, level, format ); + if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s( %p )\n", __FUNCTION__, t ); } - /* Subdivide the texture if required */ - if ( dwords <= RADEON_BUFFER_MAX_DWORDS / 2 ) { - imageRows = imageHeight; - blitRows = blitHeight; + if ( t ) { + if ( t->bound ) FLUSH_BATCH( rmesa ); + radeonSwapOutTexObj( rmesa, t ); } else { - imageRows = (RADEON_BUFFER_MAX_DWORDS * texelsPerDword)/(2 * imageWidth); - blitRows = (RADEON_BUFFER_MAX_DWORDS * texelsPerDword) / (2 * blitWidth); + t = radeonAllocTexObj( texObj ); + texObj->DriverData = t; } - for ( remaining = imageHeight ; - remaining > 0 ; - remaining -= imageRows, imageY += imageRows, blitY += blitRows ) - { - if ( remaining >= imageRows ) { - imageHeight = imageRows; - blitHeight = blitRows; - } else { - imageHeight = remaining; - blitHeight = blitRows; - } - dwords = blitWidth * blitHeight / texelsPerDword; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_MSG ) { - fprintf( stderr, " blitting: %d,%d at %d,%d\n", - imageWidth, imageHeight, imageX, imageY ); - fprintf( stderr, " %d,%d at %d,%d - %d dwords\n", - blitWidth, blitHeight, blitX, blitY, dwords ); - } - - /* Grab the indirect buffer for the texture blit */ - buffer = radeonGetBufferLocked( rmesa ); + txformat = radeonChooseTexFormat( rmesa, texImage, format, type ); + if ( txformat < 0 ) + return GL_FALSE; - dst = (CARD32 *)((char *)buffer->address + RADEON_HOSTDATA_BLIT_OFFSET); + texFormat = texImage->TexFormat; + texSize = texImage->Width * texFormat->TexelBytes; - /* Actually do the texture conversion */ - switch ( t->texelBytes ) { - case 1: - radeonConvertTexture8bpp( dst, image, - imageX, imageY, imageWidth, imageHeight, - imageWidth ); - break; - case 2: - radeonConvertTexture16bpp( dst, image, - imageX, imageY, imageWidth, imageHeight, - imageWidth ); - break; - case 4: - radeonConvertTexture32bpp( dst, image, - imageX, imageY, imageWidth, imageHeight, - imageWidth ); - break; - } - - radeonFireBlitLocked( rmesa, buffer, - offset, pitch, format, - blitX, blitY, blitWidth, blitHeight ); + /* We really shouldn't have to keep the texture image, it should be + * hung from the main texImage structure. + */ + if ( t->image[level].data ) { + FREE( t->image[level].data ); + t->image[level].data = NULL; } - rmesa->new_state |= RADEON_NEW_CONTEXT; - rmesa->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_MASKS; -} + data = (GLubyte *) MALLOC( texSize ); + if ( !data ) + return GL_FALSE; -/* Upload the texture images associated with texture `t'. This might - * require removing our own and/or other client's texture objects to - * make room for these images. - */ -/* NOTE: This function is only called while holding the hardware lock */ -int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t ) -{ - int i; - int heap; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %p )\n", - __FUNCTION__, rmesa->glCtx, t ); + if ( !_mesa_convert_texsubimage1d( texFormat->IntFormat, + 0, texImage->Width, + format, type, packing, + pixels, data ) ) { + /*fprintf( stderr, " *** convert failed!\n" );*/ + FREE( data ); + return GL_FALSE; } - if ( !t ) - return 0; - - /* Choose the heap appropriately */ - heap = t->heap = RADEON_CARD_HEAP; -#if 0 - if ( !rmesa->radeonScreen->IsPCI && - t->totalSize > rmesa->radeonScreen->texSize[heap] ) { - heap = t->heap = RADEON_AGP_HEAP; - } -#endif - - /* Do we need to eject LRU texture objects? */ - if ( !t->memBlock ) { - /* Allocate a memory block on a 4k boundary (1<<12 == 4096) */ - t->memBlock = mmAllocMem( rmesa->texHeap[heap], - t->totalSize, 12, 0 ); - -#if 0 - /* Try AGP before kicking anything out of local mem */ - if ( !t->memBlock && heap == RADEON_CARD_HEAP ) { - t->memBlock = mmAllocMem( rmesa->texHeap[RADEON_AGP_HEAP], - t->totalSize, 12, 0 ); - - if ( t->memBlock ) - heap = t->heap = RADEON_AGP_HEAP; - } -#endif - - /* Kick out textures until the requested texture fits */ - while ( !t->memBlock ) { - if ( rmesa->TexObjList[heap].prev->bound ) { - fprintf( stderr, - "radeonUploadTexImages: ran into bound texture\n" ); - return -1; - } - if ( rmesa->TexObjList[heap].prev == - &rmesa->TexObjList[heap] ) { - if ( rmesa->radeonScreen->IsPCI ) { - fprintf( stderr, "radeonUploadTexImages: upload texture " - "failure on local texture heaps, sz=%d\n", - t->totalSize ); - return -1; -#if 0 - } else if ( heap == RADEON_CARD_HEAP ) { - heap = t->heap = RADEON_AGP_HEAP; - continue; -#endif - } else { - fprintf( stderr, "radeonUploadTexImages: upload texture " - "failure on both local and AGP texture heaps, " - "sz=%d\n", - t->totalSize ); - return -1; - } - } + t->image[level].data = data; + t->dirty_images |= (1 << level); - radeonDestroyTexObj( rmesa, rmesa->TexObjList[heap].prev ); + /* Format-specific hardware state: + */ + t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK | + RADEON_TXFORMAT_ALPHA_IN_MAP); + t->pp_txformat |= txformat; - t->memBlock = mmAllocMem( rmesa->texHeap[heap], - t->totalSize, 12, 0 ); - } + if ( txformat == RADEON_TXFORMAT_RGBA8888 || + txformat == RADEON_TXFORMAT_ARGB4444 || + txformat == RADEON_TXFORMAT_ARGB1555 || + txformat == RADEON_TXFORMAT_AI88 ) { + t->pp_txformat |= RADEON_TXFORMAT_ALPHA_IN_MAP; + } - /* Set the base offset of the texture image */ - t->bufAddr = rmesa->radeonScreen->texOffset[heap] + t->memBlock->ofs; + rmesa->new_state |= RADEON_NEW_TEXTURE; - t->setup.pp_txoffset = t->bufAddr; -#if 0 - /* Fix AGP texture offsets */ - if ( heap == RADEON_AGP_HEAP ) { - t->setup.pp_tx_offset += RADEON_AGP_TEX_OFFSET + - rmesa->radeonScreen->agpTexOffset; - } -#endif + *retainInternalCopy = GL_FALSE; + return GL_TRUE; +} - /* Force loading the new state into the hardware */ - switch ( t->bound ) { - case 1: - rmesa->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_TEX0; - break; +static GLboolean +radeonDDTexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + GLboolean *retainInternalCopy ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; + const struct gl_texture_format *texFormat; + GLuint texSize; + GLint txformat; + GLubyte *data; - case 2: - rmesa->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_TEX1; - break; + if ( target != GL_TEXTURE_2D ) + return GL_FALSE; - default: - return -1; - } + if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s( %p )\n", __FUNCTION__, t ); } - /* Let the world know we've used this memory recently */ - radeonUpdateTexLRU( rmesa, t ); + if ( t ) { + if ( t->bound ) FLUSH_BATCH( rmesa ); + radeonSwapOutTexObj( rmesa, t ); + } else { + t = radeonAllocTexObj( texObj ); + texObj->DriverData = t; + } - /* Upload any images that are new */ - if ( t->dirty_images ) { - int num_levels = ((t->setup.pp_txfilter & RADEON_MAX_MIP_LEVEL_MASK) >> - RADEON_MAX_MIP_LEVEL_SHIFT); + txformat = radeonChooseTexFormat( rmesa, texImage, format, type ); + if ( txformat < 0 ) + return GL_FALSE; - for ( i = 0 ; i <= num_levels ; i++ ) { - if ( t->dirty_images & (1 << i) ) { - radeonUploadSubImage( rmesa, t, i, 0, 0, - t->image[i].width, t->image[i].height ); - } - } + texFormat = texImage->TexFormat; + texSize = texImage->Width * texImage->Height * texFormat->TexelBytes; - rmesa->dirty |= RADEON_UPLOAD_CONTEXT; + /* We really shouldn't have to keep the texture image, it should be + * hung from the main texImage structure. + */ + if ( t->image[level].data ) { + FREE( t->image[level].data ); + t->image[level].data = NULL; } - t->dirty_images = 0; - return 0; -} - + data = (GLubyte *) MALLOC( texSize ); + if ( !data ) + return GL_FALSE; -/* ================================================================ - * Texture combine functions - */ + if ( !_mesa_convert_texsubimage2d( texFormat->IntFormat, + 0, 0, texImage->Width, texImage->Height, + texImage->Width, format, type, packing, + pixels, data ) ) { + if ( 0 ) + fprintf( stderr, " *** convert failed! %s/%s-> %s\n", + gl_lookup_enum_by_nr( format ), + gl_lookup_enum_by_nr( type ), + gl_lookup_enum_by_nr( texImage->IntFormat ) ); + FREE( data ); + return GL_FALSE; + } -#define RADEON_DISABLE 0 -#define RADEON_REPLACE 1 -#define RADEON_MODULATE 2 -#define RADEON_DECAL 3 -#define RADEON_BLEND 4 -#define RADEON_ADD 5 -#define RADEON_MAX_COMBFUNC 6 + t->image[level].data = data; + t->dirty_images |= (1 << level); -static GLuint radeon_color_combine[][RADEON_MAX_COMBFUNC] = -{ - /* Unit 0: - */ - { - /* Disable combiner stage - */ - (RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_CURRENT_COLOR | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_REPLACE = 0x00802800 - */ - (RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_T0_COLOR | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_MODULATE = 0x00800142 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_T0_COLOR | - RADEON_COLOR_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_DECAL = 0x008c2d42 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_T0_COLOR | - RADEON_COLOR_ARG_C_T0_ALPHA | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_BLEND = 0x008c2902 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_TFACTOR_COLOR | - RADEON_COLOR_ARG_C_T0_COLOR | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_ADD = 0x00812802 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_T0_COLOR | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - }, - - /* Unit 1: - */ - { - /* Disable combiner stage - */ - (RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_CURRENT_COLOR | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_REPLACE = 0x00803000 - */ - (RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_T1_COLOR | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_MODULATE = 0x00800182 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_T1_COLOR | - RADEON_COLOR_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_DECAL = 0x008c3582 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_T1_COLOR | - RADEON_COLOR_ARG_C_T1_ALPHA | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_BLEND = 0x008c3102 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_TFACTOR_COLOR | - RADEON_COLOR_ARG_C_T1_COLOR | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_ADD = 0x00813002 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_T1_COLOR | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - }, - - /* Unit 2: + /* Format-specific hardware state: */ - { - /* Disable combiner stage - */ - (RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_CURRENT_COLOR | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_REPLACE = 0x00803800 - */ - (RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_T2_COLOR | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_MODULATE = 0x008001c2 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_T2_COLOR | - RADEON_COLOR_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_DECAL = 0x008c3dc2 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_T2_COLOR | - RADEON_COLOR_ARG_C_T2_ALPHA | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_BLEND = 0x008c3902 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_TFACTOR_COLOR | - RADEON_COLOR_ARG_C_T2_COLOR | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_ADD = 0x00813802 - */ - (RADEON_COLOR_ARG_A_CURRENT_COLOR | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_T2_COLOR | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - } -}; + t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK | + RADEON_TXFORMAT_ALPHA_IN_MAP); + t->pp_txformat |= txformat; -static GLuint radeon_alpha_combine[][RADEON_MAX_COMBFUNC] = -{ - /* Unit 0: - */ - { - /* Disable combiner stage - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_CURRENT_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_REPLACE = 0x00800500 - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_T0_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_MODULATE = 0x00800051 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_T0_ALPHA | - RADEON_ALPHA_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_DECAL = 0x00800100 - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_CURRENT_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_BLEND = 0x00800051 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_TFACTOR_ALPHA | - RADEON_ALPHA_ARG_C_T0_ALPHA | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_ADD = 0x00800051 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_T0_ALPHA | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - }, - - /* Unit 1: - */ - { - /* Disable combiner stage - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_CURRENT_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_REPLACE = 0x00800600 - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_T1_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_MODULATE = 0x00800061 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_T1_ALPHA | - RADEON_ALPHA_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_DECAL = 0x00800100 - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_CURRENT_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_BLEND = 0x00800061 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_TFACTOR_ALPHA | - RADEON_ALPHA_ARG_C_T1_ALPHA | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_ADD = 0x00800061 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_T1_ALPHA | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - }, - - /* Unit 2: - */ - { - /* Disable combiner stage - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_CURRENT_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_REPLACE = 0x00800700 - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_T2_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_MODULATE = 0x00800071 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_T2_ALPHA | - RADEON_ALPHA_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_DECAL = 0x00800100 - */ - (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_CURRENT_ALPHA | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_BLEND = 0x00800071 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_TFACTOR_ALPHA | - RADEON_ALPHA_ARG_C_T2_ALPHA | - RADEON_BLEND_CTL_BLEND | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), - - /* GL_ADD = 0x00800021 - */ - (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_T2_ALPHA | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_SCALE_1X | - RADEON_CLAMP_TX), + if ( txformat == RADEON_TXFORMAT_RGBA8888 || + txformat == RADEON_TXFORMAT_ARGB4444 || + txformat == RADEON_TXFORMAT_ARGB1555 || + txformat == RADEON_TXFORMAT_AI88 ) { + t->pp_txformat |= RADEON_TXFORMAT_ALPHA_IN_MAP; } -}; + rmesa->new_state |= RADEON_NEW_TEXTURE; -/* GL_EXT_texture_env_combine support - */ + *retainInternalCopy = GL_FALSE; + return GL_TRUE; +} -/* The color tables have combine functions for GL_SRC_COLOR, - * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. +/* GH: This is undoubtedly broken... */ -static GLuint radeon_texture_color[][RADEON_MAX_TEXTURE_UNITS] = -{ - { - RADEON_COLOR_ARG_A_T0_COLOR, - RADEON_COLOR_ARG_A_T1_COLOR, - RADEON_COLOR_ARG_A_T2_COLOR - }, - { - RADEON_COLOR_ARG_A_T0_COLOR | RADEON_COMP_ARG_A, - RADEON_COLOR_ARG_A_T1_COLOR | RADEON_COMP_ARG_A, - RADEON_COLOR_ARG_A_T2_COLOR | RADEON_COMP_ARG_A - }, - { - RADEON_COLOR_ARG_A_T0_ALPHA, - RADEON_COLOR_ARG_A_T1_ALPHA, - RADEON_COLOR_ARG_A_T2_ALPHA - }, - { - RADEON_COLOR_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A, - RADEON_COLOR_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A, - RADEON_COLOR_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A - }, -}; - -static GLuint radeon_tfactor_color[] = +static GLboolean +radeonDDTexImage3D( GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + GLboolean *retainInternalCopy ) { - RADEON_COLOR_ARG_A_TFACTOR_COLOR, - RADEON_COLOR_ARG_A_TFACTOR_COLOR | RADEON_COMP_ARG_A, - RADEON_COLOR_ARG_A_TFACTOR_ALPHA, - RADEON_COLOR_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A -}; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; + const struct gl_texture_format *texFormat; + GLuint texSize; + GLint txformat; + GLubyte *data; -static GLuint radeon_primary_color[] = -{ - RADEON_COLOR_ARG_A_DIFFUSE_COLOR, - RADEON_COLOR_ARG_A_DIFFUSE_COLOR | RADEON_COMP_ARG_A, - RADEON_COLOR_ARG_A_DIFFUSE_ALPHA, - RADEON_COLOR_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A -}; + if ( target != GL_TEXTURE_3D ) + return GL_FALSE; -static GLuint radeon_previous_color[] = -{ - RADEON_COLOR_ARG_A_CURRENT_COLOR, - RADEON_COLOR_ARG_A_CURRENT_COLOR | RADEON_COMP_ARG_A, - RADEON_COLOR_ARG_A_CURRENT_ALPHA, - RADEON_COLOR_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A -}; + if ( t ) { + if ( t->bound ) FLUSH_BATCH( rmesa ); + radeonSwapOutTexObj( rmesa, t ); + } else { + t = radeonAllocTexObj( texObj ); + texObj->DriverData = t; + } -/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. - */ -static GLuint radeon_texture_alpha[][RADEON_MAX_TEXTURE_UNITS] = -{ - { - RADEON_ALPHA_ARG_A_T0_ALPHA, - RADEON_ALPHA_ARG_A_T1_ALPHA, - RADEON_ALPHA_ARG_A_T2_ALPHA - }, - { - RADEON_ALPHA_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A, - RADEON_ALPHA_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A, - RADEON_ALPHA_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A - }, -}; - -static GLuint radeon_tfactor_alpha[] = -{ - RADEON_ALPHA_ARG_A_TFACTOR_ALPHA, - RADEON_ALPHA_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A -}; + txformat = radeonChooseTexFormat( rmesa, texImage, format, type ); + if ( txformat < 0 ) + return GL_FALSE; -static GLuint radeon_primary_alpha[] = -{ - RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA, - RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A -}; + texFormat = texImage->TexFormat; + texSize = (texImage->Width * texImage->Height * + texImage->Depth * texFormat->TexelBytes); -static GLuint radeon_previous_alpha[] = -{ - RADEON_ALPHA_ARG_A_CURRENT_ALPHA, - RADEON_ALPHA_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A -}; + /* We really shouldn't have to keep the texture image, it should be + * hung from the main texImage structure. + */ + if ( t->image[level].data ) { + FREE( t->image[level].data ); + t->image[level].data = NULL; + } + data = (GLubyte *) MALLOC( texSize ); + if ( !data ) + return GL_FALSE; -/* Extract the arg from slot A, shift it into the correct argument slot - * and set the corresponding complement bit. - */ -#define RADEON_COLOR_ARG( n, arg ) \ -do { \ - color_combine |= \ - ((color_arg[n] & RADEON_COLOR_ARG_MASK) \ - << RADEON_COLOR_ARG_##arg##_SHIFT); \ - color_combine |= \ - ((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \ - << RADEON_COMP_ARG_##arg##_SHIFT); \ -} while (0) - -#define RADEON_ALPHA_ARG( n, arg ) \ -do { \ - alpha_combine |= \ - ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \ - << RADEON_ALPHA_ARG_##arg##_SHIFT); \ - alpha_combine |= \ - ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \ - << RADEON_COMP_ARG_##arg##_SHIFT); \ -} while (0) + if ( !_mesa_convert_texsubimage3d( texFormat->IntFormat, + 0, 0, 0, texImage->Width, + texImage->Height, texImage->Depth, + texImage->Width, texImage->Height, + format, type, packing, + pixels, data ) ) { + FREE( data ); + return GL_FALSE; + } + + t->image[level].data = data; + t->dirty_images |= (1 << level); + rmesa->new_state |= RADEON_NEW_TEXTURE; + + *retainInternalCopy = GL_FALSE; + return GL_TRUE; +} /* ================================================================ - * Texture unit state management + * Texture subimage callbacks */ -static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) +static GLboolean +radeonDDTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - int source = rmesa->tmu_source[unit]; - struct gl_texture_object *tObj; - struct gl_texture_unit *texUnit; - GLuint enabled; - GLuint color_combine, alpha_combine; - GLuint color_arg[3], alpha_arg[3]; - GLuint i, numColorArgs = 0, numAlphaArgs = 0; - GLuint op; + radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; + const struct gl_texture_format *texFormat; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %d )\n", - __FUNCTION__, ctx, unit ); - } - - enabled = (ctx->Texture.ReallyEnabled >> (source * 4)) & TEXTURE0_ANY; - if ( enabled != TEXTURE0_2D && enabled != TEXTURE0_1D ) - return; + if ( target != GL_TEXTURE_1D ) + return GL_FALSE; - /* Only update the hardware texture state if the texture is current, - * complete and enabled. + /* FIXME: Can this ever be NULL??? */ - texUnit = &ctx->Texture.Unit[source]; - tObj = texUnit->Current; - if ( !tObj || !tObj->Complete ) - return; - - if ( ( tObj != texUnit->CurrentD[2] ) && - ( tObj != texUnit->CurrentD[1] ) ) - return; + ASSERT( t ); - /* Set the texture environment state. Isn't this nice and clean? - * The Radeon will automagically set the texture alpha to 0xff when - * the texture format does not include an alpha component. This - * reduces the amount of special-casing we have to do, alpha-only - * textures being a notable exception. - */ - switch ( texUnit->EnvMode ) { - case GL_REPLACE: - switch ( tObj->Image[0]->Format ) { - case GL_RGBA: - case GL_RGB: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_INTENSITY: - color_combine = radeon_color_combine[unit][RADEON_REPLACE]; - alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE]; - break; - case GL_ALPHA: - color_combine = radeon_color_combine[unit][RADEON_DISABLE]; - alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE]; - break; - case GL_COLOR_INDEX: - default: - return; - } - break; - - case GL_MODULATE: - switch ( tObj->Image[0]->Format ) { - case GL_RGBA: - case GL_RGB: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_INTENSITY: - color_combine = radeon_color_combine[unit][RADEON_MODULATE]; - alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; - break; - case GL_ALPHA: - color_combine = radeon_color_combine[unit][RADEON_DISABLE]; - alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; - break; - case GL_COLOR_INDEX: - default: - return; - } - break; - - case GL_DECAL: - switch ( tObj->Image[0]->Format ) { - case GL_RGBA: - case GL_RGB: - color_combine = radeon_color_combine[unit][RADEON_DECAL]; - alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE]; - break; - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_INTENSITY: - color_combine = radeon_color_combine[unit][RADEON_DISABLE]; - alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE]; - break; - case GL_COLOR_INDEX: - default: - return; - } - break; - - case GL_BLEND: - switch ( tObj->Image[0]->Format ) { - case GL_RGBA: - case GL_RGB: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - color_combine = radeon_color_combine[unit][RADEON_BLEND]; - alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; - break; - case GL_ALPHA: - color_combine = radeon_color_combine[unit][RADEON_DISABLE]; - alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; - break; - case GL_INTENSITY: - color_combine = radeon_color_combine[unit][RADEON_BLEND]; - alpha_combine = radeon_alpha_combine[unit][RADEON_BLEND]; - break; - case GL_COLOR_INDEX: - default: - return; - } - break; - - case GL_ADD: - switch ( tObj->Image[0]->Format ) { - case GL_RGBA: - case GL_RGB: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - color_combine = radeon_color_combine[unit][RADEON_ADD]; - alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; - break; - case GL_ALPHA: - color_combine = radeon_color_combine[unit][RADEON_DISABLE]; - alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; - break; - case GL_INTENSITY: - color_combine = radeon_color_combine[unit][RADEON_ADD]; - alpha_combine = radeon_alpha_combine[unit][RADEON_ADD]; - break; - case GL_COLOR_INDEX: - default: - return; - } - break; + if ( t->bound ) { + FLUSH_VB( ctx, "radeonDDTexSubImage2D" ); + FLUSH_BATCH( rmesa ); + } - case GL_COMBINE_EXT: - /* Step 0: - * Calculate how many arguments we need to process. - */ - switch ( texUnit->CombineModeRGB ) { - case GL_REPLACE: - numColorArgs = 1; - break; - case GL_MODULATE: - case GL_ADD: - case GL_ADD_SIGNED_EXT: - case GL_DOT3_RGB_EXT: - case GL_DOT3_RGBA_EXT: - numColorArgs = 2; - break; - case GL_INTERPOLATE_EXT: - numColorArgs = 3; - break; - default: - return; - } + texFormat = texImage->TexFormat; - switch ( texUnit->CombineModeA ) { - case GL_REPLACE: - numAlphaArgs = 1; - break; - case GL_MODULATE: - case GL_ADD: - case GL_ADD_SIGNED_EXT: - numAlphaArgs = 2; - break; - case GL_INTERPOLATE_EXT: - numAlphaArgs = 3; - break; - default: - return; - } + if ( !_mesa_convert_texsubimage1d( texFormat->IntFormat, + xoffset, width, format, type, packing, + pixels, t->image[level].data ) ) { + /*fprintf( stderr, " *** convert failed!\n" );*/ + return GL_FALSE; + } - /* Step 1: - * Extract the color and alpha combine function arguments. - */ - for ( i = 0 ; i < numColorArgs ; i++ ) { - op = texUnit->CombineOperandRGB[i] - GL_SRC_COLOR; - switch ( texUnit->CombineSourceRGB[i] ) { - case GL_TEXTURE: - color_arg[i] = radeon_texture_color[op][unit]; - break; - case GL_CONSTANT_EXT: - color_arg[i] = radeon_tfactor_color[op]; - break; - case GL_PRIMARY_COLOR_EXT: - color_arg[i] = radeon_primary_color[op]; - break; - case GL_PREVIOUS_EXT: - color_arg[i] = radeon_previous_color[op]; - break; - default: - return; - } - } + t->dirty_images |= (1 << level); + rmesa->new_state |= RADEON_NEW_TEXTURE; - for ( i = 0 ; i < numAlphaArgs ; i++ ) { - op = texUnit->CombineOperandA[i] - GL_SRC_ALPHA; - switch ( texUnit->CombineSourceA[i] ) { - case GL_TEXTURE: - alpha_arg[i] = radeon_texture_alpha[op][unit]; - break; - case GL_CONSTANT_EXT: - alpha_arg[i] = radeon_tfactor_alpha[op]; - break; - case GL_PRIMARY_COLOR_EXT: - alpha_arg[i] = radeon_primary_alpha[op]; - break; - case GL_PREVIOUS_EXT: - alpha_arg[i] = radeon_previous_alpha[op]; - break; - default: - return; - } - } + return GL_TRUE; +} - /* Step 2: - * Build up the color and alpha combine functions. - */ - switch ( texUnit->CombineModeRGB ) { - case GL_REPLACE: - color_combine = (RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - RADEON_COLOR_ARG( 0, C ); - break; - case GL_MODULATE: - color_combine = (RADEON_COLOR_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - RADEON_COLOR_ARG( 0, A ); - RADEON_COLOR_ARG( 1, B ); - break; - case GL_ADD: - color_combine = (RADEON_COLOR_ARG_B_ZERO | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - RADEON_COLOR_ARG( 0, A ); - RADEON_COLOR_ARG( 1, C ); - break; - case GL_ADD_SIGNED_EXT: - color_combine = (RADEON_COLOR_ARG_B_ZERO | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADDSIGNED | - RADEON_CLAMP_TX); - RADEON_COLOR_ARG( 0, A ); - RADEON_COLOR_ARG( 1, C ); - break; - case GL_INTERPOLATE_EXT: - color_combine = (RADEON_BLEND_CTL_BLEND | - RADEON_CLAMP_TX); - RADEON_COLOR_ARG( 0, B ); - RADEON_COLOR_ARG( 1, A ); - RADEON_COLOR_ARG( 2, C ); - break; - case GL_DOT3_RGB_EXT: - case GL_DOT3_RGBA_EXT: - color_combine = (RADEON_COLOR_ARG_C_ZERO | - RADEON_BLEND_CTL_DOT3 | - RADEON_CLAMP_TX); - RADEON_COLOR_ARG( 0, A ); - RADEON_COLOR_ARG( 1, B ); - break; - default: - return; - } +static GLboolean +radeonDDTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; + const struct gl_texture_format *texFormat; - switch ( texUnit->CombineModeA ) { - case GL_REPLACE: - alpha_combine = (RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - RADEON_ALPHA_ARG( 0, C ); - break; - case GL_MODULATE: - alpha_combine = (RADEON_ALPHA_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - RADEON_ALPHA_ARG( 0, A ); - RADEON_ALPHA_ARG( 1, B ); - break; - case GL_ADD: - alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - RADEON_ALPHA_ARG( 0, A ); - RADEON_ALPHA_ARG( 1, C ); - break; - case GL_ADD_SIGNED_EXT: - alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | - RADEON_COMP_ARG_B | - RADEON_BLEND_CTL_ADDSIGNED | - RADEON_CLAMP_TX); - RADEON_ALPHA_ARG( 0, A ); - RADEON_ALPHA_ARG( 1, C ); - break; - case GL_INTERPOLATE_EXT: - alpha_combine = (RADEON_BLEND_CTL_BLEND | - RADEON_CLAMP_TX); - RADEON_ALPHA_ARG( 0, B ); - RADEON_ALPHA_ARG( 1, A ); - RADEON_ALPHA_ARG( 2, C ); - break; - default: - return; - } + if ( target != GL_TEXTURE_2D ) + return GL_FALSE; - if ( texUnit->CombineModeRGB == GL_DOT3_RGB_EXT ) { - alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE; - } + /* FIXME: Can this ever be NULL??? + */ + ASSERT( t ); - /* Step 3: - * Apply the scale factor. The EXT extension has a somewhat - * unnecessary restriction that the scale must be 4x. The ARB - * extension will likely drop this and we can just apply the - * scale factors regardless. - */ - if ( texUnit->CombineModeRGB != GL_DOT3_RGB_EXT && - texUnit->CombineModeRGB != GL_DOT3_RGBA_EXT ) { - color_combine |= (texUnit->CombineScaleShiftRGB << 21); - alpha_combine |= (texUnit->CombineScaleShiftA << 21); - } else { - color_combine |= RADEON_SCALE_4X; - alpha_combine |= RADEON_SCALE_4X; - } + if ( t->bound ) { + FLUSH_VB( ctx, "radeonDDTexSubImage2D" ); + FLUSH_BATCH( rmesa ); + } - /* All done! - */ - break; + texFormat = texImage->TexFormat; - default: - return; + if ( !_mesa_convert_texsubimage2d( texFormat->IntFormat, + xoffset, yoffset, width, height, + texImage->Width, format, type, packing, + pixels, t->image[level].data ) ) { + /*fprintf( stderr, " *** convert failed!\n" );*/ + return GL_FALSE; } - rmesa->color_combine[source] = color_combine; - rmesa->alpha_combine[source] = alpha_combine; + t->dirty_images |= (1 << level); + rmesa->new_state |= RADEON_NEW_TEXTURE; + + return GL_TRUE; } -static void radeonUpdateTextureObject( GLcontext *ctx, int unit ) +/* GH: This is undoubtedly broken... + */ +static GLboolean +radeonDDTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - int source = rmesa->tmu_source[unit]; - struct gl_texture_object *tObj; - radeonTexObjPtr t; - GLuint enabled; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %d )\n", - __FUNCTION__, ctx, unit ); - } + radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; + const struct gl_texture_format *texFormat; - enabled = (ctx->Texture.ReallyEnabled >> (source * 4)) & TEXTURE0_ANY; - if ( enabled != TEXTURE0_2D && enabled != TEXTURE0_1D ) { - if ( enabled ) - rmesa->Fallback |= RADEON_FALLBACK_TEXTURE; - return; - } + if ( target != GL_TEXTURE_3D ) + return GL_FALSE; - /* Only update the hardware texture state if the texture is current, - * complete and enabled. + /* FIXME: Can this ever be NULL??? */ - tObj = ctx->Texture.Unit[source].Current; - if ( !tObj || !tObj->Complete ) - return; + ASSERT( t ); - if ( ( tObj != ctx->Texture.Unit[source].CurrentD[2] ) && - ( tObj != ctx->Texture.Unit[source].CurrentD[1] ) ) - return; - - if ( !tObj->DriverData ) { - /* If this is the first time the texture has been used, then create - * a new texture object for it. - */ - radeonCreateTexObj( rmesa, tObj ); - - if ( !tObj->DriverData ) { - /* Can't create a texture object... */ - fprintf( stderr, "%s: texture object creation failed!\n", - __FUNCTION__ ); - rmesa->Fallback |= RADEON_FALLBACK_TEXTURE; - return; - } - } - - /* We definately have a valid texture now */ - t = tObj->DriverData; - - /* Force the texture unit state to be loaded into the hardware */ - rmesa->dirty |= RADEON_UPLOAD_CONTEXT | (RADEON_UPLOAD_TEX0 << unit); + if ( t->bound ) + FLUSH_BATCH( rmesa ); - /* Force any texture images to be loaded into the hardware */ - if ( t->dirty_images ) - rmesa->dirty |= (RADEON_UPLOAD_TEX0IMAGES << unit); + texFormat = texImage->TexFormat; - /* Bind to the given texture unit */ - rmesa->CurrentTexObj[unit] = t; - t->bound = unit + 1; + if ( !_mesa_convert_texsubimage3d( texFormat->IntFormat, + xoffset, yoffset, zoffset, + width, height, depth, + texImage->Width, texImage->Height, + format, type, packing, + pixels, t->image[level].data ) ) { + /*fprintf( stderr, " *** convert failed!\n" );*/ + return GL_FALSE; + } - if ( t->memBlock ) - radeonUpdateTexLRU( rmesa, t ); + t->dirty_images |= (1 << level); + rmesa->new_state |= RADEON_NEW_TEXTURE; - switch ( unit ) { - case 0: - rmesa->setup.pp_cntl |= (RADEON_TEX_0_ENABLE | - RADEON_TEX_BLEND_0_ENABLE); - break; - case 1: - rmesa->setup.pp_cntl |= (RADEON_TEX_1_ENABLE | - RADEON_TEX_BLEND_1_ENABLE); - break; - } + return GL_TRUE; } -void radeonUpdateTextureState( GLcontext *ctx ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p ) en=0x%x\n", - __FUNCTION__, ctx, ctx->Texture.ReallyEnabled ); - } - /* Clear any texturing fallbacks */ - rmesa->Fallback &= ~RADEON_FALLBACK_TEXTURE; +/* ================================================================ + * DEPRECATED... + */ - /* Unbind any currently bound textures */ - if ( rmesa->CurrentTexObj[0] ) rmesa->CurrentTexObj[0]->bound = 0; - if ( rmesa->CurrentTexObj[1] ) rmesa->CurrentTexObj[1]->bound = 0; - rmesa->CurrentTexObj[0] = NULL; - rmesa->CurrentTexObj[1] = NULL; +static GLvoid *radeonDDGetTexImage( GLcontext *ctx, GLenum target, GLint level, + const struct gl_texture_object *texObj, + GLenum *formatOut, GLenum *typeOut, + GLboolean *freeImageOut ) +{ + const struct gl_texture_image *texImage = texObj->Image[level]; + const struct gl_texture_format *texFormat = texImage->TexFormat; + radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; + GLubyte *data; - if ( ctx->Enabled & (TEXTURE0_3D|TEXTURE1_3D) ) - rmesa->Fallback |= RADEON_FALLBACK_TEXTURE; + if ( !t || !t->image[level].data ) + return NULL; - /* Disable all texturing until it is known to be good */ - rmesa->setup.pp_cntl &= ~(RADEON_TEX_ENABLE_MASK | - RADEON_TEX_BLEND_ENABLE_MASK); + data = (GLubyte *) MALLOC( texImage->Width * texImage->Height * 4 ); + if ( !data ) + return NULL; - radeonUpdateTextureObject( ctx, 0 ); - radeonUpdateTextureEnv( ctx, 0 ); + if ( 0 ) + fprintf( stderr, " in=%d out=%s\n", + texFormat->IntFormat, + gl_lookup_enum_by_nr( texImage->Format ) ); - if ( rmesa->multitex ) { - radeonUpdateTextureObject( ctx, 1 ); - radeonUpdateTextureEnv( ctx, 1 ); + switch ( target ) { + case GL_TEXTURE_1D: + _mesa_unconvert_teximage1d( texFormat->IntFormat, texImage->Format, + texImage->Width, + t->image[level].data, data ); + break; + case GL_TEXTURE_2D: + _mesa_unconvert_teximage2d( texFormat->IntFormat, texImage->Format, + texImage->Width, texImage->Height, + t->image[level].data, data ); + break; + default: + return NULL; } - rmesa->dirty |= RADEON_UPLOAD_CONTEXT; + *formatOut = texImage->Format; + *typeOut = GL_UNSIGNED_BYTE; + *freeImageOut = GL_TRUE; + + return data; } /* ================================================================ - * DD interface texturing functions - * - * FIXME: Many of these are deprecated -- we should move to the new - * single-copy texture interface. + * Texture state callbacks */ + #define SCALED_FLOAT_TO_BYTE( x, scale ) \ ((((GLint)((256.0F / scale) * (x))) - 1) / 2) @@ -2067,79 +784,6 @@ static void radeonDDTexEnv( GLcontext *ctx, GLenum target, } } -static void radeonDDTexImage( GLcontext *ctx, GLenum target, - struct gl_texture_object *tObj, GLint level, - GLint internalFormat, - const struct gl_texture_image *image ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) - fprintf( stderr, "%s( %p, level %d )\n", __FUNCTION__, tObj, level ); - - if ( ( target != GL_TEXTURE_2D ) && - ( target != GL_TEXTURE_1D ) ) - return; - - if ( level >= RADEON_MAX_TEXTURE_LEVELS ) - return; - - t = (radeonTexObjPtr)tObj->DriverData; - if ( t ) { - if ( t->bound ) FLUSH_BATCH( rmesa ); - - /* Destroy the old texture, and upload a new one. The actual - * uploading of the texture image occurs in the UploadSubImage - * function. - */ - radeonDestroyTexObj( rmesa, t ); - rmesa->new_state |= RADEON_NEW_TEXTURE; - } -} - -static void radeonDDTexSubImage( GLcontext *ctx, GLenum target, - struct gl_texture_object *tObj, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLint internalFormat, - const struct gl_texture_image *image ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t; - - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, level %d ) size: %d,%d of %d,%d\n", - __FUNCTION__, tObj, level, width, height, - image->Width, image->Height ); - } - - if ( ( target != GL_TEXTURE_2D ) && - ( target != GL_TEXTURE_1D ) ) - return; - - if ( level >= RADEON_MAX_TEXTURE_LEVELS ) - return; - - t = (radeonTexObjPtr)tObj->DriverData; - if ( t ) { - if ( t->bound ) FLUSH_BATCH( rmesa ); - -#if 0 - /* FIXME: Only upload textures if we already have space in the heap. - */ - LOCK_HARDWARE( rmesa ); - radeonUploadSubImage( rmesa, t, level, - xoffset, yoffset, width, height ); - UNLOCK_HARDWARE( rmesa ); -#else - radeonDestroyTexObj( rmesa, t ); -#endif - /* Update the context state */ - rmesa->new_state |= RADEON_NEW_TEXTURE; - } -} - static void radeonDDTexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat *params ) @@ -2156,7 +800,7 @@ static void radeonDDTexParameter( GLcontext *ctx, GLenum target, * created with current state before it is used, so we don't have * to do anything now. */ - if ( !t || !t->bound ) + if ( !t ) return; if ( ( target != GL_TEXTURE_2D ) && @@ -2192,25 +836,38 @@ static void radeonDDBindTexture( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLint unit = ctx->Texture.CurrentUnit; + radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData; + GLuint unit = ctx->Texture.CurrentUnit; if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %p ) unit=%d\n", - __FUNCTION__, tObj, ctx->Texture.CurrentUnit ); + __FUNCTION__, tObj, unit ); } FLUSH_BATCH( rmesa ); + if ( !t ) { + t = radeonAllocTexObj( tObj ); + tObj->DriverData = t; + } + + /* Unbind a currently bound texture. + */ if ( rmesa->CurrentTexObj[unit] ) { - rmesa->CurrentTexObj[unit]->bound = 0; + rmesa->CurrentTexObj[unit]->bound &= ~(unit + 1); rmesa->CurrentTexObj[unit] = NULL; } + /* Bind to the given texture unit. + */ + rmesa->CurrentTexObj[unit] = t; + t->bound |= unit + 1; + rmesa->new_state |= RADEON_NEW_TEXTURE; } static void radeonDDDeleteTexture( GLcontext *ctx, - struct gl_texture_object *tObj ) + struct gl_texture_object *tObj ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData; @@ -2218,8 +875,8 @@ static void radeonDDDeleteTexture( GLcontext *ctx, if ( t ) { if ( t->bound ) { FLUSH_BATCH( rmesa ); - - rmesa->CurrentTexObj[t->bound-1] = 0; + if ( t->bound & TEX_0 ) rmesa->CurrentTexObj[0] = NULL; + if ( t->bound & TEX_1 ) rmesa->CurrentTexObj[1] = NULL; rmesa->new_state |= RADEON_NEW_TEXTURE; } @@ -2240,14 +897,19 @@ static GLboolean radeonDDIsTextureResident( GLcontext *ctx, void radeonDDInitTextureFuncs( GLcontext *ctx ) { + ctx->Driver.TexImage1D = radeonDDTexImage1D; + ctx->Driver.TexImage2D = radeonDDTexImage2D; + ctx->Driver.TexImage3D = NULL /*radeonDDTexImage3D*/; + ctx->Driver.TexSubImage1D = radeonDDTexSubImage1D; + ctx->Driver.TexSubImage2D = radeonDDTexSubImage2D; + ctx->Driver.TexSubImage3D = NULL /*radeonDDTexSubImage3D*/; + ctx->Driver.GetTexImage = radeonDDGetTexImage; ctx->Driver.TexEnv = radeonDDTexEnv; - ctx->Driver.TexImage = radeonDDTexImage; - ctx->Driver.TexSubImage = radeonDDTexSubImage; ctx->Driver.TexParameter = radeonDDTexParameter; ctx->Driver.BindTexture = radeonDDBindTexture; ctx->Driver.DeleteTexture = radeonDDDeleteTexture; - ctx->Driver.UpdateTexturePalette = NULL; - ctx->Driver.ActiveTexture = NULL; ctx->Driver.IsTextureResident = radeonDDIsTextureResident; ctx->Driver.PrioritizeTexture = NULL; + ctx->Driver.ActiveTexture = NULL; + ctx->Driver.UpdateTexturePalette = NULL; } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.h index 6bf967761..967048dd1 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.h @@ -45,9 +45,11 @@ extern int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t ); extern void radeonAgeTextures( radeonContextPtr rmesa, int heap ); extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ); +extern void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ); extern void radeonPrintLocalLRU( radeonContextPtr rmesa, int heap ); extern void radeonPrintGlobalLRU( radeonContextPtr rmesa, int heap ); +extern void radeonUpdateTexLRU(radeonContextPtr rmesa, radeonTexObjPtr t ); extern void radeonDDInitTextureFuncs( GLcontext *ctx ); diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c new file mode 100644 index 000000000..52c202bee --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c @@ -0,0 +1,509 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <martin@valinux.com> + * Gareth Hughes <gareth@valinux.com> + * + */ + +#include "radeon_context.h" +#include "radeon_state.h" +#include "radeon_ioctl.h" +#include "radeon_vb.h" +#include "radeon_tex.h" + +#include "mmath.h" +#include "simple_list.h" +#include "enums.h" +#include "mem.h" + + +/* Destroy hardware state associated with texture `t'. + */ +void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) +{ +#if ENABLE_PERF_BOXES + /* Bump the performace counter */ + rmesa->c_textureSwaps++; +#endif + if ( !t ) return; + + if ( t->memBlock ) { + mmFreeMem( t->memBlock ); + t->memBlock = NULL; + } + + if ( t->tObj ) + t->tObj->DriverData = NULL; + + if ( t->bound & TEX_0 ) rmesa->CurrentTexObj[0] = NULL; + if ( t->bound & TEX_1 ) rmesa->CurrentTexObj[1] = NULL; + + remove_from_list( t ); + FREE( t ); +} + +/* Keep track of swapped out texture objects. + */ +void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) +{ +#if ENABLE_PERF_BOXES + /* Bump the performace counter */ + rmesa->c_textureSwaps++; +#endif + if ( t->memBlock ) { + mmFreeMem( t->memBlock ); + t->memBlock = NULL; + } + + t->dirty_images = ~0; + move_to_tail( &rmesa->SwappedOut, t ); +} + +/* Print out debugging information about texture LRU. + */ +void radeonPrintLocalLRU( radeonContextPtr rmesa, int heap ) +{ + radeonTexObjPtr t; + int sz = 1 << (rmesa->radeonScreen->logTexGranularity[heap]); + + fprintf( stderr, "\nLocal LRU, heap %d:\n", heap ); + + foreach ( t, &rmesa->TexObjList[heap] ) { + if (!t->tObj) { + fprintf( stderr, "Placeholder %d at 0x%x sz 0x%x\n", + t->memBlock->ofs / sz, + t->memBlock->ofs, + t->memBlock->size ); + } else { + fprintf( stderr, "Texture (bound %d) at 0x%x sz 0x%x\n", + t->bound, + t->memBlock->ofs, + t->memBlock->size ); + } + } + + fprintf( stderr, "\n" ); +} + +void radeonPrintGlobalLRU( radeonContextPtr rmesa, int heap ) +{ + radeon_tex_region_t *list = rmesa->sarea->texList[heap]; + int i, j; + + fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list ); + + for ( i = 0, j = RADEON_NR_TEX_REGIONS ; i < RADEON_NR_TEX_REGIONS ; i++ ) { + fprintf( stderr, "list[%d] age %d next %d prev %d\n", + j, list[j].age, list[j].next, list[j].prev ); + j = list[j].next; + if ( j == RADEON_NR_TEX_REGIONS ) break; + } + + if ( j != RADEON_NR_TEX_REGIONS ) { + fprintf( stderr, "Loop detected in global LRU\n" ); + for ( i = 0 ; i < RADEON_NR_TEX_REGIONS ; i++ ) { + fprintf( stderr, "list[%d] age %d next %d prev %d\n", + i, list[i].age, list[i].next, list[i].prev ); + } + } + + fprintf( stderr, "\n" ); +} + +/* Reset the global texture LRU. + */ +static void radeonResetGlobalLRU( radeonContextPtr rmesa, int heap ) +{ + radeon_tex_region_t *list = rmesa->sarea->texList[heap]; + int sz = 1 << rmesa->radeonScreen->logTexGranularity[heap]; + int i; + + /* + * (Re)initialize the global circular LRU list. The last element in + * the array (RADEON_NR_TEX_REGIONS) is the sentinal. Keeping it at + * the end of the array allows it to be addressed rationally when + * looking up objects at a particular location in texture memory. + */ + for ( i = 0 ; (i+1) * sz <= rmesa->radeonScreen->texSize[heap] ; i++ ) { + list[i].prev = i-1; + list[i].next = i+1; + list[i].age = 0; + } + + i--; + list[0].prev = RADEON_NR_TEX_REGIONS; + list[i].prev = i-1; + list[i].next = RADEON_NR_TEX_REGIONS; + list[RADEON_NR_TEX_REGIONS].prev = i; + list[RADEON_NR_TEX_REGIONS].next = 0; + rmesa->sarea->texAge[heap] = 0; +} + +/* Update the local and glock texture LRUs. + */ +void radeonUpdateTexLRU(radeonContextPtr rmesa, radeonTexObjPtr t ) +{ + int heap = t->heap; + radeon_tex_region_t *list = rmesa->sarea->texList[heap]; + int sz = rmesa->radeonScreen->logTexGranularity[heap]; + int start = t->memBlock->ofs >> sz; + int end = (t->memBlock->ofs + t->memBlock->size-1) >> sz; + int i; + + rmesa->lastTexAge[heap] = ++rmesa->sarea->texAge[heap]; + + if ( !t->memBlock ) { + fprintf( stderr, "no memblock\n\n" ); + return; + } + + /* Update our local LRU */ + move_to_head( &rmesa->TexObjList[heap], t ); + + /* Update the global LRU */ + for ( i = start ; i <= end ; i++ ) { + list[i].in_use = 1; + list[i].age = rmesa->lastTexAge[heap]; + + /* remove_from_list(i) */ + list[(CARD32)list[i].next].prev = list[i].prev; + list[(CARD32)list[i].prev].next = list[i].next; + + /* insert_at_head(list, i) */ + list[i].prev = RADEON_NR_TEX_REGIONS; + list[i].next = list[RADEON_NR_TEX_REGIONS].next; + list[(CARD32)list[RADEON_NR_TEX_REGIONS].next].prev = i; + list[RADEON_NR_TEX_REGIONS].next = i; + } + + if ( 0 ) { + radeonPrintGlobalLRU( rmesa, t->heap ); + radeonPrintLocalLRU( rmesa, t->heap ); + } +} + +/* Update our notion of what textures have been changed since we last + * held the lock. This pertains to both our local textures and the + * textures belonging to other clients. Keep track of other client's + * textures by pushing a placeholder texture onto the LRU list -- these + * are denoted by (tObj == NULL). + */ +static void radeonTexturesGone( radeonContextPtr rmesa, int heap, + int offset, int size, int in_use ) +{ + radeonTexObjPtr t, tmp; + + foreach_s ( t, tmp, &rmesa->TexObjList[heap] ) { + if ( t->memBlock->ofs >= offset + size || + t->memBlock->ofs + t->memBlock->size <= offset ) + continue; + + /* It overlaps - kick it out. Need to hold onto the currently + * bound objects, however. + */ + if ( t->bound ) { + radeonSwapOutTexObj( rmesa, t ); + } else { + radeonDestroyTexObj( rmesa, t ); + } + } + + if ( in_use ) { + t = (radeonTexObjPtr) CALLOC( sizeof(*t) ); + if ( !t ) return; + + t->memBlock = mmAllocMem( rmesa->texHeap[heap], size, 0, offset ); + if ( !t->memBlock ) { + fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n", + (int)size, (int)offset ); + mmDumpMemInfo( rmesa->texHeap[heap] ); + return; + } + insert_at_head( &rmesa->TexObjList[heap], t ); + } +} + +/* Update our client's shared texture state. If another client has + * modified a region in which we have textures, then we need to figure + * out which of our textures has been removed, and update our global + * LRU. + */ +void radeonAgeTextures( radeonContextPtr rmesa, int heap ) +{ + RADEONSAREAPrivPtr sarea = rmesa->sarea; + + if ( sarea->texAge[heap] != rmesa->lastTexAge[heap] ) { + int sz = 1 << rmesa->radeonScreen->logTexGranularity[heap]; + int nr = 0; + int idx; + + for ( idx = sarea->texList[heap][RADEON_NR_TEX_REGIONS].prev ; + idx != RADEON_NR_TEX_REGIONS && nr < RADEON_NR_TEX_REGIONS ; + idx = sarea->texList[heap][idx].prev, nr++ ) + { + /* If switching texturing schemes, then the SAREA might not + * have been properly cleared, so we need to reset the + * global texture LRU. + */ + if ( idx * sz > rmesa->radeonScreen->texSize[heap] ) { + nr = RADEON_NR_TEX_REGIONS; + break; + } + + if ( sarea->texList[heap][idx].age > rmesa->lastTexAge[heap] ) { + radeonTexturesGone( rmesa, heap, idx * sz, sz, + sarea->texList[heap][idx].in_use ); + } + } + + if ( nr == RADEON_NR_TEX_REGIONS ) { + radeonTexturesGone( rmesa, heap, 0, + rmesa->radeonScreen->texSize[heap], 0 ); + radeonResetGlobalLRU( rmesa, heap ); + } + + rmesa->dirty |= (RADEON_UPLOAD_CONTEXT | + RADEON_UPLOAD_TEX0IMAGES | + RADEON_UPLOAD_TEX1IMAGES); + rmesa->lastTexAge[heap] = sarea->texAge[heap]; + } +} + + +/* ================================================================ + * Texture image uploads + */ + +/* Upload the texture image associated with texture `t' at level `level' + * at the address relative to `start'. + */ +static void radeonUploadSubImage( radeonContextPtr rmesa, + radeonTexObjPtr t, GLint level, + GLint x, GLint y, GLint width, GLint height ) +{ + struct gl_texture_image *texImage; + const struct gl_texture_format *texFormat; + GLint texelsPerDword = 0; + GLint imageX, imageY, imageWidth, imageHeight; + GLint blitX, blitY, blitWidth, blitHeight; + GLint imageRows, blitRows; + GLint remaining; + GLint format, dwords; + CARD32 pitch, offset; + drmBufPtr buffer; + CARD32 *dst; + GLint ret; + + /* Ensure we have a valid texture to upload */ + texImage = t->tObj->Image[level]; + if ( !texImage ) + return; + + texFormat = texImage->TexFormat; + + switch ( texFormat->TexelBytes ) { + case 1: + texelsPerDword = 4; + break; + case 2: + texelsPerDword = 2; + break; + case 4: + texelsPerDword = 1; + break; + } + + format = t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK; + + imageX = 0; + imageY = 0; + imageWidth = texImage->Width; + imageHeight = texImage->Height; + + blitX = t->image[level].x; + blitY = t->image[level].y; + blitWidth = t->image[level].width; + blitHeight = t->image[level].height; + + /* dwords = t->image[level].dwords; */ + offset = t->bufAddr; + pitch = (t->image[0].width * texFormat->TexelBytes) / 64; + + if ( RADEON_DEBUG & DEBUG_VERBOSE_MSG ) { + fprintf( stderr, " upload image: %d,%d at %d,%d\n", + imageWidth, imageHeight, imageX, imageY ); + fprintf( stderr, " upload blit: %d,%d at %d,%d\n", + blitWidth, blitHeight, blitX, blitY ); + fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x " + "level: %d format: %x\n", + (GLuint)offset, (GLuint)pitch, level, format ); + } + + ret = drmRadeonLoadTexture( rmesa->driFd, offset, pitch, format, + imageWidth, imageHeight, &t->image[level] ); + + if ( ret ) { + UNLOCK_HARDWARE( rmesa ); + fprintf( stderr, "drmRadeonTextureBlit: return = %d\n", ret ); + exit( 1 ); + } + + rmesa->new_state |= RADEON_NEW_CONTEXT; + rmesa->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_MASKS; +} + +/* Upload the texture images associated with texture `t'. This might + * require removing our own and/or other client's texture objects to + * make room for these images. + */ +/* NOTE: This function is only called while holding the hardware lock */ +int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t ) +{ + int i; + int heap; + + if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s( %p, %p )\n", + __FUNCTION__, rmesa->glCtx, t->tObj ); + } + + if ( !t ) + return 0; + + /* Choose the heap appropriately */ + heap = t->heap = RADEON_CARD_HEAP; +#if 0 + if ( !rmesa->radeonScreen->IsPCI && + t->totalSize > rmesa->radeonScreen->texSize[heap] ) { + heap = t->heap = RADEON_AGP_HEAP; + } +#endif + + /* Do we need to eject LRU texture objects? */ + if ( !t->memBlock ) { + /* Allocate a memory block on a 4k boundary (1<<12 == 4096) */ + t->memBlock = mmAllocMem( rmesa->texHeap[heap], + t->totalSize, 12, 0 ); + +#if 0 + /* Try AGP before kicking anything out of local mem */ + if ( !t->memBlock && heap == RADEON_CARD_HEAP ) { + t->memBlock = mmAllocMem( rmesa->texHeap[RADEON_AGP_HEAP], + t->totalSize, 12, 0 ); + + if ( t->memBlock ) + heap = t->heap = RADEON_AGP_HEAP; + } +#endif + + /* Kick out textures until the requested texture fits */ + while ( !t->memBlock ) { + if ( rmesa->TexObjList[heap].prev->bound ) { + fprintf( stderr, + "radeonUploadTexImages: ran into bound texture\n" ); + return -1; + } + if ( rmesa->TexObjList[heap].prev == + &rmesa->TexObjList[heap] ) { + if ( rmesa->radeonScreen->IsPCI ) { + fprintf( stderr, "radeonUploadTexImages: upload texture " + "failure on local texture heaps, sz=%d\n", + t->totalSize ); + return -1; +#if 0 + } else if ( heap == RADEON_CARD_HEAP ) { + heap = t->heap = RADEON_AGP_HEAP; + continue; +#endif + } else { + fprintf( stderr, "radeonUploadTexImages: upload texture " + "failure on both local and AGP texture heaps, " + "sz=%d\n", + t->totalSize ); + return -1; + } + } + + radeonDestroyTexObj( rmesa, rmesa->TexObjList[heap].prev ); + + t->memBlock = mmAllocMem( rmesa->texHeap[heap], + t->totalSize, 12, 0 ); + } + + /* Set the base offset of the texture image */ + t->bufAddr = rmesa->radeonScreen->texOffset[heap] + t->memBlock->ofs; + + t->pp_txoffset = t->bufAddr; +#if 0 + /* Fix AGP texture offsets */ + if ( heap == RADEON_AGP_HEAP ) { + t->setup.pp_tx_offset += RADEON_AGP_TEX_OFFSET + + rmesa->radeonScreen->agpTexOffset; + } +#endif + + /* Force loading the new state into the hardware */ + switch ( t->bound ) { + case 1: + rmesa->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_TEX0; + break; + + case 2: + rmesa->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_TEX1; + break; + + default: + return -1; + } + } + + /* Let the world know we've used this memory recently */ + radeonUpdateTexLRU( rmesa, t ); + + /* Upload any images that are new */ + if ( t->dirty_images ) { + int levels = ((t->pp_txfilter & RADEON_MAX_MIP_LEVEL_MASK) >> + RADEON_MAX_MIP_LEVEL_SHIFT); + + for ( i = 0 ; i <= levels ; i++ ) { + if ( t->dirty_images & (1 << i) ) { + radeonUploadSubImage( rmesa, t, i, 0, 0, + t->image[i].width, t->image[i].height ); + } + } + + rmesa->dirty |= RADEON_UPLOAD_CONTEXT; + } + + t->dirty_images = 0; + return 0; +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_texobj.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_texobj.h index b63d5c6a7..7cec84e9a 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_texobj.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_texobj.h @@ -40,17 +40,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_sarea.h" #include "mm.h" -/* Handle the Radeon's tightly packed mipmaps and strict offset, - * pitch rules for blits by assigning each mipmap a set of - * coordinates that can be used for a hostdata blit. - */ -typedef struct { - GLuint x; /* Blit coordinates */ - GLuint y; - GLuint width; /* Blit dimensions */ - GLuint height; - GLuint dwords; /* Size of image level */ -} radeonTexImage; +#define TEX_0 1 +#define TEX_1 2 typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr; @@ -72,16 +63,15 @@ struct radeon_tex_obj { GLint bound; /* Texture unit currently bound to */ GLint heap; /* Texture heap currently stored in */ - radeonTexImage image[RADEON_MAX_TEXTURE_LEVELS]; /* Image data for all - mipmap levels */ + drmRadeonTexImage image[RADEON_MAX_TEXTURE_LEVELS]; GLint totalSize; /* Total size of the texture including all mipmap levels */ - GLint texelBytes; /* Number of bytes per texel */ - - GLboolean hasAlpha; - radeon_texture_regs_t setup; /* Setup regs for texture */ + GLuint pp_txfilter; /* Hardware register values */ + GLuint pp_txformat; + GLuint pp_txoffset; + GLuint pp_border_color; }; #endif /* __RADEON_TEXOBJ_H__ */ diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c new file mode 100644 index 000000000..2a076717e --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c @@ -0,0 +1,1103 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <martin@valinux.com> + * Gareth Hughes <gareth@valinux.com> + * + */ + +#include "radeon_context.h" +#include "radeon_state.h" +#include "radeon_ioctl.h" +#include "radeon_vb.h" +#include "radeon_tex.h" + +#include "mmath.h" +#include "simple_list.h" +#include "enums.h" +#include "mem.h" + +static void radeonSetTexImages( radeonContextPtr rmesa, + struct gl_texture_object *tObj ) +{ + radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData; + struct gl_texture_image *texImage = tObj->Image[0]; + const struct gl_texture_format *texFormat = texImage->TexFormat; + GLint log2Width, log2Height, log2Size; + GLint totalSize; + GLint texelsPerDword = 0, blitWidth = 0, blitPitch = 0; + GLint x, y, width, height; + GLint i; + + /* Calculate dimensions in log domain. + */ + for ( i = 1, log2Height = 0 ; i < texImage->Height ; i *= 2 ) { + log2Height++; + } + for ( i = 1, log2Width = 0 ; i < texImage->Width ; i *= 2 ) { + log2Width++; + } + log2Size = MAX2( log2Width, log2Height ); + + /* The Radeon has a 64-byte minimum pitch for all blits. We + * calculate the equivalent number of texels to simplify the + * calculation of the texture image area. + */ + switch ( texFormat->TexelBytes ) { + case 4: + texelsPerDword = 1; + blitPitch = 16; + break; + case 2: + texelsPerDword = 2; + blitPitch = 32; + break; + case 1: + texelsPerDword = 4; + blitPitch = 64; + break; + } + + /* Select the larger of the two widths for our global texture image + * coordinate space. As the Radeon has very strict offset rules, we + * can't upload mipmaps directly and have to reference their location + * from the aligned start of the whole image. + */ + blitWidth = MAX2( texImage->Width, blitPitch ); + + /* Calculate mipmap offsets and dimensions. + */ + totalSize = 0; + x = 0; + y = 0; + + for ( i = 0 ; i <= log2Size ; i++ ) { + GLuint size; + + texImage = tObj->Image[i]; + if ( !texImage ) + break; + + width = texImage->Width; + height = texImage->Height; + + /* Texture images have a minimum pitch of 32 bytes (half of the + * 64-byte minimum pitch for blits). For images that have a + * width smaller than this, we must pad each texture image + * scanline out to this amount. + */ + if ( width < blitPitch / 2 ) { + width = blitPitch / 2; + } + + size = width * height * texFormat->TexelBytes; + totalSize += size; + ASSERT( (totalSize & 31) == 0 ); + + while ( width < blitWidth && height > 1 ) { + width *= 2; + height /= 2; + } + + t->image[i].x = x; + t->image[i].y = y; + + t->image[i].width = width; + t->image[i].height = height; + + /* While blits must have a pitch of at least 64 bytes, mipmaps + * must be aligned on a 32-byte boundary (just like each texture + * image scanline). + */ + if ( width >= blitWidth ) { + y += height; + } else { + x += width; + if ( x >= blitWidth ) { + x = 0; + y++; + } + } + + if ( 0 ) { + fprintf( stderr, "level=%d p=%d %dx%d -> %dx%d at (%d,%d)\n", + i, blitWidth, texImage->Width, texImage->Height, + t->image[i].width, t->image[i].height, + t->image[i].x, t->image[i].y ); + } + } + + /* Align the total size of texture memory block. + */ + t->totalSize = (totalSize + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK; + + /* Hardware state: + */ + t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK; + t->pp_txfilter |= i << RADEON_MAX_MIP_LEVEL_SHIFT; + + t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK | + RADEON_TXFORMAT_HEIGHT_MASK); + t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) | + (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT)); +} + + +/* ================================================================ + * Texture combine functions + */ + +#define RADEON_DISABLE 0 +#define RADEON_REPLACE 1 +#define RADEON_MODULATE 2 +#define RADEON_DECAL 3 +#define RADEON_BLEND 4 +#define RADEON_ADD 5 +#define RADEON_MAX_COMBFUNC 6 + +static GLuint radeon_color_combine[][RADEON_MAX_COMBFUNC] = +{ + /* Unit 0: + */ + { + /* Disable combiner stage + */ + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_CURRENT_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_REPLACE = 0x00802800 + */ + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_T0_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_MODULATE = 0x00800142 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_T0_COLOR | + RADEON_COLOR_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_DECAL = 0x008c2d42 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_T0_COLOR | + RADEON_COLOR_ARG_C_T0_ALPHA | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_BLEND = 0x008c2902 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_TFACTOR_COLOR | + RADEON_COLOR_ARG_C_T0_COLOR | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_ADD = 0x00812802 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_T0_COLOR | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + }, + + /* Unit 1: + */ + { + /* Disable combiner stage + */ + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_CURRENT_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_REPLACE = 0x00803000 + */ + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_T1_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_MODULATE = 0x00800182 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_T1_COLOR | + RADEON_COLOR_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_DECAL = 0x008c3582 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_T1_COLOR | + RADEON_COLOR_ARG_C_T1_ALPHA | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_BLEND = 0x008c3102 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_TFACTOR_COLOR | + RADEON_COLOR_ARG_C_T1_COLOR | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_ADD = 0x00813002 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_T1_COLOR | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + }, + + /* Unit 2: + */ + { + /* Disable combiner stage + */ + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_CURRENT_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_REPLACE = 0x00803800 + */ + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_T2_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_MODULATE = 0x008001c2 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_T2_COLOR | + RADEON_COLOR_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_DECAL = 0x008c3dc2 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_T2_COLOR | + RADEON_COLOR_ARG_C_T2_ALPHA | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_BLEND = 0x008c3902 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_TFACTOR_COLOR | + RADEON_COLOR_ARG_C_T2_COLOR | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_ADD = 0x00813802 + */ + (RADEON_COLOR_ARG_A_CURRENT_COLOR | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_T2_COLOR | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + } +}; + +static GLuint radeon_alpha_combine[][RADEON_MAX_COMBFUNC] = +{ + /* Unit 0: + */ + { + /* Disable combiner stage + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_REPLACE = 0x00800500 + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_T0_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_MODULATE = 0x00800051 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_T0_ALPHA | + RADEON_ALPHA_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_DECAL = 0x00800100 + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_BLEND = 0x00800051 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_TFACTOR_ALPHA | + RADEON_ALPHA_ARG_C_T0_ALPHA | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_ADD = 0x00800051 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_T0_ALPHA | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + }, + + /* Unit 1: + */ + { + /* Disable combiner stage + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_REPLACE = 0x00800600 + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_T1_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_MODULATE = 0x00800061 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_T1_ALPHA | + RADEON_ALPHA_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_DECAL = 0x00800100 + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_BLEND = 0x00800061 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_TFACTOR_ALPHA | + RADEON_ALPHA_ARG_C_T1_ALPHA | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_ADD = 0x00800061 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_T1_ALPHA | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + }, + + /* Unit 2: + */ + { + /* Disable combiner stage + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_REPLACE = 0x00800700 + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_T2_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_MODULATE = 0x00800071 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_T2_ALPHA | + RADEON_ALPHA_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_DECAL = 0x00800100 + */ + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_BLEND = 0x00800071 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_TFACTOR_ALPHA | + RADEON_ALPHA_ARG_C_T2_ALPHA | + RADEON_BLEND_CTL_BLEND | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + + /* GL_ADD = 0x00800021 + */ + (RADEON_ALPHA_ARG_A_CURRENT_ALPHA | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_T2_ALPHA | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX), + } +}; + + +/* GL_EXT_texture_env_combine support + */ + +/* The color tables have combine functions for GL_SRC_COLOR, + * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. + */ +static GLuint radeon_texture_color[][RADEON_MAX_TEXTURE_UNITS] = +{ + { + RADEON_COLOR_ARG_A_T0_COLOR, + RADEON_COLOR_ARG_A_T1_COLOR, + RADEON_COLOR_ARG_A_T2_COLOR + }, + { + RADEON_COLOR_ARG_A_T0_COLOR | RADEON_COMP_ARG_A, + RADEON_COLOR_ARG_A_T1_COLOR | RADEON_COMP_ARG_A, + RADEON_COLOR_ARG_A_T2_COLOR | RADEON_COMP_ARG_A + }, + { + RADEON_COLOR_ARG_A_T0_ALPHA, + RADEON_COLOR_ARG_A_T1_ALPHA, + RADEON_COLOR_ARG_A_T2_ALPHA + }, + { + RADEON_COLOR_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A, + RADEON_COLOR_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A, + RADEON_COLOR_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A + }, +}; + +static GLuint radeon_tfactor_color[] = +{ + RADEON_COLOR_ARG_A_TFACTOR_COLOR, + RADEON_COLOR_ARG_A_TFACTOR_COLOR | RADEON_COMP_ARG_A, + RADEON_COLOR_ARG_A_TFACTOR_ALPHA, + RADEON_COLOR_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A +}; + +static GLuint radeon_primary_color[] = +{ + RADEON_COLOR_ARG_A_DIFFUSE_COLOR, + RADEON_COLOR_ARG_A_DIFFUSE_COLOR | RADEON_COMP_ARG_A, + RADEON_COLOR_ARG_A_DIFFUSE_ALPHA, + RADEON_COLOR_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A +}; + +static GLuint radeon_previous_color[] = +{ + RADEON_COLOR_ARG_A_CURRENT_COLOR, + RADEON_COLOR_ARG_A_CURRENT_COLOR | RADEON_COMP_ARG_A, + RADEON_COLOR_ARG_A_CURRENT_ALPHA, + RADEON_COLOR_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A +}; + +/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. + */ +static GLuint radeon_texture_alpha[][RADEON_MAX_TEXTURE_UNITS] = +{ + { + RADEON_ALPHA_ARG_A_T0_ALPHA, + RADEON_ALPHA_ARG_A_T1_ALPHA, + RADEON_ALPHA_ARG_A_T2_ALPHA + }, + { + RADEON_ALPHA_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A, + RADEON_ALPHA_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A, + RADEON_ALPHA_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A + }, +}; + +static GLuint radeon_tfactor_alpha[] = +{ + RADEON_ALPHA_ARG_A_TFACTOR_ALPHA, + RADEON_ALPHA_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A +}; + +static GLuint radeon_primary_alpha[] = +{ + RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA, + RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A +}; + +static GLuint radeon_previous_alpha[] = +{ + RADEON_ALPHA_ARG_A_CURRENT_ALPHA, + RADEON_ALPHA_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A +}; + + +/* Extract the arg from slot A, shift it into the correct argument slot + * and set the corresponding complement bit. + */ +#define RADEON_COLOR_ARG( n, arg ) \ +do { \ + color_combine |= \ + ((color_arg[n] & RADEON_COLOR_ARG_MASK) \ + << RADEON_COLOR_ARG_##arg##_SHIFT); \ + color_combine |= \ + ((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \ + << RADEON_COMP_ARG_##arg##_SHIFT); \ +} while (0) + +#define RADEON_ALPHA_ARG( n, arg ) \ +do { \ + alpha_combine |= \ + ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \ + << RADEON_ALPHA_ARG_##arg##_SHIFT); \ + alpha_combine |= \ + ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \ + << RADEON_COMP_ARG_##arg##_SHIFT); \ +} while (0) + + +/* ================================================================ + * Texture unit state management + */ + +static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + int source = rmesa->tmu_source[unit]; + struct gl_texture_object *tObj; + struct gl_texture_unit *texUnit; + GLuint enabled; + GLuint color_combine, alpha_combine; + GLuint color_arg[3], alpha_arg[3]; + GLuint i, numColorArgs = 0, numAlphaArgs = 0; + GLuint op; + + if ( RADEON_DEBUG & DEBUG_VERBOSE_MSG ) { + fprintf( stderr, "%s( %p, %d )\n", + __FUNCTION__, ctx, unit ); + } + + enabled = (ctx->Texture.ReallyEnabled >> (source * 4)) & TEXTURE0_ANY; + if ( enabled != TEXTURE0_2D && enabled != TEXTURE0_1D ) + return; + + /* Only update the hardware texture state if the texture is current, + * complete and enabled. + */ + texUnit = &ctx->Texture.Unit[source]; + tObj = texUnit->Current; + if ( !tObj || !tObj->Complete ) + return; + + if ( ( tObj != texUnit->CurrentD[2] ) && + ( tObj != texUnit->CurrentD[1] ) ) + return; + + /* Set the texture environment state. Isn't this nice and clean? + * The Radeon will automagically set the texture alpha to 0xff when + * the texture format does not include an alpha component. This + * reduces the amount of special-casing we have to do, alpha-only + * textures being a notable exception. + */ + switch ( texUnit->EnvMode ) { + case GL_REPLACE: + switch ( tObj->Image[0]->Format ) { + case GL_RGBA: + case GL_RGB: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + color_combine = radeon_color_combine[unit][RADEON_REPLACE]; + alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE]; + break; + case GL_ALPHA: + color_combine = radeon_color_combine[unit][RADEON_DISABLE]; + alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE]; + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_MODULATE: + switch ( tObj->Image[0]->Format ) { + case GL_RGBA: + case GL_RGB: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + color_combine = radeon_color_combine[unit][RADEON_MODULATE]; + alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; + break; + case GL_ALPHA: + color_combine = radeon_color_combine[unit][RADEON_DISABLE]; + alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_DECAL: + switch ( tObj->Image[0]->Format ) { + case GL_RGBA: + case GL_RGB: + color_combine = radeon_color_combine[unit][RADEON_DECAL]; + alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE]; + break; + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + color_combine = radeon_color_combine[unit][RADEON_DISABLE]; + alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE]; + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_BLEND: + switch ( tObj->Image[0]->Format ) { + case GL_RGBA: + case GL_RGB: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + color_combine = radeon_color_combine[unit][RADEON_BLEND]; + alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; + break; + case GL_ALPHA: + color_combine = radeon_color_combine[unit][RADEON_DISABLE]; + alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; + break; + case GL_INTENSITY: + color_combine = radeon_color_combine[unit][RADEON_BLEND]; + alpha_combine = radeon_alpha_combine[unit][RADEON_BLEND]; + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_ADD: + switch ( tObj->Image[0]->Format ) { + case GL_RGBA: + case GL_RGB: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + color_combine = radeon_color_combine[unit][RADEON_ADD]; + alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; + break; + case GL_ALPHA: + color_combine = radeon_color_combine[unit][RADEON_DISABLE]; + alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE]; + break; + case GL_INTENSITY: + color_combine = radeon_color_combine[unit][RADEON_ADD]; + alpha_combine = radeon_alpha_combine[unit][RADEON_ADD]; + break; + case GL_COLOR_INDEX: + default: + return; + } + break; + + case GL_COMBINE_EXT: + /* Step 0: + * Calculate how many arguments we need to process. + */ + switch ( texUnit->CombineModeRGB ) { + case GL_REPLACE: + numColorArgs = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED_EXT: + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + numColorArgs = 2; + break; + case GL_INTERPOLATE_EXT: + numColorArgs = 3; + break; + default: + return; + } + + switch ( texUnit->CombineModeA ) { + case GL_REPLACE: + numAlphaArgs = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED_EXT: + numAlphaArgs = 2; + break; + case GL_INTERPOLATE_EXT: + numAlphaArgs = 3; + break; + default: + return; + } + + /* Step 1: + * Extract the color and alpha combine function arguments. + */ + for ( i = 0 ; i < numColorArgs ; i++ ) { + op = texUnit->CombineOperandRGB[i] - GL_SRC_COLOR; + switch ( texUnit->CombineSourceRGB[i] ) { + case GL_TEXTURE: + color_arg[i] = radeon_texture_color[op][unit]; + break; + case GL_CONSTANT_EXT: + color_arg[i] = radeon_tfactor_color[op]; + break; + case GL_PRIMARY_COLOR_EXT: + color_arg[i] = radeon_primary_color[op]; + break; + case GL_PREVIOUS_EXT: + color_arg[i] = radeon_previous_color[op]; + break; + default: + return; + } + } + + for ( i = 0 ; i < numAlphaArgs ; i++ ) { + op = texUnit->CombineOperandA[i] - GL_SRC_ALPHA; + switch ( texUnit->CombineSourceA[i] ) { + case GL_TEXTURE: + alpha_arg[i] = radeon_texture_alpha[op][unit]; + break; + case GL_CONSTANT_EXT: + alpha_arg[i] = radeon_tfactor_alpha[op]; + break; + case GL_PRIMARY_COLOR_EXT: + alpha_arg[i] = radeon_primary_alpha[op]; + break; + case GL_PREVIOUS_EXT: + alpha_arg[i] = radeon_previous_alpha[op]; + break; + default: + return; + } + } + + /* Step 2: + * Build up the color and alpha combine functions. + */ + switch ( texUnit->CombineModeRGB ) { + case GL_REPLACE: + color_combine = (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, C ); + break; + case GL_MODULATE: + color_combine = (RADEON_COLOR_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, A ); + RADEON_COLOR_ARG( 1, B ); + break; + case GL_ADD: + color_combine = (RADEON_COLOR_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, A ); + RADEON_COLOR_ARG( 1, C ); + break; + case GL_ADD_SIGNED_EXT: + color_combine = (RADEON_COLOR_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADDSIGNED | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, A ); + RADEON_COLOR_ARG( 1, C ); + break; + case GL_INTERPOLATE_EXT: + color_combine = (RADEON_BLEND_CTL_BLEND | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, B ); + RADEON_COLOR_ARG( 1, A ); + RADEON_COLOR_ARG( 2, C ); + break; + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + color_combine = (RADEON_COLOR_ARG_C_ZERO | + RADEON_BLEND_CTL_DOT3 | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, A ); + RADEON_COLOR_ARG( 1, B ); + break; + default: + return; + } + + switch ( texUnit->CombineModeA ) { + case GL_REPLACE: + alpha_combine = (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + RADEON_ALPHA_ARG( 0, C ); + break; + case GL_MODULATE: + alpha_combine = (RADEON_ALPHA_ARG_C_ZERO | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + RADEON_ALPHA_ARG( 0, A ); + RADEON_ALPHA_ARG( 1, B ); + break; + case GL_ADD: + alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + RADEON_ALPHA_ARG( 0, A ); + RADEON_ALPHA_ARG( 1, C ); + break; + case GL_ADD_SIGNED_EXT: + alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_ADDSIGNED | + RADEON_CLAMP_TX); + RADEON_ALPHA_ARG( 0, A ); + RADEON_ALPHA_ARG( 1, C ); + break; + case GL_INTERPOLATE_EXT: + alpha_combine = (RADEON_BLEND_CTL_BLEND | + RADEON_CLAMP_TX); + RADEON_ALPHA_ARG( 0, B ); + RADEON_ALPHA_ARG( 1, A ); + RADEON_ALPHA_ARG( 2, C ); + break; + default: + return; + } + + if ( texUnit->CombineModeRGB == GL_DOT3_RGB_EXT ) { + alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE; + } + + /* Step 3: + * Apply the scale factor. The EXT extension has a somewhat + * unnecessary restriction that the scale must be 4x. The ARB + * extension will likely drop this and we can just apply the + * scale factors regardless. + */ + if ( texUnit->CombineModeRGB != GL_DOT3_RGB_EXT && + texUnit->CombineModeRGB != GL_DOT3_RGBA_EXT ) { + color_combine |= (texUnit->CombineScaleShiftRGB << 21); + alpha_combine |= (texUnit->CombineScaleShiftA << 21); + } else { + color_combine |= RADEON_SCALE_4X; + alpha_combine |= RADEON_SCALE_4X; + } + + /* All done! + */ + break; + + default: + return; + } + + rmesa->color_combine[source] = color_combine; + rmesa->alpha_combine[source] = alpha_combine; +} + +static void radeonUpdateTextureObject( GLcontext *ctx, int unit ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + int source = rmesa->tmu_source[unit]; + struct gl_texture_object *tObj; + radeonTexObjPtr t; + GLuint enabled; + + if ( RADEON_DEBUG & DEBUG_VERBOSE_MSG ) { + fprintf( stderr, "%s( %p, %d )\n", + __FUNCTION__, ctx, unit ); + } + + enabled = (ctx->Texture.ReallyEnabled >> (source * 4)) & TEXTURE0_ANY; + if ( enabled != TEXTURE0_2D && enabled != TEXTURE0_1D ) { + if ( enabled ) + rmesa->Fallback |= RADEON_FALLBACK_TEXTURE; + return; + } + + /* Only update the hardware texture state if the texture is current, + * complete and enabled. + */ + tObj = ctx->Texture.Unit[source].Current; + if ( !tObj || !tObj->Complete ) + return; + + if ( ( tObj != ctx->Texture.Unit[source].CurrentD[2] ) && + ( tObj != ctx->Texture.Unit[source].CurrentD[1] ) ) + return; + + /* We definately have a valid texture now */ + t = tObj->DriverData; + + /* Force the texture unit state to be loaded into the hardware */ + rmesa->dirty |= RADEON_UPLOAD_CONTEXT | (RADEON_UPLOAD_TEX0 << unit); + + /* Force any texture images to be loaded into the hardware */ + if ( t->dirty_images ) { + if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, " t->dirty_images = 0x%x\n", t->dirty_images ); + } + radeonSetTexImages( rmesa, tObj ); + rmesa->dirty |= (RADEON_UPLOAD_TEX0IMAGES << unit); + } + + if ( t->memBlock ) + radeonUpdateTexLRU( rmesa, t ); + + switch ( unit ) { + case 0: + rmesa->setup.pp_cntl |= (RADEON_TEX_0_ENABLE | + RADEON_TEX_BLEND_0_ENABLE); + break; + case 1: + rmesa->setup.pp_cntl |= (RADEON_TEX_1_ENABLE | + RADEON_TEX_BLEND_1_ENABLE); + break; + } +} + +void radeonUpdateTextureState( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s( %p ) en=0x%x\n", + __FUNCTION__, ctx, ctx->Texture.ReallyEnabled ); + } + + /* Clear any texturing fallbacks */ + rmesa->Fallback &= ~RADEON_FALLBACK_TEXTURE; + + /* Disable all texturing until it is known to be good */ + rmesa->setup.pp_cntl &= ~(RADEON_TEX_ENABLE_MASK | + RADEON_TEX_BLEND_ENABLE_MASK); + + radeonUpdateTextureObject( ctx, 0 ); + radeonUpdateTextureEnv( ctx, 0 ); + + if ( rmesa->multitex ) { + radeonUpdateTextureObject( ctx, 1 ); + radeonUpdateTextureEnv( ctx, 1 ); + } + + rmesa->dirty |= RADEON_UPLOAD_CONTEXT; +} diff --git a/xc/lib/GL/mesa/src/drv/tdfx/Imakefile b/xc/lib/GL/mesa/src/drv/tdfx/Imakefile index ebb353844..9f45df60d 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/Imakefile +++ b/xc/lib/GL/mesa/src/drv/tdfx/Imakefile @@ -150,6 +150,7 @@ MESA_INCLUDES = -I. -I.. -I../../include ../../stages.c \ ../../state.c \ ../../stencil.c \ + ../../texformat.c \ ../../teximage.c \ ../../texobj.c \ ../../texstate.c \ @@ -223,6 +224,7 @@ MESA_INCLUDES = -I. -I.. -I../../include ../../stages.o \ ../../state.o \ ../../stencil.o \ + ../../texformat.o \ ../../teximage.o \ ../../texobj.o \ ../../texstate.o \ diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.c index 1d6d41724..0c6e399c1 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.c @@ -43,9 +43,22 @@ #include "tdfx_render.h" #include "tdfx_pipeline.h" #include "tdfx_span.h" +#include "tdfx_tex.h" #include "tdfx_texman.h" #include "extensions.h" +#ifndef TDFX_DEBUG +int TDFX_DEBUG = (0 +/* | DEBUG_ALWAYS_SYNC */ +/* | DEBUG_VERBOSE_API */ +/* | DEBUG_VERBOSE_MSG */ +/* | DEBUG_VERBOSE_LRU */ +/* | DEBUG_VERBOSE_DRI */ +/* | DEBUG_VERBOSE_IOCTL */ +/* | DEBUG_VERBOSE_2D */ +/* | DEBUG_VERBOSE_TEXTURE */ + ); +#endif #if 0 @@ -75,15 +88,13 @@ static void tdfxDDInitExtensions( GLcontext *ctx ) gl_extensions_disable( ctx, "GL_INGR_blend_func_separate" ); gl_extensions_enable( ctx, "GL_HP_occlusion_test" ); - if ( !fxMesa->haveTwoTMUs ) { + if ( fxMesa->numTMUs == 1 ) { gl_extensions_disable( ctx, "GL_EXT_texture_env_add" ); gl_extensions_disable( ctx, "GL_ARB_multitexture" ); } if ( TDFX_IS_NAPALM( fxMesa ) ) { - gl_extensions_enable( ctx, "GL_ARB_texture_compression" ); gl_extensions_enable( ctx, "GL_EXT_texture_env_combine" ); - gl_extensions_enable( ctx, "GL_3DFX_texture_compression_FXT1" ); } if (fxMesa->haveHwStencil) { @@ -178,16 +189,10 @@ GLboolean tdfxCreateContext( Display *dpy, GLvisual *mesaVis, fxMesa->Glide.Initialized = GL_FALSE; fxMesa->Glide.Board = 0; - - if (getenv("FX_EMULATE_SINGLE_TMU")) { - fxMesa->haveTwoTMUs = GL_FALSE; - } - else { - if ( TDFX_IS_BANSHEE( fxMesa ) ) { - fxMesa->haveTwoTMUs = GL_FALSE; - } else { - fxMesa->haveTwoTMUs = GL_TRUE; - } + if ( getenv( "FX_EMULATE_SINGLE_TMU" ) || TDFX_IS_BANSHEE( fxMesa ) ) { + fxMesa->numTMUs = 1; + } else { + fxMesa->numTMUs = 2; } fxMesa->stats.swapBuffer = 0; @@ -218,6 +223,7 @@ GLboolean tdfxCreateContext( Display *dpy, GLvisual *mesaVis, tdfxDDInitStateFuncs( ctx ); tdfxDDInitRenderFuncs( ctx ); tdfxDDInitSpanFuncs( ctx ); + tdfxDDInitTextureFuncs( ctx ); ctx->Driver.TriangleCaps = (DD_TRI_CULL | DD_TRI_LIGHT_TWOSIDE | @@ -448,19 +454,21 @@ void tdfxDestroyContext( tdfxContextPtr fxMesa ) } if ( fxMesa ) { - if (fxMesa->glCtx->Shared->RefCount == 1) { + GLcontext *ctx = fxMesa->glCtx; + struct gl_texture_object *tObj; + + if ( ctx->Shared->RefCount == 1 ) { /* This share group is about to go away, free our private * texture object data. */ - struct gl_texture_object *tObj; - tObj = fxMesa->glCtx->Shared->TexObjectList; - while (tObj) { - tdfxTMFreeTexture(fxMesa, tObj); - tObj = tObj->Next; + LOCK_HARDWARE( fxMesa ); + for ( tObj = ctx->Shared->TexObjectList ; tObj ; tObj = tObj->Next ) { + tdfxTMFreeTextureLocked( fxMesa, tObj ); } + UNLOCK_HARDWARE( fxMesa ); } - tdfxTMClose(fxMesa); /* free texture memory */ + tdfxTMClose( fxMesa ); /* free texture memory */ XFree( fxMesa ); } diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.h b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.h index 927c5f10a..a73347435 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.h +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_context.h @@ -280,9 +280,7 @@ typedef struct { volatile int fifoOwner; volatile int ctxOwner; volatile int texOwner; -} -TDFXSAREAPriv; - +} TDFXSAREAPriv; typedef struct { GLuint swapBuffer; @@ -292,73 +290,72 @@ typedef struct { GLuint texSwaps; } tdfxStats; - - /* * Memory range from startAddr to endAddr-1 */ typedef struct mem_range { struct mem_range *next; FxU32 startAddr, endAddr; -} -tdfxMemRange; +} tdfxMemRange; +typedef struct { + GLvoid *data; + GLsizei width, height; + FxU32 size; +} tdfxTexRawData; typedef struct { - GLsizei width, height; /* image size */ - GLint texelSize; /* How many bytes to a texel */ - GrTextureFormat_t glideFormat; /* Glide image format */ - void *data; /* Glide-formated texture image */ - FxU32 dataSize; /* image size in bytes */ -} -tdfxMipMapLevel; + tdfxTexRawData original; /* Mesa-formatted texture image */ + tdfxTexRawData rescaled; /* Only needed if aspect ratio > 8:1 */ + + GLvoid *data; /* Final version of texture image */ + FxU32 size; /* image size in bytes */ + + GrTextureFormat_t glideFormat; /* Glide image format */ + GLint wScale, hScale; /* Broken hardware... */ +} tdfxTexImage, *tdfxTexImagePtr; #define TDFX_NUM_TMU 2 -typedef struct tdfxTexInfo_t -{ +typedef struct { GLboolean isInTM; GLboolean reloadImages; /* if true, resend images to Glide */ GLuint lastTimeUsed; FxU32 whichTMU; GrTexInfo info; - GrAspectRatio_t aspectRatio; - tdfxMipMapLevel mipmapLevel[MAX_TEXTURE_LEVELS]; - tdfxMemRange *tm[TDFX_NUM_TMU]; + tdfxTexImage image[MAX_TEXTURE_LEVELS]; + tdfxMemRange *range[TDFX_NUM_TMU]; GLint minLevel, maxLevel; + GrMipMapMode_t mmMode; + GrAspectRatio_t aspectRatio; + FxBool LODblend; GrTextureFilterMode_t minFilt; GrTextureFilterMode_t magFilt; GrTextureClampMode_t sClamp; GrTextureClampMode_t tClamp; - FxBool LODblend; - GrMipMapMode_t mmMode; - GLfloat sScale, tScale; /* texcoord scale factor */ + GLfloat sScale, tScale; /* texcoord scale factor */ GuTexPalette palette; -} -tdfxTexInfo; - +} tdfxTexObj, *tdfxTexObjPtr; -#define TDFX_TEXTURE_DATA(mesaObj) ((tdfxTexInfo *)((mesaObj)->DriverData)) +#define TDFX_TEXTURE_DATA(tObj) ((tdfxTexObjPtr)((tObj)->DriverData)) - -/* - * This is state which may be shared by several tdfx contexts. +/* This is state which may be shared by several tdfx contexts. * It hangs off of Mesa's gl_shared_state object (ctx->Shared->DriverData). */ -struct tdfxSharedState { +typedef struct tdfx_shared_state { GLboolean umaTexMemory; - GLuint totalTexMem[TDFX_NUM_TMU]; /* constant */ - GLuint freeTexMem[TDFX_NUM_TMU]; /* changes as we go */ - tdfxMemRange *tmPool; - tdfxMemRange *tmFree[TDFX_NUM_TMU]; -}; + GLuint totalTexMem[TDFX_NUM_TMU]; /* constant */ + GLuint freeTexMem[TDFX_NUM_TMU]; /* changes as we go */ + tdfxMemRange *rangePool; + tdfxMemRange *freeRanges[TDFX_NUM_TMU]; +} tdfxSharedState, *tdfxSharedStatePtr; @@ -635,6 +632,7 @@ struct tdfx_context { GLuint tmu_source[TDFX_NUM_TMU]; GLuint tex_dest[MAX_TEXTURE_UNITS]; + GLuint numTMUs; GLuint SetupIndex; GLuint SetupDone; @@ -646,10 +644,6 @@ struct tdfx_context { GLfloat sScale0, tScale0; GLfloat sScale1, tScale1; -#if 0 - GLuint last_tri_caps; - GLuint stw_hint_state; /* for grHints */ -#endif GLuint using_fast_path, passes, multipass; GLuint texBindNumber; GLint tmuSrc; @@ -657,13 +651,6 @@ struct tdfx_context { int screen_width; int screen_height; -#if 0 - void *state; /* Glide state buffer */ - - GLint textureAlign; - GLboolean verbose; -#endif - GLboolean haveTwoTMUs; /* True if we have 2 tmu's */ GLboolean haveHwStencil; GLint maxPendingSwapBuffers; @@ -773,6 +760,7 @@ extern int TDFX_DEBUG; #define DEBUG_VERBOSE_DRI 0x10 #define DEBUG_VERBOSE_IOCTL 0x20 #define DEBUG_VERBOSE_2D 0x40 +#define DEBUG_VERBOSE_TEXTURE 0x80 #endif /* GLX_DIRECT_RENDERING */ diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_dd.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_dd.c index ec5b25871..3f76fb88d 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_dd.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_dd.c @@ -43,9 +43,11 @@ #include "enums.h" #include "pb.h" +#if defined(USE_X86_ASM) || defined(USE_3DNOW_ASM) || defined(USE_KATMAI_ASM) +#include "X86/common_x86_asm.h" +#endif - -#define TDFX_DATE "20010104" +#define TDFX_DATE "20010305" /* These are used in calls to FX_grColorMaskv() */ @@ -63,10 +65,12 @@ static const GLubyte *tdfxDDGetString( GLcontext *ctx, GLenum name ) tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; switch ( name ) { - case GL_RENDERER: - { - static char buffer[100]; - char hardware[100]; + case GL_VENDOR: + return "VA Linux Systems, Inc."; + + case GL_RENDERER: { + static char buffer[128]; + char hardware[128]; strcpy( hardware, FX_grGetString( fxMesa, GR_HARDWARE ) ); @@ -83,19 +87,41 @@ static const GLubyte *tdfxDDGetString( GLcontext *ctx, GLenum name ) strcpy( hardware, "Voodoo5" ); } else { - /* unexpected result: replace spaces with hyphens */ + /* Unexpected result: replace spaces with hyphens */ int i; for ( i = 0 ; hardware[i] ; i++ ) { if ( hardware[i] == ' ' || hardware[i] == '\t' ) hardware[i] = '-'; } } - /* now make the GL_RENDERER string */ + /* Now make the GL_RENDERER string */ sprintf( buffer, "Mesa DRI %s " TDFX_DATE, hardware ); + + /* Append any CPU-specific information. + */ +#ifdef USE_X86_ASM + if ( gl_x86_cpu_features ) { + strncat( buffer, " x86", 4 ); + } +#endif +#ifdef USE_MMX_ASM + if ( cpu_has_mmx ) { + strncat( buffer, "/MMX", 4 ); + } +#endif +#ifdef USE_3DNOW_ASM + if ( cpu_has_3dnow ) { + strncat( buffer, "/3DNow!", 7 ); + } +#endif +#ifdef USE_KATMAI_ASM + if ( cpu_has_xmm ) { + strncat( buffer, "/SSE", 4 ); + } +#endif return buffer; } - case GL_VENDOR: - return "VA Linux Systems, Inc."; + default: return NULL; } diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_render.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_render.c index 97931a351..da60bee16 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_render.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_render.c @@ -594,16 +594,13 @@ static void uploadTextureImages( tdfxContextPtr fxMesa ) { GLcontext *ctx = fxMesa->glCtx; int unit; - for (unit = 0; unit < TDFX_NUM_TMU; unit++) { - if (ctx->Texture.Unit[unit].ReallyEnabled == TEXTURE0_2D) { + for ( unit = 0 ; unit < TDFX_NUM_TMU ; unit++ ) { + if ( ctx->Texture.Unit[unit].ReallyEnabled == TEXTURE0_2D ) { struct gl_texture_object *tObj = ctx->Texture.Unit[unit].CurrentD[2]; - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); - if (ti && ti->reloadImages) { - /* - printf("download texture image on unit %d\n", unit); - */ - tdfxTMDownloadTexture(fxMesa, tObj); - ti->reloadImages = GL_FALSE; + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + if ( t && t->reloadImages ) { + tdfxTMDownloadTextureLocked( fxMesa, tObj ); + t->reloadImages = GL_FALSE; } } } diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c index eb9a6a98b..d630fbd8c 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_state.c @@ -45,7 +45,6 @@ #include "tdfx_vb.h" #include "tdfx_tex.h" #include "tdfx_texman.h" -#include "tdfx_texstate.h" #include "tdfx_tris.h" #include "tdfx_render.h" @@ -1535,15 +1534,6 @@ void tdfxDDInitStateFuncs( GLcontext *ctx ) ctx->Driver.Scissor = tdfxDDScissor; ctx->Driver.ShadeModel = tdfxDDShadeModel; - ctx->Driver.BindTexture = tdfxDDBindTexture; - ctx->Driver.DeleteTexture = tdfxDDDeleteTexture; - ctx->Driver.TexEnv = tdfxDDTexEnv; - ctx->Driver.TexParameter = tdfxDDTexParameter; - ctx->Driver.TexImage2D = tdfxDDTexImage2D; - ctx->Driver.TexSubImage2D = tdfxDDTexSubImage2D; - ctx->Driver.GetTexImage = tdfxDDGetTexImage; - ctx->Driver.UpdateTexturePalette = tdfxDDTexturePalette; - if ( fxMesa->haveHwStencil ) { ctx->Driver.StencilFunc = tdfxDDStencilFunc; ctx->Driver.StencilMask = tdfxDDStencilMask; diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.c index c572e22a8..e0f2d2eb0 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.c @@ -35,39 +35,37 @@ * */ -#include "image.h" -#include "texutil.h" #include "tdfx_context.h" #include "tdfx_tex.h" #include "tdfx_texman.h" +#include "enums.h" +#include "image.h" +#include "texutil.h" + +#define TX_DITHER_NONE 0x00000000 -static int -logbase2(int n) +static int logbase2( int n ) { - GLint i = 1; - GLint log2 = 0; - - if (n < 0) { - return -1; - } - - while (n > i) { - i *= 2; - log2++; - } - if (i != n) { - return -1; - } - else { - return log2; - } + GLint i = 1; + GLint log2 = 0; + + if ( n < 0 ) + return -1; + + while ( n > i ) { + i *= 2; + log2++; + } + if ( i != n ) { + return -1; + } else { + return log2; + } } - -/* - * Compute various texture image parameters. +/* Compute various texture image parameters. * Input: w, h - source texture width and height * Output: lodlevel - Glide lod level token for the larger texture dimension * aspectratio - Glide aspect ratio token @@ -84,1520 +82,977 @@ logbase2(int n) * 32 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x2 (=-1) * 32 32 GR_LOD_LOG2_32 (=5) GR_ASPECT_LOG2_1x1 (=0) */ -static void -tdfxTexGetInfo(const GLcontext *ctx, int w, int h, - GrLOD_t *lodlevel, GrAspectRatio_t *aspectratio, - float *sscale, float *tscale, - int *wscale, int *hscale) +static void tdfxTexGetInfo( const GLcontext *ctx, int w, int h, + GrLOD_t *lodlevel, GrAspectRatio_t *aspectratio, + float *sscale, float *tscale, + int *wscale, int *hscale ) { - int logw, logh, ar, lod, ws, hs; - float s, t; - - ASSERT(w >= 1); - ASSERT(h >= 1); - - logw = logbase2(w); - logh = logbase2(h); - ar = logw - logh; /* aspect ratio = difference in log dimensions */ - - /* Hardware only allows a maximum aspect ratio of 8x1, so handle - |ar| > 3 by scaling the image and using an 8x1 aspect ratio */ - if (ar >= 0) { - ASSERT(width >= height); - lod = logw; - s = 256.0; - ws = 1; - if (ar <= GR_ASPECT_LOG2_8x1) { - t = 256 >> ar; - hs = 1; - } - else { - /* have to stretch image height */ - t = 32.0; - hs = 1 << (ar - 3); - } - } - else { - ASSERT(width < height); - lod = logh; - t = 256.0; - hs = 1; - if (ar >= GR_ASPECT_LOG2_1x8) { - s = 256 >> -ar; - ws = 1; - } - else { - /* have to stretch image width */ - s = 32.0; - ws = 1 << (-ar - 3); - } - } - - if (ar < GR_ASPECT_LOG2_1x8) - ar = GR_ASPECT_LOG2_1x8; - else if (ar > GR_ASPECT_LOG2_8x1) - ar = GR_ASPECT_LOG2_8x1; - - if (lodlevel) - *lodlevel = (GrLOD_t) lod; - if (aspectratio) - *aspectratio = (GrAspectRatio_t) ar; - if (sscale) - *sscale = s; - if (tscale) - *tscale = t; - if (wscale) - *wscale = ws; - if (hscale) - *hscale = hs; + int logw, logh, ar, lod, ws, hs; + float s, t; + + ASSERT( w >= 1 ); + ASSERT( h >= 1 ); + + logw = logbase2( w ); + logh = logbase2( h ); + ar = logw - logh; /* aspect ratio = difference in log dimensions */ + + /* Hardware only allows a maximum aspect ratio of 8x1, so handle + * |ar| > 3 by scaling the image and using an 8x1 aspect ratio. + */ + if ( ar >= 0 ) { + ASSERT( width >= height ); + lod = logw; + s = 256.0; + ws = 1; + if ( ar <= GR_ASPECT_LOG2_8x1 ) { + t = 256 >> ar; + hs = 1; + } else { + /* have to stretch image height */ + t = 32.0; + hs = 1 << (ar - 3); + } + } else { + ASSERT( width < height ); + lod = logh; + t = 256.0; + hs = 1; + if ( ar >= GR_ASPECT_LOG2_1x8 ) { + s = 256 >> -ar; + ws = 1; + } else { + /* have to stretch image width */ + s = 32.0; + ws = 1 << (-ar - 3); + } + } + + if ( ar < GR_ASPECT_LOG2_1x8 ) { + ar = GR_ASPECT_LOG2_1x8; + } else if ( ar > GR_ASPECT_LOG2_8x1 ) { + ar = GR_ASPECT_LOG2_8x1; + } + + if ( lodlevel ) + *lodlevel = (GrLOD_t)lod; + if ( aspectratio ) + *aspectratio = (GrAspectRatio_t)ar; + if ( sscale ) + *sscale = s; + if ( tscale ) + *tscale = t; + if ( wscale ) + *wscale = ws; + if ( hscale ) + *hscale = hs; } -/* - * We need to call this when a texture object's minification filter +/* We need to call this when a texture object's minification filter * or texture image sizes change. */ -static void RevalidateTexture(GLcontext *ctx, struct gl_texture_object *tObj) +static void tdfxRevalidateTexture( GLcontext *ctx, + struct gl_texture_object *tObj ) { - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); - GLint minl, maxl; - - if (!ti) - return; - - minl = maxl = tObj->BaseLevel; - - if (tObj->Image[minl]) { - maxl = MIN2(tObj->MaxLevel, tObj->Image[minl]->MaxLog2); - - /* compute largeLodLog2, aspect ratio and texcoord scale factors */ - tdfxTexGetInfo(ctx, tObj->Image[minl]->Width, tObj->Image[minl]->Height, - &ti->info.largeLodLog2, - &ti->info.aspectRatioLog2, - &(ti->sScale), &(ti->tScale), NULL, NULL); - } - - if (tObj->Image[maxl] && (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) { - /* mipmapping: need to compute smallLodLog2 */ - tdfxTexGetInfo(ctx, tObj->Image[maxl]->Width, - tObj->Image[maxl]->Height, - &ti->info.smallLodLog2, NULL, - NULL, NULL, NULL, NULL); - } - else { - /* not mipmapping: smallLodLog2 = largeLodLog2 */ - ti->info.smallLodLog2 = ti->info.largeLodLog2; - } - - ti->minLevel = minl; - ti->maxLevel = maxl; - ti->info.data = NULL; + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + GLint minl, maxl; + + if ( !t ) + return; + + minl = maxl = tObj->BaseLevel; + + if ( tObj->Image[minl] ) { + maxl = MIN2( tObj->MaxLevel, tObj->Image[minl]->MaxLog2 ); + + /* Compute largeLodLog2, aspect ratio and texcoord scale factors. + */ + tdfxTexGetInfo( ctx, + tObj->Image[minl]->Width, tObj->Image[minl]->Height, + &t->info.largeLodLog2, &t->info.aspectRatioLog2, + &t->sScale, &t->tScale, NULL, NULL ); + } + + if ( tObj->Image[maxl] && + tObj->MinFilter != GL_NEAREST && + tObj->MinFilter != GL_LINEAR ) { + /* Mipmapping: need to compute smallLodLog2 */ + tdfxTexGetInfo( ctx, + tObj->Image[maxl]->Width, tObj->Image[maxl]->Height, + &t->info.smallLodLog2, + NULL, NULL, NULL, NULL, NULL ); + } else { + /* Not mipmapping: smallLodLog2 = largeLodLog2 */ + t->info.smallLodLog2 = t->info.largeLodLog2; + } + + t->minLevel = minl; + t->maxLevel = maxl; + t->info.data = NULL; } -static tdfxTexInfo * -fxAllocTexObjData(tdfxContextPtr fxMesa) +static tdfxTexObjPtr tdfxAllocTexObj( tdfxContextPtr fxMesa ) { - tdfxTexInfo *ti; - int i; + tdfxTexObjPtr t; + int i; - if (!(ti = CALLOC(sizeof(tdfxTexInfo)))) { - gl_problem(NULL, "tdfx driver: out of memory"); - return NULL; - } + t = CALLOC( sizeof(tdfxTexObj) ); + if ( !t ) { + gl_problem( NULL, "tdfx driver: out of memory" ); + return NULL; + } - ti->isInTM = GL_FALSE; + t->isInTM = GL_FALSE; - ti->whichTMU = TDFX_TMU_NONE; + t->whichTMU = TDFX_TMU_NONE; - ti->tm[TDFX_TMU0] = NULL; - ti->tm[TDFX_TMU1] = NULL; + t->range[TDFX_TMU0] = NULL; + t->range[TDFX_TMU1] = NULL; - ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; - ti->magFilt = GR_TEXTUREFILTER_BILINEAR; + t->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; + t->magFilt = GR_TEXTUREFILTER_BILINEAR; - ti->sClamp = GR_TEXTURECLAMP_WRAP; - ti->tClamp = GR_TEXTURECLAMP_WRAP; + t->sClamp = GR_TEXTURECLAMP_WRAP; + t->tClamp = GR_TEXTURECLAMP_WRAP; - ti->mmMode = GR_MIPMAP_NEAREST; - ti->LODblend = FXFALSE; + t->mmMode = GR_MIPMAP_NEAREST; + t->LODblend = FXFALSE; - for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { - ti->mipmapLevel[i].data = NULL; - } + for ( i = 0 ; i < MAX_TEXTURE_LEVELS ; i++ ) { + t->image[i].original.data = NULL; + t->image[i].rescaled.data = NULL; + } - return ti; + return t; } -/* - * Called via glBindTexture. +/* Given an OpenGL internal texture format, return the corresponding + * Glide internal texture format and MesaIntTexFormat. + * If allow32bpp is true, we'll return 32-bit texel formats when + * appropriate. */ - -void -tdfxDDBindTexture(GLcontext * ctx, GLenum target, - struct gl_texture_object *tObj) +static GrTextureFormat_t +tdfxTexGetFormat( tdfxContextPtr fxMesa, struct gl_texture_image *texImage, + GLenum format, GLenum type ) { - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - tdfxTexInfo *ti; + const GLboolean allow32bpp = TDFX_IS_NAPALM(fxMesa); + const GLboolean is32bpp = ( fxMesa->fxScreen->cpp == 4 ); + const struct gl_texture_format *texFormat; + GrTextureFormat_t ret; + + if ( 0 ) + fprintf( stderr, "internal=%s format=%s type=%s\n", + texImage->IntFormat == 3 ? "GL_RGB (3)" : + texImage->IntFormat == 4 ? "GL_RGBA (4)" : + gl_lookup_enum_by_nr( texImage->IntFormat ), + gl_lookup_enum_by_nr( format ), + gl_lookup_enum_by_nr( type ) ); + +#define SET_FORMAT( gr, gl ) \ + do { \ + ret = (gr); \ + texFormat = &(gl); \ + } while (0) + +#define SET_FORMAT_32BPP( gr32, gl32, gr16, gl16 ) \ + do { \ + if ( allow32bpp ) { \ + ret = (gr32); \ + texFormat = &(gl32); \ + } else { \ + ret = (gr16); \ + texFormat = &(gl16); \ + } \ + } while (0) + + switch ( texImage->IntFormat ) { + /* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has + * got to be better than sticking them way down the end of this + * huge list. + */ + case GL_RGBA: + case 4: + if ( format == GL_BGRA ) { + if ( type == GL_UNSIGNED_INT_8_8_8_8_REV && allow32bpp ) { + SET_FORMAT( GR_TEXFMT_ARGB_8888, _mesa_texformat_argb8888 ); + break; + } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { + SET_FORMAT( GR_TEXFMT_ARGB_4444, _mesa_texformat_argb4444 ); + break; + } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { + SET_FORMAT( GR_TEXFMT_ARGB_1555, _mesa_texformat_argb1555 ); + break; + } + } + if ( allow32bpp && is32bpp ) { + SET_FORMAT( GR_TEXFMT_ARGB_8888, _mesa_texformat_rgba8888 ); + } else { + SET_FORMAT( GR_TEXFMT_ARGB_4444, _mesa_texformat_argb4444 ); + } + break; + + case GL_RGB: + case 3: + if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { + SET_FORMAT( GR_TEXFMT_RGB_565, _mesa_texformat_rgb565 ); + break; + } + if ( allow32bpp && is32bpp ) { + SET_FORMAT( GR_TEXFMT_ARGB_8888, _mesa_texformat_rgba8888 ); + } else { + SET_FORMAT( GR_TEXFMT_RGB_565, _mesa_texformat_rgb565 ); + } + break; + + /* GH: Okay, keep checking as normal. Still test for GL_RGB, + * GL_RGBA formats first. + */ + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + SET_FORMAT_32BPP( GR_TEXFMT_ARGB_8888, _mesa_texformat_argb8888, + GR_TEXFMT_ARGB_4444, _mesa_texformat_argb4444 ); + break; + + case GL_RGBA4: + case GL_RGBA2: + SET_FORMAT( GR_TEXFMT_ARGB_4444, _mesa_texformat_argb4444 ); + break; + + case GL_RGB5_A1: + SET_FORMAT( GR_TEXFMT_ARGB_1555, _mesa_texformat_argb1555 ); + break; + + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + SET_FORMAT_32BPP( GR_TEXFMT_ARGB_8888, _mesa_texformat_argb8888, + GR_TEXFMT_RGB_565, _mesa_texformat_rgb565 ); + break; + + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + SET_FORMAT( GR_TEXFMT_RGB_565, _mesa_texformat_rgb565 ); + break; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + SET_FORMAT( GR_TEXFMT_ALPHA_8, _mesa_texformat_a8 ); + break; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + SET_FORMAT( GR_TEXFMT_INTENSITY_8, _mesa_texformat_l8 ); + break; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + SET_FORMAT( GR_TEXFMT_ALPHA_INTENSITY_88, _mesa_texformat_al88 ); + break; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + SET_FORMAT( GR_TEXFMT_ALPHA_8, _mesa_texformat_i8 ); + break; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + SET_FORMAT( GR_TEXFMT_P_8, _mesa_texformat_ci8 ); + break; + + default: + fprintf( stderr, "bad texture format in fxTexGetFormat() %d", + texImage->IntFormat ); + return -1; + } + + texImage->TexFormat = texFormat; + + return ret; +} - if (MESA_VERBOSE & VERBOSE_DRIVER) { - fprintf(stderr, "fxmesa: fxDDTexBind(%d,%p)\n", tObj->Name, - tObj->DriverData); - } - if (target != GL_TEXTURE_2D) - return; +static GLboolean +tdfxDDTexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, + GLboolean *retainInternalCopy ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + const struct gl_texture_format *texFormat; + GrTextureFormat_t glideFormat; + tdfxTexObjPtr t; + tdfxTexImagePtr image; + GLint dstWidth, dstHeight, wScale, hScale; + GLint size; + void *data; + + if ( 0 ) { + printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n", + texObj->Name, texImage->IntFormat, format, type, + texImage->Width, texImage->Height); + } + + if ( target != GL_TEXTURE_2D || texImage->Border > 0 ) + return GL_FALSE; + + if ( !texObj->DriverData ) + texObj->DriverData = tdfxAllocTexObj( fxMesa ); + + t = TDFX_TEXTURE_DATA(texObj); + image = &t->image[level]; + + /* Determine the appropriate GL internal texel format, Mesa internal + * texel format, and texelSize (bytes) given the user's internal + * texture format hint. + */ + glideFormat = tdfxTexGetFormat( fxMesa, texImage, format, type ); - if (!tObj->DriverData) { - tObj->DriverData = fxAllocTexObjData(fxMesa); - } + /* Get the destination internal format. + */ + texFormat = texImage->TexFormat; - ti = TDFX_TEXTURE_DATA(tObj); - ti->lastTimeUsed = fxMesa->texBindNumber++; + /* Determine width and height scale factors for texture. Remember, + * Glide is limited to 8:1 aspect ratios. + */ + tdfxTexGetInfo( ctx, + texImage->Width, texImage->Height, + NULL, NULL, NULL, NULL, + &wScale, &hScale ); + dstWidth = texImage->Width * wScale; + dstHeight = texImage->Height * hScale; + + /* Allocate new storage for texture image, if needed. This + * conditional wants to set uncompressedImage to point to the + * uncompressed image, and mml->data to the texture data. If the + * image is uncompressed, these are identical. If the image is not + * compressed, these are different. + */ + if ( !image->original.data || image->glideFormat != glideFormat || + image->original.width != texImage->Width || + image->original.height != texImage->Height ) + { + if ( image->original.data ) { + FREE( image->original.data ); + image->original.data = NULL; + } + if ( image->rescaled.data ) { + FREE( image->rescaled.data ); + image->rescaled.data = NULL; + } + + size = texImage->Width * texImage->Height * texFormat->TexelBytes; + image->original.data = (void *) MALLOC( size ); + if ( !image->original.data ) + return GL_FALSE; + + image->original.width = texImage->Width; + image->original.height = texImage->Height; + image->original.size = size; + + image->glideFormat = glideFormat; + image->wScale = wScale; + image->hScale = hScale; + + t->info.format = glideFormat; + tdfxTMMoveOutTM( fxMesa, texObj ); + } + + /* Store the texture image into the 'original' space. + */ + if ( !_mesa_convert_texsubimage2d( texFormat->IntFormat, + 0, 0, texImage->Width, + texImage->Height, texImage->Width, + format, type, packing, pixels, + image->original.data ) ) { + return GL_FALSE; + } + + data = image->original.data; + size = image->original.size; + + /* GH: Sigh... + */ + if ( wScale > 1 || hScale > 1 ) { + if ( image->rescaled.data ) { + FREE( image->rescaled.data ); + image->rescaled.data = NULL; + } - fxMesa->new_state |= TDFX_NEW_TEXTURE; -} + size = dstWidth * dstHeight * texFormat->TexelBytes; + image->rescaled.data = (void *) MALLOC( size ); + if ( !image->rescaled.data ) + return GL_FALSE; + image->rescaled.width = dstWidth; + image->rescaled.height = dstHeight; + image->rescaled.size = size; -/* - * Called via glTexEnv. - */ -void -tdfxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname, - const GLfloat * param) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - - if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { - if (param) - fprintf(stderr, "fxmesa: texenv(%x,%x)\n", pname, - (GLint) (*param)); - else - fprintf(stderr, "fxmesa: texenv(%x)\n", pname); - } + _mesa_rescale_teximage2d( texFormat, + texImage->Width, texImage->Height, + dstWidth, dstHeight, + image->original.data, image->rescaled.data ); - fxMesa->new_state |= TDFX_NEW_TEXTURE; -} + data = image->rescaled.data; + } + image->data = data; + image->size = size; -/* - * Called via glTexParameter. - */ -void -tdfxDDTexParameter(GLcontext * ctx, GLenum target, - struct gl_texture_object *tObj, - GLenum pname, const GLfloat * params) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - GLenum param = (GLenum) (GLint) params[0]; - tdfxTexInfo *ti; - - if (MESA_VERBOSE & VERBOSE_DRIVER) { - fprintf(stderr, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj->Name, - tObj->DriverData, pname, param); - } - - if (target != GL_TEXTURE_2D) - return; - - if (!tObj->DriverData) - tObj->DriverData = fxAllocTexObjData(fxMesa); - - ti = TDFX_TEXTURE_DATA(tObj); - - switch (pname) { - case GL_TEXTURE_MIN_FILTER: - switch (param) { - case GL_NEAREST: - ti->mmMode = GR_MIPMAP_DISABLE; - ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; - ti->LODblend = FXFALSE; - break; - case GL_LINEAR: - ti->mmMode = GR_MIPMAP_DISABLE; - ti->minFilt = GR_TEXTUREFILTER_BILINEAR; - ti->LODblend = FXFALSE; - break; - case GL_NEAREST_MIPMAP_LINEAR: - if (TDFX_IS_NAPALM(fxMesa)) { - if (fxMesa->haveTwoTMUs) { - ti->mmMode = GR_MIPMAP_NEAREST; - ti->LODblend = FXTRUE; - } - else { - ti->mmMode = GR_MIPMAP_NEAREST_DITHER; - ti->LODblend = FXFALSE; - } - ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; - break; - } - /* XXX Voodoo3/Banshee mipmap blending seems to produce - * incorrectly filtered colors for the smallest mipmap levels. - * To work-around we fall-through here and use a different filter. - */ - case GL_NEAREST_MIPMAP_NEAREST: - ti->mmMode = GR_MIPMAP_NEAREST; - ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; - ti->LODblend = FXFALSE; - break; - case GL_LINEAR_MIPMAP_LINEAR: - if (TDFX_IS_NAPALM(fxMesa)) { - if (fxMesa->haveTwoTMUs) { - ti->mmMode = GR_MIPMAP_NEAREST; - ti->LODblend = FXTRUE; - } - else { - ti->mmMode = GR_MIPMAP_NEAREST_DITHER; - ti->LODblend = FXFALSE; - } - ti->minFilt = GR_TEXTUREFILTER_BILINEAR; - break; - } - /* XXX Voodoo3/Banshee mipmap blending seems to produce - * incorrectly filtered colors for the smallest mipmap levels. - * To work-around we fall-through here and use a different filter. - */ - case GL_LINEAR_MIPMAP_NEAREST: - ti->mmMode = GR_MIPMAP_NEAREST; - ti->minFilt = GR_TEXTUREFILTER_BILINEAR; - ti->LODblend = FXFALSE; - break; - default: - break; - } - RevalidateTexture(ctx, tObj); - fxMesa->new_state |= TDFX_NEW_TEXTURE; - break; - - case GL_TEXTURE_MAG_FILTER: - switch (param) { - case GL_NEAREST: - ti->magFilt = GR_TEXTUREFILTER_POINT_SAMPLED; - break; - case GL_LINEAR: - ti->magFilt = GR_TEXTUREFILTER_BILINEAR; - break; - default: - break; - } - fxMesa->new_state |= TDFX_NEW_TEXTURE; - break; - - case GL_TEXTURE_WRAP_S: - switch (param) { - case GL_CLAMP: - ti->sClamp = GR_TEXTURECLAMP_CLAMP; - break; - case GL_REPEAT: - ti->sClamp = GR_TEXTURECLAMP_WRAP; - break; - default: - break; - } - fxMesa->new_state |= TDFX_NEW_TEXTURE; - break; - - case GL_TEXTURE_WRAP_T: - switch (param) { - case GL_CLAMP: - ti->tClamp = GR_TEXTURECLAMP_CLAMP; - break; - case GL_REPEAT: - ti->tClamp = GR_TEXTURECLAMP_WRAP; - break; - default: - break; - } - fxMesa->new_state |= TDFX_NEW_TEXTURE; - break; - - case GL_TEXTURE_BORDER_COLOR: - /* TO DO */ - break; - case GL_TEXTURE_MIN_LOD: - /* TO DO */ - break; - case GL_TEXTURE_MAX_LOD: - /* TO DO */ - break; - case GL_TEXTURE_BASE_LEVEL: - RevalidateTexture(ctx, tObj); - break; - case GL_TEXTURE_MAX_LEVEL: - RevalidateTexture(ctx, tObj); - break; - - default: - break; - } -} + tdfxRevalidateTexture( ctx, texObj ); + t->reloadImages = GL_TRUE; + fxMesa->new_state |= TDFX_NEW_TEXTURE; -/* - * Called via glDeleteTextures to delete a texture object. - * Here, we delete the Glide data associated with the texture. - */ -void -tdfxDDDeleteTexture(GLcontext * ctx, struct gl_texture_object *tObj) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - tdfxTMFreeTexture(fxMesa, tObj); - fxMesa->new_state |= TDFX_NEW_TEXTURE; + *retainInternalCopy = GL_FALSE; + return GL_TRUE; } -/* - * Return true if texture is resident, false otherwise. - */ -GLboolean -tdfxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj) +static GLboolean +tdfxDDTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) { - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); - return (GLboolean) (ti && ti->isInTM); -} + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(texObj); + tdfxTexImagePtr image; + if ( target != GL_TEXTURE_2D ) + return GL_FALSE; + if ( !t ) + return GL_FALSE; -/* - * Convert a gl_color_table texture palette to Glide's format. - */ -static void -convertPalette(FxU32 data[256], const struct gl_color_table *table) -{ - const GLubyte *tableUB = (const GLubyte *) table->Table; - GLint width = table->Size; - FxU32 r, g, b, a; - GLint i; - - ASSERT(table->TableType == GL_UNSIGNED_BYTE); - - switch (table->Format) { - case GL_INTENSITY: - for (i = 0; i < width; i++) { - r = tableUB[i]; - g = tableUB[i]; - b = tableUB[i]; - a = tableUB[i]; - data[i] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - case GL_LUMINANCE: - for (i = 0; i < width; i++) { - r = tableUB[i]; - g = tableUB[i]; - b = tableUB[i]; - a = 255; - data[i] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - case GL_ALPHA: - for (i = 0; i < width; i++) { - r = g = b = 255; - a = tableUB[i]; - data[i] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - case GL_LUMINANCE_ALPHA: - for (i = 0; i < width; i++) { - r = g = b = tableUB[i * 2 + 0]; - a = tableUB[i * 2 + 1]; - data[i] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - case GL_RGB: - for (i = 0; i < width; i++) { - r = tableUB[i * 3 + 0]; - g = tableUB[i * 3 + 1]; - b = tableUB[i * 3 + 2]; - a = 255; - data[i] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - case GL_RGBA: - for (i = 0; i < width; i++) { - r = tableUB[i * 4 + 0]; - g = tableUB[i * 4 + 1]; - b = tableUB[i * 4 + 2]; - a = tableUB[i * 4 + 3]; - data[i] = (a << 24) | (r << 16) | (g << 8) | b; - } - break; - } -} + if ( 0 ) { + fprintf( stderr, "TexSubImage id=%d lvl=%d int=0x%x format=0x%x type=0x%x x=%d y=%d w=%d h=%d fullW=%d fullH=%d\n", + texObj->Name, level, texImage->IntFormat, format, type, + xoffset, yoffset, width, height, + texImage->Width, texImage->Height ); + } + image = &t->image[level]; + /* Must have an existing texture image! + */ + assert( image->original.data ); -void -tdfxDDTexturePalette(GLcontext * ctx, struct gl_texture_object *tObj) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - - if (tObj) { - /* per-texture palette */ - tdfxTexInfo *ti; - if (!tObj->DriverData) - tObj->DriverData = fxAllocTexObjData(fxMesa); - ti = TDFX_TEXTURE_DATA(tObj); - convertPalette(ti->palette.data, &tObj->Palette); - /*tdfxTexInvalidate(ctx, tObj);*/ - } - else { - /* global texture palette */ - convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette); - } - fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX too heavy-handed */ + if ( !_mesa_convert_texsubimage2d( texImage->TexFormat->IntFormat, + xoffset, yoffset, width, height, + texImage->Width, + format, type, packing, + pixels, image->original.data ) ) { + return GL_FALSE; + } + + /* Rescale the original image again if we have to. + */ + if ( image->wScale > 1 || image->hScale > 1 ) { + assert( image->rescaled.data ); + _mesa_rescale_teximage2d( texImage->TexFormat, + image->original.width, image->original.height, + image->rescaled.width, image->rescaled.height, + image->original.data, image->rescaled.data ); + } + + t->reloadImages = GL_TRUE; /* signal the image needs to be reloaded */ + fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX this might be a bit much */ + + return GL_TRUE; } -/* - * Given an OpenGL internal texture format, return the corresponding - * Glide internal texture format and MesaIntTexFormat. - * If allow32bpp is true, we'll return 32-bit texel formats when - * appropriate. - */ -static void -tdfxTexGetFormat(GLenum intFormatHint, GLboolean allow32bpp, - GrTextureFormat_t *glideFormat, - MesaIntTexFormat *mesaFormat, - GLint *texelSize) -{ - switch (intFormatHint) { - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - if (glideFormat) - *glideFormat = GR_TEXFMT_INTENSITY_8; - if (mesaFormat) - *mesaFormat = MESA_L8; - if (texelSize) - *texelSize = 1; - break; - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - if (glideFormat) - *glideFormat = GR_TEXFMT_ALPHA_INTENSITY_88; - if (mesaFormat) - *mesaFormat = MESA_A8_L8; - if (texelSize) - *texelSize = 2; - break; - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - if (glideFormat) - *glideFormat = GR_TEXFMT_ALPHA_8; - if (mesaFormat) - *mesaFormat = MESA_I8; - if (texelSize) - *texelSize = 1; - break; - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - if (glideFormat) - *glideFormat = GR_TEXFMT_ALPHA_8; - if (mesaFormat) - *mesaFormat = MESA_A8; - if (texelSize) - *texelSize = 1; - break; - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - if (glideFormat) - *glideFormat = GR_TEXFMT_RGB_565; - if (mesaFormat) - *mesaFormat = MESA_R5_G6_B5; - if (texelSize) - *texelSize = 2; - break; - case 3: - case GL_RGB: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - if (allow32bpp) { - if (glideFormat) - *glideFormat = GR_TEXFMT_ARGB_8888; - if (mesaFormat) - *mesaFormat = MESA_FF_R8_G8_B8; - if (texelSize) - *texelSize = 4; - } - else { - if (glideFormat) - *glideFormat = GR_TEXFMT_RGB_565; - if (mesaFormat) - *mesaFormat = MESA_R5_G6_B5; - if (texelSize) - *texelSize = 2; - } - break; - case GL_RGBA2: - case GL_RGBA4: - if (glideFormat) - *glideFormat = GR_TEXFMT_ARGB_4444; - if (mesaFormat) - *mesaFormat = MESA_A4_R4_G4_B4; - if (texelSize) - *texelSize = 2; - break; - case 4: - case GL_RGBA: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - if (allow32bpp) { - if (glideFormat) - *glideFormat = GR_TEXFMT_ARGB_8888; - if (mesaFormat) - *mesaFormat = MESA_A8_R8_G8_B8; - if (texelSize) - *texelSize = 4; - } - else { - if (glideFormat) - *glideFormat = GR_TEXFMT_ARGB_4444; - if (mesaFormat) - *mesaFormat = MESA_A4_R4_G4_B4; - if (texelSize) - *texelSize = 2; - } - break; - case GL_RGB5_A1: - if (glideFormat) - *glideFormat = GR_TEXFMT_ARGB_1555; - if (mesaFormat) - *mesaFormat = MESA_A1_R5_G5_B5; - if (texelSize) - *texelSize = 2; - break; - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - if (glideFormat) - *glideFormat = GR_TEXFMT_P_8; - if (mesaFormat) - *mesaFormat = MESA_C8; - if (texelSize) - *texelSize = 1; - break; - case GL_COMPRESSED_RGB_FXT1_3DFX: - if (glideFormat) - *glideFormat = GR_TEXFMT_ARGB_CMP_FXT1; - if (mesaFormat) - *mesaFormat = MESA_A8_R8_G8_B8; - if (texelSize) - *texelSize = 4; - break; - case GL_COMPRESSED_RGBA_FXT1_3DFX: - if (glideFormat) - *glideFormat = GR_TEXFMT_ARGB_CMP_FXT1; - if (mesaFormat) - *mesaFormat = MESA_A8_R8_G8_B8; - if (texelSize) - *texelSize = 4; - break; - default: - fprintf(stderr, "bad texture format in fxTexGetFormat() %d", intFormatHint); - break; - } -} +/* ================================================================ + * + */ -/**********************************************************************/ -/**** NEW TEXTURE IMAGE FUNCTIONS ****/ -/**********************************************************************/ +static void tdfxDDTexEnv( GLcontext *ctx, GLenum target, + GLenum pname, const GLfloat *param ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); -static FxBool TexusFatalError = FXFALSE; -static FxBool TexusError = FXFALSE; + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + if ( param ) { + fprintf( stderr, __FUNCTION__"( %x, %x )\n", pname, (GLint)(*param) ); + } else { + fprintf( stderr, __FUNCTION__"( %x )\n", pname ); + } + } -#define TX_DITHER_NONE 0x00000000 + fxMesa->new_state |= TDFX_NEW_TEXTURE; +} -static void -fxTexusError(const char *string, FxBool fatal) +static void tdfxDDTexParameter( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, + GLenum pname, const GLfloat *params ) { - gl_problem(NULL, string); - /* - * Just propagate the fatal value up. - */ - TexusError = FXTRUE; - TexusFatalError = fatal; + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GLenum param = (GLenum) (GLint) params[0]; + tdfxTexObjPtr t; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, __FUNCTION__ "( %d, %p, %x, %x )\n", + tObj->Name, tObj->DriverData, pname, param ); + } + + if ( target != GL_TEXTURE_2D ) + return; + + if ( !tObj->DriverData ) + tObj->DriverData = tdfxAllocTexObj( fxMesa ); + + t = TDFX_TEXTURE_DATA(tObj); + + switch ( pname ) { + case GL_TEXTURE_MIN_FILTER: + switch ( param ) { + case GL_NEAREST: + t->mmMode = GR_MIPMAP_DISABLE; + t->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; + t->LODblend = FXFALSE; + break; + + case GL_LINEAR: + t->mmMode = GR_MIPMAP_DISABLE; + t->minFilt = GR_TEXTUREFILTER_BILINEAR; + t->LODblend = FXFALSE; + break; + + case GL_NEAREST_MIPMAP_LINEAR: + if ( TDFX_IS_NAPALM(fxMesa) ) { + if ( fxMesa->numTMUs > 1 ) { + t->mmMode = GR_MIPMAP_NEAREST; + t->LODblend = FXTRUE; + } else { + t->mmMode = GR_MIPMAP_NEAREST_DITHER; + t->LODblend = FXFALSE; + } + t->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; + break; + } + /* XXX Voodoo3/Banshee mipmap blending seems to produce + * incorrectly filtered colors for the smallest mipmap levels. + * To work-around we fall-through here and use a different filter. + */ + case GL_NEAREST_MIPMAP_NEAREST: + t->mmMode = GR_MIPMAP_NEAREST; + t->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; + t->LODblend = FXFALSE; + break; + + case GL_LINEAR_MIPMAP_LINEAR: + if ( TDFX_IS_NAPALM(fxMesa) ) { + if ( fxMesa->numTMUs > 1 ) { + t->mmMode = GR_MIPMAP_NEAREST; + t->LODblend = FXTRUE; + } else { + t->mmMode = GR_MIPMAP_NEAREST_DITHER; + t->LODblend = FXFALSE; + } + t->minFilt = GR_TEXTUREFILTER_BILINEAR; + break; + } + /* XXX Voodoo3/Banshee mipmap blending seems to produce + * incorrectly filtered colors for the smallest mipmap levels. + * To work-around we fall-through here and use a different filter. + */ + case GL_LINEAR_MIPMAP_NEAREST: + t->mmMode = GR_MIPMAP_NEAREST; + t->minFilt = GR_TEXTUREFILTER_BILINEAR; + t->LODblend = FXFALSE; + break; + default: + break; + } + tdfxRevalidateTexture( ctx, tObj ); + fxMesa->new_state |= TDFX_NEW_TEXTURE; + break; + + case GL_TEXTURE_MAG_FILTER: + switch ( param ) { + case GL_NEAREST: + t->magFilt = GR_TEXTUREFILTER_POINT_SAMPLED; + break; + case GL_LINEAR: + t->magFilt = GR_TEXTUREFILTER_BILINEAR; + break; + default: + break; + } + fxMesa->new_state |= TDFX_NEW_TEXTURE; + break; + + case GL_TEXTURE_WRAP_S: + switch ( param ) { + case GL_CLAMP: + t->sClamp = GR_TEXTURECLAMP_CLAMP; + break; + case GL_REPEAT: + t->sClamp = GR_TEXTURECLAMP_WRAP; + break; + default: + break; + } + fxMesa->new_state |= TDFX_NEW_TEXTURE; + break; + + case GL_TEXTURE_WRAP_T: + switch ( param ) { + case GL_CLAMP: + t->tClamp = GR_TEXTURECLAMP_CLAMP; + break; + case GL_REPEAT: + t->tClamp = GR_TEXTURECLAMP_WRAP; + break; + default: + break; + } + fxMesa->new_state |= TDFX_NEW_TEXTURE; + break; + + case GL_TEXTURE_BASE_LEVEL: + tdfxRevalidateTexture( ctx, tObj ); + break; + + case GL_TEXTURE_MAX_LEVEL: + tdfxRevalidateTexture( ctx, tObj ); + break; + + case GL_TEXTURE_BORDER_COLOR: + /* TO DO */ + break; + case GL_TEXTURE_MIN_LOD: + /* TO DO */ + break; + case GL_TEXTURE_MAX_LOD: + /* TO DO */ + break; + + default: + break; + } } -GLboolean -tdfxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level, - GLenum format, GLenum type, const GLvoid * pixels, - const struct gl_pixelstore_attrib * packing, - struct gl_texture_object * texObj, - struct gl_texture_image * texImage, - GLboolean * retainInternalCopy) +static void tdfxDDBindTexture( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj ) { - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - const GLboolean allow32bpt = TDFX_IS_NAPALM(fxMesa); - GrTextureFormat_t gldformat; - tdfxTexInfo *ti; - tdfxMipMapLevel *mml; - GLint dstWidth, dstHeight, wScale, hScale, texelSize, dstStride; - MesaIntTexFormat intFormat; - GLboolean isCompressedFormat; - GLint texsize; - void *uncompressedImage; - - /* - printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n", - texObj->Name, texImage->IntFormat, format, type, - texImage->Width, texImage->Height); - */ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + tdfxTexObjPtr t; - isCompressedFormat = texImage->IsCompressed; - if (target != GL_TEXTURE_2D || texImage->Border > 0) - return GL_FALSE; - - if (!texObj->DriverData) - texObj->DriverData = fxAllocTexObjData(fxMesa); - - ti = TDFX_TEXTURE_DATA(texObj); - mml = &ti->mipmapLevel[level]; - - /* Determine the appropriate GL internal texel format, Mesa internal - * texel format, and texelSize (bytes) given the user's internal - * texture format hint. - */ - tdfxTexGetFormat(texImage->IntFormat, allow32bpt, - &gldformat, &intFormat, &texelSize); - - /* Determine width and height scale factors for texture. - * Remember, Glide is limited to 8:1 aspect ratios. - */ - tdfxTexGetInfo(ctx, - texImage->Width, texImage->Height, - NULL, /* lod level */ - NULL, /* aspect ratio */ - NULL, NULL, /* sscale, tscale */ - &wScale, &hScale); - dstWidth = texImage->Width * wScale; - dstHeight = texImage->Height * hScale; - if (isCompressedFormat) { - texsize = tdfxDDCompressedImageSize(ctx, - texImage->IntFormat, - 2, - texImage->Width, - texImage->Height, - 1); - } - else { - texsize = dstWidth * dstHeight * texelSize; - } - - /* - * If the image is not compressed, this doesn't - * matter, but it might as well have a sensible - * value, and it might save a failure later on. - */ - texImage->CompressedSize = texsize; - /* housekeeping */ - _mesa_set_teximage_component_sizes(intFormat, texImage); - - /* - * allocate new storage for texture image, if needed. - * This conditional wants to set uncompressedImage to - * point to the uncompressed image, and mml->data to - * the texture data. If the image is uncompressed, - * these are identical. If the image is not compressed, - * these are different. - */ - if (!mml->data || mml->glideFormat != gldformat || - mml->width != dstWidth || mml->height != dstHeight || - texsize != mml->dataSize ) { - if (mml->data) { - FREE(mml->data); - } - uncompressedImage - = (void *)MALLOC(dstWidth * dstHeight * texelSize); - if (!uncompressedImage) { - return GL_FALSE; - } - if (isCompressedFormat) { - mml->data = MALLOC(texsize); - if (!mml->data) { - FREE(uncompressedImage); - return GL_FALSE; - } - } else { - mml->data = uncompressedImage; - } - mml->texelSize = texelSize; - mml->glideFormat = gldformat; - mml->width = dstWidth; - mml->height = dstHeight; - mml->dataSize = texsize; - ti->info.format = gldformat; - tdfxTMMoveOutTM(fxMesa, texObj); - /*tdfxTexInvalidate(ctx, texObj);*/ - } - else { - /* - * Here we don't have to allocate anything, but we - * do have to point uncompressedImage to the uncompressed - * data. - */ - if (isCompressedFormat) { - uncompressedImage - = (void *)MALLOC(dstWidth * dstHeight * texelSize); - if (!uncompressedImage) { - return GL_FALSE; - } - } else { - uncompressedImage = mml->data; - } - } - - dstStride = dstWidth * texelSize; - - /* store the texture image into uncompressedImage */ - if (!_mesa_convert_teximage(intFormat, - dstWidth, dstHeight, - uncompressedImage, - dstStride, - texImage->Width, texImage->Height, - format, type, pixels, packing)) { - /*printf("convert failed\n");*/ - return GL_FALSE; /* not necessarily an error */ - } - - /* - * Now compress it if necessary. - */ - if (isCompressedFormat) { - TxErrorCallbackFnc_t oldErrorCallback; - (*txErrorSetCallbackProc)(fxTexusError, &oldErrorCallback); - (*txImgQuantizeProc)((char *)mml->data, - (char *)uncompressedImage, - texImage->Width, - texImage->Height, - gldformat, - TX_DITHER_NONE); - (*txErrorSetCallbackProc)(oldErrorCallback, NULL); - if (uncompressedImage != mml->data) { - /* - * We do not need this any more, errors or no. - */ - FREE(uncompressedImage); - } - TexusError = FXFALSE; - if (TexusFatalError) { - FREE(mml->data); - mml->data = NULL; - TexusFatalError = FXFALSE; - return GL_FALSE; - } - } - - - RevalidateTexture(ctx, texObj); - - ti->reloadImages = GL_TRUE; - fxMesa->new_state |= TDFX_NEW_TEXTURE; - - *retainInternalCopy = GL_FALSE; - return GL_TRUE; -} + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, __FUNCTION__ "( %d, %p )\n", + tObj->Name, tObj->DriverData ); + } + if ( target != GL_TEXTURE_2D ) + return; -GLboolean -tdfxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid * pixels, - const struct gl_pixelstore_attrib * packing, - struct gl_texture_object * texObj, - struct gl_texture_image * texImage) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - tdfxTexInfo *ti; - GLint wscale, hscale, dstStride = 0; - tdfxMipMapLevel *mml; - GLboolean result; - void *uncompressedImage = (void *)0; - FxU32 uncompressedSize; - TxErrorCallbackFnc_t oldErrorCallback; - - if (target != GL_TEXTURE_2D) - return GL_FALSE; - - if (!texObj->DriverData) - return GL_FALSE; - - /* - printf("TexSubImage id=%d lvl=%d int=0x%x format=0x%x type=0x%x x=%d y=%d w=%d h=%d fullW=%d fullH=%d\n", - texObj->Name, level, - texImage->IntFormat, format, type, xoffset, yoffset, width, height, - texImage->Width, texImage->Height); - */ + if ( !tObj->DriverData ) + tObj->DriverData = tdfxAllocTexObj( fxMesa ); - ti = TDFX_TEXTURE_DATA(texObj); - mml = &ti->mipmapLevel[level]; - - tdfxTexGetInfo(ctx, texImage->Width, texImage->Height, NULL, NULL, - NULL, NULL, &wscale, &hscale); - - /* - * Must have an existing texture image! - */ - assert(mml->data); - - switch (mml->glideFormat) { - case GR_TEXFMT_INTENSITY_8: - dstStride = mml->width; - result = _mesa_convert_texsubimage(MESA_I8, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - break; - case GR_TEXFMT_ALPHA_8: - dstStride = mml->width; - result = _mesa_convert_texsubimage(MESA_A8, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - break; - case GR_TEXFMT_P_8: - dstStride = mml->width; - result = _mesa_convert_texsubimage(MESA_C8, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - break; - case GR_TEXFMT_ALPHA_INTENSITY_88: - dstStride = mml->width * 2; - result = _mesa_convert_texsubimage(MESA_A8_L8, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - break; - case GR_TEXFMT_RGB_565: - dstStride = mml->width * 2; - result = _mesa_convert_texsubimage(MESA_R5_G6_B5, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - break; - case GR_TEXFMT_ARGB_4444: - dstStride = mml->width * 2; - result = _mesa_convert_texsubimage(MESA_A4_R4_G4_B4, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - break; - case GR_TEXFMT_ARGB_CMP_FXT1: - /* - * There are some special legality constraints for compressed - * textures. - */ - if ((xoffset != texImage->Border) - || (yoffset != texImage->Border)) { - gl_error( ctx, - GL_INVALID_OPERATION, - "glTexSubImage2D(offset)" ); - return GL_FALSE; - } - if ((width != texImage->Width) - || (height != texImage->Height)) { - gl_error( ctx, - GL_INVALID_VALUE, - "glTexSubImage2D(image size)" ); - return GL_FALSE; - } - /* - * The width and height have to be multiples of - * 8 and 4 respectively. - */ - width = (mml->width + 0x7) &~ 0x7; - height = (mml->height + 0x3) &~ 0x3; - /* - * A texel is 8888 for this format. - */ - uncompressedSize = mml->width * mml->height * 4; - uncompressedImage = (void *)MALLOC(uncompressedSize); - /* - * Convert the data. - */ - dstStride = mml->width * 4; - result = _mesa_convert_texsubimage(MESA_A8_R8_G8_B8, xoffset, yoffset, - mml->width, mml->height, uncompressedImage, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - if (!result) { - FREE(uncompressedImage); - printf("TexSubImage convert failed\n"); - return GL_FALSE; - } - /* - * Now that we have converted the data, then compress it. - */ - (*txErrorSetCallbackProc)(fxTexusError, &oldErrorCallback); - (*txImgQuantizeProc)((char *)mml->data, - (char *)uncompressedImage, - mml->width, - mml->height, - mml->glideFormat, - TX_DITHER_NONE); - (*txErrorSetCallbackProc)(oldErrorCallback, NULL); - result = TexusFatalError; - TexusFatalError = TexusError = FXFALSE; - /* - * We don't need this any more. - */ - FREE(uncompressedImage); - break; - case GR_TEXFMT_ARGB_8888: - { - MesaIntTexFormat intFormat; - if (texImage->Format == GL_RGB) { - /* An RGB image padded out to 4 bytes/texel */ - intFormat = MESA_FF_R8_G8_B8; - } - else { - intFormat = MESA_A8_R8_G8_B8; - } - dstStride = mml->width * 4; - result = _mesa_convert_texsubimage(intFormat, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - } - break; - case GR_TEXFMT_ARGB_1555: - dstStride = mml->width * 2; - result = _mesa_convert_texsubimage(MESA_A1_R5_G5_B5, xoffset, yoffset, - mml->width, mml->height, mml->data, - dstStride, width, height, - texImage->Width, texImage->Height, - format, type, pixels, packing); - break; - default: - gl_problem(NULL, "tdfx driver: fxTexBuildSubImageMap() bad format"); - result = GL_FALSE; - } - - if (!result) { - return GL_FALSE; - } - - ti->reloadImages = GL_TRUE; /* signal the image needs to be reloaded */ - fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX this might be a bit much */ - - return GL_TRUE; + t = TDFX_TEXTURE_DATA(tObj); + t->lastTimeUsed = fxMesa->texBindNumber++; + + fxMesa->new_state |= TDFX_NEW_TEXTURE; } +static void tdfxDDDeleteTexture( GLcontext *ctx, + struct gl_texture_object *tObj ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); -/**********************************************************************/ -/**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/ -/**********************************************************************/ + LOCK_HARDWARE( fxMesa ); + tdfxTMFreeTextureLocked( fxMesa, tObj ); + UNLOCK_HARDWARE( fxMesa ); -GLboolean -tdfxDDCompressedTexImage2D( GLcontext *ctx, GLenum target, - GLint level, GLsizei imageSize, - const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, - GLboolean *retainInternalCopy) -{ - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - const GLboolean allow32bpt = TDFX_IS_NAPALM(fxMesa); - GrTextureFormat_t gldformat; - tdfxTexInfo *ti; - tdfxMipMapLevel *mml; - GLint dstWidth, dstHeight, wScale, hScale, texelSize; - MesaIntTexFormat intFormat; - GLboolean isCompressedFormat; - GLsizei texsize; - - if (target != GL_TEXTURE_2D || texImage->Border > 0) - return GL_FALSE; - - if (!texObj->DriverData) - texObj->DriverData = fxAllocTexObjData(fxMesa); - - ti = TDFX_TEXTURE_DATA(texObj); - mml = &ti->mipmapLevel[level]; - - isCompressedFormat = tdfxDDIsCompressedGlideFormatMacro(texImage->IntFormat); - if (!isCompressedFormat) { - gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(format)" ); - return GL_FALSE; - } - /* Determine the apporpriate GL internal texel format, Mesa internal - * texel format, and texelSize (bytes) given the user's internal - * texture format hint. - */ - tdfxTexGetFormat(texImage->IntFormat, allow32bpt, - &gldformat, &intFormat, &texelSize); - - /* Determine width and height scale factors for texture. - * Remember, Glide is limited to 8:1 aspect ratios. - */ - tdfxTexGetInfo(ctx, - texImage->Width, texImage->Height, - NULL, /* lod level */ - NULL, /* aspect ratio */ - NULL, NULL, /* sscale, tscale */ - &wScale, &hScale); - dstWidth = texImage->Width * wScale; - dstHeight = texImage->Height * hScale; - /* housekeeping */ - _mesa_set_teximage_component_sizes(intFormat, texImage); - - texsize = tdfxDDCompressedImageSize(ctx, - texImage->IntFormat, - 2, - texImage->Width, - texImage->Height, - 1); - if (texsize != imageSize) { - gl_error(ctx, - GL_INVALID_VALUE, - "glCompressedTexImage2D(texsize)"); - return GL_FALSE; - } - - /* allocate new storage for texture image, if needed */ - if (!mml->data || mml->glideFormat != gldformat || - mml->width != dstWidth || mml->height != dstHeight || - texsize != mml->dataSize) { - if (mml->data) { - FREE(mml->data); - } - mml->data = MALLOC(texsize); - if (!mml->data) { - return GL_FALSE; - } - mml->texelSize = texelSize; - mml->glideFormat = gldformat; - mml->width = dstWidth; - mml->height = dstHeight; - tdfxTMMoveOutTM(fxMesa, texObj); - /*tdfxTexInvalidate(ctx, texObj);*/ - } - - /* save the texture data */ - MEMCPY(mml->data, data, imageSize); - - RevalidateTexture(ctx, texObj); - - ti->reloadImages = GL_TRUE; - fxMesa->new_state |= TDFX_NEW_TEXTURE; - - *retainInternalCopy = GL_FALSE; - return GL_TRUE; + fxMesa->new_state |= TDFX_NEW_TEXTURE; } -GLboolean -tdfxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target, - GLint level, GLint xoffset, - GLint yoffset, GLsizei width, - GLint height, GLenum format, - GLsizei imageSize, const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) +static GLboolean tdfxDDIsTextureResident( GLcontext *ctx, + struct gl_texture_object *tObj ) { - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - tdfxTexInfo *ti; - tdfxMipMapLevel *mml; - - /* - * We punt if we are not replacing the entire image. This - * is allowed by the spec. - */ - if ((xoffset != 0) && (yoffset != 0) - && (width != texImage->Width) - && (height != texImage->Height)) { - return GL_FALSE; - } - - ti = TDFX_TEXTURE_DATA(texObj); - mml = &ti->mipmapLevel[level]; - if (imageSize != mml->dataSize) { - return GL_FALSE; - } - MEMCPY(data, mml->data, imageSize); - - ti->reloadImages = GL_TRUE; - fxMesa->new_state |= TDFX_NEW_TEXTURE; - - return GL_TRUE; + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + + return ( t && t->isInTM ); } -#if 0 +/* Convert a gl_color_table texture palette to Glide's format. + */ static void -PrintTexture(int w, int h, int c, const GLubyte * data) +tdfxConvertPalette( FxU32 data[256], const struct gl_color_table *table ) { - int i, j; - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - if (c == 2) - printf("%02x %02x ", data[0], data[1]); - else if (c == 3) - printf("%02x %02x %02x ", data[0], data[1], data[2]); - data += c; - } - printf("\n"); - } + const GLubyte *tableUB = (const GLubyte *) table->Table; + GLint width = table->Size; + FxU32 r, g, b, a; + GLint i; + + ASSERT( table->TableType == GL_UNSIGNED_BYTE ); + + switch ( table->Format ) { + case GL_RGBA: + for ( i = 0 ; i < width ; i++ ) { + r = tableUB[i * 4 + 0]; + g = tableUB[i * 4 + 1]; + b = tableUB[i * 4 + 2]; + a = tableUB[i * 4 + 3]; + data[i] = PACK_COLOR_8888( a, r, g, b ); + } + break; + case GL_RGB: + for ( i = 0 ; i < width ; i++ ) { + r = tableUB[i * 3 + 0]; + g = tableUB[i * 3 + 1]; + b = tableUB[i * 3 + 2]; + a = 255; + data[i] = PACK_COLOR_8888( a, r, g, b ); + } + break; + case GL_LUMINANCE: + for ( i = 0 ; i < width ; i++ ) { + r = tableUB[i]; + g = tableUB[i]; + b = tableUB[i]; + a = 255; + data[i] = PACK_COLOR_8888( a, r, g, b ); + } + break; + case GL_ALPHA: + for ( i = 0 ; i < width ; i++ ) { + r = g = b = 255; + a = tableUB[i]; + data[i] = PACK_COLOR_8888( a, r, g, b ); + } + break; + case GL_LUMINANCE_ALPHA: + for ( i = 0 ; i < width ; i++ ) { + r = g = b = tableUB[i * 2 + 0]; + a = tableUB[i * 2 + 1]; + data[i] = PACK_COLOR_8888( a, r, g, b ); + } + break; + case GL_INTENSITY: + for ( i = 0 ; i < width ; i++ ) { + r = tableUB[i]; + g = tableUB[i]; + b = tableUB[i]; + a = tableUB[i]; + data[i] = PACK_COLOR_8888( a, r, g, b ); + } + break; + } } -#endif - -GLboolean -tdfxDDTestProxyTexImage(GLcontext *ctx, GLenum target, - GLint level, GLint internalFormat, - GLenum format, GLenum type, - GLint width, GLint height, - GLint depth, GLint border) +static void +tdfxDDTexturePalette( GLcontext *ctx, struct gl_texture_object *tObj ) { - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - - switch (target) { - case GL_PROXY_TEXTURE_1D: - return GL_TRUE; /* software rendering */ - case GL_PROXY_TEXTURE_2D: - { - struct gl_texture_object *tObj; - tdfxTexInfo *ti; - int memNeeded; - - tObj = ctx->Texture.Proxy2D; - if (!tObj->DriverData) - tObj->DriverData = fxAllocTexObjData(fxMesa); - ti = TDFX_TEXTURE_DATA(tObj); - - /* assign the parameters to test against */ - tObj->Image[level]->Width = width; - tObj->Image[level]->Height = height; - tObj->Image[level]->Border = border; - tObj->Image[level]->IntFormat = internalFormat; - if (level == 0) { - /* don't use mipmap levels > 0 */ - tObj->MinFilter = tObj->MagFilter = GL_NEAREST; - } - else { - /* test with all mipmap levels */ - tObj->MinFilter = GL_LINEAR_MIPMAP_LINEAR; - tObj->MagFilter = GL_NEAREST; - } - RevalidateTexture(ctx, tObj); - - /* - printf("small lodlog2 0x%x\n", ti->info.smallLodLog2); - printf("large lodlog2 0x%x\n", ti->info.largeLodLog2); - printf("aspect ratio 0x%x\n", ti->info.aspectRatioLog2); - printf("glide format 0x%x\n", ti->info.format); - printf("data %p\n", ti->info.data); - printf("lodblend %d\n", (int) ti->LODblend); - */ - - /* determine where texture will reside */ - if (ti->LODblend && !shared->umaTexMemory) { - /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */ - memNeeded = FX_grTexTextureMemRequired_NoLock( - GR_MIPMAPLEVELMASK_BOTH, &(ti->info)); - } - else { - /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */ - memNeeded = FX_grTexTextureMemRequired_NoLock( - GR_MIPMAPLEVELMASK_BOTH, &(ti->info)); - } - /* - printf("Proxy test %d > %d\n", memNeeded, shared->totalTexMem[0]); - */ - if (memNeeded > shared->totalTexMem[0]) - return GL_FALSE; - else - return GL_TRUE; - } - case GL_PROXY_TEXTURE_3D: - return GL_TRUE; /* software rendering */ - default: - return GL_TRUE; /* never happens, silence compiler */ - } + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + tdfxTexObjPtr t; + + if ( tObj ) { + /* Per-texture palette */ + if ( !tObj->DriverData ) + tObj->DriverData = tdfxAllocTexObj(fxMesa); + + t = TDFX_TEXTURE_DATA(tObj); + tdfxConvertPalette( t->palette.data, &tObj->Palette ); + /*tdfxTexInvalidate( ctx, tObj );*/ + } else { + /* Global texture palette */ + tdfxConvertPalette( fxMesa->glbPalette.data, &ctx->Texture.Palette ); + } + + fxMesa->new_state |= TDFX_NEW_TEXTURE; /* XXX too heavy-handed */ } -/* - * Return a texture image to Mesa. This is either to satisfy - * a glGetTexImage() call or to prepare for software texturing. - */ -GLvoid * -tdfxDDGetTexImage(GLcontext * ctx, GLenum target, GLint level, - const struct gl_texture_object *texObj, - GLenum * formatOut, GLenum * typeOut, - GLboolean * freeImageOut) -{ - tdfxTexInfo *ti; - tdfxMipMapLevel *mml; - - if (target != GL_TEXTURE_2D) - return NULL; - - if (!texObj->DriverData) - return NULL; - - ti = TDFX_TEXTURE_DATA(texObj); - mml = &ti->mipmapLevel[level]; - if (mml->data) { - MesaIntTexFormat mesaFormat; - GLenum glFormat; - struct gl_texture_image *texImage = texObj->Image[level]; - GLint srcStride; - void *uncompressedImage = NULL; - - GLubyte *data = - (GLubyte *) MALLOC(texImage->Width * texImage->Height * 4); - if (!data) - return NULL; - - uncompressedImage = (void *)mml->data; - switch (mml->glideFormat) { - case GR_TEXFMT_INTENSITY_8: - mesaFormat = MESA_I8; - glFormat = GL_INTENSITY; - srcStride = mml->width; - break; - case GR_TEXFMT_ALPHA_INTENSITY_88: - mesaFormat = MESA_A8_L8; - glFormat = GL_LUMINANCE_ALPHA; - srcStride = mml->width; - break; - case GR_TEXFMT_ALPHA_8: - if (texImage->Format == GL_INTENSITY) { - mesaFormat = MESA_I8; - glFormat = GL_INTENSITY; - } - else { - mesaFormat = MESA_A8; - glFormat = GL_ALPHA; - } - srcStride = mml->width; - break; - case GR_TEXFMT_RGB_565: - mesaFormat = MESA_R5_G6_B5; - glFormat = GL_RGB; - srcStride = mml->width * 2; - break; - case GR_TEXFMT_ARGB_8888: - mesaFormat = MESA_A8_R8_G8_B8; - glFormat = GL_RGBA; - srcStride = mml->width * 4; - break; - case GR_TEXFMT_ARGB_4444: - mesaFormat = MESA_A4_R4_G4_B4; - glFormat = GL_RGBA; - srcStride = mml->width * 2; - break; - case GR_TEXFMT_ARGB_1555: - mesaFormat = MESA_A1_R5_G5_B5; - glFormat = GL_RGBA; - srcStride = mml->width * 2; - break; - case GR_TEXFMT_P_8: - mesaFormat = MESA_C8; - glFormat = GL_COLOR_INDEX; - srcStride = mml->width; - break; - case GR_TEXFMT_ARGB_CMP_FXT1: - mesaFormat = MESA_A8_R8_G8_B8; - glFormat = GL_RGBA; - srcStride = mml->width * 4; - /* - * Allocate data for the uncompressed image, - * decompress the image. The data will be deallocated - * after it is converted to the mesa format. - */ - uncompressedImage = MALLOC(mml->width * mml->height * 4); - if (!uncompressedImage) { - gl_problem(NULL, "can't get memory in tdfxDDGetTexImage"); - return NULL; - } - (*txImgDequantizeFXT1Proc)((FxU32 *)uncompressedImage, - (FxU32 *)mml->data, - mml->width, - mml->height); - break; - default: - gl_problem(NULL, "Bad glideFormat in tdfxDDGetTexImage"); - return NULL; - } - _mesa_unconvert_teximage(mesaFormat, mml->width, mml->height, - uncompressedImage, srcStride, texImage->Width, - texImage->Height, glFormat, data); - if (uncompressedImage != mml->data) { - FREE(uncompressedImage); - } - *formatOut = glFormat; - *typeOut = GL_UNSIGNED_BYTE; - *freeImageOut = GL_TRUE; - return data; - } - else { - return NULL; - } -} -/* - * This is called from _mesa_GetCompressedTexImage. We just - * copy out the compressed data. - */ -void -tdfxDDGetCompressedTexImage( GLcontext *ctx, GLenum target, - GLint lod, void *image, - const struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - tdfxTexInfo *ti; - tdfxMipMapLevel *mml; - if (target != GL_TEXTURE_2D) - return; +/**********************************************************************/ +/**** NEW TEXTURE IMAGE FUNCTIONS ****/ +/**********************************************************************/ - if (!texObj->DriverData) - return; - ti = TDFX_TEXTURE_DATA(texObj); - mml = &ti->mipmapLevel[lod]; - if (mml->data) { - MEMCPY(image, mml->data, mml->dataSize); - } -} -/* - * Calculate a specific texture format given a generic - * texture format. - */ -GLint -tdfxDDSpecificCompressedTexFormat(GLcontext *ctx, - GLint internalFormat, - GLint numDimensions) +#if 0 +static void +PrintTexture(int w, int h, int c, const GLubyte * data) { - if (numDimensions != 2) { - return internalFormat; - } - /* - * If we don't have pointers to the functions, then - * we drop back to uncompressed format. The logic - * in Mesa proper handles this for us. - * - * This is just to ease the transition to a Glide with - * the texus2 library. - */ - if (!txImgQuantizeProc || !txImgDequantizeFXT1Proc) { - return internalFormat; - } - switch (internalFormat) { - case GL_COMPRESSED_RGB_ARB: - return GL_COMPRESSED_RGB_FXT1_3DFX; - case GL_COMPRESSED_RGBA_ARB: - return GL_COMPRESSED_RGBA_FXT1_3DFX; - } - return internalFormat; + int i, j; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + if (c == 2) + printf("%02x %02x ", data[0], data[1]); + else if (c == 3) + printf("%02x %02x %02x ", data[0], data[1], data[2]); + data += c; + } + printf("\n"); + } } +#endif -/* - * Calculate a specific texture format given a generic - * texture format. - */ -GLint -tdfxDDBaseCompressedTexFormat(GLcontext *ctx, - GLint internalFormat) + +static GLboolean +tdfxDDTestProxyTexImage( GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLenum format, GLenum type, + GLint width, GLint height, + GLint depth, GLint border ) { - switch (internalFormat) { - case GL_COMPRESSED_RGB_FXT1_3DFX: - return GL_RGB; - case GL_COMPRESSED_RGBA_FXT1_3DFX: - return GL_RGBA; - } - return -1; + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; + + switch (target) { + case GL_PROXY_TEXTURE_1D: + return GL_TRUE; /* software rendering */ + case GL_PROXY_TEXTURE_2D: + { + struct gl_texture_object *tObj; + tdfxTexObjPtr t; + int memNeeded; + + tObj = ctx->Texture.Proxy2D; + if (!tObj->DriverData) + tObj->DriverData = tdfxAllocTexObj(fxMesa); + t = TDFX_TEXTURE_DATA(tObj); + + /* assign the parameters to test against */ + tObj->Image[level]->Width = width; + tObj->Image[level]->Height = height; + tObj->Image[level]->Border = border; + tObj->Image[level]->IntFormat = internalFormat; + if (level == 0) { + /* don't use mipmap levels > 0 */ + tObj->MinFilter = tObj->MagFilter = GL_NEAREST; + } + else { + /* test with all mipmap levels */ + tObj->MinFilter = GL_LINEAR_MIPMAP_LINEAR; + tObj->MagFilter = GL_NEAREST; + } + tdfxRevalidateTexture(ctx, tObj); + + /* + printf("small lodlog2 0x%x\n", t->info.smallLodLog2); + printf("large lodlog2 0x%x\n", t->info.largeLodLog2); + printf("aspect ratio 0x%x\n", t->info.aspectRatioLog2); + printf("glide format 0x%x\n", t->info.format); + printf("data %p\n", t->info.data); + printf("lodblend %d\n", (int) t->LODblend); + */ + + /* determine where texture will reside */ + if (t->LODblend && !tss->umaTexMemory) { + /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */ + memNeeded = FX_grTexTextureMemRequired_NoLock( + GR_MIPMAPLEVELMASK_BOTH, &(t->info)); + } + else { + /* XXX GR_MIPMAPLEVELMASK_BOTH might not be right, but works */ + memNeeded = FX_grTexTextureMemRequired_NoLock( + GR_MIPMAPLEVELMASK_BOTH, &(t->info)); + } + /* + printf("Proxy test %d > %d\n", memNeeded, tss->totalTexMem[0]); + */ + if (memNeeded > tss->totalTexMem[0]) + return GL_FALSE; + else + return GL_TRUE; + } + case GL_PROXY_TEXTURE_3D: + return GL_TRUE; /* software rendering */ + default: + return GL_TRUE; /* never happens, silence compiler */ + } } -/* - * Tell us if an image is compressed. The real work is done - * in a macro, but we need to have a function to create a - * function pointer. + +/* Return a texture image to Mesa. This is either to satisfy + * a glGetTexImage() call or to prepare for software texturing. */ -GLboolean -tdfxDDIsCompressedFormat(GLcontext *ctx, GLint internalFormat) +static GLvoid * +tdfxDDGetTexImage( GLcontext *ctx, GLenum target, GLint level, + const struct gl_texture_object *texObj, + GLenum *formatOut, GLenum *typeOut, + GLboolean *freeImageOut ) { - return tdfxDDIsCompressedFormatMacro(internalFormat); + const struct gl_texture_image *texImage = texObj->Image[level]; + const struct gl_texture_format *texFormat = texImage->TexFormat; + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(texObj); + tdfxTexImagePtr image; + GLubyte *data; + + if ( target != GL_TEXTURE_2D ) + return NULL; + if ( !t ) + return NULL; + + image = &t->image[level]; + if ( !image->original.data ) + return NULL; + + data = (GLubyte *) MALLOC( texImage->Width * texImage->Height * 4 ); + if ( !data ) + return NULL; + + _mesa_unconvert_teximage2d( texFormat->IntFormat, texImage->Format, + texImage->Width, texImage->Height, + image->original.data, data ); + + *formatOut = texImage->Format; + *typeOut = GL_UNSIGNED_BYTE; + *freeImageOut = GL_TRUE; + + return data; } -/* - * Calculate the image size of a compressed texture. - * - * The current compressed format, the FXT1 family, all - * map 8x32 texel blocks into 128 bits. - * - * We return 0 if we can't calculate the size. - * - * Glide would report this out to us, but we don't have - * exactly the right parameters. - */ -GLsizei -tdfxDDCompressedImageSize(GLcontext *ctx, - GLenum intFormat, - GLuint numDimensions, - GLuint width, - GLuint height, - GLuint depth) +void tdfxDDInitTextureFuncs( GLcontext *ctx ) { - if (numDimensions != 2) { - return 0; - } - switch (intFormat) { - case GL_COMPRESSED_RGB_FXT1_3DFX: - case GL_COMPRESSED_RGBA_FXT1_3DFX: - /* - * Round height and width to multiples of 4 and 8, - * divide the resulting product by 32 to get the number - * of blocks, and multiply by 32 = 128/8 to get the. - * number of bytes required. That is to say, just - * return the product. Remember that we are returning - * bytes, not texels, so we have shrunk the texture - * by a factor of the texel size. - */ - width = (width + 0x7) &~ 0x7; - height = (height + 0x3) &~ 0x3; - return width * height; - } - return 0; + ctx->Driver.TexImage2D = tdfxDDTexImage2D; + ctx->Driver.TexSubImage2D = tdfxDDTexSubImage2D; + ctx->Driver.GetTexImage = tdfxDDGetTexImage; + ctx->Driver.TexEnv = tdfxDDTexEnv; + ctx->Driver.TexParameter = tdfxDDTexParameter; + ctx->Driver.BindTexture = tdfxDDBindTexture; + ctx->Driver.DeleteTexture = tdfxDDDeleteTexture; + ctx->Driver.IsTextureResident = tdfxDDIsTextureResident; + ctx->Driver.UpdateTexturePalette = tdfxDDTexturePalette; } diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.h b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.h index 95ef3b018..1132f3f35 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.h +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.h @@ -35,123 +35,12 @@ * */ -#ifndef _TDFX_TEX_H_ -#define _TDFX_TEX_H_ +#ifndef __TDFX_TEX_H__ +#define __TDFX_TEX_H__ +extern void tdfxUpdateTextureState( GLcontext *ctx ); +extern void tdfxUpdateTextureBinding( GLcontext *ctx ); -#include "texutil.h" - - -#define tdfxDDIsCompressedFormatMacro(internalFormat) \ - (((internalFormat) == GL_COMPRESSED_RGB_FXT1_3DFX) || \ - ((internalFormat) == GL_COMPRESSED_RGBA_FXT1_3DFX)) -#define tdfxDDIsCompressedGlideFormatMacro(internalFormat) \ - ((internalFormat) == GR_TEXFMT_ARGB_CMP_FXT1) - - - -extern void -tdfxTexValidate(GLcontext * ctx, struct gl_texture_object *tObj); - -extern void -tdfxDDBindTexture(GLcontext * ctx, GLenum target, - struct gl_texture_object *tObj); - -extern void -tdfxDDDeleteTexture(GLcontext * ctx, struct gl_texture_object *tObj); - -extern GLboolean -tdfxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj); - -extern void -tdfxDDTexturePalette(GLcontext * ctx, struct gl_texture_object *tObj); - -#if 000 /* DEAD? */ -extern void -fxDDTexUseGlobalPalette(GLcontext * ctx, GLboolean state); -#endif - -extern void -tdfxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname, - const GLfloat * param); - -extern void -tdfxDDTexParameter(GLcontext * ctx, GLenum target, - struct gl_texture_object *tObj, - GLenum pname, const GLfloat * params); - -extern GLboolean -tdfxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level, - GLenum format, GLenum type, const GLvoid * pixels, - const struct gl_pixelstore_attrib * packing, - struct gl_texture_object * texObj, - struct gl_texture_image * texImage, - GLboolean * retainInternalCopy); - -extern GLboolean -tdfxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid * pixels, - const struct gl_pixelstore_attrib * packing, - struct gl_texture_object * texObj, - struct gl_texture_image * texImage); - -extern GLboolean -tdfxDDCompressedTexImage2D( GLcontext *ctx, GLenum target, - GLint level, GLsizei imageSize, - const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, - GLboolean *retainInternalCopy); - -extern GLboolean -tdfxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target, - GLint level, GLint xoffset, - GLint yoffset, GLsizei width, - GLint height, GLenum format, - GLsizei imageSize, const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ); - -extern GLboolean -tdfxDDTestProxyTexImage(GLcontext *ctx, GLenum target, - GLint level, GLint internalFormat, - GLenum format, GLenum type, - GLint width, GLint height, - GLint depth, GLint border); - -extern GLvoid * -tdfxDDGetTexImage(GLcontext * ctx, GLenum target, GLint level, - const struct gl_texture_object *texObj, - GLenum * formatOut, GLenum * typeOut, - GLboolean * freeImageOut); - -extern void -tdfxDDGetCompressedTexImage( GLcontext *ctx, GLenum target, - GLint lod, void *image, - const struct gl_texture_object *texObj, - struct gl_texture_image *texImage ); - -extern GLint -tdfxDDSpecificCompressedTexFormat(GLcontext *ctx, - GLint internalFormat, - GLint numDimensions); - -extern GLint -tdfxDDBaseCompressedTexFormat(GLcontext *ctx, - GLint internalFormat); - -extern GLboolean -tdfxDDIsCompressedFormat(GLcontext *ctx, GLint internalFormat); - -extern GLsizei -tdfxDDCompressedImageSize(GLcontext *ctx, - GLenum intFormat, - GLuint numDimensions, - GLuint width, - GLuint height, - GLuint depth); - +extern void tdfxDDInitTextureFuncs( GLcontext *ctx ); #endif diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.c index 97fe9d4c6..8ca93f91a 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.c @@ -39,930 +39,882 @@ #include "tdfx_tex.h" #include "tdfx_texman.h" +#define BAD_ADDRESS ((FxU32) -1) -#define BAD_ADDRESS ((FxU32) -1) - - -#if 0 /* DEBUG use */ -/* - * Verify the consistancy of the texture memory manager. +/* Verify the consistancy of the texture memory manager. * This involves: * Traversing all texture objects and computing total memory used. * Traverse the free block list and computing total memory free. * Compare the total free and total used amounts to the total memory size. * Make various assertions about the results. */ -static void -VerifyFreeList(tdfxContextPtr fxMesa, FxU32 tmu) +static void tdfxTMVerifyFreeList( tdfxContextPtr fxMesa, FxU32 unit ) { - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - tdfxMemRange *block; - int prevStart = -1, prevEnd = -1; - int totalFree = 0; - int numObj = 0, numRes = 0; - int totalUsed = 0; - - for (block = shared->tmFree[tmu]; block; block = block->next) { - assert( block->endAddr > 0 ); - assert( block->startAddr <= shared->totalTexMem[tmu] ); - assert( block->endAddr <= shared->totalTexMem[tmu] ); - assert( (int) block->startAddr > prevStart ); - assert( (int) block->startAddr >= prevEnd ); - prevStart = (int) block->startAddr; - prevEnd = (int) block->endAddr; - totalFree += (block->endAddr - block->startAddr); - } - assert(totalFree == shared->freeTexMem[tmu]); - - { - struct gl_texture_object *obj; - for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) { - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(obj); - numObj++; - if (ti) { - if (ti->isInTM) { - numRes++; - assert(ti->tm[0]); - if (ti->tm[tmu]) - totalUsed += (ti->tm[tmu]->endAddr - ti->tm[tmu]->startAddr); - } - else { - assert(!ti->tm[0]); - } - } - } - } - - printf("totalFree: %d totalUsed: %d totalMem: %d #objs=%d #res=%d\n", - shared->freeTexMem[tmu], totalUsed, shared->totalTexMem[tmu], - numObj, numRes); - - assert(totalUsed + totalFree == shared->totalTexMem[tmu]); -} + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + struct gl_texture_object *texObj; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; + tdfxMemRange *block; + int prevStart = -1, prevEnd = -1; + int totalFree = 0; + int numObj = 0, numRes = 0; + int totalUsed = 0; + + for ( block = tss->freeRanges[unit] ; block ; block = block->next ) { + assert( block->endAddr > 0 ); + assert( block->startAddr <= tss->totalTexMem[unit] ); + assert( block->endAddr <= tss->totalTexMem[unit] ); + assert( (int) block->startAddr > prevStart ); + assert( (int) block->startAddr >= prevEnd ); + prevStart = (int) block->startAddr; + prevEnd = (int) block->endAddr; + totalFree += (block->endAddr - block->startAddr); + } + assert( totalFree == tss->freeTexMem[unit] ); + + for ( texObj = ss->TexObjectList ; texObj ; texObj = texObj->Next ) { + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(texObj); + numObj++; + if ( t ) { + if ( t->isInTM ) { + numRes++; + assert( t->range[0] ); + if ( t->range[unit] ) + totalUsed += (t->range[unit]->endAddr - t->range[unit]->startAddr); + } else { + assert(!t->range[0]); + } + } + } + fprintf( stderr, + "totalFree: %d totalUsed: %d totalMem: %d #objs=%d #res=%d\n", + tss->freeTexMem[unit], totalUsed, tss->totalTexMem[unit], + numObj, numRes ); + + assert( totalUsed + totalFree == tss->totalTexMem[unit] ); +} -static void -dump_texmem(tdfxContextPtr fxMesa) +static void tdfxTMDumpTexMem( tdfxContextPtr fxMesa ) { - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - struct gl_texture_object *oldestObj, *obj, *lowestPriorityObj; - tdfxMemRange *r; - FxU32 prev; - - printf("DUMP Objects:\n"); - for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) { - tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj); - - if (info && info->isInTM) { - printf("Obj %8p: %4d info = %p\n", obj, obj->Name, info); - - printf(" isInTM=%d whichTMU=%d lastTimeUsed=%d\n", - info->isInTM, info->whichTMU, info->lastTimeUsed); - printf(" tm[0] = %p", info->tm[0]); - assert(info->tm[0]); - if (info->tm[0]) { - printf(" tm startAddr = %d endAddr = %d", - info->tm[0]->startAddr, - info->tm[0]->endAddr); - } - printf("\n"); - printf(" tm[1] = %p", info->tm[1]); - if (info->tm[1]) { - printf(" tm startAddr = %d endAddr = %d", - info->tm[1]->startAddr, - info->tm[1]->endAddr); - } - printf("\n"); - } - } - - VerifyFreeList(fxMesa, 0); - VerifyFreeList(fxMesa, 1); - - printf("Free memory unit 0: %d bytes\n", shared->freeTexMem[0]); - prev = 0; - for (r = shared->tmFree[0]; r; r = r->next) { - printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev); - prev = r->endAddr; - } - - printf("Free memory unit 1: %d bytes\n", shared->freeTexMem[1]); - prev = 0; - for (r = shared->tmFree[1]; r; r = r->next) { - printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev); - prev = r->endAddr; - } + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; + struct gl_texture_object *texObj; + tdfxMemRange *r; + FxU32 prev; + + printf( "DUMP Objects:\n" ); + for ( texObj = ss->TexObjectList ; texObj ; texObj = texObj->Next ) { + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(texObj); + + if ( t && t->isInTM ) { + printf( "Obj %8p: %4d info = %p\n", texObj, texObj->Name, t ); + + printf( " isInTM=%d whichTMU=%ld lastTimeUsed=%d\n", + t->isInTM, t->whichTMU, t->lastTimeUsed ); + printf( " tm[0] = %p", t->range[0] ); + assert( t->range[0] ); + if ( t->range[0] ) { + printf( " tm startAddr = %ld endAddr = %ld", + t->range[0]->startAddr, + t->range[0]->endAddr ); + } + printf( "\n" ); + printf( " tm[1] = %p", t->range[1] ); + if ( t->range[1] ) { + printf( " tm startAddr = %ld endAddr = %ld", + t->range[1]->startAddr, + t->range[1]->endAddr ); + } + printf( "\n" ); + } + } -} -#endif + tdfxTMVerifyFreeList( fxMesa, 0 ); + tdfxTMVerifyFreeList( fxMesa, 1 ); + + printf( "Free memory unit 0: %d bytes\n", tss->freeTexMem[0] ); + prev = 0; + for ( r = tss->freeRanges[0] ; r ; r = r->next ) { + printf( "%8p: start %8ld end %8ld size %8ld gap %8ld\n", + r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, + r->startAddr - prev ); + prev = r->endAddr; + } + printf( "Free memory unit 1: %d bytes\n", tss->freeTexMem[1] ); + prev = 0; + for ( r = tss->freeRanges[1] ; r ; r = r->next ) { + printf( "%8p: start %8ld end %8ld size %8ld gap %8ld\n", + r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, + r->startAddr - prev ); + prev = r->endAddr; + } +} #ifdef TEXSANITY -static void -fubar(void) +static void fubar( void ) { + /* GH: What am I meant to do??? */ } -/* - * Sanity Check +/* Sanity Check */ -static void -sanity(tdfxContextPtr fxMesa) +static void sanity( tdfxContextPtr fxMesa ) { - tdfxMemRange *tmp, *prev, *pos; - - prev = 0; - tmp = fxMesa->tmFree[0]; - while (tmp) { - if (!tmp->startAddr && !tmp->endAddr) { - fprintf(stderr, "Textures fubar\n"); - fubar(); - } - if (tmp->startAddr >= tmp->endAddr) { - fprintf(stderr, "Node fubar\n"); - fubar(); - } - if (prev && (prev->startAddr >= tmp->startAddr || - prev->endAddr > tmp->startAddr)) { - fprintf(stderr, "Sorting fubar\n"); - fubar(); - } - prev = tmp; - tmp = tmp->next; - } - prev = 0; - tmp = fxMesa->tmFree[1]; - while (tmp) { - if (!tmp->startAddr && !tmp->endAddr) { - fprintf(stderr, "Textures fubar\n"); - fubar(); - } - if (tmp->startAddr >= tmp->endAddr) { - fprintf(stderr, "Node fubar\n"); - fubar(); - } - if (prev && (prev->startAddr >= tmp->startAddr || - prev->endAddr > tmp->startAddr)) { - fprintf(stderr, "Sorting fubar\n"); - fubar(); - } - prev = tmp; - tmp = tmp->next; - } + tdfxMemRange *tmp, *prev, *pos; + + prev = 0; + tmp = fxMesa->freeRanges[0]; + while ( tmp ) { + if ( !tmp->startAddr && !tmp->endAddr ) { + fprintf( stderr, "Textures fubar\n" ); + fubar(); + } + if ( tmp->startAddr >= tmp->endAddr ) { + fprintf( stderr, "Node fubar\n" ); + fubar(); + } + if ( prev && ( prev->startAddr >= tmp->startAddr || + prev->endAddr > tmp->startAddr ) ) { + fprintf( stderr, "Sorting fubar\n" ); + fubar(); + } + prev = tmp; + tmp = tmp->next; + } + + prev = 0; + tmp = fxMesa->freeRanges[1]; + while ( tmp ) { + if ( !tmp->startAddr && !tmp->endAddr ) { + fprintf( stderr, "Textures fubar\n" ); + fubar(); + } + if ( tmp->startAddr >= tmp->endAddr ) { + fprintf( stderr, "Node fubar\n" ); + fubar(); + } + if ( prev && ( prev->startAddr >= tmp->startAddr || + prev->endAddr > tmp->startAddr ) ) { + fprintf( stderr, "Sorting fubar\n" ); + fubar(); + } + prev = tmp; + tmp = tmp->next; + } } #endif - - - -/* - * Allocate and initialize a new MemRange struct. - * Try to allocate it from the pool of free MemRange nodes rather than malloc. +/* Allocate and initialize a new MemRange struct. Try to allocate it + * from the pool of free MemRange nodes rather than malloc. */ static tdfxMemRange * -NewRangeNode(tdfxContextPtr fxMesa, FxU32 start, FxU32 end) +tdfxTMNewRangeNode( tdfxContextPtr fxMesa, FxU32 start, FxU32 end ) { - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - tdfxMemRange *result; - - _glthread_LOCK_MUTEX(mesaShared->Mutex); - if (shared && shared->tmPool) { - result = shared->tmPool; - shared->tmPool = shared->tmPool->next; - } - else { - result = MALLOC(sizeof(tdfxMemRange)); - - } - _glthread_UNLOCK_MUTEX(mesaShared->Mutex); - - if (!result) { - /*fprintf(stderr, "fxDriver: out of memory!\n");*/ - return NULL; - } - - result->startAddr = start; - result->endAddr = end; - result->next = NULL; - - return result; + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; + tdfxMemRange *range; + + _glthread_LOCK_MUTEX( ss->Mutex ); + if ( tss && tss->rangePool ) { + range = tss->rangePool; + tss->rangePool = tss->rangePool->next; + } else { + range = MALLOC( sizeof(tdfxMemRange) ); + } + _glthread_UNLOCK_MUTEX( ss->Mutex ); + + if ( !range ) { + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, __FUNCTION__ ": out of memory!\n" ); + return NULL; + } + + range->startAddr = start; + range->endAddr = end; + range->next = NULL; + + return range; } -/* - * Initialize texture memory. - * We take care of one or both TMU's here. +/* Initialize texture memory. We take care of one or both TMU's here. */ -void -tdfxTMInit(tdfxContextPtr fxMesa) +void tdfxTMInit( tdfxContextPtr fxMesa ) { - if (!fxMesa->glCtx->Shared->DriverData) { - const char *extensions; - struct tdfxSharedState *shared = CALLOC_STRUCT(tdfxSharedState); - if (!shared) - return; - - extensions = FX_grGetString(fxMesa, GR_EXTENSION); - if (strstr(extensions, "TEXUMA")) { - FxU32 start, end; - shared->umaTexMemory = GL_TRUE; - FX_grEnable(fxMesa, GR_TEXTURE_UMA_EXT); - start = FX_grTexMinAddress(fxMesa, 0); - end = FX_grTexMaxAddress(fxMesa, 0); - shared->totalTexMem[0] = end - start; - shared->totalTexMem[1] = 0; - shared->freeTexMem[0] = end - start; - shared->freeTexMem[1] = 0; - shared->tmFree[0] = NewRangeNode(fxMesa, start, end); - shared->tmFree[1] = NULL; - /*printf("UMA tex memory: %d\n", (int) (end - start));*/ - } - else { - const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1; - int tmu; - shared->umaTexMemory = GL_FALSE; - for (tmu = 0; tmu < numTMUs; tmu++) { - FxU32 start = FX_grTexMinAddress(fxMesa, tmu); - FxU32 end = FX_grTexMaxAddress(fxMesa, tmu); - shared->totalTexMem[tmu] = end - start; - shared->freeTexMem[tmu] = end - start; - shared->tmFree[tmu] = NewRangeNode(fxMesa, start, end); - /*printf("Split tex memory: %d\n", (int) (end - start));*/ - } - } - - shared->tmPool = NULL; - fxMesa->glCtx->Shared->DriverData = shared; - /*printf("Texture memory init UMA: %d\n", shared->umaTexMemory);*/ - } + GLcontext *ctx = fxMesa->glCtx; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, __FUNCTION__ "\n" ); + + if ( !ctx->Shared->DriverData ) { + const char *extensions; + tdfxSharedStatePtr tss = CALLOC_STRUCT( tdfx_shared_state ); + + if ( !tss ) + return; + + LOCK_HARDWARE( fxMesa ); + + extensions = grGetString( GR_EXTENSION ); + + if ( strstr( extensions, " TEXUMA " ) ) { + FxU32 start, end; + + tss->umaTexMemory = GL_TRUE; + + grEnable( GR_TEXTURE_UMA_EXT ); + + start = grTexMinAddress( 0 ); + end = grTexMaxAddress( 0 ); + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, " UMA tex memory: %d\n", (int)(end - start) ); + + tss->totalTexMem[0] = end - start; + tss->totalTexMem[1] = 0; + tss->freeTexMem[0] = end - start; + tss->freeTexMem[1] = 0; + tss->freeRanges[0] = tdfxTMNewRangeNode( fxMesa, start, end ); + tss->freeRanges[1] = NULL; + } else { + int unit; + + tss->umaTexMemory = GL_FALSE; + + for ( unit = 0 ; unit < fxMesa->numTMUs ; unit++ ) { + FxU32 start, end; + + start = grTexMinAddress( unit ); + end = grTexMaxAddress( unit ); + + tss->totalTexMem[unit] = end - start; + tss->freeTexMem[unit] = end - start; + tss->freeRanges[unit] = tdfxTMNewRangeNode( fxMesa, start, end ); + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, " Split tex memory: %d\n", + (int)(end - start) ); + } + } + + UNLOCK_HARDWARE( fxMesa ); + + tss->rangePool = NULL; + ctx->Shared->DriverData = tss; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, " init UMA: %d\n", tss->umaTexMemory ); + } } -/* - * Clean-up texture memory before destroying context. +/* Clean-up texture memory before destroying context. */ -void -tdfxTMClose(tdfxContextPtr fxMesa) +void tdfxTMClose( tdfxContextPtr fxMesa ) { - if (fxMesa->glCtx->Shared->RefCount == 1) { - /* refcount will soon go to zero, free our 3dfx stuff */ - struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData; - - const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1; - int tmu; - tdfxMemRange *tmp, *next; - - /* Deallocate the pool of free tdfxMemRange nodes */ - tmp = shared->tmPool; - while (tmp) { - next = tmp->next; - FREE(tmp); - tmp = next; - } - - /* Delete the texture memory block tdfxMemRange nodes */ - for (tmu = 0; tmu < numTMUs; tmu++) { - tmp = shared->tmFree[tmu]; - while (tmp) { - next = tmp->next; - FREE(tmp); - tmp = next; - } - } - - FREE(shared); - fxMesa->glCtx->Shared->DriverData = NULL; - } -} + GLcontext *ctx = fxMesa->glCtx; + if ( ctx->Shared->RefCount == 1 ) { + /* RefCount will soon go to zero, free our 3dfx stuff */ + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ctx->Shared->DriverData; + int unit; + tdfxMemRange *tmp, *next; + + /* Deallocate the pool of free tdfxMemRange nodes */ + tmp = tss->rangePool; + while ( tmp ) { + next = tmp->next; + FREE( tmp ); + tmp = next; + } + /* Delete the texture memory block tdfxMemRange nodes */ + for ( unit = 0 ; unit < fxMesa->numTMUs ; unit++ ) { + tmp = tss->freeRanges[unit]; + while ( tmp ) { + next = tmp->next; + FREE( tmp ); + tmp = next; + } + } -/* - * Delete a tdfxMemRange struct. - * We keep a linked list of free/available tdfxMemRange structs to - * avoid extra malloc/free calls. - */ -#if 0 -static void -DeleteRangeNode_NoLock(struct TdfxSharedState *shared, tdfxMemRange *range) -{ - /* insert at head of list */ - range->next = shared->tmPool; - shared->tmPool = range; + FREE( tss ); + ctx->Shared->DriverData = NULL; + } } -#endif -#define DELETE_RANGE_NODE(shared, range) \ - (range)->next = (shared)->tmPool; \ - (shared)->tmPool = (range) +/* Delete a tdfxMemRange struct. + * We keep a linked list of free/available tdfxMemRange structs to + * avoid extra malloc/free calls. + */ +#define DELETE_RANGE_NODE( tss, range ) \ +do { \ + (range)->next = (tss)->rangePool; \ + (tss)->rangePool = (range); \ +} while (0) -/* - * When we've run out of texture memory we have to throw out an +/* When we've run out of texture memory we have to throw out an * existing texture to make room for the new one. This function * determins the texture to throw out. */ static struct gl_texture_object * -FindOldestObject(tdfxContextPtr fxMesa, FxU32 tmu) +tdfxTMFindOldestObject( tdfxContextPtr fxMesa, FxU32 unit ) { - const GLuint bindnumber = fxMesa->texBindNumber; - struct gl_texture_object *oldestObj, *obj, *lowestPriorityObj; - GLfloat lowestPriority; - GLuint oldestAge; - - oldestObj = NULL; - oldestAge = 0; - - lowestPriority = 1.0F; - lowestPriorityObj = NULL; - - for (obj = fxMesa->glCtx->Shared->TexObjectList; obj; obj = obj->Next) { - tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj); - - if (info && info->isInTM && - ((info->whichTMU == tmu) || (info->whichTMU == TDFX_TMU_BOTH) || - (info->whichTMU == TDFX_TMU_SPLIT))) { - GLuint age, lasttime; - - assert(info->tm[0]); - lasttime = info->lastTimeUsed; - - if (lasttime > bindnumber) - age = bindnumber + (UINT_MAX - lasttime + 1); /* TO DO: check wrap around */ - else - age = bindnumber - lasttime; - - if (age >= oldestAge) { - oldestAge = age; - oldestObj = obj; - } - - /* examine priority */ - if (obj->Priority < lowestPriority) { - lowestPriority = obj->Priority; - lowestPriorityObj = obj; - } - } - } - - if (lowestPriority < 1.0) { - ASSERT(lowestPriorityObj); - /* - printf("discard %d pri=%f\n", lowestPriorityObj->Name, lowestPriority); - */ - return lowestPriorityObj; - } - else { - /* - printf("discard %d age=%d\n", oldestObj->Name, oldestAge); - */ - return oldestObj; - } -} + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + const GLuint bindNumber = fxMesa->texBindNumber; + struct gl_texture_object *oldestObj, *texObj, *lowestPriorityObj; + GLfloat lowestPriority; + GLuint oldestAge; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, __FUNCTION__ "\n" ); + + oldestObj = NULL; + oldestAge = 0; + + lowestPriority = 1.0F; + lowestPriorityObj = NULL; + + for ( texObj = ss->TexObjectList ; texObj ; texObj = texObj->Next ) { + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(texObj); + + if ( t && t->isInTM && + ( ( t->whichTMU == unit ) || + ( t->whichTMU == TDFX_TMU_BOTH ) || + ( t->whichTMU == TDFX_TMU_SPLIT ) ) ) { + GLuint age, lastTime; + + assert( t->range[0] ); + lastTime = t->lastTimeUsed; + + if ( lastTime > bindNumber ) { + /* TODO: check wrap around */ + age = bindNumber + (UINT_MAX - lastTime + 1); + } else { + age = bindNumber - lastTime; + } + if ( age >= oldestAge ) { + oldestAge = age; + oldestObj = texObj; + } + /* examine priority */ + if ( texObj->Priority < lowestPriority ) { + lowestPriority = texObj->Priority; + lowestPriorityObj = texObj; + } + } + } -#if 0 -static void -FlushTexMemory(tdfxContextPtr fxMesa) -{ - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - struct gl_texture_object *obj; - - for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) { - if (obj->RefCount < 2) { - /* don't flush currently bound textures */ - tdfxTMMoveOutTM_NoLock(fxMesa, obj); - } - } + if ( lowestPriority < 1.0 ) { + ASSERT( lowestPriorityObj ); + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, "discard %d pri=%f\n", + lowestPriorityObj->Name, lowestPriority ); + return lowestPriorityObj; + } else { + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) + fprintf( stderr, "discard %d age=%d\n", + oldestObj->Name, oldestAge ); + return oldestObj; + } } -#endif -/* - * Find the address (offset?) at which we can store a new texture. - * <tmu> is the texture unit. +/* Find the address (offset?) at which we can store a new texture. + * <unit> is the texture unit. * <size> is the texture size in bytes. */ -static FxU32 -FindStartAddr(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 size) +static FxU32 tdfxTMFindStartAddr( tdfxContextPtr fxMesa, + FxU32 unit, FxU32 size ) { - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - tdfxMemRange *prev, *block; - FxU32 result; -#if 0 - int discardedCount = 0; -#define MAX_DISCARDS 10 -#endif + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; + struct gl_texture_object *texObj; + tdfxMemRange *prev, *block; + FxU32 result; + + if ( tss->umaTexMemory ) { + assert( unit == TDFX_TMU0 ); + } - if (shared->umaTexMemory) { - assert(tmu == TDFX_TMU0); - } - - _glthread_LOCK_MUTEX(mesaShared->Mutex); - while (1) { - prev = NULL; - block = shared->tmFree[tmu]; - while (block) { - if (block->endAddr - block->startAddr >= size) { - /* The texture will fit here */ - result = block->startAddr; - block->startAddr += size; - if (block->startAddr == block->endAddr) { - /* Remove this node since it's empty */ - if (prev) { - prev->next = block->next; - } - else { - shared->tmFree[tmu] = block->next; - } - DELETE_RANGE_NODE(shared, block); - } - shared->freeTexMem[tmu] -= size; - _glthread_UNLOCK_MUTEX(mesaShared->Mutex); - return result; - } - prev = block; - block = block->next; - } - /* We failed to find a block large enough to accomodate <size> bytes. - * Find the oldest texObject and free it. - */ -#if 0 - discardedCount++; - if (discardedCount > MAX_DISCARDS + 1) { - gl_problem(NULL, "tdfx driver: extreme texmem fragmentation"); - _glthread_UNLOCK_MUTEX(mesaShared->Mutex); - return BAD_ADDRESS; - } - else if (discardedCount > MAX_DISCARDS) { - /* texture memory is probably really fragmented, flush it */ - FlushTexMemory(fxMesa); - } - else -#endif - { - struct gl_texture_object *obj = FindOldestObject(fxMesa, tmu); - if (obj) { - tdfxTMMoveOutTM_NoLock(fxMesa, obj); - fxMesa->stats.texSwaps++; - } - else { - gl_problem(NULL, "tdfx driver: extreme texmem fragmentation"); - _glthread_UNLOCK_MUTEX(mesaShared->Mutex); - return BAD_ADDRESS; - } - } - } - - /* never get here, but play it safe */ - _glthread_UNLOCK_MUTEX(mesaShared->Mutex); - return BAD_ADDRESS; + _glthread_LOCK_MUTEX( ss->Mutex ); + while ( 1 ) { + prev = NULL; + block = tss->freeRanges[unit]; + + while ( block ) { + if ( block->endAddr - block->startAddr >= size ) { + /* The texture will fit here */ + result = block->startAddr; + block->startAddr += size; + if ( block->startAddr == block->endAddr ) { + /* Remove this node since it's empty */ + if ( prev ) { + prev->next = block->next; + } else { + tss->freeRanges[unit] = block->next; + } + DELETE_RANGE_NODE( tss, block ); + } + tss->freeTexMem[unit] -= size; + _glthread_UNLOCK_MUTEX( ss->Mutex ); + return result; + } + prev = block; + block = block->next; + } + + /* We failed to find a block large enough to accomodate <size> bytes. + * Find the oldest texObject and free it. + */ + texObj = tdfxTMFindOldestObject( fxMesa, unit ); + if ( texObj ) { + tdfxTMMoveOutTMLocked( fxMesa, texObj ); + fxMesa->stats.texSwaps++; + } else { + gl_problem( NULL, "tdfx driver: extreme texmem fragmentation" ); + _glthread_UNLOCK_MUTEX( ss->Mutex ); + return BAD_ADDRESS; + } + } + + /* never get here, but play it safe */ + _glthread_UNLOCK_MUTEX( ss->Mutex ); + return BAD_ADDRESS; } -/* - * Remove the given tdfxMemRange node from hardware texture memory. +/* Remove the given tdfxMemRange node from hardware texture memory. */ -static void -RemoveRange_NoLock(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range) +static void tdfxTMRemoveRangeLocked( tdfxContextPtr fxMesa, + FxU32 unit, tdfxMemRange *range ) { - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - tdfxMemRange *block, *prev; - - if (shared->umaTexMemory) { - assert(tmu == TDFX_TMU0); - } - - if (!range) - return; - - if (range->startAddr == range->endAddr) { - DELETE_RANGE_NODE(shared, range); - return; - } - shared->freeTexMem[tmu] += range->endAddr - range->startAddr; - - /* find position in linked list to insert this tdfxMemRange node */ - prev = NULL; - block = shared->tmFree[tmu]; - while (block) { - assert(range->startAddr != block->startAddr); - if (range->startAddr > block->startAddr) { - prev = block; - block = block->next; - } - else { - break; - } - } - - /* Insert the free block, combine with adjacent blocks when possible */ - range->next = block; - if (block) { - if (range->endAddr == block->startAddr) { - /* Combine */ - block->startAddr = range->startAddr; - DELETE_RANGE_NODE(shared, range); - range = block; - } - } - if (prev) { - if (prev->endAddr == range->startAddr) { - /* Combine */ - prev->endAddr = range->endAddr; - prev->next = range->next; - DELETE_RANGE_NODE(shared, range); - } - else { - prev->next = range; - } - } - else { - shared->tmFree[tmu] = range; - } -} + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; + tdfxMemRange *block, *prev; + if ( tss->umaTexMemory ) { + assert( unit == TDFX_TMU0 ); + } -#if 0 /* NOT USED */ -static void -RemoveRange(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range) -{ - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - _glthread_LOCK_MUTEX(mesaShared->Mutex); - RemoveRange_NoLock(fxMesa, tmu, range); - _glthread_UNLOCK_MUTEX(mesaShared->Mutex); + if ( !range ) + return; + + if ( range->startAddr == range->endAddr ) { + DELETE_RANGE_NODE( tss, range ); + return; + } + tss->freeTexMem[unit] += range->endAddr - range->startAddr; + + /* find position in linked list to insert this tdfxMemRange node */ + prev = NULL; + block = tss->freeRanges[unit]; + while ( block ) { + assert( range->startAddr != block->startAddr ); + if ( range->startAddr > block->startAddr ) { + prev = block; + block = block->next; + } else { + break; + } + } + + /* Insert the free block, combine with adjacent blocks when possible */ + range->next = block; + if ( block ) { + if ( range->endAddr == block->startAddr ) { + /* Combine */ + block->startAddr = range->startAddr; + DELETE_RANGE_NODE( tss, range ); + range = block; + } + } + if ( prev ) { + if ( prev->endAddr == range->startAddr ) { + /* Combine */ + prev->endAddr = range->endAddr; + prev->next = range->next; + DELETE_RANGE_NODE( tss, range ); + } else { + prev->next = range; + } + } else { + tss->freeRanges[unit] = range; + } } -#endif -/* - * Allocate space for a texture image. +/* Allocate space for a texture image. * <tmu> is the texture unit * <texmemsize> is the number of bytes to allocate */ static tdfxMemRange * -AllocTexMem(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 texmemsize) +tdfxTMAllocTexMem( tdfxContextPtr fxMesa, FxU32 unit, FxU32 size ) { - FxU32 startAddr; - startAddr = FindStartAddr(fxMesa, tmu, texmemsize); - if (startAddr == BAD_ADDRESS) { - printf("AllocTexMem returned NULL! tmu=%d texmemsize=%d\n", - tmu, texmemsize); - return NULL; - } - else { - tdfxMemRange *range; - range = NewRangeNode(fxMesa, startAddr, startAddr + texmemsize); - return range; - } + tdfxMemRange *range = NULL; + FxU32 start; + + start = tdfxTMFindStartAddr( fxMesa, unit, size ); + + if ( start != BAD_ADDRESS ) { + range = tdfxTMNewRangeNode( fxMesa, start, start + size ); + } else { + fprintf( stderr, + "tdfxTMAllocTexMem returned NULL! unit=%ld size=%ld\n", + unit, size ); + } + return range; } -/* - * Download (copy) the given texture data (all mipmap levels) into the - * Voodoo's texture memory. - * The texture memory must have already been allocated. +/* Download (copy) the given texture data (all mipmap levels) into the + * Voodoo's texture memory. The texture memory must have already been + * allocated. */ -void -tdfxTMDownloadTexture(tdfxContextPtr fxMesa, struct gl_texture_object *tObj) +void tdfxTMDownloadTextureLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj ) { - tdfxTexInfo *ti; - GLint l; - FxU32 targetTMU; - - assert(tObj); - ti = TDFX_TEXTURE_DATA(tObj); - assert(ti); - targetTMU = ti->whichTMU; - - switch (targetTMU) { - case TDFX_TMU0: - case TDFX_TMU1: - if (ti->tm[targetTMU]) { - for (l = ti->minLevel; l <= ti->maxLevel - && ti->mipmapLevel[l].data; l++) { - GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel; - FX_grTexDownloadMipMapLevel_NoLock(targetTMU, - ti->tm[targetTMU]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_BOTH, - ti->mipmapLevel[l].data); - } - } - break; - case TDFX_TMU_SPLIT: - if (ti->tm[TDFX_TMU0] && ti->tm[TDFX_TMU1]) { - for (l = ti->minLevel; l <= ti->maxLevel - && ti->mipmapLevel[l].data; l++) { - GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel; - FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0, - ti->tm[TDFX_TMU0]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_ODD, - ti->mipmapLevel[l].data); - - FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1, - ti->tm[TDFX_TMU1]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_EVEN, - ti->mipmapLevel[l].data); - } - } - break; - case TDFX_TMU_BOTH: - if (ti->tm[TDFX_TMU0] && ti->tm[TDFX_TMU1]) { - for (l = ti->minLevel; l <= ti->maxLevel - && ti->mipmapLevel[l].data; l++) { - GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel; - FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0, - ti->tm[TDFX_TMU0]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_BOTH, - ti->mipmapLevel[l].data); - - FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1, - ti->tm[TDFX_TMU1]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_BOTH, - ti->mipmapLevel[l].data); - } - } - break; - default: - gl_problem(NULL, "error in tdfxTMDownloadTexture: bad tmu"); - return; - } + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + FxU32 targetTMU; + GLint l; + + assert( tObj ); + assert( t ); + + targetTMU = t->whichTMU; + + switch ( targetTMU ) { + case TDFX_TMU0: + case TDFX_TMU1: + if ( t->range[targetTMU] ) { + for ( l = t->minLevel ; l <= t->maxLevel && t->image[l].data ; l++ ) { + GrLOD_t glideLod = t->info.largeLodLog2 - l + tObj->BaseLevel; + + grTexDownloadMipMapLevel( targetTMU, + t->range[targetTMU]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_BOTH, + t->image[l].data ); + } + } + break; + + case TDFX_TMU_SPLIT: + if ( t->range[TDFX_TMU0] && t->range[TDFX_TMU1] ) { + for ( l = t->minLevel ; l <= t->maxLevel && t->image[l].data ; l++ ) { + GrLOD_t glideLod = t->info.largeLodLog2 - l + tObj->BaseLevel; + + grTexDownloadMipMapLevel( GR_TMU0, + t->range[TDFX_TMU0]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_ODD, + t->image[l].data ); + + grTexDownloadMipMapLevel( GR_TMU1, + t->range[TDFX_TMU1]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_EVEN, + t->image[l].data ); + } + } + break; + + case TDFX_TMU_BOTH: + if ( t->range[TDFX_TMU0] && t->range[TDFX_TMU1] ) { + for ( l = t->minLevel ; l <= t->maxLevel && t->image[l].data ; l++ ) { + GrLOD_t glideLod = t->info.largeLodLog2 - l + tObj->BaseLevel; + + grTexDownloadMipMapLevel( GR_TMU0, + t->range[TDFX_TMU0]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_BOTH, + t->image[l].data ); + + grTexDownloadMipMapLevel( GR_TMU1, + t->range[TDFX_TMU1]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_BOTH, + t->image[l].data ); + } + } + break; + + default: + gl_problem( NULL, "error in tdfxTMDownloadTexture: bad unit" ); + return; + } } -void -tdfxTMReloadMipMapLevel(GLcontext *ctx, struct gl_texture_object *tObj, - GLint level) +void tdfxTMReloadMipMapLevelLocked( GLcontext *ctx, + struct gl_texture_object *tObj, + GLint level ) { - tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); - GrLOD_t glideLod; - FxU32 tmu; - - tmu = ti->whichTMU; - glideLod = ti->info.largeLodLog2 - level + tObj->BaseLevel; - ASSERT(ti->isInTM); - - switch (tmu) { - case TDFX_TMU0: - case TDFX_TMU1: - FX_grTexDownloadMipMapLevel(fxMesa, tmu, - ti->tm[tmu]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_BOTH, - ti->mipmapLevel[level].data); - break; - case TDFX_TMU_SPLIT: - FX_grTexDownloadMipMapLevel(fxMesa, GR_TMU0, - ti->tm[GR_TMU0]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_ODD, - ti->mipmapLevel[level].data); - - FX_grTexDownloadMipMapLevel(fxMesa, GR_TMU1, - ti->tm[GR_TMU1]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_EVEN, - ti->mipmapLevel[level].data); - break; - case TDFX_TMU_BOTH: - FX_grTexDownloadMipMapLevel(fxMesa, GR_TMU0, - ti->tm[GR_TMU0]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_BOTH, - ti->mipmapLevel[level].data); - - FX_grTexDownloadMipMapLevel(fxMesa, GR_TMU1, - ti->tm[GR_TMU1]->startAddr, - glideLod, - ti->info.largeLodLog2, - ti->info.aspectRatioLog2, - ti->info.format, - GR_MIPMAPLEVELMASK_BOTH, - ti->mipmapLevel[level].data); - break; - - default: - gl_problem(ctx, "error in tdfxTMReloadMipMapLevel(): wrong tmu"); - break; - } + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + GrLOD_t glideLod; + FxU32 unit; + + ASSERT( t->isInTM ); + + unit = t->whichTMU; + glideLod = t->info.largeLodLog2 - level + tObj->BaseLevel; + + switch ( unit ) { + case TDFX_TMU0: + case TDFX_TMU1: + grTexDownloadMipMapLevel( unit, + t->range[unit]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_BOTH, + t->image[level].data ); + break; + + case TDFX_TMU_SPLIT: + grTexDownloadMipMapLevel( GR_TMU0, + t->range[GR_TMU0]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_ODD, + t->image[level].data ); + + grTexDownloadMipMapLevel( GR_TMU1, + t->range[GR_TMU1]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_EVEN, + t->image[level].data ); + break; + + case TDFX_TMU_BOTH: + grTexDownloadMipMapLevel( GR_TMU0, + t->range[GR_TMU0]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_BOTH, + t->image[level].data ); + + grTexDownloadMipMapLevel( GR_TMU1, + t->range[GR_TMU1]->startAddr, + glideLod, + t->info.largeLodLog2, + t->info.aspectRatioLog2, + t->info.format, + GR_MIPMAPLEVELMASK_BOTH, + t->image[level].data ); + break; + + default: + gl_problem( ctx, "error in tdfxTMReloadMipMapLevel(): wrong unit" ); + break; + } } -/* - * Allocate space for the given texture in texture memory then +/* Allocate space for the given texture in texture memory then * download (copy) it into that space. */ -void -tdfxTMMoveInTM_NoLock( tdfxContextPtr fxMesa, struct gl_texture_object *tObj, - FxU32 targetTMU ) +void tdfxTMMoveInTMLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj, FxU32 targetTMU ) { - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); - FxU32 texmemsize; - - fxMesa->stats.reqTexUpload++; - - if (ti->isInTM) { - if (ti->whichTMU == targetTMU) - return; - if (targetTMU == TDFX_TMU_SPLIT || ti->whichTMU == TDFX_TMU_SPLIT) { - tdfxTMMoveOutTM_NoLock(fxMesa, tObj); - } - else { - if (ti->whichTMU == TDFX_TMU_BOTH) - return; - targetTMU = TDFX_TMU_BOTH; - } - } - - ti->whichTMU = targetTMU; - - switch (targetTMU) { - case TDFX_TMU0: - case TDFX_TMU1: - texmemsize = FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH, - &(ti->info)); - ti->tm[targetTMU] = AllocTexMem(fxMesa, targetTMU, texmemsize); - break; - case TDFX_TMU_SPLIT: - texmemsize = FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_ODD, - &(ti->info)); - ti->tm[TDFX_TMU0] = AllocTexMem(fxMesa, TDFX_TMU0, texmemsize); - if (ti->tm[TDFX_TMU0]) - fxMesa->stats.memTexUpload += texmemsize; - - texmemsize = FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_EVEN, - &(ti->info)); - ti->tm[TDFX_TMU1] = AllocTexMem(fxMesa, TDFX_TMU1, texmemsize); - break; - case TDFX_TMU_BOTH: - texmemsize = FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH, - &(ti->info)); - ti->tm[TDFX_TMU0] = AllocTexMem(fxMesa, TDFX_TMU0, texmemsize); - if (ti->tm[TDFX_TMU0]) - fxMesa->stats.memTexUpload += texmemsize; - - texmemsize = FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH, - &(ti->info)); - ti->tm[TDFX_TMU1] = AllocTexMem(fxMesa, TDFX_TMU1, texmemsize); - break; - default: - gl_problem(NULL, "error in tdfxTMMoveInTM() -> bad tmu (%d)"); - return; - } - - ti->reloadImages = GL_TRUE; - ti->isInTM = GL_TRUE; - - fxMesa->stats.texUpload++; + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + FxU32 size; + + fxMesa->stats.reqTexUpload++; + + if ( t->isInTM ) { + if ( t->whichTMU == targetTMU ) + return; + + if ( targetTMU == TDFX_TMU_SPLIT || t->whichTMU == TDFX_TMU_SPLIT ) { + tdfxTMMoveOutTMLocked( fxMesa, tObj ); + } else { + if ( t->whichTMU == TDFX_TMU_BOTH ) + return; + targetTMU = TDFX_TMU_BOTH; + } + } + + t->whichTMU = targetTMU; + + switch ( targetTMU ) { + case TDFX_TMU0: + case TDFX_TMU1: + size = grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, &t->info ); + t->range[targetTMU] = tdfxTMAllocTexMem(fxMesa, targetTMU, size); + break; + + case TDFX_TMU_SPLIT: + size = grTexTextureMemRequired( GR_MIPMAPLEVELMASK_ODD, &t->info ); + t->range[TDFX_TMU0] = tdfxTMAllocTexMem( fxMesa, TDFX_TMU0, size ); + if ( t->range[TDFX_TMU0] ) + fxMesa->stats.memTexUpload += size; + + size = grTexTextureMemRequired( GR_MIPMAPLEVELMASK_EVEN, &t->info ); + t->range[TDFX_TMU1] = tdfxTMAllocTexMem( fxMesa, TDFX_TMU1, size ); + break; + + case TDFX_TMU_BOTH: + size = grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, &t->info ); + t->range[TDFX_TMU0] = tdfxTMAllocTexMem( fxMesa, TDFX_TMU0, size ); + if ( t->range[TDFX_TMU0] ) + fxMesa->stats.memTexUpload += size; + + size = grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, &t->info ); + t->range[TDFX_TMU1] = tdfxTMAllocTexMem( fxMesa, TDFX_TMU1, size ); + break; + + default: + gl_problem( NULL, "error in tdfxTMMoveInTM() -> bad unit (%d)" ); + return; + } + + t->reloadImages = GL_TRUE; + t->isInTM = GL_TRUE; + + fxMesa->stats.texUpload++; } -/* - * Move the given texture out of hardware texture memory. +/* Move the given texture out of hardware texture memory. * This deallocates the texture's memory space. */ -void -tdfxTMMoveOutTM_NoLock( tdfxContextPtr fxMesa, struct gl_texture_object *tObj ) +void tdfxTMMoveOutTMLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj ) { - struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); - - if (MESA_VERBOSE & VERBOSE_DRIVER) { - fprintf(stderr, "fxmesa: fxTMMoveOutTM(%p (%d))\n", tObj, tObj->Name); - } - - /* - VerifyFreeList(fxMesa, 0); - VerifyFreeList(fxMesa, 1); - */ - - if (!ti || !ti->isInTM) - return; - - switch (ti->whichTMU) { - case TDFX_TMU0: - case TDFX_TMU1: - RemoveRange_NoLock(fxMesa, ti->whichTMU, ti->tm[ti->whichTMU]); - break; - case TDFX_TMU_SPLIT: - case TDFX_TMU_BOTH: - assert(!shared->umaTexMemory); - RemoveRange_NoLock(fxMesa, TDFX_TMU0, ti->tm[TDFX_TMU0]); - RemoveRange_NoLock(fxMesa, TDFX_TMU1, ti->tm[TDFX_TMU1]); - break; - default: - gl_problem(NULL, "tdfx driver: bad tmu in tdfxTMMOveOutTM()"); - return; - } - - ti->isInTM = GL_FALSE; - ti->tm[0] = NULL; - ti->tm[1] = NULL; - ti->whichTMU = TDFX_TMU_NONE; - - /* - VerifyFreeList(fxMesa, 0); - VerifyFreeList(fxMesa, 1); - */ + struct gl_shared_state *ss = fxMesa->glCtx->Shared; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) { + fprintf( stderr, __FUNCTION__ "( %p (%d) )\n", tObj, tObj->Name ); + tdfxTMVerifyFreeList( fxMesa, 0 ); + tdfxTMVerifyFreeList( fxMesa, 1 ); + } + + if ( !t || !t->isInTM ) + return; + + switch ( t->whichTMU ) { + case TDFX_TMU0: + case TDFX_TMU1: + tdfxTMRemoveRangeLocked( fxMesa, t->whichTMU, t->range[t->whichTMU] ); + break; + + case TDFX_TMU_SPLIT: + case TDFX_TMU_BOTH: + assert( !tss->umaTexMemory ); + tdfxTMRemoveRangeLocked( fxMesa, TDFX_TMU0, t->range[TDFX_TMU0] ); + tdfxTMRemoveRangeLocked( fxMesa, TDFX_TMU1, t->range[TDFX_TMU1] ); + break; + + default: + gl_problem( NULL, "tdfx driver: bad unit in tdfxTMMOveOutTM()" ); + return; + } + + t->isInTM = GL_FALSE; + t->range[0] = NULL; + t->range[1] = NULL; + t->whichTMU = TDFX_TMU_NONE; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) { + tdfxTMVerifyFreeList( fxMesa, 0 ); + tdfxTMVerifyFreeList( fxMesa, 1 ); + } } -/* - * Called via glDeleteTexture to delete a texture object. - */ -void -tdfxTMFreeTexture(tdfxContextPtr fxMesa, struct gl_texture_object *tObj) +void tdfxTMFreeTextureLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj ) { - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); - if (ti) { - int i; - tdfxTMMoveOutTM(fxMesa, tObj); - for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { - if (ti->mipmapLevel[i].data) { - FREE(ti->mipmapLevel[i].data); - ti->mipmapLevel[i].data = NULL; - } - } - FREE(ti); - tObj->DriverData = NULL; - } - /* - VerifyFreeList(fxMesa, 0); - VerifyFreeList(fxMesa, 1); - */ -} + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); + + if ( t ) { + int i; + tdfxTMMoveOutTMLocked( fxMesa, tObj ); + for ( i = 0 ; i < MAX_TEXTURE_LEVELS ; i++ ) { + if ( t->image[i].original.data ) { + FREE( t->image[i].original.data ); + t->image[i].original.data = NULL; + t->image[i].original.width = 0; + t->image[i].original.height = 0; + t->image[i].original.size = 0; + } + if ( t->image[i].rescaled.data ) { + FREE( t->image[i].rescaled.data ); + t->image[i].rescaled.data = NULL; + t->image[i].rescaled.width = 0; + t->image[i].rescaled.height = 0; + t->image[i].rescaled.size = 0; + } + } + FREE( t ); + tObj->DriverData = NULL; + } + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) { + tdfxTMVerifyFreeList( fxMesa, 0 ); + tdfxTMVerifyFreeList( fxMesa, 1 ); + } +} -/* - * After a context switch this function will be called to restore +/* After a context switch this function will be called to restore * texture memory for the new context. */ -void tdfxTMRestoreTextures_NoLock( tdfxContextPtr fxMesa ) +void tdfxTMRestoreTexturesLocked( tdfxContextPtr fxMesa ) { GLcontext *ctx = fxMesa->glCtx; struct gl_texture_object *tObj; int i; for ( tObj = ctx->Shared->TexObjectList ; tObj ; tObj = tObj->Next ) { - tdfxTexInfo *ti = TDFX_TEXTURE_DATA( tObj ); - if ( ti && ti->isInTM ) { + tdfxTexObjPtr t = TDFX_TEXTURE_DATA( tObj ); + if ( t && t->isInTM ) { for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) { if ( ctx->Texture.Unit[i].Current == tObj ) { - tdfxTMDownloadTexture( fxMesa, tObj ); + tdfxTMDownloadTextureLocked( fxMesa, tObj ); break; } } if ( i == MAX_TEXTURE_UNITS ) { - tdfxTMMoveOutTM_NoLock( fxMesa, tObj ); + tdfxTMMoveOutTMLocked( fxMesa, tObj ); } } } - /* - VerifyFreeList(fxMesa, 0); - VerifyFreeList(fxMesa, 1); - */ + + if ( TDFX_DEBUG & DEBUG_VERBOSE_TEXTURE ) { + tdfxTMVerifyFreeList( fxMesa, 0 ); + tdfxTMVerifyFreeList( fxMesa, 1 ); + } } diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.h b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.h index 1965aaa84..6979367a0 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.h +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texman.h @@ -38,47 +38,39 @@ #ifndef __TDFX_TEXMAN_H__ #define __TDFX_TEXMAN_H__ - #include "tdfx_lock.h" - extern void tdfxTMInit( tdfxContextPtr fxMesa ); - extern void tdfxTMClose( tdfxContextPtr fxMesa ); -extern void tdfxTMDownloadTexture(tdfxContextPtr fxMesa, - struct gl_texture_object *tObj); - -extern void tdfxTMReloadMipMapLevel( GLcontext *ctx, - struct gl_texture_object *tObj, - GLint level ); - -extern void tdfxTMMoveInTM_NoLock( tdfxContextPtr fxMesa, - struct gl_texture_object *tObj, - FxU32 targetTMU ); - -extern void tdfxTMMoveOutTM_NoLock( tdfxContextPtr fxMesa, - struct gl_texture_object *tObj ); - -extern void tdfxTMFreeTexture( tdfxContextPtr fxMesa, - struct gl_texture_object *tObj ); - -extern void tdfxTMRestoreTextures_NoLock( tdfxContextPtr fxMesa ); - - -#define tdfxTMMoveInTM( fxMesa, tObj, targetTMU ) \ - do { \ - LOCK_HARDWARE( fxMesa ); \ - tdfxTMMoveInTM_NoLock( fxMesa, tObj, targetTMU ); \ - UNLOCK_HARDWARE( fxMesa ); \ - } while (0) - -#define tdfxTMMoveOutTM( fxMesa, tObj ) \ - do { \ - LOCK_HARDWARE( fxMesa ); \ - tdfxTMMoveOutTM_NoLock( fxMesa, tObj ); \ - UNLOCK_HARDWARE( fxMesa ); \ - } while (0) - +extern void tdfxTMDownloadTextureLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj ); +extern void tdfxTMReloadMipMapLevelLocked( GLcontext *ctx, + struct gl_texture_object *tObj, + GLint level ); +extern void tdfxTMMoveInTMLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj, + FxU32 targetTMU ); +extern void tdfxTMMoveOutTMLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj ); +extern void tdfxTMRestoreTexturesLocked( tdfxContextPtr fxMesa ); + +extern void tdfxTMFreeTextureLocked( tdfxContextPtr fxMesa, + struct gl_texture_object *tObj ); + + +#define tdfxTMMoveInTM( fxMesa, tObj, targetTMU ) \ +do { \ + LOCK_HARDWARE( fxMesa ); \ + tdfxTMMoveInTMLocked( fxMesa, tObj, targetTMU ); \ + UNLOCK_HARDWARE( fxMesa ); \ +} while (0) + +#define tdfxTMMoveOutTM( fxMesa, tObj ) \ +do { \ + LOCK_HARDWARE( fxMesa ); \ + tdfxTMMoveOutTMLocked( fxMesa, tObj ); \ + UNLOCK_HARDWARE( fxMesa ); \ +} while (0) #endif diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.c index 5493eea8a..368f051a3 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.c @@ -38,7 +38,6 @@ #include "tdfx_state.h" #include "tdfx_tex.h" #include "tdfx_texman.h" -#include "tdfx_texstate.h" /* ============================================================= @@ -1270,105 +1269,105 @@ SetupDoubleTexEnvVoodoo3(GLcontext *ctx, int tmu0, static void setupSingleTMU(tdfxContextPtr fxMesa, struct gl_texture_object *tObj) { - struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData; - tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); const GLcontext *ctx = fxMesa->glCtx; + tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ctx->Shared->DriverData; + tdfxTexObjPtr t = TDFX_TEXTURE_DATA(tObj); /* Make sure we're not loaded incorrectly */ - if (ti->isInTM && !shared->umaTexMemory) { + if (t->isInTM && !tss->umaTexMemory) { /* if doing filtering between mipmap levels, alternate mipmap levels * must be in alternate TMUs. */ - if (ti->LODblend) { - if (ti->whichTMU != TDFX_TMU_SPLIT) - tdfxTMMoveOutTM_NoLock(fxMesa, tObj); + if (t->LODblend) { + if (t->whichTMU != TDFX_TMU_SPLIT) + tdfxTMMoveOutTMLocked(fxMesa, tObj); } else { - if (ti->whichTMU == TDFX_TMU_SPLIT) - tdfxTMMoveOutTM_NoLock(fxMesa, tObj); + if (t->whichTMU == TDFX_TMU_SPLIT) + tdfxTMMoveOutTMLocked(fxMesa, tObj); } } /* Make sure we're loaded correctly */ - if (!ti->isInTM) { + if (!t->isInTM) { /* Have to download the texture */ - if (shared->umaTexMemory) { - tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0); + if (tss->umaTexMemory) { + tdfxTMMoveInTMLocked(fxMesa, tObj, TDFX_TMU0); } else { /* Voodoo3 (split texture memory) */ - if (ti->LODblend) { - tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU_SPLIT); + if (t->LODblend) { + tdfxTMMoveInTMLocked(fxMesa, tObj, TDFX_TMU_SPLIT); } else { #if 0 /* XXX putting textures into the second memory bank when the * first bank is full is not working at this time. */ - if (fxMesa->haveTwoTMUs) { - GLint memReq = FX_grTexTextureMemRequired_NoLock( - GR_MIPMAPLEVELMASK_BOTH, &(ti->info)); - if (shared->freeTexMem[TDFX_TMU0] > memReq) { - tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0); + if (fxMesa->numTMUs > 1) { + GLint memReq = + grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, &t->info ); + if (tss->freeTexMem[TDFX_TMU0] > memReq) { + tdfxTMMoveInTMLocked(fxMesa, tObj, TDFX_TMU0); } else { - tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU1); + tdfxTMMoveInTMLocked(fxMesa, tObj, TDFX_TMU1); } } else #endif { - tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0); + tdfxTMMoveInTMLocked( fxMesa, tObj, TDFX_TMU0 ); } } } } - if (ti->LODblend && ti->whichTMU == TDFX_TMU_SPLIT) { + if (t->LODblend && t->whichTMU == TDFX_TMU_SPLIT) { /* mipmap levels split between texture banks */ GLint u; - if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) { + if (t->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) { fxMesa->TexPalette.Type = GR_TEXTABLE_PALETTE_6666_EXT; - fxMesa->TexPalette.Data = &(ti->palette); + fxMesa->TexPalette.Data = &(t->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } for (u = 0; u < 2; u++) { - fxMesa->TexParams[u].sClamp = ti->sClamp; - fxMesa->TexParams[u].tClamp = ti->tClamp; - fxMesa->TexParams[u].minFilt = ti->minFilt; - fxMesa->TexParams[u].magFilt = ti->magFilt; - fxMesa->TexParams[u].mmMode = ti->mmMode; - fxMesa->TexParams[u].LODblend = ti->LODblend; + fxMesa->TexParams[u].sClamp = t->sClamp; + fxMesa->TexParams[u].tClamp = t->tClamp; + fxMesa->TexParams[u].minFilt = t->minFilt; + fxMesa->TexParams[u].magFilt = t->magFilt; + fxMesa->TexParams[u].mmMode = t->mmMode; + fxMesa->TexParams[u].LODblend = t->LODblend; fxMesa->TexParams[u].LodBias = ctx->Texture.Unit[u].LodBias; } fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; - fxMesa->TexSource[0].StartAddress = ti->tm[TDFX_TMU0]->startAddr; + fxMesa->TexSource[0].StartAddress = t->range[TDFX_TMU0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD; - fxMesa->TexSource[0].Info = &(ti->info); - fxMesa->TexSource[1].StartAddress = ti->tm[TDFX_TMU1]->startAddr; + fxMesa->TexSource[0].Info = &(t->info); + fxMesa->TexSource[1].StartAddress = t->range[TDFX_TMU1]->startAddr; fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN; - fxMesa->TexSource[1].Info = &(ti->info); + fxMesa->TexSource[1].Info = &(t->info); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; } else { FxU32 tmu; - if (ti->whichTMU == TDFX_TMU_BOTH) + if (t->whichTMU == TDFX_TMU_BOTH) tmu = TDFX_TMU0; else - tmu = ti->whichTMU; + tmu = t->whichTMU; - if (shared->umaTexMemory) { - assert(ti->whichTMU == TDFX_TMU0); + if (tss->umaTexMemory) { + assert(t->whichTMU == TDFX_TMU0); assert(tmu == TDFX_TMU0); } - if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) { + if (t->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) { fxMesa->TexPalette.Type = GR_TEXTABLE_PALETTE_6666_EXT; - fxMesa->TexPalette.Data = &(ti->palette); + fxMesa->TexPalette.Data = &(t->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } @@ -1377,18 +1376,18 @@ setupSingleTMU(tdfxContextPtr fxMesa, struct gl_texture_object *tObj) * texture memory, so perhaps it's not a good idea. */ - if (fxMesa->TexParams[tmu].sClamp != ti->sClamp || - fxMesa->TexParams[tmu].tClamp != ti->tClamp || - fxMesa->TexParams[tmu].minFilt != ti->minFilt || - fxMesa->TexParams[tmu].magFilt != ti->magFilt || - fxMesa->TexParams[tmu].mmMode != ti->mmMode || + if (fxMesa->TexParams[tmu].sClamp != t->sClamp || + fxMesa->TexParams[tmu].tClamp != t->tClamp || + fxMesa->TexParams[tmu].minFilt != t->minFilt || + fxMesa->TexParams[tmu].magFilt != t->magFilt || + fxMesa->TexParams[tmu].mmMode != t->mmMode || fxMesa->TexParams[tmu].LODblend != FXFALSE || fxMesa->TexParams[tmu].LodBias != ctx->Texture.Unit[tmu].LodBias) { - fxMesa->TexParams[tmu].sClamp = ti->sClamp; - fxMesa->TexParams[tmu].tClamp = ti->tClamp; - fxMesa->TexParams[tmu].minFilt = ti->minFilt; - fxMesa->TexParams[tmu].magFilt = ti->magFilt; - fxMesa->TexParams[tmu].mmMode = ti->mmMode; + fxMesa->TexParams[tmu].sClamp = t->sClamp; + fxMesa->TexParams[tmu].tClamp = t->tClamp; + fxMesa->TexParams[tmu].minFilt = t->minFilt; + fxMesa->TexParams[tmu].magFilt = t->magFilt; + fxMesa->TexParams[tmu].mmMode = t->mmMode; fxMesa->TexParams[tmu].LODblend = FXFALSE; fxMesa->TexParams[tmu].LodBias = ctx->Texture.Unit[tmu].LodBias; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; @@ -1397,16 +1396,16 @@ setupSingleTMU(tdfxContextPtr fxMesa, struct gl_texture_object *tObj) /* Glide texture source info */ fxMesa->TexSource[0].Info = NULL; fxMesa->TexSource[1].Info = NULL; - if (ti->tm[tmu]) { - fxMesa->TexSource[tmu].StartAddress = ti->tm[tmu]->startAddr; + if (t->range[tmu]) { + fxMesa->TexSource[tmu].StartAddress = t->range[tmu]->startAddr; fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu].Info = &(ti->info); + fxMesa->TexSource[tmu].Info = &(t->info); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; } } - fxMesa->sScale0 = ti->sScale; - fxMesa->tScale0 = ti->tScale; + fxMesa->sScale0 = t->sScale; + fxMesa->tScale0 = t->tScale; } static void @@ -1420,12 +1419,12 @@ selectSingleTMUSrc(tdfxContextPtr fxMesa, GLint tmu, FxBool LODblend) fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; - if (fxMesa->haveTwoTMUs) { - const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; + if ( fxMesa->numTMUs > 1 ) { + const struct gl_shared_state *ss = fxMesa->glCtx->Shared; + const tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; int tmu; - if (shared->umaTexMemory) + if (tss->umaTexMemory) tmu = GR_TMU0; else tmu = GR_TMU1; @@ -1447,7 +1446,7 @@ selectSingleTMUSrc(tdfxContextPtr fxMesa, GLint tmu, FxBool LODblend) fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; - if (fxMesa->haveTwoTMUs) { + if ( fxMesa->numTMUs > 1 ) { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO; @@ -1511,7 +1510,7 @@ static void print_state(tdfxContextPtr fxMesa) static void setupTextureSingleTMU(GLcontext * ctx, GLuint unit) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - tdfxTexInfo *ti; + tdfxTexObjPtr t; struct gl_texture_object *tObj; int tmu; GLenum envMode, baseFormat; @@ -1530,17 +1529,17 @@ static void setupTextureSingleTMU(GLcontext * ctx, GLuint unit) setupSingleTMU(fxMesa, tObj); - ti = TDFX_TEXTURE_DATA(tObj); - if (ti->whichTMU == TDFX_TMU_BOTH) + t = TDFX_TEXTURE_DATA(tObj); + if (t->whichTMU == TDFX_TMU_BOTH) tmu = TDFX_TMU0; else - tmu = ti->whichTMU; + tmu = t->whichTMU; if (fxMesa->tmuSrc != tmu) { - selectSingleTMUSrc(fxMesa, tmu, ti->LODblend); + selectSingleTMUSrc(fxMesa, tmu, t->LODblend); } - if (ti->reloadImages) + if (t->reloadImages) fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES; /* Some texture environments not supported */ @@ -1627,35 +1626,35 @@ setupDoubleTMU(tdfxContextPtr fxMesa, #define T0_IN_TMU1 0x10 #define T1_IN_TMU1 0x20 - const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; + const struct gl_shared_state *ss = fxMesa->glCtx->Shared; + const tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; const GLcontext *ctx = fxMesa->glCtx; - tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0); - tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1); + tdfxTexObjPtr t0 = TDFX_TEXTURE_DATA(tObj0); + tdfxTexObjPtr t1 = TDFX_TEXTURE_DATA(tObj1); GLuint tstate = 0; int tmu0 = 0, tmu1 = 1; - if (shared->umaTexMemory) { - if (!ti0->isInTM) { - tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0); - assert(ti0->isInTM); + if (tss->umaTexMemory) { + if (!t0->isInTM) { + tdfxTMMoveInTMLocked(fxMesa, tObj0, TDFX_TMU0); + assert(t0->isInTM); } - if (!ti1->isInTM) { - tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0); - assert(ti1->isInTM); + if (!t1->isInTM) { + tdfxTMMoveInTMLocked(fxMesa, tObj1, TDFX_TMU0); + assert(t1->isInTM); } } else { /* We shouldn't need to do this. There is something wrong with multitexturing when the TMUs are swapped. So, we're forcing them to always be loaded correctly. !!! */ - if (ti0->whichTMU == TDFX_TMU1) - tdfxTMMoveOutTM_NoLock(fxMesa, tObj0); - if (ti1->whichTMU == TDFX_TMU0) - tdfxTMMoveOutTM_NoLock(fxMesa, tObj1); + if (t0->whichTMU == TDFX_TMU1) + tdfxTMMoveOutTMLocked(fxMesa, tObj0); + if (t1->whichTMU == TDFX_TMU0) + tdfxTMMoveOutTMLocked(fxMesa, tObj1); - if (ti0->isInTM) { - switch (ti0->whichTMU) { + if (t0->isInTM) { + switch (t0->whichTMU) { case TDFX_TMU0: tstate |= T0_IN_TMU0; break; @@ -1673,8 +1672,8 @@ setupDoubleTMU(tdfxContextPtr fxMesa, else tstate |= T0_NOT_IN_TMU; - if (ti1->isInTM) { - switch (ti1->whichTMU) { + if (t1->isInTM) { + switch (t1->whichTMU) { case TDFX_TMU0: tstate |= T1_IN_TMU0; break; @@ -1697,7 +1696,7 @@ setupDoubleTMU(tdfxContextPtr fxMesa, if (!(((tstate & T0_IN_TMU0) && (tstate & T1_IN_TMU1)) || ((tstate & T0_IN_TMU1) && (tstate & T1_IN_TMU0)))) { if (tObj0 == tObj1) { - tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU_BOTH); + tdfxTMMoveInTMLocked(fxMesa, tObj1, TDFX_TMU_BOTH); } else { /* Find the minimal way to correct the situation */ @@ -1705,10 +1704,10 @@ setupDoubleTMU(tdfxContextPtr fxMesa, /* We have one in the standard order, setup the other */ if (tstate & T0_IN_TMU0) { /* T0 is in TMU0, put T1 in TMU1 */ - tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1); + tdfxTMMoveInTMLocked(fxMesa, tObj1, TDFX_TMU1); } else { - tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0); + tdfxTMMoveInTMLocked(fxMesa, tObj0, TDFX_TMU0); } /* tmu0 and tmu1 are setup */ } @@ -1716,36 +1715,36 @@ setupDoubleTMU(tdfxContextPtr fxMesa, /* we have one in the reverse order, setup the other */ if (tstate & T1_IN_TMU0) { /* T1 is in TMU0, put T0 in TMU1 */ - tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU1); + tdfxTMMoveInTMLocked(fxMesa, tObj0, TDFX_TMU1); } else { - tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0); + tdfxTMMoveInTMLocked(fxMesa, tObj1, TDFX_TMU0); } tmu0 = 1; tmu1 = 0; } else { /* Nothing is loaded */ - tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0); - tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1); + tdfxTMMoveInTMLocked(fxMesa, tObj0, TDFX_TMU0); + tdfxTMMoveInTMLocked(fxMesa, tObj1, TDFX_TMU1); /* tmu0 and tmu1 are setup */ } } } } - ti0->lastTimeUsed = fxMesa->texBindNumber; - ti1->lastTimeUsed = fxMesa->texBindNumber; + t0->lastTimeUsed = fxMesa->texBindNumber; + t1->lastTimeUsed = fxMesa->texBindNumber; if (!ctx->Texture.SharedPalette) { - if (ti0->info.format == GR_TEXFMT_P_8) { + if (t0->info.format == GR_TEXFMT_P_8) { fxMesa->TexPalette.Type = GR_TEXTABLE_PALETTE_6666_EXT; - fxMesa->TexPalette.Data = &(ti0->palette); + fxMesa->TexPalette.Data = &(t0->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } - else if (ti1->info.format == GR_TEXFMT_P_8) { + else if (t1->info.format == GR_TEXFMT_P_8) { fxMesa->TexPalette.Type = GR_TEXTABLE_PALETTE_6666_EXT; - fxMesa->TexPalette.Data = &(ti1->palette); + fxMesa->TexPalette.Data = &(t1->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } else { @@ -1756,25 +1755,25 @@ setupDoubleTMU(tdfxContextPtr fxMesa, /* * Setup Unit 0 */ - assert(ti0->isInTM); - assert(ti0->tm[tmu0]); - fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr; + assert(t0->isInTM); + assert(t0->range[tmu0]); + fxMesa->TexSource[tmu0].StartAddress = t0->range[tmu0]->startAddr; fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu0].Info = &(ti0->info); + fxMesa->TexSource[tmu0].Info = &(t0->info); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; - if (fxMesa->TexParams[tmu0].sClamp != ti0->sClamp || - fxMesa->TexParams[tmu0].tClamp != ti0->tClamp || - fxMesa->TexParams[tmu0].minFilt != ti0->minFilt || - fxMesa->TexParams[tmu0].magFilt != ti0->magFilt || - fxMesa->TexParams[tmu0].mmMode != ti0->mmMode || + if (fxMesa->TexParams[tmu0].sClamp != t0->sClamp || + fxMesa->TexParams[tmu0].tClamp != t0->tClamp || + fxMesa->TexParams[tmu0].minFilt != t0->minFilt || + fxMesa->TexParams[tmu0].magFilt != t0->magFilt || + fxMesa->TexParams[tmu0].mmMode != t0->mmMode || fxMesa->TexParams[tmu0].LODblend != FXFALSE || fxMesa->TexParams[tmu0].LodBias != ctx->Texture.Unit[tmu0].LodBias) { - fxMesa->TexParams[tmu0].sClamp = ti0->sClamp; - fxMesa->TexParams[tmu0].tClamp = ti0->tClamp; - fxMesa->TexParams[tmu0].minFilt = ti0->minFilt; - fxMesa->TexParams[tmu0].magFilt = ti0->magFilt; - fxMesa->TexParams[tmu0].mmMode = ti0->mmMode; + fxMesa->TexParams[tmu0].sClamp = t0->sClamp; + fxMesa->TexParams[tmu0].tClamp = t0->tClamp; + fxMesa->TexParams[tmu0].minFilt = t0->minFilt; + fxMesa->TexParams[tmu0].magFilt = t0->magFilt; + fxMesa->TexParams[tmu0].mmMode = t0->mmMode; fxMesa->TexParams[tmu0].LODblend = FXFALSE; fxMesa->TexParams[tmu0].LodBias = ctx->Texture.Unit[tmu0].LodBias; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; @@ -1783,42 +1782,42 @@ setupDoubleTMU(tdfxContextPtr fxMesa, /* * Setup Unit 1 */ - if (shared->umaTexMemory) { - ASSERT(ti1->isInTM); - ASSERT(ti1->tm[0]); - fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr; + if (tss->umaTexMemory) { + ASSERT(t1->isInTM); + ASSERT(t1->range[0]); + fxMesa->TexSource[tmu1].StartAddress = t1->range[0]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu1].Info = &(ti1->info); + fxMesa->TexSource[tmu1].Info = &(t1->info); } else { - ASSERT(ti1->isInTM); - ASSERT(ti1->tm[tmu1]); - fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr; + ASSERT(t1->isInTM); + ASSERT(t1->range[tmu1]); + fxMesa->TexSource[tmu1].StartAddress = t1->range[tmu1]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu1].Info = &(ti1->info); + fxMesa->TexSource[tmu1].Info = &(t1->info); } - if (fxMesa->TexParams[tmu1].sClamp != ti1->sClamp || - fxMesa->TexParams[tmu1].tClamp != ti1->tClamp || - fxMesa->TexParams[tmu1].minFilt != ti1->minFilt || - fxMesa->TexParams[tmu1].magFilt != ti1->magFilt || - fxMesa->TexParams[tmu1].mmMode != ti1->mmMode || + if (fxMesa->TexParams[tmu1].sClamp != t1->sClamp || + fxMesa->TexParams[tmu1].tClamp != t1->tClamp || + fxMesa->TexParams[tmu1].minFilt != t1->minFilt || + fxMesa->TexParams[tmu1].magFilt != t1->magFilt || + fxMesa->TexParams[tmu1].mmMode != t1->mmMode || fxMesa->TexParams[tmu1].LODblend != FXFALSE || fxMesa->TexParams[tmu1].LodBias != ctx->Texture.Unit[tmu1].LodBias) { - fxMesa->TexParams[tmu1].sClamp = ti1->sClamp; - fxMesa->TexParams[tmu1].tClamp = ti1->tClamp; - fxMesa->TexParams[tmu1].minFilt = ti1->minFilt; - fxMesa->TexParams[tmu1].magFilt = ti1->magFilt; - fxMesa->TexParams[tmu1].mmMode = ti1->mmMode; + fxMesa->TexParams[tmu1].sClamp = t1->sClamp; + fxMesa->TexParams[tmu1].tClamp = t1->tClamp; + fxMesa->TexParams[tmu1].minFilt = t1->minFilt; + fxMesa->TexParams[tmu1].magFilt = t1->magFilt; + fxMesa->TexParams[tmu1].mmMode = t1->mmMode; fxMesa->TexParams[tmu1].LODblend = FXFALSE; fxMesa->TexParams[tmu1].LodBias = ctx->Texture.Unit[tmu1].LodBias; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; } - fxMesa->sScale0 = ti0->sScale; - fxMesa->tScale0 = ti0->tScale; - fxMesa->sScale1 = ti1->sScale; - fxMesa->tScale1 = ti1->tScale; + fxMesa->sScale0 = t0->sScale; + fxMesa->tScale0 = t0->tScale; + fxMesa->sScale1 = t1->sScale; + fxMesa->tScale1 = t1->tScale; #undef T0_NOT_IN_TMU #undef T1_NOT_IN_TMU @@ -1833,8 +1832,8 @@ static void setupTextureDoubleTMU(GLcontext * ctx) tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); struct gl_texture_object *tObj0 = ctx->Texture.Unit[0].CurrentD[2]; struct gl_texture_object *tObj1 = ctx->Texture.Unit[1].CurrentD[2]; - tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0); - tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1); + tdfxTexObjPtr t0 = TDFX_TEXTURE_DATA(tObj0); + tdfxTexObjPtr t1 = TDFX_TEXTURE_DATA(tObj1); struct gl_texture_image *baseImage0 = tObj0->Image[tObj0->BaseLevel]; struct gl_texture_image *baseImage1 = tObj1->Image[tObj1->BaseLevel]; const GLenum envMode0 = ctx->Texture.Unit[0].EnvMode; @@ -1847,7 +1846,7 @@ static void setupTextureDoubleTMU(GLcontext * ctx) setupDoubleTMU(fxMesa, tObj0, tObj1); - if (ti0->reloadImages || ti1->reloadImages) + if (t0->reloadImages || t1->reloadImages) fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES; fxMesa->tmuSrc = TDFX_TMU_BOTH; @@ -1893,7 +1892,7 @@ static void setupTextureDoubleTMU(GLcontext * ctx) } else { int unit0, unit1; - if ((ti0->whichTMU == TDFX_TMU1) || (ti1->whichTMU == TDFX_TMU0)) + if ((t0->whichTMU == TDFX_TMU1) || (t1->whichTMU == TDFX_TMU0)) unit0 = 1; else unit0 = 0; @@ -1924,34 +1923,34 @@ static void setupTextureDoubleTMU(GLcontext * ctx) } -void -tdfxUpdateTextureState( GLcontext *ctx ) +void tdfxUpdateTextureState( GLcontext *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); - GLuint tex2Denabled = ctx->Texture.ReallyEnabled; + GLuint enabled = ctx->Texture.ReallyEnabled; - if (!fxMesa->haveTwoTMUs) - tex2Denabled &= TEXTURE0_2D; + if ( fxMesa->numTMUs == 1 ) + enabled &= TEXTURE0_2D; - switch (tex2Denabled) { + switch ( enabled ) { case TEXTURE0_2D: LOCK_HARDWARE( fxMesa ); /* XXX remove locking eventually */ - setupTextureSingleTMU(ctx, 0); + setupTextureSingleTMU( ctx, 0 ); UNLOCK_HARDWARE( fxMesa ); break; case TEXTURE1_2D: LOCK_HARDWARE( fxMesa ); - setupTextureSingleTMU(ctx, 1); + setupTextureSingleTMU( ctx, 1 ); UNLOCK_HARDWARE( fxMesa ); break; - case (TEXTURE0_2D | TEXTURE1_2D): + case TEXTURE0_2D | TEXTURE1_2D: LOCK_HARDWARE( fxMesa ); - setupTextureDoubleTMU(ctx); + setupTextureDoubleTMU( ctx ); UNLOCK_HARDWARE( fxMesa ); break; + default: - /* disable hardware texturing */ - if (TDFX_IS_NAPALM(fxMesa)) { + /* Disable hardware texturing */ + if ( TDFX_IS_NAPALM( fxMesa ) ) { fxMesa->ColorCombineExt.SourceA = GR_CMBX_ITRGB; fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X; fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO; @@ -1972,9 +1971,8 @@ tdfxUpdateTextureState( GLcontext *ctx ) fxMesa->AlphaCombineExt.InvertD = FXFALSE; fxMesa->AlphaCombineExt.Shift = 0; fxMesa->AlphaCombineExt.Invert = FXFALSE; - } - else { - /* Voodoo 3*/ + } else { + /* Voodoo 3 */ fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE; fxMesa->ColorCombine.Local = GR_COMBINE_LOCAL_ITERATED; @@ -1997,106 +1995,103 @@ tdfxUpdateTextureState( GLcontext *ctx ) } - -/* - * This is a special case of texture state update. +/* This is a special case of texture state update. * It's used when we've simply bound a new texture to a texture * unit and the new texture has the exact same attributes as the * previously bound texture. * This is very common in Quake3. */ -void -tdfxUpdateTextureBinding( GLcontext *ctx ) +void tdfxUpdateTextureBinding( GLcontext *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + const struct gl_shared_state *ss = fxMesa->glCtx->Shared; + const tdfxSharedStatePtr tss = (tdfxSharedStatePtr)ss->DriverData; struct gl_texture_object *tObj0 = ctx->Texture.Unit[0].CurrentD[2]; struct gl_texture_object *tObj1 = ctx->Texture.Unit[1].CurrentD[2]; - tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0); - tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1); - - const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; - const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; + tdfxTexObjPtr t0 = TDFX_TEXTURE_DATA(tObj0); + tdfxTexObjPtr t1 = TDFX_TEXTURE_DATA(tObj1); - if (ti0) { - fxMesa->sScale0 = ti0->sScale; - fxMesa->tScale0 = ti0->tScale; - if (ti0->info.format == GR_TEXFMT_P_8) { + if ( t0 ) { + fxMesa->sScale0 = t0->sScale; + fxMesa->tScale0 = t0->tScale; + if ( t0->info.format == GR_TEXFMT_P_8 ) { fxMesa->TexPalette.Type = GR_TEXTABLE_PALETTE_6666_EXT; - fxMesa->TexPalette.Data = &(ti0->palette); + fxMesa->TexPalette.Data = &t0->palette; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; - } - else if (ti1 && ti1->info.format == GR_TEXFMT_P_8) { + } else if ( t1 && t1->info.format == GR_TEXFMT_P_8 ) { fxMesa->TexPalette.Type = GR_TEXTABLE_PALETTE_6666_EXT; - fxMesa->TexPalette.Data = &(ti1->palette); + fxMesa->TexPalette.Data = &t1->palette; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } } - if (ti1) { - fxMesa->sScale1 = ti1->sScale; - fxMesa->tScale1 = ti1->tScale; + if ( t1 ) { + fxMesa->sScale1 = t1->sScale; + fxMesa->tScale1 = t1->tScale; } - if (ctx->Texture.ReallyEnabled == TEXTURE0_2D) { - if (shared->umaTexMemory) { - fxMesa->TexSource[0].StartAddress = ti0->tm[0]->startAddr; + switch ( ctx->Texture.ReallyEnabled ) { + case TEXTURE0_2D: + if ( tss->umaTexMemory ) { + fxMesa->TexSource[0].StartAddress = t0->range[0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[0].Info = &(ti0->info); - } - else { - if (ti0->LODblend && ti0->whichTMU == TDFX_TMU_SPLIT) { - fxMesa->TexSource[0].StartAddress = ti0->tm[TDFX_TMU0]->startAddr; + fxMesa->TexSource[0].Info = &(t0->info); + } else { + if ( t0->LODblend && t0->whichTMU == TDFX_TMU_SPLIT ) { + fxMesa->TexSource[0].StartAddress = t0->range[TDFX_TMU0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD; - fxMesa->TexSource[0].Info = &(ti0->info); - fxMesa->TexSource[1].StartAddress = ti0->tm[TDFX_TMU1]->startAddr; + fxMesa->TexSource[0].Info = &t0->info; + fxMesa->TexSource[1].StartAddress = t0->range[TDFX_TMU1]->startAddr; fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN; - fxMesa->TexSource[1].Info = &(ti0->info); - } - else { - FxU32 tmu; - if (ti0->whichTMU == TDFX_TMU_BOTH) - tmu = TDFX_TMU0; - else - tmu = ti0->whichTMU; + fxMesa->TexSource[1].Info = &t0->info; + } else { + FxU32 unit; + if ( t0->whichTMU == TDFX_TMU_BOTH ) { + unit = TDFX_TMU0; + } else { + unit = t0->whichTMU; + } fxMesa->TexSource[0].Info = NULL; fxMesa->TexSource[1].Info = NULL; - if (ti0->tm[tmu]) { - fxMesa->TexSource[tmu].StartAddress = ti0->tm[tmu]->startAddr; - fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu].Info = &(ti0->info); + if ( t0->range[unit] ) { + fxMesa->TexSource[unit].StartAddress = t0->range[unit]->startAddr; + fxMesa->TexSource[unit].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; + fxMesa->TexSource[unit].Info = &t0->info; } } } - } - else if (ctx->Texture.ReallyEnabled == TEXTURE1_2D) { - if (shared->umaTexMemory) { - fxMesa->TexSource[0].StartAddress = ti1->tm[0]->startAddr; + break; + + case TEXTURE1_2D: + if ( tss->umaTexMemory ) { + fxMesa->TexSource[0].StartAddress = t1->range[0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[0].Info = &(ti1->info); + fxMesa->TexSource[0].Info = &t1->info; } - } - else if (ctx->Texture.ReallyEnabled == (TEXTURE0_2D | TEXTURE1_2D)) { - if (shared->umaTexMemory) { + break; + + case TEXTURE0_2D | TEXTURE1_2D: + if ( tss->umaTexMemory ) { const FxU32 tmu0 = 0, tmu1 = 1; - fxMesa->TexSource[tmu0].StartAddress = ti0->tm[0]->startAddr; + fxMesa->TexSource[tmu0].StartAddress = t0->range[0]->startAddr; fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu0].Info = &(ti0->info); + fxMesa->TexSource[tmu0].Info = &t0->info; - fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr; + fxMesa->TexSource[tmu1].StartAddress = t1->range[0]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu1].Info = &(ti1->info); + fxMesa->TexSource[tmu1].Info = &t1->info; } else { const FxU32 tmu0 = 0, tmu1 = 1; - fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr; + fxMesa->TexSource[tmu0].StartAddress = t0->range[tmu0]->startAddr; fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu0].Info = &(ti0->info); + fxMesa->TexSource[tmu0].Info = &t0->info; - fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr; + fxMesa->TexSource[tmu1].StartAddress = t1->range[tmu1]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; - fxMesa->TexSource[tmu1].Info = &(ti1->info); + fxMesa->TexSource[tmu1].Info = &t1->info; } + break; } - fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; } diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.h b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.h deleted file mode 100644 index 0c0d4adcb..000000000 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- mode: c; c-basic-offset: 3 -*- - * - * Copyright 2000 VA Linux Systems Inc., Fremont, California. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -/* $XFree86$ */ - -/* - * Original rewrite: - * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000 - * - * Authors: - * Gareth Hughes <gareth@valinux.com> - * Brian Paul <brianp@valinux.com> - * - */ - -#ifndef __TDFX_TEXSTATE_H__ -#define __TDFX_TEXSTATE_H__ - -extern void tdfxUpdateTextureState( GLcontext *ctx ); -extern void tdfxUpdateTextureBinding( GLcontext *ctx ); - -#endif diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_wrapper.h b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_wrapper.h index 20e5530c5..0adb85b41 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_wrapper.h +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_wrapper.h @@ -552,8 +552,6 @@ extern FxBool FX_grLfbLock(tdfxContextPtr fxMesa, UNLOCK_HARDWARE(fxMesa); \ } while (0) -#define FX_grTexDownloadMipMapLevel_NoLock grTexDownloadMipMapLevel - #define FX_grTexDownloadMipMapLevelPartial(fxMesa, t, sa, tlod, llod, ar, f, eo, d, s, e); \ do { \ LOCK_HARDWARE(fxMesa); \ diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_xmesa.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_xmesa.c index 06930691d..ef0c580ae 100644 --- a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_xmesa.c +++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_xmesa.c @@ -52,19 +52,6 @@ #include "tdfx_texman.h" -#ifndef TDFX_DEBUG -int TDFX_DEBUG = (0 -/* | DEBUG_ALWAYS_SYNC */ -/* | DEBUG_VERBOSE_API */ -/* | DEBUG_VERBOSE_MSG */ -/* | DEBUG_VERBOSE_LRU */ -/* | DEBUG_VERBOSE_DRI */ -/* | DEBUG_VERBOSE_IOCTL */ -/* | DEBUG_VERBOSE_2D */ - ); -#endif - - GLboolean XMesaInitDriver( __DRIscreenPrivate *sPriv ) { diff --git a/xc/programs/Xserver/GL/mesa/src/Imakefile b/xc/programs/Xserver/GL/mesa/src/Imakefile index c2ead442c..05f2cfe1f 100644 --- a/xc/programs/Xserver/GL/mesa/src/Imakefile +++ b/xc/programs/Xserver/GL/mesa/src/Imakefile @@ -147,6 +147,8 @@ LinkSourceFile(state.c,$(MESASRCDIR)/src) LinkSourceFile(state.h,$(MESASRCDIR)/src) LinkSourceFile(stencil.c,$(MESASRCDIR)/src) LinkSourceFile(stencil.h,$(MESASRCDIR)/src) +LinkSourceFile(texformat.c, $(MESASRCDIR)/src) +LinkSourceFile(texformat.h, $(MESASRCDIR)/src) LinkSourceFile(texgen_tmp.h,$(MESASRCDIR)/src) LinkSourceFile(teximage.c,$(MESASRCDIR)/src) LinkSourceFile(teximage.h,$(MESASRCDIR)/src) @@ -245,6 +247,7 @@ LinkSourceFile(zoom.h,$(MESASRCDIR)/src) stages.c \ state.c \ stencil.c \ + texformat.c \ teximage.c \ texobj.c \ texstate.c \ @@ -321,6 +324,7 @@ LinkSourceFile(zoom.h,$(MESASRCDIR)/src) stages.o \ state.o \ stencil.o \ + texformat.o \ teximage.o \ texobj.o \ texstate.o \ @@ -384,4 +388,3 @@ InstallDriverSDKLibraryModule(GLcore,$(DRIVERSDKMODULEDIR),extensions) DependSubdirs($(SUBDIRS)) MakeLintLibSubdirs($(SUBDIRS)) LintSubdirs($(SUBDIRS)) - diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h index c29db273b..20ad35cbc 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h @@ -1068,36 +1068,36 @@ #define RADEON_PP_TXFORMAT_0 0x1c58 #define RADEON_PP_TXFORMAT_1 0x1c70 #define RADEON_PP_TXFORMAT_2 0x1c88 -# define RADEON_TXF_8BPP_I (0 << 0) -# define RADEON_TXF_16BPP_AI88 (1 << 0) -# define RADEON_TXF_8BPP_RGB332 (2 << 0) -# define RADEON_TXF_16BPP_ARGB1555 (3 << 0) -# define RADEON_TXF_16BPP_RGB565 (4 << 0) -# define RADEON_TXF_16BPP_ARGB4444 (5 << 0) -# define RADEON_TXF_32BPP_ARGB8888 (6 << 0) -# define RADEON_TXF_32BPP_RGBA8888 (7 << 0) -# define RADEON_TXF_8BPP_Y (8 << 0) -# define RADEON_TXF_FORMAT_MASK (31 << 0) -# define RADEON_TXF_FORMAT_SHIFT 0 -# define RADEON_TXF_APPLE_YUV_MODE (1 << 5) -# define RADEON_TXF_ALPHA_IN_MAP (1 << 6) -# define RADEON_TXF_NON_POWER2 (1 << 7) -# define RADEON_TXF_WIDTH_MASK (15 << 8) -# define RADEON_TXF_WIDTH_SHIFT 8 -# define RADEON_TXF_HEIGHT_MASK (15 << 12) -# define RADEON_TXF_HEIGHT_SHIFT 12 -# define RADEON_TXF_ST_ROUTE_STQ0 (0 << 24) -# define RADEON_TXF_ST_ROUTE_MASK (3 << 24) -# define RADEON_TXF_ST_ROUTE_STQ1 (1 << 24) -# define RADEON_TXF_ST_ROUTE_STQ2 (2 << 24) -# define RADEON_TXF_ENDIAN_NO_SWAP (0 << 26) -# define RADEON_TXF_ENDIAN_16BPP_SWAP (1 << 26) -# define RADEON_TXF_ENDIAN_32BPP_SWAP (2 << 26) -# define RADEON_TXF_ENDIAN_HALFDW_SWAP (3 << 26) -# define RADEON_TXF_ALPHA_MASK_ENABLE (1 << 28) -# define RADEON_TXF_CHROMA_KEY_ENABLE (1 << 29) -# define RADEON_TXF_CUBIC_MAP_ENABLE (1 << 30) -# define RADEON_TXF_PERSPECTIVE_ENABLE (1 << 31) +# define RADEON_TXFORMAT_I8 (0 << 0) +# define RADEON_TXFORMAT_AI88 (1 << 0) +# define RADEON_TXFORMAT_RGB332 (2 << 0) +# define RADEON_TXFORMAT_ARGB1555 (3 << 0) +# define RADEON_TXFORMAT_RGB565 (4 << 0) +# define RADEON_TXFORMAT_ARGB4444 (5 << 0) +# define RADEON_TXFORMAT_ARGB8888 (6 << 0) +# define RADEON_TXFORMAT_RGBA8888 (7 << 0) +# define RADEON_TXFORMAT_Y8 (8 << 0) +# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) +# define RADEON_TXFORMAT_FORMAT_SHIFT 0 +# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) +# define RADEON_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define RADEON_TXFORMAT_NON_POWER2 (1 << 7) +# define RADEON_TXFORMAT_WIDTH_MASK (15 << 8) +# define RADEON_TXFORMAT_WIDTH_SHIFT 8 +# define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12) +# define RADEON_TXFORMAT_HEIGHT_SHIFT 12 +# define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26) +# define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26) +# define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26) +# define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3 << 26) +# define RADEON_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +# define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31) #define RADEON_PP_TXOFFSET_0 0x1c5c #define RADEON_PP_TXOFFSET_1 0x1c74 #define RADEON_PP_TXOFFSET_2 0x1c8c diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h index 14cb002fd..b80f35e52 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h @@ -81,7 +81,7 @@ /* Vertex/indirect buffer size */ -#define RADEON_BUFFER_SIZE 16384 +#define RADEON_BUFFER_SIZE 65536 /* Byte offsets for indirect buffer data */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h index 40a85875b..30b75e1e3 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h @@ -439,7 +439,7 @@ typedef struct drm_agp_info { #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) -#define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4b, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c index 2f20806c9..3feb4b240 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c @@ -843,11 +843,8 @@ int radeon_cp_start( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( dev_priv->cp_running ) { DRM_DEBUG( "%s while CP running\n", __FUNCTION__ ); return 0; @@ -876,11 +873,7 @@ int radeon_cp_stop( struct inode *inode, struct file *filp, int ret; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) ) return -EFAULT; @@ -922,11 +915,8 @@ int radeon_cp_reset( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv ) { DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); return -EINVAL; @@ -948,11 +938,7 @@ int radeon_cp_idle( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); return radeon_do_cp_idle( dev_priv ); } @@ -964,11 +950,7 @@ int radeon_engine_reset( struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); return radeon_do_engine_reset( dev ); } @@ -1018,11 +1000,7 @@ int radeon_fullscreen( struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_radeon_fullscreen_t fs; - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg, sizeof(fs) ) ) @@ -1246,14 +1224,10 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp, int ret = 0; drm_dma_t d; - if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) ) - return -EFAULT; + LOCK_TEST_WITH_RETURN( dev ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) ) + return -EFAULT; /* Please don't send us buffers. */ @@ -1277,7 +1251,7 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp, ret = radeon_cp_get_buffers( dev, &d ); } - if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) ) + if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) ) return -EFAULT; return ret; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h index a7d7a71bb..50a7d6ed8 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h @@ -73,7 +73,7 @@ /* Vertex/indirect buffer size */ -#define RADEON_BUFFER_SIZE 16384 +#define RADEON_BUFFER_SIZE 65536 /* Byte offsets for indirect buffer data */ @@ -304,14 +304,20 @@ typedef struct drm_radeon_indices { int discard; /* Client finished with buffer? */ } drm_radeon_indices_t; -typedef struct drm_radeon_blit { - int idx; - int pitch; +typedef struct drm_radeon_tex_image { + unsigned int x, y; /* Blit coordinates */ + unsigned int width, height; + const void *data; +} drm_radeon_tex_image_t; + +typedef struct drm_radeon_texture { int offset; + int pitch; int format; - unsigned short x, y; - unsigned short width, height; -} drm_radeon_blit_t; + int width; /* Texture image coordinates */ + int height; + drm_radeon_tex_image_t *image; +} drm_radeon_texture_t; typedef struct drm_radeon_stipple { unsigned int *mask; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c index cf59f866a..1aa889aee 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c @@ -36,7 +36,7 @@ #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20010216" +#define DRIVER_DATE "20010305" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 @@ -55,7 +55,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_BLIT)] = { radeon_cp_blit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 }, diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h index e67a610fb..d279b0467 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h @@ -161,8 +161,8 @@ extern int radeon_cp_vertex( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int radeon_cp_indices( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -extern int radeon_cp_blit( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ); +extern int radeon_cp_texture( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); extern int radeon_cp_stipple( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int radeon_cp_indirect( struct inode *inode, struct file *filp, @@ -478,14 +478,14 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp, #define RADEON_COLOR_FORMAT_RGB8 9 #define RADEON_COLOR_FORMAT_ARGB4444 15 -#define RADEON_TXF_8BPP_I 0 -#define RADEON_TXF_16BPP_AI88 1 -#define RADEON_TXF_8BPP_RGB332 2 -#define RADEON_TXF_16BPP_ARGB1555 3 -#define RADEON_TXF_16BPP_RGB565 4 -#define RADEON_TXF_16BPP_ARGB4444 5 -#define RADEON_TXF_32BPP_ARGB8888 6 -#define RADEON_TXF_32BPP_RGBA8888 7 +#define RADEON_TXFORMAT_I8 0 +#define RADEON_TXFORMAT_AI88 1 +#define RADEON_TXFORMAT_RGB332 2 +#define RADEON_TXFORMAT_ARGB1555 3 +#define RADEON_TXFORMAT_RGB565 4 +#define RADEON_TXFORMAT_ARGB4444 5 +#define RADEON_TXFORMAT_ARGB8888 6 +#define RADEON_TXFORMAT_RGBA8888 7 /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ @@ -586,6 +586,16 @@ extern int RADEON_READ_PLL( drm_device_t *dev, int addr ); * Misc helper macros */ +#define LOCK_TEST_WITH_RETURN( dev ) \ +do { \ + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ + dev->lock.pid != current->pid ) { \ + DRM_ERROR( "%s called without lock held\n", \ + __FUNCTION__ ); \ + return -EINVAL; \ + } \ +} while (0) + #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ do { \ drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; \ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c index 9b84a7397..ff1b3512f 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c @@ -972,50 +972,67 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, sarea_priv->nbox = 0; } -static int radeon_cp_dispatch_blit( drm_device_t *dev, - drm_radeon_blit_t *blit ) +#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32)) + +static int radeon_cp_dispatch_texture( drm_device_t *dev, + drm_radeon_texture_t *tex, + drm_radeon_tex_image_t *image ) { drm_radeon_private_t *dev_priv = dev->dev_private; - drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_radeon_buf_priv_t *buf_priv; u32 format; - u32 *data; - int dword_shift, dwords; + u32 *buffer; + u8 *data; + int size, dwords, tex_width, blit_width; + u32 y, height; + int ret = 0, i; RING_LOCALS; - DRM_DEBUG( "blit: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", - blit->offset >> 10, blit->pitch, blit->format, - blit->x, blit->y, blit->width, blit->height ); - radeon_update_ring_snapshot( dev_priv ); + /* FIXME: Be smarter about this... + */ + buf = radeon_freelist_get( dev ); + if ( !buf ) return -EAGAIN; + + DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", + tex->offset >> 10, tex->pitch, tex->format, + image->x, image->y, image->width, image->height ); + + buf_priv = buf->dev_private; /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll * use a shift instead. */ - switch ( blit->format ) { - case RADEON_TXF_32BPP_ARGB8888: - case RADEON_TXF_32BPP_RGBA8888: + switch ( tex->format ) { + case RADEON_TXFORMAT_ARGB8888: + case RADEON_TXFORMAT_RGBA8888: format = RADEON_COLOR_FORMAT_ARGB8888; - dword_shift = 0; + tex_width = tex->width * 4; + blit_width = image->width * 4; break; - case RADEON_TXF_16BPP_AI88: - case RADEON_TXF_16BPP_ARGB1555: - case RADEON_TXF_16BPP_RGB565: - case RADEON_TXF_16BPP_ARGB4444: + case RADEON_TXFORMAT_AI88: + case RADEON_TXFORMAT_ARGB1555: + case RADEON_TXFORMAT_RGB565: + case RADEON_TXFORMAT_ARGB4444: format = RADEON_COLOR_FORMAT_RGB565; - dword_shift = 1; + tex_width = tex->width * 2; + blit_width = image->width * 2; break; - case RADEON_TXF_8BPP_I: - case RADEON_TXF_8BPP_RGB332: + case RADEON_TXFORMAT_I8: + case RADEON_TXFORMAT_RGB332: format = RADEON_COLOR_FORMAT_CI8; - dword_shift = 2; + tex_width = tex->width * 1; + blit_width = image->width * 1; break; default: - DRM_ERROR( "invalid blit format %d\n", blit->format ); + DRM_ERROR( "invalid texture format %d\n", tex->format ); return -EINVAL; } + DRM_DEBUG( " tex=%dx%d blit=%d\n", + tex_width, tex->height, blit_width ); + /* Flush the pixel cache. This ensures no pixel data gets mixed * up with the texture data from the host data blit, otherwise * part of the texture image may be corrupted. @@ -1027,46 +1044,81 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev, ADVANCE_RING(); - /* Dispatch the indirect buffer. + /* Make a copy of the parameters in case we have to update them + * for a multi-pass texture blit. */ - buf = dma->buflist[blit->idx]; - buf_priv = buf->dev_private; + y = image->y; + height = image->height; + data = (u8 *)image->data; - if ( buf->pid != current->pid ) { - DRM_ERROR( "process %d using buffer owned by %d\n", - current->pid, buf->pid ); - return -EINVAL; - } - if ( buf->pending ) { - DRM_ERROR( "sending pending buffer %d\n", blit->idx ); - return -EINVAL; - } + size = height * blit_width; - buf_priv->discard = 1; + if ( size > RADEON_MAX_TEXTURE_SIZE ) { + /* Texture image is too large, do a multipass upload */ + ret = -EAGAIN; - dwords = (blit->width * blit->height) >> dword_shift; - if ( !dwords ) dwords = 1; + /* Adjust the blit size to fit the indirect buffer */ + height = RADEON_MAX_TEXTURE_SIZE / blit_width; + size = height * blit_width; - data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); + /* Update the input parameters for next time */ + image->y += height; + image->height -= height; + image->data = (char *)image->data + size; - data[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); - data[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (format << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_S | - RADEON_DP_SRC_SOURCE_HOST_DATA | - RADEON_GMC_CLR_CMP_CNTL_DIS | - RADEON_GMC_WR_MSK_DIS); + if ( copy_to_user( tex->image, image, sizeof(*image) ) ) + return -EFAULT; + } else if ( size < 4 ) { + size = 4; + } - data[2] = (blit->pitch << 22) | (blit->offset >> 10); - data[3] = 0xffffffff; - data[4] = 0xffffffff; - data[5] = (blit->y << 16) | blit->x; - data[6] = (blit->height << 16) | blit->width; - data[7] = dwords; + dwords = size / 4; + + /* Dispatch the indirect buffer. + */ + buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); + + buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); + buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (format << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_HOST_DATA | + RADEON_GMC_CLR_CMP_CNTL_DIS | + RADEON_GMC_WR_MSK_DIS); + + buffer[2] = (tex->pitch << 22) | (tex->offset >> 10); + buffer[3] = 0xffffffff; + buffer[4] = 0xffffffff; + buffer[5] = (y << 16) | image->x; + buffer[6] = (height << 16) | image->width; + buffer[7] = dwords; + + buffer += 8; + + if ( tex_width >= 32 ) { + /* Texture image width is larger than the minimum, so we + * can upload it directly. + */ + if ( copy_from_user( buffer, data, dwords * sizeof(u32) ) ) + return -EFAULT; + } else { + /* Texture image width is less than the minimum, so we + * need to pad out each image scanline to the minimum + * width. + */ + for ( i = 0 ; i < tex->height ; i++ ) { + if ( copy_from_user( buffer, data, tex_width ) ) + return -EFAULT; + buffer += 8; + data += tex_width; + } + } + buf->pid = current->pid; buf->used = (dwords + 8) * sizeof(u32); + buf_priv->discard = 1; radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); @@ -1081,7 +1133,7 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev, ADVANCE_RING(); - return 0; + return ret; } static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple ) @@ -1122,11 +1174,7 @@ int radeon_cp_clear( struct inode *inode, struct file *filp, drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg, sizeof(clear) ) ) @@ -1156,11 +1204,7 @@ int radeon_cp_swap( struct inode *inode, struct file *filp, drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG( "%s\n", __FUNCTION__ ); - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1189,11 +1233,8 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp, drm_radeon_buf_priv_t *buf_priv; drm_radeon_vertex_t vertex; - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; @@ -1255,11 +1296,8 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, drm_radeon_indices_t elts; int count; - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; @@ -1321,38 +1359,34 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, return 0; } -int radeon_cp_blit( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) +int radeon_cp_texture( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_device_dma_t *dma = dev->dma; - drm_radeon_blit_t blit; + drm_radeon_texture_t tex; + drm_radeon_tex_image_t image; - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); - if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg, - sizeof(blit) ) ) + if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) ) return -EFAULT; - DRM_DEBUG( "%s: pid=%d index=%d\n", - __FUNCTION__, current->pid, blit.idx ); - - if ( blit.idx < 0 || blit.idx > dma->buf_count ) { - DRM_ERROR( "sending %d buffers (of %d max)\n", - blit.idx, dma->buf_count ); + if ( tex.image == NULL ) { + DRM_ERROR( "null texture image!\n" ); return -EINVAL; } + if ( copy_from_user( &image, + (drm_radeon_tex_image_t *)tex.image, + sizeof(image) ) ) + return -EFAULT; + RING_SPACE_TEST_WITH_RETURN( dev_priv ); VB_AGE_TEST_WITH_RETURN( dev_priv ); - return radeon_cp_dispatch_blit( dev, &blit ); + return radeon_cp_dispatch_texture( dev, &tex, &image ); } int radeon_cp_stipple( struct inode *inode, struct file *filp, @@ -1364,18 +1398,13 @@ int radeon_cp_stipple( struct inode *inode, struct file *filp, drm_radeon_stipple_t stipple; u32 mask[32]; - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg, sizeof(stipple) ) ) return -EFAULT; - if ( copy_from_user( &mask, stipple.mask, - 32 * sizeof(u32) ) ) + if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) ) return -EFAULT; RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1397,11 +1426,8 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp, drm_radeon_indirect_t indirect; RING_LOCALS; - if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || - dev->lock.pid != current->pid ) { - DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); - return -EINVAL; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c index 62caddadc..944a030ff 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c @@ -311,25 +311,32 @@ int drmRadeonFlushIndices( int fd, int prim, int index, } } -int drmRadeonTextureBlit( int fd, int index, - int offset, int pitch, int format, - int x, int y, int width, int height ) +int drmRadeonLoadTexture( int fd, int offset, int pitch, int format, + int width, int height, drmRadeonTexImage *image ) { - drm_radeon_blit_t blit; - - blit.idx = index; - blit.offset = offset; - blit.pitch = pitch; - blit.format = format; - blit.x = x; - blit.y = y; - blit.width = width; - blit.height = height; - - if ( ioctl( fd, DRM_IOCTL_RADEON_BLIT, &blit ) < 0 ) { - return -errno; - } else { + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; + int ret; + + tex.offset = offset; + tex.pitch = pitch; + tex.format = format; + tex.width = width; + tex.height = height; + tex.image = &tmp; + + /* This gets updated by the kernel when a multipass blit is needed. + */ + memcpy( &tmp, image, sizeof(drm_radeon_tex_image_t) ); + + do { + ret = ioctl( fd, DRM_IOCTL_RADEON_TEXTURE, &tex ); + } while ( ret && errno == EAGAIN ); + + if ( ret == 0 ) { return 0; + } else { + return -errno; } } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h index 40a85875b..30b75e1e3 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h @@ -439,7 +439,7 @@ typedef struct drm_agp_info { #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) -#define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4b, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h index 87f70590d..e3bf83fdd 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h @@ -43,27 +43,35 @@ #define DRM_RADEON_DEPTH 0x4 typedef struct { - int sarea_priv_offset; - int is_pci; - int cp_mode; - int agp_size; - int ring_size; - int usec_timeout; - - unsigned int fb_bpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_bpp; - unsigned int depth_offset, depth_pitch; - - unsigned int fb_offset; - unsigned int mmio_offset; - unsigned int ring_offset; - unsigned int ring_rptr_offset; - unsigned int buffers_offset; - unsigned int agp_textures_offset; + int sarea_priv_offset; + int is_pci; + int cp_mode; + int agp_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned int fb_offset; + unsigned int mmio_offset; + unsigned int ring_offset; + unsigned int ring_rptr_offset; + unsigned int buffers_offset; + unsigned int agp_textures_offset; } drmRadeonInit; +typedef struct { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + void *data; +} drmRadeonTexImage; + extern int drmRadeonInitCP( int fd, drmRadeonInit *info ); extern int drmRadeonCleanupCP( int fd ); @@ -87,9 +95,9 @@ extern int drmRadeonFlushVertexBuffer( int fd, int prim, int index, extern int drmRadeonFlushIndices( int fd, int prim, int index, int start, int end, int discard ); -extern int drmRadeonTextureBlit( int fd, int index, - int offset, int pitch, int format, - int x, int y, int width, int height ); +extern int drmRadeonLoadTexture( int fd, int offset, int pitch, int format, + int width, int height, + drmRadeonTexImage *image ); extern int drmRadeonPolygonStipple( int fd, unsigned int *mask ); |