diff options
Diffstat (limited to 'src/mesa/drivers/dri/r200/r200_texstate.c')
-rw-r--r-- | src/mesa/drivers/dri/r200/r200_texstate.c | 1622 |
1 files changed, 0 insertions, 1622 deletions
diff --git a/src/mesa/drivers/dri/r200/r200_texstate.c b/src/mesa/drivers/dri/r200/r200_texstate.c deleted file mode 100644 index f8e45e12b63..00000000000 --- a/src/mesa/drivers/dri/r200/r200_texstate.c +++ /dev/null @@ -1,1622 +0,0 @@ -/* -Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. - -The Weather Channel (TM) funded Tungsten Graphics to develop the -initial release of the Radeon 8500 driver under the XFree86 license. -This notice must be preserved. - -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 THE COPYRIGHT OWNER(S) AND/OR ITS 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: - * Keith Whitwell <keithw@vmware.com> - */ - -#include "main/glheader.h" - -#include "main/context.h" -#include "main/macros.h" -#include "main/state.h" -#include "main/teximage.h" -#include "main/texobj.h" -#include "main/enums.h" - -#include "radeon_common.h" -#include "radeon_mipmap_tree.h" -#include "r200_context.h" -#include "r200_state.h" -#include "r200_ioctl.h" -#include "r200_swtcl.h" -#include "r200_tex.h" -#include "r200_tcl.h" - -#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \ - && (tx_table_be[f].format != 0xffffffff) ) - -/* ================================================================ - * Texture combine functions - */ - -/* GL_ARB_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 r200_register_color[][R200_MAX_TEXTURE_UNITS] = -{ - { - R200_TXC_ARG_A_R0_COLOR, - R200_TXC_ARG_A_R1_COLOR, - R200_TXC_ARG_A_R2_COLOR, - R200_TXC_ARG_A_R3_COLOR, - R200_TXC_ARG_A_R4_COLOR, - R200_TXC_ARG_A_R5_COLOR - }, - { - R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A - }, - { - R200_TXC_ARG_A_R0_ALPHA, - R200_TXC_ARG_A_R1_ALPHA, - R200_TXC_ARG_A_R2_ALPHA, - R200_TXC_ARG_A_R3_ALPHA, - R200_TXC_ARG_A_R4_ALPHA, - R200_TXC_ARG_A_R5_ALPHA - }, - { - R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A - }, -}; - -static GLuint r200_tfactor_color[] = -{ - R200_TXC_ARG_A_TFACTOR_COLOR, - R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_TFACTOR_ALPHA, - R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A -}; - -static GLuint r200_tfactor1_color[] = -{ - R200_TXC_ARG_A_TFACTOR1_COLOR, - R200_TXC_ARG_A_TFACTOR1_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_TFACTOR1_ALPHA, - R200_TXC_ARG_A_TFACTOR1_ALPHA | R200_TXC_COMP_ARG_A -}; - -static GLuint r200_primary_color[] = -{ - R200_TXC_ARG_A_DIFFUSE_COLOR, - R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_DIFFUSE_ALPHA, - R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A -}; - -/* GL_ZERO table - indices 0-3 - * GL_ONE table - indices 1-4 - */ -static GLuint r200_zero_color[] = -{ - R200_TXC_ARG_A_ZERO, - R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_ZERO, - R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A, - R200_TXC_ARG_A_ZERO -}; - -/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. - */ -static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] = -{ - { - R200_TXA_ARG_A_R0_ALPHA, - R200_TXA_ARG_A_R1_ALPHA, - R200_TXA_ARG_A_R2_ALPHA, - R200_TXA_ARG_A_R3_ALPHA, - R200_TXA_ARG_A_R4_ALPHA, - R200_TXA_ARG_A_R5_ALPHA - }, - { - R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A, - R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A, - R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A, - R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A, - R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A, - R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A - }, -}; - -static GLuint r200_tfactor_alpha[] = -{ - R200_TXA_ARG_A_TFACTOR_ALPHA, - R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A -}; - -static GLuint r200_tfactor1_alpha[] = -{ - R200_TXA_ARG_A_TFACTOR1_ALPHA, - R200_TXA_ARG_A_TFACTOR1_ALPHA | R200_TXA_COMP_ARG_A -}; - -static GLuint r200_primary_alpha[] = -{ - R200_TXA_ARG_A_DIFFUSE_ALPHA, - R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A -}; - -/* GL_ZERO table - indices 0-1 - * GL_ONE table - indices 1-2 - */ -static GLuint r200_zero_alpha[] = -{ - R200_TXA_ARG_A_ZERO, - R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A, - R200_TXA_ARG_A_ZERO, -}; - - -/* Extract the arg from slot A, shift it into the correct argument slot - * and set the corresponding complement bit. - */ -#define R200_COLOR_ARG( n, arg ) \ -do { \ - color_combine |= \ - ((color_arg[n] & R200_TXC_ARG_A_MASK) \ - << R200_TXC_ARG_##arg##_SHIFT); \ - color_combine |= \ - ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \ - << R200_TXC_COMP_ARG_##arg##_SHIFT); \ -} while (0) - -#define R200_ALPHA_ARG( n, arg ) \ -do { \ - alpha_combine |= \ - ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \ - << R200_TXA_ARG_##arg##_SHIFT); \ - alpha_combine |= \ - ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \ - << R200_TXA_COMP_ARG_##arg##_SHIFT); \ -} while (0) - - -/* ================================================================ - * Texture unit state management - */ - -static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slot, GLuint replaceargs ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - const struct gl_texture_unit *rtexUnit = &ctx->Texture.Unit[unit]; - const struct gl_fixedfunc_texture_unit *texUnit = - &ctx->Texture.FixedFuncUnit[unit]; - GLuint color_combine, alpha_combine; - GLuint color_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] & - ~(R200_TXC_SCALE_MASK | R200_TXC_OUTPUT_REG_MASK | R200_TXC_TFACTOR_SEL_MASK | - R200_TXC_TFACTOR1_SEL_MASK); - GLuint alpha_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] & - ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK | R200_TXA_OUTPUT_REG_MASK | - R200_TXA_TFACTOR_SEL_MASK | R200_TXA_TFACTOR1_SEL_MASK); - - if ( R200_DEBUG & RADEON_TEXTURE ) { - fprintf( stderr, "%s( %p, %d )\n", __func__, (void *)ctx, unit ); - } - - /* Set the texture environment state. Isn't this nice and clean? - * The chip 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. - */ - - color_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXC_OUTPUT_REG_SHIFT) | - (unit << R200_TXC_TFACTOR_SEL_SHIFT) | - (replaceargs << R200_TXC_TFACTOR1_SEL_SHIFT); - alpha_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXA_OUTPUT_REG_SHIFT) | - (unit << R200_TXA_TFACTOR_SEL_SHIFT) | - (replaceargs << R200_TXA_TFACTOR1_SEL_SHIFT); - - if ( !rtexUnit->_Current ) { - assert( unit == 0); - color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO - | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD; - alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO - | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD; - } - else { - GLuint color_arg[3], alpha_arg[3]; - GLuint i; - const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB; - const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; - GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB; - GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA; - - - const GLint replaceoprgb = - ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->OperandRGB[0] - GL_SRC_COLOR; - const GLint replaceopa = - ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->OperandA[0] - GL_SRC_ALPHA; - - /* Step 1: - * Extract the color and alpha combine function arguments. - */ - for ( i = 0 ; i < numColorArgs ; i++ ) { - GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR; - const GLint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i]; - assert(op >= 0); - assert(op <= 3); - switch ( srcRGBi ) { - case GL_TEXTURE: - color_arg[i] = r200_register_color[op][unit]; - break; - case GL_CONSTANT: - color_arg[i] = r200_tfactor_color[op]; - break; - case GL_PRIMARY_COLOR: - color_arg[i] = r200_primary_color[op]; - break; - case GL_PREVIOUS: - if (replaceargs != unit) { - const GLint srcRGBreplace = - ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->SourceRGB[0]; - if (op >= 2) { - op = op ^ replaceopa; - } - else { - op = op ^ replaceoprgb; - } - switch (srcRGBreplace) { - case GL_TEXTURE: - color_arg[i] = r200_register_color[op][replaceargs]; - break; - case GL_CONSTANT: - color_arg[i] = r200_tfactor1_color[op]; - break; - case GL_PRIMARY_COLOR: - color_arg[i] = r200_primary_color[op]; - break; - case GL_PREVIOUS: - if (slot == 0) - color_arg[i] = r200_primary_color[op]; - else - color_arg[i] = r200_register_color[op] - [rmesa->state.texture.unit[replaceargs - 1].outputreg]; - break; - case GL_ZERO: - color_arg[i] = r200_zero_color[op]; - break; - case GL_ONE: - color_arg[i] = r200_zero_color[op+1]; - break; - case GL_TEXTURE0: - case GL_TEXTURE1: - case GL_TEXTURE2: - case GL_TEXTURE3: - case GL_TEXTURE4: - case GL_TEXTURE5: - color_arg[i] = r200_register_color[op][srcRGBreplace - GL_TEXTURE0]; - break; - default: - return GL_FALSE; - } - } - else { - if (slot == 0) - color_arg[i] = r200_primary_color[op]; - else - color_arg[i] = r200_register_color[op] - [rmesa->state.texture.unit[unit - 1].outputreg]; - } - break; - case GL_ZERO: - color_arg[i] = r200_zero_color[op]; - break; - case GL_ONE: - color_arg[i] = r200_zero_color[op+1]; - break; - case GL_TEXTURE0: - case GL_TEXTURE1: - case GL_TEXTURE2: - case GL_TEXTURE3: - case GL_TEXTURE4: - case GL_TEXTURE5: - color_arg[i] = r200_register_color[op][srcRGBi - GL_TEXTURE0]; - break; - default: - return GL_FALSE; - } - } - - for ( i = 0 ; i < numAlphaArgs ; i++ ) { - GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA; - const GLint srcAi = texUnit->_CurrentCombine->SourceA[i]; - assert(op >= 0); - assert(op <= 1); - switch ( srcAi ) { - case GL_TEXTURE: - alpha_arg[i] = r200_register_alpha[op][unit]; - break; - case GL_CONSTANT: - alpha_arg[i] = r200_tfactor_alpha[op]; - break; - case GL_PRIMARY_COLOR: - alpha_arg[i] = r200_primary_alpha[op]; - break; - case GL_PREVIOUS: - if (replaceargs != unit) { - const GLint srcAreplace = - ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->SourceA[0]; - op = op ^ replaceopa; - switch (srcAreplace) { - case GL_TEXTURE: - alpha_arg[i] = r200_register_alpha[op][replaceargs]; - break; - case GL_CONSTANT: - alpha_arg[i] = r200_tfactor1_alpha[op]; - break; - case GL_PRIMARY_COLOR: - alpha_arg[i] = r200_primary_alpha[op]; - break; - case GL_PREVIOUS: - if (slot == 0) - alpha_arg[i] = r200_primary_alpha[op]; - else - alpha_arg[i] = r200_register_alpha[op] - [rmesa->state.texture.unit[replaceargs - 1].outputreg]; - break; - case GL_ZERO: - alpha_arg[i] = r200_zero_alpha[op]; - break; - case GL_ONE: - alpha_arg[i] = r200_zero_alpha[op+1]; - break; - case GL_TEXTURE0: - case GL_TEXTURE1: - case GL_TEXTURE2: - case GL_TEXTURE3: - case GL_TEXTURE4: - case GL_TEXTURE5: - alpha_arg[i] = r200_register_alpha[op][srcAreplace - GL_TEXTURE0]; - break; - default: - return GL_FALSE; - } - } - else { - if (slot == 0) - alpha_arg[i] = r200_primary_alpha[op]; - else - alpha_arg[i] = r200_register_alpha[op] - [rmesa->state.texture.unit[unit - 1].outputreg]; - } - break; - case GL_ZERO: - alpha_arg[i] = r200_zero_alpha[op]; - break; - case GL_ONE: - alpha_arg[i] = r200_zero_alpha[op+1]; - break; - case GL_TEXTURE0: - case GL_TEXTURE1: - case GL_TEXTURE2: - case GL_TEXTURE3: - case GL_TEXTURE4: - case GL_TEXTURE5: - alpha_arg[i] = r200_register_alpha[op][srcAi - GL_TEXTURE0]; - break; - default: - return GL_FALSE; - } - } - - /* Step 2: - * Build up the color and alpha combine functions. - */ - switch ( texUnit->_CurrentCombine->ModeRGB ) { - case GL_REPLACE: - color_combine = (R200_TXC_ARG_A_ZERO | - R200_TXC_ARG_B_ZERO | - R200_TXC_OP_MADD); - R200_COLOR_ARG( 0, C ); - break; - case GL_MODULATE: - color_combine = (R200_TXC_ARG_C_ZERO | - R200_TXC_OP_MADD); - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, B ); - break; - case GL_ADD: - color_combine = (R200_TXC_ARG_B_ZERO | - R200_TXC_COMP_ARG_B | - R200_TXC_OP_MADD); - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, C ); - break; - case GL_ADD_SIGNED: - color_combine = (R200_TXC_ARG_B_ZERO | - R200_TXC_COMP_ARG_B | - R200_TXC_BIAS_ARG_C | /* new */ - R200_TXC_OP_MADD); /* was ADDSIGNED */ - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, C ); - break; - case GL_SUBTRACT: - color_combine = (R200_TXC_ARG_B_ZERO | - R200_TXC_COMP_ARG_B | - R200_TXC_NEG_ARG_C | - R200_TXC_OP_MADD); - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, C ); - break; - case GL_INTERPOLATE: - color_combine = (R200_TXC_OP_LERP); - R200_COLOR_ARG( 0, B ); - R200_COLOR_ARG( 1, A ); - R200_COLOR_ARG( 2, C ); - break; - - case GL_DOT3_RGB_EXT: - case GL_DOT3_RGBA_EXT: - /* The EXT version of the DOT3 extension does not support the - * scale factor, but the ARB version (and the version in OpenGL - * 1.3) does. - */ - RGBshift = 0; - FALLTHROUGH; - - case GL_DOT3_RGB: - case GL_DOT3_RGBA: - /* DOT3 works differently on R200 than on R100. On R100, just - * setting the DOT3 mode did everything for you. On R200, the - * driver has to enable the biasing and scale in the inputs to - * put them in the proper [-1,1] range. This is what the 4x and - * the -0.5 in the DOT3 spec do. The post-scale is then set - * normally. - */ - - color_combine = (R200_TXC_ARG_C_ZERO | - R200_TXC_OP_DOT3 | - R200_TXC_BIAS_ARG_A | - R200_TXC_BIAS_ARG_B | - R200_TXC_SCALE_ARG_A | - R200_TXC_SCALE_ARG_B); - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, B ); - break; - - case GL_MODULATE_ADD_ATI: - color_combine = (R200_TXC_OP_MADD); - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, C ); - R200_COLOR_ARG( 2, B ); - break; - case GL_MODULATE_SIGNED_ADD_ATI: - color_combine = (R200_TXC_BIAS_ARG_C | /* new */ - R200_TXC_OP_MADD); /* was ADDSIGNED */ - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, C ); - R200_COLOR_ARG( 2, B ); - break; - case GL_MODULATE_SUBTRACT_ATI: - color_combine = (R200_TXC_NEG_ARG_C | - R200_TXC_OP_MADD); - R200_COLOR_ARG( 0, A ); - R200_COLOR_ARG( 1, C ); - R200_COLOR_ARG( 2, B ); - break; - default: - return GL_FALSE; - } - - switch ( texUnit->_CurrentCombine->ModeA ) { - case GL_REPLACE: - alpha_combine = (R200_TXA_ARG_A_ZERO | - R200_TXA_ARG_B_ZERO | - R200_TXA_OP_MADD); - R200_ALPHA_ARG( 0, C ); - break; - case GL_MODULATE: - alpha_combine = (R200_TXA_ARG_C_ZERO | - R200_TXA_OP_MADD); - R200_ALPHA_ARG( 0, A ); - R200_ALPHA_ARG( 1, B ); - break; - case GL_ADD: - alpha_combine = (R200_TXA_ARG_B_ZERO | - R200_TXA_COMP_ARG_B | - R200_TXA_OP_MADD); - R200_ALPHA_ARG( 0, A ); - R200_ALPHA_ARG( 1, C ); - break; - case GL_ADD_SIGNED: - alpha_combine = (R200_TXA_ARG_B_ZERO | - R200_TXA_COMP_ARG_B | - R200_TXA_BIAS_ARG_C | /* new */ - R200_TXA_OP_MADD); /* was ADDSIGNED */ - R200_ALPHA_ARG( 0, A ); - R200_ALPHA_ARG( 1, C ); - break; - case GL_SUBTRACT: - alpha_combine = (R200_TXA_ARG_B_ZERO | - R200_TXA_COMP_ARG_B | - R200_TXA_NEG_ARG_C | - R200_TXA_OP_MADD); - R200_ALPHA_ARG( 0, A ); - R200_ALPHA_ARG( 1, C ); - break; - case GL_INTERPOLATE: - alpha_combine = (R200_TXA_OP_LERP); - R200_ALPHA_ARG( 0, B ); - R200_ALPHA_ARG( 1, A ); - R200_ALPHA_ARG( 2, C ); - break; - - case GL_MODULATE_ADD_ATI: - alpha_combine = (R200_TXA_OP_MADD); - R200_ALPHA_ARG( 0, A ); - R200_ALPHA_ARG( 1, C ); - R200_ALPHA_ARG( 2, B ); - break; - case GL_MODULATE_SIGNED_ADD_ATI: - alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */ - R200_TXA_OP_MADD); /* was ADDSIGNED */ - R200_ALPHA_ARG( 0, A ); - R200_ALPHA_ARG( 1, C ); - R200_ALPHA_ARG( 2, B ); - break; - case GL_MODULATE_SUBTRACT_ATI: - alpha_combine = (R200_TXA_NEG_ARG_C | - R200_TXA_OP_MADD); - R200_ALPHA_ARG( 0, A ); - R200_ALPHA_ARG( 1, C ); - R200_ALPHA_ARG( 2, B ); - break; - default: - return GL_FALSE; - } - - if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT) - || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) { - alpha_scale |= R200_TXA_DOT_ALPHA; - Ashift = RGBshift; - } - - /* Step 3: - * Apply the scale factor. - */ - color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT); - alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT); - - /* All done! - */ - } - - if ( rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] != color_combine || - rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] != alpha_combine || - rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] != color_scale || - rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] != alpha_scale) { - R200_STATECHANGE( rmesa, pix[slot] ); - rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] = color_combine; - rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] = alpha_combine; - rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] = color_scale; - rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] = alpha_scale; - } - - return GL_TRUE; -} - -void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format, - __DRIdrawable *dPriv) -{ - struct gl_texture_object *texObj; - struct gl_texture_image *texImage; - struct radeon_renderbuffer *rb; - radeon_texture_image *rImage; - radeonContextPtr radeon; - struct radeon_framebuffer *rfb; - radeonTexObjPtr t; - uint32_t pitch_val; - mesa_format texFormat; - - radeon = pDRICtx->driverPrivate; - - rfb = dPriv->driverPrivate; - texObj = _mesa_get_current_tex_object(&radeon->glCtx, target); - texImage = _mesa_get_tex_image(&radeon->glCtx, texObj, target, 0); - - rImage = get_radeon_texture_image(texImage); - t = radeon_tex_obj(texObj); - if (t == NULL) { - return; - } - - radeon_update_renderbuffers(pDRICtx, dPriv, GL_TRUE); - rb = rfb->color_rb[0]; - if (rb->bo == NULL) { - /* Failed to BO for the buffer */ - return; - } - - _mesa_lock_texture(&radeon->glCtx, texObj); - if (t->bo) { - radeon_bo_unref(t->bo); - t->bo = NULL; - } - if (rImage->bo) { - radeon_bo_unref(rImage->bo); - rImage->bo = NULL; - } - - radeon_miptree_unreference(&t->mt); - radeon_miptree_unreference(&rImage->mt); - - rImage->bo = rb->bo; - radeon_bo_ref(rImage->bo); - t->bo = rb->bo; - radeon_bo_ref(t->bo); - t->tile_bits = 0; - t->image_override = GL_TRUE; - t->override_offset = 0; - t->pp_txpitch &= (1 << 13) -1; - pitch_val = rb->pitch; - switch (rb->cpp) { - case 4: - if (texture_format == __DRI_TEXTURE_FORMAT_RGB) - texFormat = MESA_FORMAT_BGR_UNORM8; - else - texFormat = MESA_FORMAT_B8G8R8A8_UNORM; - break; - case 3: - default: - texFormat = MESA_FORMAT_BGR_UNORM8; - break; - case 2: - texFormat = MESA_FORMAT_B5G6R5_UNORM; - break; - } - - t->pp_txformat = tx_table_le[texFormat].format; - t->pp_txfilter |= tx_table_le[texFormat].filter; - - _mesa_init_teximage_fields(&radeon->glCtx, texImage, - rb->base.Base.Width, rb->base.Base.Height, - 1, 0, - rb->cpp, texFormat); - rImage->base.RowStride = rb->pitch / rb->cpp; - - - t->pp_txsize = ((rb->base.Base.Width - 1) << RADEON_TEX_USIZE_SHIFT) - | ((rb->base.Base.Height - 1) << RADEON_TEX_VSIZE_SHIFT); - - if (target == GL_TEXTURE_RECTANGLE_NV) { - t->pp_txformat |= R200_TXFORMAT_NON_POWER2; - t->pp_txpitch = pitch_val; - t->pp_txpitch -= 32; - } else { - t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK | - R200_TXFORMAT_HEIGHT_MASK | - R200_TXFORMAT_CUBIC_MAP_ENABLE | - R200_TXFORMAT_F5_WIDTH_MASK | - R200_TXFORMAT_F5_HEIGHT_MASK); - t->pp_txformat |= ((texImage->WidthLog2 << R200_TXFORMAT_WIDTH_SHIFT) | - (texImage->HeightLog2 << R200_TXFORMAT_HEIGHT_SHIFT)); - } - - t->validated = GL_TRUE; - _mesa_unlock_texture(&radeon->glCtx, texObj); - return; -} - - -void r200SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) -{ - r200SetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); -} - - -#define REF_COLOR 1 -#define REF_ALPHA 2 - -static GLboolean r200UpdateAllTexEnv( struct gl_context *ctx ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLint i, j, currslot; - GLint maxunitused = -1; - GLboolean texregfree[6] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; - GLubyte stageref[7] = {0, 0, 0, 0, 0, 0, 0}; - GLint nextunit[R200_MAX_TEXTURE_UNITS] = {0, 0, 0, 0, 0, 0}; - GLint currentnext = -1; - GLboolean ok; - - /* find highest used unit */ - for ( j = 0; j < R200_MAX_TEXTURE_UNITS; j++) { - if (ctx->Texture.Unit[j]._Current) { - maxunitused = j; - } - } - stageref[maxunitused + 1] = REF_COLOR | REF_ALPHA; - - for ( j = maxunitused; j >= 0; j-- ) { - const struct gl_texture_unit *rtexUnit = &ctx->Texture.Unit[j]; - const struct gl_fixedfunc_texture_unit *texUnit = - &ctx->Texture.FixedFuncUnit[j]; - - rmesa->state.texture.unit[j].outputreg = -1; - - if (stageref[j + 1]) { - - /* use the lowest available reg. That gets us automatically reg0 for the last stage. - need this even for disabled units, as it may get referenced due to the replace - optimization */ - for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS; i++ ) { - if (texregfree[i]) { - rmesa->state.texture.unit[j].outputreg = i; - break; - } - } - if (rmesa->state.texture.unit[j].outputreg == -1) { - /* no more free regs we can use. Need a fallback :-( */ - return GL_FALSE; - } - - nextunit[j] = currentnext; - - if (!rtexUnit->_Current) { - /* the not enabled stages are referenced "indirectly", - must not cut off the lower stages */ - stageref[j] = REF_COLOR | REF_ALPHA; - continue; - } - currentnext = j; - - const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB; - const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; - const GLboolean isdot3rgba = (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) || - (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT); - - - /* check if we need the color part, special case for dot3_rgba - as if only the alpha part is referenced later on it still is using the color part */ - if ((stageref[j + 1] & REF_COLOR) || isdot3rgba) { - for ( i = 0 ; i < numColorArgs ; i++ ) { - const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i]; - const GLuint op = texUnit->_CurrentCombine->OperandRGB[i]; - switch ( srcRGBi ) { - case GL_PREVIOUS: - /* op 0/1 are referencing color, op 2/3 alpha */ - stageref[j] |= (op >> 1) + 1; - break; - case GL_TEXTURE: - texregfree[j] = GL_FALSE; - break; - case GL_TEXTURE0: - case GL_TEXTURE1: - case GL_TEXTURE2: - case GL_TEXTURE3: - case GL_TEXTURE4: - case GL_TEXTURE5: - texregfree[srcRGBi - GL_TEXTURE0] = GL_FALSE; - break; - default: /* don't care about other sources here */ - break; - } - } - } - - /* alpha args are ignored for dot3_rgba */ - if ((stageref[j + 1] & REF_ALPHA) && !isdot3rgba) { - - for ( i = 0 ; i < numAlphaArgs ; i++ ) { - const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i]; - switch ( srcAi ) { - case GL_PREVIOUS: - stageref[j] |= REF_ALPHA; - break; - case GL_TEXTURE: - texregfree[j] = GL_FALSE; - break; - case GL_TEXTURE0: - case GL_TEXTURE1: - case GL_TEXTURE2: - case GL_TEXTURE3: - case GL_TEXTURE4: - case GL_TEXTURE5: - texregfree[srcAi - GL_TEXTURE0] = GL_FALSE; - break; - default: /* don't care about other sources here */ - break; - } - } - } - } - } - - /* don't enable texture sampling for units if the result is not used */ - for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) { - if (ctx->Texture.Unit[i]._Current && !texregfree[i]) - rmesa->state.texture.unit[i].unitneeded = 1 << _mesa_tex_target_to_index(ctx, ctx->Texture.Unit[i]._Current->Target); - else rmesa->state.texture.unit[i].unitneeded = 0; - } - - ok = GL_TRUE; - currslot = 0; - rmesa->state.envneeded = 1; - - i = 0; - while ((i <= maxunitused) && (i >= 0)) { - /* only output instruction if the results are referenced */ - if (ctx->Texture.Unit[i]._Current && stageref[i+1]) { - GLuint replaceunit = i; - /* try to optimize GL_REPLACE away (only one level deep though) */ - if ( (ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ModeRGB == GL_REPLACE) && - (ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ModeA == GL_REPLACE) && - (ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ScaleShiftRGB == 0) && - (ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ScaleShiftA == 0) && - (nextunit[i] > 0) ) { - /* yippie! can optimize it away! */ - replaceunit = i; - i = nextunit[i]; - } - - /* need env instruction slot */ - rmesa->state.envneeded |= 1 << currslot; - ok = r200UpdateTextureEnv( ctx, i, currslot, replaceunit ); - if (!ok) return GL_FALSE; - currslot++; - } - i = i + 1; - } - - if (currslot == 0) { - /* need one stage at least */ - rmesa->state.texture.unit[0].outputreg = 0; - ok = r200UpdateTextureEnv( ctx, 0, 0, 0 ); - } - - R200_STATECHANGE( rmesa, ctx ); - rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_BLEND_ENABLE_MASK | R200_MULTI_PASS_ENABLE); - rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= rmesa->state.envneeded << R200_TEX_BLEND_0_ENABLE_SHIFT; - - return ok; -} - -#undef REF_COLOR -#undef REF_ALPHA - - -#define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \ - R200_MIN_FILTER_MASK | \ - R200_MAG_FILTER_MASK | \ - R200_MAX_ANISO_MASK | \ - R200_YUV_TO_RGB | \ - R200_YUV_TEMPERATURE_MASK | \ - R200_CLAMP_S_MASK | \ - R200_CLAMP_T_MASK | \ - R200_BORDER_MODE_D3D ) - -#define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \ - R200_TXFORMAT_HEIGHT_MASK | \ - R200_TXFORMAT_FORMAT_MASK | \ - R200_TXFORMAT_F5_WIDTH_MASK | \ - R200_TXFORMAT_F5_HEIGHT_MASK | \ - R200_TXFORMAT_ALPHA_IN_MAP | \ - R200_TXFORMAT_CUBIC_MAP_ENABLE | \ - R200_TXFORMAT_NON_POWER2) - -#define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \ - R200_TEXCOORD_MASK | \ - R200_MIN_MIP_LEVEL_MASK | \ - R200_CLAMP_Q_MASK | \ - R200_VOLUME_FILTER_MASK) - - -static void disable_tex_obj_state( r200ContextPtr rmesa, - int unit ) -{ - - R200_STATECHANGE( rmesa, vtx ); - rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3)); - - R200_STATECHANGE( rmesa, ctx ); - rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit); - if (rmesa->radeon.TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) { - TCL_FALLBACK( &rmesa->radeon.glCtx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE); - } - - /* Actually want to keep all units less than max active texture - * enabled, right? Fix this for >2 texunits. - */ - - { - GLuint tmp = rmesa->TexGenEnabled; - - rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit); - rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit); - rmesa->TexGenNeedNormals[unit] = GL_FALSE; - rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit); - - if (tmp != rmesa->TexGenEnabled) { - rmesa->recheck_texgen[unit] = GL_TRUE; - rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; - } - } -} -static void import_tex_obj_state( r200ContextPtr rmesa, - int unit, - radeonTexObjPtr texobj ) -{ -/* do not use RADEON_DB_STATE to avoid stale texture caches */ - GLuint *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0]; - - R200_STATECHANGE( rmesa, tex[unit] ); - - cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK; - cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK; - cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; - cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK; - cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK; - cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK; - cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */ - cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */ - cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color; - - if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) { - GLuint *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0]; - - R200_STATECHANGE( rmesa, cube[unit] ); - cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces; - /* that value is submitted twice. could change cube atom - to not include that command when new drm is used */ - cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces; - } - -} - -static void set_texgen_matrix( r200ContextPtr rmesa, - GLuint unit, - const GLfloat *s_plane, - const GLfloat *t_plane, - const GLfloat *r_plane, - const GLfloat *q_plane ) -{ - GLfloat m[16]; - - m[0] = s_plane[0]; - m[4] = s_plane[1]; - m[8] = s_plane[2]; - m[12] = s_plane[3]; - - m[1] = t_plane[0]; - m[5] = t_plane[1]; - m[9] = t_plane[2]; - m[13] = t_plane[3]; - - m[2] = r_plane[0]; - m[6] = r_plane[1]; - m[10] = r_plane[2]; - m[14] = r_plane[3]; - - m[3] = q_plane[0]; - m[7] = q_plane[1]; - m[11] = q_plane[2]; - m[15] = q_plane[3]; - - _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m); - _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) ); - rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit; -} - - -static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled, - const GLfloat *planeS, - const GLfloat *planeT, - const GLfloat *planeR, - const GLfloat *planeQ) -{ - GLuint needtgenable = 0; - - if (!(texGenEnabled & S_BIT)) { - if (((texGenEnabled & T_BIT) && planeT[0] != 0.0) || - ((texGenEnabled & R_BIT) && planeR[0] != 0.0) || - ((texGenEnabled & Q_BIT) && planeQ[0] != 0.0)) { - needtgenable |= S_BIT; - } - } - if (!(texGenEnabled & T_BIT)) { - if (((texGenEnabled & S_BIT) && planeS[1] != 0.0) || - ((texGenEnabled & R_BIT) && planeR[1] != 0.0) || - ((texGenEnabled & Q_BIT) && planeQ[1] != 0.0)) { - needtgenable |= T_BIT; - } - } - if (!(texGenEnabled & R_BIT)) { - if (((texGenEnabled & S_BIT) && planeS[2] != 0.0) || - ((texGenEnabled & T_BIT) && planeT[2] != 0.0) || - ((texGenEnabled & Q_BIT) && planeQ[2] != 0.0)) { - needtgenable |= R_BIT; - } - } - if (!(texGenEnabled & Q_BIT)) { - if (((texGenEnabled & S_BIT) && planeS[3] != 0.0) || - ((texGenEnabled & T_BIT) && planeT[3] != 0.0) || - ((texGenEnabled & R_BIT) && planeR[3] != 0.0)) { - needtgenable |= Q_BIT; - } - } - - return needtgenable; -} - - -/* - * Returns GL_FALSE if fallback required. - */ -static GLboolean r200_validate_texgen( struct gl_context *ctx, GLuint unit ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - const struct gl_fixedfunc_texture_unit *texUnit = - &ctx->Texture.FixedFuncUnit[unit]; - GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4; - GLuint tgi, tgcm; - GLuint mode = 0; - GLboolean mixed_fallback = GL_FALSE; - static const GLfloat I[16] = { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 }; - static const GLfloat reflect[16] = { - -1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, -1, 0, - 0, 0, 0, 1 }; - - rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit); - rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit); - rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit); - rmesa->TexGenNeedNormals[unit] = GL_FALSE; - tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK << - inputshift); - tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK << - (unit * 4)); - - if (0) - fprintf(stderr, "%s unit %d\n", __func__, unit); - - if (texUnit->TexGenEnabled & S_BIT) { - mode = texUnit->GenS.Mode; - } else { - tgcm |= R200_TEXGEN_COMP_S << (unit * 4); - } - - if (texUnit->TexGenEnabled & T_BIT) { - if (texUnit->GenT.Mode != mode) - mixed_fallback = GL_TRUE; - } else { - tgcm |= R200_TEXGEN_COMP_T << (unit * 4); - } - if (texUnit->TexGenEnabled & R_BIT) { - if (texUnit->GenR.Mode != mode) - mixed_fallback = GL_TRUE; - } else { - tgcm |= R200_TEXGEN_COMP_R << (unit * 4); - } - - if (texUnit->TexGenEnabled & Q_BIT) { - if (texUnit->GenQ.Mode != mode) - mixed_fallback = GL_TRUE; - } else { - tgcm |= R200_TEXGEN_COMP_Q << (unit * 4); - } - - if (mixed_fallback) { - if (R200_DEBUG & RADEON_FALLBACKS) - fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n", - texUnit->TexGenEnabled, texUnit->GenS.Mode, texUnit->GenT.Mode, - texUnit->GenR.Mode, texUnit->GenQ.Mode); - return GL_FALSE; - } - -/* we CANNOT do mixed mode if the texgen mode requires a plane where the input - is not enabled for texgen, since the planes are concatenated into texmat, - and thus the input will come from texcoord rather than tex gen equation! - Either fallback or just hope that those texcoords aren't really needed... - Assuming the former will cause lots of unnecessary fallbacks, the latter will - generate bogus results sometimes - it's pretty much impossible to really know - when a fallback is needed, depends on texmat and what sort of texture is bound - etc, - for now fallback if we're missing either S or T bits, there's a high - probability we need the texcoords in that case. - That's a lot of work for some obscure texgen mixed mode fixup - why oh why - doesn't the chip just directly accept the plane parameters :-(. */ - switch (mode) { - case GL_OBJECT_LINEAR: { - GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled, - texUnit->ObjectPlane[GEN_S], - texUnit->ObjectPlane[GEN_T], - texUnit->ObjectPlane[GEN_R], - texUnit->ObjectPlane[GEN_Q] ); - if (needtgenable & (S_BIT | T_BIT)) { - if (R200_DEBUG & RADEON_FALLBACKS) - fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n", - texUnit->TexGenEnabled); - return GL_FALSE; - } - if (needtgenable & (R_BIT)) { - tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4)); - } - if (needtgenable & (Q_BIT)) { - tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4)); - } - - tgi |= R200_TEXGEN_INPUT_OBJ << inputshift; - set_texgen_matrix( rmesa, unit, - (texUnit->TexGenEnabled & S_BIT) ? texUnit->ObjectPlane[GEN_S] : I, - (texUnit->TexGenEnabled & T_BIT) ? texUnit->ObjectPlane[GEN_T] : I + 4, - (texUnit->TexGenEnabled & R_BIT) ? texUnit->ObjectPlane[GEN_R] : I + 8, - (texUnit->TexGenEnabled & Q_BIT) ? texUnit->ObjectPlane[GEN_Q] : I + 12); - } - break; - - case GL_EYE_LINEAR: { - GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled, - texUnit->EyePlane[GEN_S], - texUnit->EyePlane[GEN_T], - texUnit->EyePlane[GEN_R], - texUnit->EyePlane[GEN_Q] ); - if (needtgenable & (S_BIT | T_BIT)) { - if (R200_DEBUG & RADEON_FALLBACKS) - fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n", - texUnit->TexGenEnabled); - return GL_FALSE; - } - if (needtgenable & (R_BIT)) { - tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4)); - } - if (needtgenable & (Q_BIT)) { - tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4)); - } - tgi |= R200_TEXGEN_INPUT_EYE << inputshift; - set_texgen_matrix( rmesa, unit, - (texUnit->TexGenEnabled & S_BIT) ? texUnit->EyePlane[GEN_S] : I, - (texUnit->TexGenEnabled & T_BIT) ? texUnit->EyePlane[GEN_T] : I + 4, - (texUnit->TexGenEnabled & R_BIT) ? texUnit->EyePlane[GEN_R] : I + 8, - (texUnit->TexGenEnabled & Q_BIT) ? texUnit->EyePlane[GEN_Q] : I + 12); - } - break; - - case GL_REFLECTION_MAP_NV: - rmesa->TexGenNeedNormals[unit] = GL_TRUE; - tgi |= R200_TEXGEN_INPUT_EYE_REFLECT << inputshift; - /* pretty weird, must only negate when lighting is enabled? */ - if (ctx->Light.Enabled) - set_texgen_matrix( rmesa, unit, - (texUnit->TexGenEnabled & S_BIT) ? reflect : I, - (texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4, - (texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8, - I + 12); - break; - - case GL_NORMAL_MAP_NV: - rmesa->TexGenNeedNormals[unit] = GL_TRUE; - tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift; - break; - - case GL_SPHERE_MAP: - rmesa->TexGenNeedNormals[unit] = GL_TRUE; - tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift; - break; - - case 0: - /* All texgen units were disabled, so just pass coords through. */ - tgi |= unit << inputshift; - break; - - default: - /* Unsupported mode, fallback: - */ - if (R200_DEBUG & RADEON_FALLBACKS) - fprintf(stderr, "fallback unsupported texgen, %d\n", - texUnit->GenS.Mode); - return GL_FALSE; - } - - rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit; - rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit; - - if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] || - tgcm != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2]) - { - R200_STATECHANGE(rmesa, tcg); - rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = tgi; - rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = tgcm; - } - - return GL_TRUE; -} - -void set_re_cntl_d3d( struct gl_context *ctx, int unit, GLboolean use_d3d ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - - GLuint re_cntl; - - re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D << (2 * unit)); - if (use_d3d) - re_cntl |= R200_VTX_STQ0_D3D << (2 * unit); - - if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) { - R200_STATECHANGE( rmesa, set ); - rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl; - } -} - -/** - * Compute the cached hardware register values for the given texture object. - * - * \param rmesa Context pointer - * \param t the r300 texture object - */ -static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t) -{ - const struct gl_texture_image *firstImage = t->base.Image[0][t->minLod]; - GLint log2Width, log2Height, log2Depth, texelBytes; - uint extra_size = 0; - - if ( t->bo ) { - return; - } - - log2Width = firstImage->WidthLog2; - log2Height = firstImage->HeightLog2; - log2Depth = firstImage->DepthLog2; - texelBytes = _mesa_get_format_bytes(firstImage->TexFormat); - - radeon_print(RADEON_TEXTURE, RADEON_TRACE, - "%s(%p, tex %p) log2(w %d, h %d, d %d), texelBytes %d. format %d\n", - __func__, rmesa, t, log2Width, log2Height, - log2Depth, texelBytes, firstImage->TexFormat); - - if (!t->image_override) { - if (VALID_FORMAT(firstImage->TexFormat)) { -#if UTIL_ARCH_LITTLE_ENDIAN - const struct tx_table *table = tx_table_le; -#else - const struct tx_table *table = tx_table_be; -#endif - - t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK | - R200_TXFORMAT_ALPHA_IN_MAP); - t->pp_txfilter &= ~R200_YUV_TO_RGB; - - t->pp_txformat |= table[ firstImage->TexFormat ].format; - t->pp_txfilter |= table[ firstImage->TexFormat ].filter; - - - } else { - _mesa_problem(NULL, "unexpected texture format in %s", - __func__); - return; - } - } - - t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK; - t->pp_txfilter |= ((t->maxLod) << R200_MAX_MIP_LEVEL_SHIFT) - & R200_MAX_MIP_LEVEL_MASK; - - if ( t->pp_txfilter & - (R200_MIN_FILTER_NEAREST_MIP_NEAREST - | R200_MIN_FILTER_NEAREST_MIP_LINEAR - | R200_MIN_FILTER_LINEAR_MIP_NEAREST - | R200_MIN_FILTER_LINEAR_MIP_LINEAR - | R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST - | R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR)) - extra_size = t->minLod; - - t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK | - R200_TXFORMAT_HEIGHT_MASK | - R200_TXFORMAT_CUBIC_MAP_ENABLE | - R200_TXFORMAT_F5_WIDTH_MASK | - R200_TXFORMAT_F5_HEIGHT_MASK); - t->pp_txformat |= (((log2Width + extra_size) << R200_TXFORMAT_WIDTH_SHIFT) | - ((log2Height + extra_size)<< R200_TXFORMAT_HEIGHT_SHIFT)); - - t->tile_bits = 0; - - t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK - | R200_MIN_MIP_LEVEL_MASK); - - t->pp_txformat_x |= (t->minLod << R200_MIN_MIP_LEVEL_SHIFT) - & R200_MIN_MIP_LEVEL_MASK; - - if (t->base.Target == GL_TEXTURE_3D) { - t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT); - t->pp_txformat_x |= R200_TEXCOORD_VOLUME; - - } - else if (t->base.Target == GL_TEXTURE_CUBE_MAP) { - assert(log2Width == log2Height); - t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) | - (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) | - /* don't think we need this bit, if it exists at all - fglrx does not set it */ - (R200_TXFORMAT_CUBIC_MAP_ENABLE)); - t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV; - t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) | - (log2Height << R200_FACE_HEIGHT_1_SHIFT) | - (log2Width << R200_FACE_WIDTH_2_SHIFT) | - (log2Height << R200_FACE_HEIGHT_2_SHIFT) | - (log2Width << R200_FACE_WIDTH_3_SHIFT) | - (log2Height << R200_FACE_HEIGHT_3_SHIFT) | - (log2Width << R200_FACE_WIDTH_4_SHIFT) | - (log2Height << R200_FACE_HEIGHT_4_SHIFT)); - } - else { - /* If we don't in fact send enough texture coordinates, q will be 1, - * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?) - */ - t->pp_txformat_x |= R200_TEXCOORD_PROJ; - } - /* FIXME: NPOT sizes, is it correct really? */ - t->pp_txsize = (((firstImage->Width - 1) << R200_PP_TX_WIDTHMASK_SHIFT) - | ((firstImage->Height - 1) << R200_PP_TX_HEIGHTMASK_SHIFT)); - - if ( !t->image_override ) { - if (_mesa_is_format_compressed(firstImage->TexFormat)) - t->pp_txpitch = (firstImage->Width + 63) & ~(63); - else - t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63); - t->pp_txpitch -= 32; - } - - if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) { - t->pp_txformat |= R200_TXFORMAT_NON_POWER2; - } - -} - -static GLboolean r200_validate_texture(struct gl_context *ctx, struct gl_texture_object *texObj, int unit) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - radeonTexObj *t = radeon_tex_obj(texObj); - - if (!radeon_validate_texture_miptree(ctx, _mesa_get_samplerobj(ctx, unit), texObj)) - return GL_FALSE; - - r200_validate_texgen(ctx, unit); - /* Configure the hardware registers (more precisely, the cached version - * of the hardware registers). */ - setup_hardware_state(rmesa, t); - - if (texObj->Target == GL_TEXTURE_RECTANGLE_NV || - texObj->Target == GL_TEXTURE_2D || - texObj->Target == GL_TEXTURE_1D) - set_re_cntl_d3d( ctx, unit, GL_FALSE ); - else - set_re_cntl_d3d( ctx, unit, GL_TRUE ); - R200_STATECHANGE( rmesa, ctx ); - rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit; - - R200_STATECHANGE( rmesa, vtx ); - rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3)); - rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3); - - rmesa->recheck_texgen[unit] = GL_TRUE; - r200TexUpdateParameters(ctx, unit); - import_tex_obj_state( rmesa, unit, t ); - - if (rmesa->recheck_texgen[unit]) { - GLboolean fallback = !r200_validate_texgen( ctx, unit ); - TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback); - rmesa->recheck_texgen[unit] = 0; - rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; - } - - t->validated = GL_TRUE; - - FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback ); - - return !t->border_fallback; -} - -static GLboolean r200UpdateTextureUnit(struct gl_context *ctx, int unit) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded; - - if (!unitneeded) { - /* disable the unit */ - disable_tex_obj_state(rmesa, unit); - return GL_TRUE; - } - - if (!r200_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) { - _mesa_warning(ctx, - "failed to validate texture for unit %d.\n", - unit); - rmesa->state.texture.unit[unit].texobj = NULL; - return GL_FALSE; - } - - rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current); - return GL_TRUE; -} - - -void r200UpdateTextureState( struct gl_context *ctx ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLboolean ok; - GLuint dbg; - - /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or - rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since - we use these to determine if we want to emit the corresponding state - atoms. */ - R200_NEWPRIM( rmesa ); - - if (_mesa_ati_fragment_shader_enabled(ctx)) { - GLuint i; - for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) { - if (ctx->Texture.Unit[i]._Current) - rmesa->state.texture.unit[i].unitneeded = 1 << _mesa_tex_target_to_index(ctx, ctx->Texture.Unit[i]._Current->Target); - else - rmesa->state.texture.unit[i].unitneeded = 0; - } - ok = GL_TRUE; - } - else { - ok = r200UpdateAllTexEnv( ctx ); - } - if (ok) { - ok = (r200UpdateTextureUnit( ctx, 0 ) && - r200UpdateTextureUnit( ctx, 1 ) && - r200UpdateTextureUnit( ctx, 2 ) && - r200UpdateTextureUnit( ctx, 3 ) && - r200UpdateTextureUnit( ctx, 4 ) && - r200UpdateTextureUnit( ctx, 5 )); - } - - if (ok && _mesa_ati_fragment_shader_enabled(ctx)) { - r200UpdateFragmentShader(ctx); - } - - FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok ); - - if (rmesa->radeon.TclFallback) - r200ChooseVertexState( ctx ); - - - if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) { - - /* - * T0 hang workaround ------------- - * not needed for r200 derivatives - */ - if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE && - (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) { - - R200_STATECHANGE(rmesa, ctx); - R200_STATECHANGE(rmesa, tex[1]); - rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE; - if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE)) - rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; - rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE; - } - else if (!_mesa_ati_fragment_shader_enabled(ctx)) { - if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) && - (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & R200_TXFORMAT_LOOKUP_DISABLE)) { - R200_STATECHANGE(rmesa, tex[1]); - rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~R200_TXFORMAT_LOOKUP_DISABLE; - } - } - /* do the same workaround for the first pass of a fragment shader. - * completely unknown if necessary / sufficient. - */ - if ((rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_ENABLE_MASK) == R200_PPX_TEX_0_ENABLE && - (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) { - - R200_STATECHANGE(rmesa, cst); - R200_STATECHANGE(rmesa, tex[1]); - rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_1_ENABLE; - if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE)) - rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; - rmesa->hw.tex[1].cmd[TEX_PP_TXMULTI_CTL] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE; - } - - /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ? - looks like that's not the case, if 8500/9100 owners don't complain remove this... - for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) { - if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE | - R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) && - ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > - R200_MIN_FILTER_LINEAR)) { - R200_STATECHANGE(rmesa, ctx); - R200_STATECHANGE(rmesa, tex[i+1]); - rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i); - rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; - rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000; - } - else { - if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) && - (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) { - R200_STATECHANGE(rmesa, tex[i+1]); - rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000; - } - } - } */ - - /* - * Texture cache LRU hang workaround ------------- - * not needed for r200 derivatives - * hopefully this covers first pass of a shader as well - */ - - /* While the cases below attempt to only enable the workaround in the - * specific cases necessary, they were insufficient. See bugzilla #1519, - * #729, #814. Tests with quake3 showed no impact on performance. - */ - dbg = 0x6; - - /* - if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) && - ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & - 0x04) == 0)) || - ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) && - ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & - 0x04) == 0)) || - ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) && - ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & - 0x04) == 0))) - { - dbg |= 0x02; - } - - if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) && - ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & - 0x04) == 0)) || - ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) && - ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & - 0x04) == 0)) || - ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) && - ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & - 0x04) == 0))) - { - dbg |= 0x04; - }*/ - - if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) { - R200_STATECHANGE( rmesa, tam ); - rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg; - if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg); - } - } -} |