diff options
Diffstat (limited to 'src/i810texstate.c')
-rw-r--r-- | src/i810texstate.c | 752 |
1 files changed, 752 insertions, 0 deletions
diff --git a/src/i810texstate.c b/src/i810texstate.c new file mode 100644 index 0000000..558aef9 --- /dev/null +++ b/src/i810texstate.c @@ -0,0 +1,752 @@ +/* + * GLX Hardware Device Driver for Intel i810 + * Copyright (C) 1999 Keith Whitwell + * + * 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 + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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. + * + */ + +#include "glheader.h" +#include "macros.h" +#include "mtypes.h" +#include "texformat.h" +#include "simple_list.h" +#include "enums.h" + +#include "mm.h" + +#include "i810screen.h" +#include "i810_dri.h" + +#include "i810context.h" +#include "i810tex.h" +#include "i810state.h" +#include "i810ioctl.h" + + + + +static void i810SetTexImages( i810ContextPtr imesa, + struct gl_texture_object *tObj ) +{ + GLuint height, width, pitch, i, textureFormat, log_pitch; + i810TextureObjectPtr t = (i810TextureObjectPtr) tObj->DriverData; + const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; + GLint numLevels; + GLint log2Width, log2Height; + +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + + t->texelBytes = 2; + switch (baseImage->TexFormat->MesaFormat) { + case MESA_FORMAT_ARGB1555: + textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_ARGB1555; + break; + case MESA_FORMAT_ARGB4444: + textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_ARGB4444; + break; + case MESA_FORMAT_RGB565: + textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_RGB565; + break; + case MESA_FORMAT_AL88: + textureFormat = MI1_FMT_16BPP | MI1_PF_16BPP_AY88; + break; + case MESA_FORMAT_YCBCR: + textureFormat = MI1_FMT_422 | MI1_PF_422_YCRCB_SWAP_Y + | MI1_COLOR_CONV_ENABLE; + break; + case MESA_FORMAT_YCBCR_REV: + textureFormat = MI1_FMT_422 | MI1_PF_422_YCRCB + | MI1_COLOR_CONV_ENABLE; + break; + case MESA_FORMAT_CI8: + textureFormat = MI1_FMT_8CI | MI1_PF_8CI_ARGB4444; + t->texelBytes = 1; + break; + + default: + fprintf(stderr, "i810SetTexImages: bad image->Format\n" ); + return; + } + + driCalculateTextureFirstLastLevel( (driTextureObject *) t ); + + numLevels = t->base.lastLevel - t->base.firstLevel + 1; + + log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; + log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; + + /* Figure out the amount of memory required to hold all the mipmap + * levels. Choose the smallest pitch to accomodate the largest + * mipmap: + */ + width = tObj->Image[0][t->base.firstLevel]->Width * t->texelBytes; + for (pitch = 32, log_pitch=2 ; pitch < width ; pitch *= 2 ) + log_pitch++; + + /* All images must be loaded at this pitch. Count the number of + * lines required: + */ + for ( height = i = 0 ; i < numLevels ; i++ ) { + t->image[i].image = tObj->Image[0][t->base.firstLevel + i]; + t->image[i].offset = height * pitch; + t->image[i].internalFormat = baseImage->_BaseFormat; + height += t->image[i].image->Height; + } + + t->Pitch = pitch; + t->base.totalSize = height*pitch; + t->max_level = i-1; + t->dirty = I810_UPLOAD_TEX0 | I810_UPLOAD_TEX1; + t->Setup[I810_TEXREG_MI1] = (MI1_MAP_0 | textureFormat | log_pitch); + t->Setup[I810_TEXREG_MLL] = (GFX_OP_MAP_LOD_LIMITS | + MLL_MAP_0 | + MLL_UPDATE_MAX_MIP | + MLL_UPDATE_MIN_MIP | + ((numLevels - 1) << MLL_MIN_MIP_SHIFT)); + + LOCK_HARDWARE( imesa ); + i810UploadTexImagesLocked( imesa, t ); + UNLOCK_HARDWARE( imesa ); +} + +/* ================================================================ + * Texture combine functions + */ + + +static void set_color_stage( unsigned color, int stage, + i810ContextPtr imesa ) +{ + if ( color != imesa->Setup[I810_CTXREG_MC0 + stage] ) { + I810_STATECHANGE( imesa, I810_UPLOAD_CTX ); + imesa->Setup[I810_CTXREG_MC0 + stage] = color; + } +} + + +static void set_alpha_stage( unsigned alpha, int stage, + i810ContextPtr imesa ) +{ + if ( alpha != imesa->Setup[I810_CTXREG_MA0 + stage] ) { + I810_STATECHANGE( imesa, I810_UPLOAD_CTX ); + imesa->Setup[I810_CTXREG_MA0 + stage] = alpha; + } +} + + +static const unsigned operand_modifiers[] = { + 0, MC_ARG_INVERT, + MC_ARG_REPLICATE_ALPHA, MC_ARG_INVERT | MC_ARG_REPLICATE_ALPHA +}; + +/** + * Configure the hardware bits for the specified texture environment. + * + * Configures the hardware bits for the texture environment state for the + * specified texture unit. As combine stages are added, the values pointed + * to by \c color_stage and \c alpha_stage are incremented. + * + * \param ctx GL context pointer. + * \param unit Texture unit to be added. + * \param color_stage Next available hardware color combine stage. + * \param alpha_stage Next available hardware alpha combine stage. + * + * \returns + * If the combine mode for the specified texture unit could be added without + * requiring a software fallback, \c GL_TRUE is returned. Otherwise, + * \c GL_FALSE is returned. + * + * \todo + * If the mode is (GL_REPLACE, GL_PREVIOUS), treat it as though the texture + * stage is disabled. That is, don't emit any combine stages. + * + * \todo + * Add support for ATI_texture_env_combine3 modes. This will require using + * two combine stages. + * + * \todo + * Add support for the missing \c GL_INTERPOLATE modes. This will require + * using all three combine stages. There is a comment in the function + * describing how this might work. + * + * \todo + * If, after all the combine stages have been emitted, a texture is never + * actually used, disable the texture unit. That should save texture some + * memory bandwidth. This won't happen in this function, but this seems like + * a reasonable place to make note of it. + */ +static GLboolean +i810UpdateTexEnvCombine( GLcontext *ctx, GLuint unit, + int * color_stage, int * alpha_stage ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint color_arg[3] = { + MC_ARG_ONE, MC_ARG_ONE, MC_ARG_ONE + }; + GLuint alpha_arg[3] = { + MA_ARG_ITERATED_ALPHA, MA_ARG_ITERATED_ALPHA, MA_ARG_ITERATED_ALPHA + }; + GLuint i; + GLuint color_combine, alpha_combine; + const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB; + const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; + GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB; + GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA; + + + if ( !texUnit->_ReallyEnabled ) { + return GL_TRUE; + } + + + if ((*color_stage >= 3) || (*alpha_stage >= 3)) { + return GL_FALSE; + } + + + /* Step 1: + * Extract the color and alpha combine function arguments. + */ + + for ( i = 0 ; i < numColorArgs ; i++ ) { + unsigned op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR; + assert(op >= 0); + assert(op <= 3); + switch ( texUnit->_CurrentCombine->SourceRGB[i] ) { + case GL_TEXTURE0: + color_arg[i] = MC_ARG_TEX0_COLOR; + break; + case GL_TEXTURE1: + color_arg[i] = MC_ARG_TEX1_COLOR; + break; + case GL_TEXTURE: + color_arg[i] = (unit == 0) + ? MC_ARG_TEX0_COLOR : MC_ARG_TEX1_COLOR; + break; + case GL_CONSTANT: + color_arg[i] = MC_ARG_COLOR_FACTOR; + break; + case GL_PRIMARY_COLOR: + color_arg[i] = MC_ARG_ITERATED_COLOR; + break; + case GL_PREVIOUS: + color_arg[i] = (unit == 0) + ? MC_ARG_ITERATED_COLOR : MC_ARG_CURRENT_COLOR; + break; + case GL_ZERO: + /* Toggle the low bit of the op value. The is the 'invert' bit, + * and it acts to convert GL_ZERO+op to the equivalent GL_ONE+op. + */ + op ^= 1; + + /*FALLTHROUGH*/ + + case GL_ONE: + color_arg[i] = MC_ARG_ONE; + break; + default: + return GL_FALSE; + } + + color_arg[i] |= operand_modifiers[op]; + } + + + for ( i = 0 ; i < numAlphaArgs ; i++ ) { + unsigned op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA; + assert(op >= 0); + assert(op <= 1); + switch ( texUnit->_CurrentCombine->SourceA[i] ) { + case GL_TEXTURE0: + alpha_arg[i] = MA_ARG_TEX0_ALPHA; + break; + case GL_TEXTURE1: + alpha_arg[i] = MA_ARG_TEX1_ALPHA; + break; + case GL_TEXTURE: + alpha_arg[i] = (unit == 0) + ? MA_ARG_TEX0_ALPHA : MA_ARG_TEX1_ALPHA; + break; + case GL_CONSTANT: + alpha_arg[i] = MA_ARG_ALPHA_FACTOR; + break; + case GL_PRIMARY_COLOR: + alpha_arg[i] = MA_ARG_ITERATED_ALPHA; + break; + case GL_PREVIOUS: + alpha_arg[i] = (unit == 0) + ? MA_ARG_ITERATED_ALPHA : MA_ARG_CURRENT_ALPHA; + break; + case GL_ZERO: + /* Toggle the low bit of the op value. The is the 'invert' bit, + * and it acts to convert GL_ZERO+op to the equivalent GL_ONE+op. + */ + op ^= 1; + + /*FALLTHROUGH*/ + + case GL_ONE: + if (i != 2) { + return GL_FALSE; + } + + alpha_arg[i] = MA_ARG_ONE; + break; + default: + return GL_FALSE; + } + + alpha_arg[i] |= operand_modifiers[op]; + } + + + /* Step 2: + * Build up the color and alpha combine functions. + */ + switch ( texUnit->_CurrentCombine->ModeRGB ) { + case GL_REPLACE: + color_combine = MC_OP_ARG1; + break; + case GL_MODULATE: + color_combine = MC_OP_MODULATE + RGBshift; + RGBshift = 0; + break; + case GL_ADD: + color_combine = MC_OP_ADD; + break; + case GL_ADD_SIGNED: + color_combine = MC_OP_ADD_SIGNED; + break; + case GL_SUBTRACT: + color_combine = MC_OP_SUBTRACT; + break; + case GL_INTERPOLATE: + /* For interpolation, the i810 hardware has some limitations. It + * can't handle using the secondary or diffuse color (diffuse alpha + * is okay) for the third argument. + * + * It is possible to emulate the missing modes by using multiple + * combine stages. Unfortunately it requires all three stages to + * emulate a single interpolate stage. The (arg0*arg2) portion is + * done in stage zero and writes to MC_DEST_ACCUMULATOR. The + * (arg1*(1-arg2)) portion is done in stage 1, and the final stage is + * (MC_ARG1_ACCUMULATOR | MC_ARG2_CURRENT_COLOR | MC_OP_ADD). + * + * It can also be done without using the accumulator by rearranging + * the equation as (arg1 + (arg2 * (arg0 - arg1))). Too bad the i810 + * doesn't support the MODULATE_AND_ADD mode that the i830 supports. + * If it did, the interpolate could be done in only two stages. + */ + + if ( (color_arg[2] & MC_ARG_INVERT) != 0 ) { + unsigned temp = color_arg[0]; + + color_arg[0] = color_arg[1]; + color_arg[1] = temp; + color_arg[2] &= ~MC_ARG_INVERT; + } + + switch (color_arg[2]) { + case (MC_ARG_ONE): + case (MC_ARG_ONE | MC_ARG_REPLICATE_ALPHA): + color_combine = MC_OP_ARG1; + color_arg[1] = MC_ARG_ONE; + break; + + case (MC_ARG_COLOR_FACTOR): + return GL_FALSE; + + case (MC_ARG_COLOR_FACTOR | MC_ARG_REPLICATE_ALPHA): + color_combine = MC_OP_LIN_BLEND_ALPHA_FACTOR; + break; + + case (MC_ARG_ITERATED_COLOR): + return GL_FALSE; + + case (MC_ARG_ITERATED_COLOR | MC_ARG_REPLICATE_ALPHA): + color_combine = MC_OP_LIN_BLEND_ITER_ALPHA; + break; + + case (MC_ARG_SPECULAR_COLOR): + case (MC_ARG_SPECULAR_COLOR | MC_ARG_REPLICATE_ALPHA): + return GL_FALSE; + + case (MC_ARG_TEX0_COLOR): + color_combine = MC_OP_LIN_BLEND_TEX0_COLOR; + break; + + case (MC_ARG_TEX0_COLOR | MC_ARG_REPLICATE_ALPHA): + color_combine = MC_OP_LIN_BLEND_TEX0_ALPHA; + break; + + case (MC_ARG_TEX1_COLOR): + color_combine = MC_OP_LIN_BLEND_TEX1_COLOR; + break; + + case (MC_ARG_TEX1_COLOR | MC_ARG_REPLICATE_ALPHA): + color_combine = MC_OP_LIN_BLEND_TEX1_ALPHA; + break; + + default: + return GL_FALSE; + } + break; + + default: + return GL_FALSE; + } + + + switch ( texUnit->_CurrentCombine->ModeA ) { + case GL_REPLACE: + alpha_combine = MA_OP_ARG1; + break; + case GL_MODULATE: + alpha_combine = MA_OP_MODULATE + Ashift; + Ashift = 0; + break; + case GL_ADD: + alpha_combine = MA_OP_ADD; + break; + case GL_ADD_SIGNED: + alpha_combine = MA_OP_ADD_SIGNED; + break; + case GL_SUBTRACT: + alpha_combine = MA_OP_SUBTRACT; + break; + case GL_INTERPOLATE: + if ( (alpha_arg[2] & MA_ARG_INVERT) != 0 ) { + unsigned temp = alpha_arg[0]; + + alpha_arg[0] = alpha_arg[1]; + alpha_arg[1] = temp; + alpha_arg[2] &= ~MA_ARG_INVERT; + } + + switch (alpha_arg[2]) { + case MA_ARG_ONE: + alpha_combine = MA_OP_ARG1; + alpha_arg[1] = MA_ARG_ITERATED_ALPHA; + break; + + case MA_ARG_ALPHA_FACTOR: + alpha_combine = MA_OP_LIN_BLEND_ALPHA_FACTOR; + break; + + case MA_ARG_ITERATED_ALPHA: + alpha_combine = MA_OP_LIN_BLEND_ITER_ALPHA; + break; + + case MA_ARG_TEX0_ALPHA: + alpha_combine = MA_OP_LIN_BLEND_TEX0_ALPHA; + break; + + case MA_ARG_TEX1_ALPHA: + alpha_combine = MA_OP_LIN_BLEND_TEX1_ALPHA; + break; + + default: + return GL_FALSE; + } + break; + + default: + return GL_FALSE; + } + + + color_combine |= GFX_OP_MAP_COLOR_STAGES | (*color_stage << MC_STAGE_SHIFT) + | MC_UPDATE_DEST | MC_DEST_CURRENT + | MC_UPDATE_ARG1 | (color_arg[0] << MC_ARG1_SHIFT) + | MC_UPDATE_ARG2 | (color_arg[1] << MC_ARG2_SHIFT) + | MC_UPDATE_OP; + + alpha_combine |= GFX_OP_MAP_ALPHA_STAGES | (*alpha_stage << MA_STAGE_SHIFT) + | MA_UPDATE_ARG1 | (alpha_arg[0] << MA_ARG1_SHIFT) + | MA_UPDATE_ARG2 | (alpha_arg[1] << MA_ARG2_SHIFT) + | MA_UPDATE_OP; + + set_color_stage( color_combine, *color_stage, imesa ); + set_alpha_stage( alpha_combine, *alpha_stage, imesa ); + (*color_stage)++; + (*alpha_stage)++; + + + /* Step 3: + * Apply the scale factor. + */ + /* The only operation where the i810 directly supports adding a post- + * scale factor is modulate. For all the other modes the post-scale is + * emulated by inserting and extra modulate stage. For the modulate + * case, the scaling is handled above when color_combine / alpha_combine + * are initially set. + */ + + if ( RGBshift != 0 ) { + const unsigned color_scale = GFX_OP_MAP_COLOR_STAGES + | (*color_stage << MC_STAGE_SHIFT) + | MC_UPDATE_DEST | MC_DEST_CURRENT + | MC_UPDATE_ARG1 | (MC_ARG_CURRENT_COLOR << MC_ARG1_SHIFT) + | MC_UPDATE_ARG2 | (MC_ARG_ONE << MC_ARG2_SHIFT) + | MC_UPDATE_OP | (MC_OP_MODULATE + RGBshift); + + if ( *color_stage >= 3 ) { + return GL_FALSE; + } + + set_color_stage( color_scale, *color_stage, imesa ); + (*color_stage)++; + } + + + if ( Ashift != 0 ) { + const unsigned alpha_scale = GFX_OP_MAP_ALPHA_STAGES + | (*alpha_stage << MA_STAGE_SHIFT) + | MA_UPDATE_ARG1 | (MA_ARG_CURRENT_ALPHA << MA_ARG1_SHIFT) + | MA_UPDATE_ARG2 | (MA_ARG_ONE << MA_ARG2_SHIFT) + | MA_UPDATE_OP | (MA_OP_MODULATE + Ashift); + + if ( *alpha_stage >= 3 ) { + return GL_FALSE; + } + + set_alpha_stage( alpha_scale, *alpha_stage, imesa ); + (*alpha_stage)++; + } + + return GL_TRUE; +} + +static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; + + if (tObj->Image[0][tObj->BaseLevel]->Border > 0) { + return GL_FALSE; + } + + /* Upload teximages (not pipelined) + */ + if (t->base.dirty_images[0]) { + I810_FIREVERTICES(imesa); + i810SetTexImages( imesa, tObj ); + if (!t->base.memBlock) { + return GL_FALSE; + } + } + + /* Update state if this is a different texture object to last + * time. + */ + if (imesa->CurrentTexObj[unit] != t) { + I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); + imesa->CurrentTexObj[unit] = t; + t->base.bound |= (1U << unit); + + /* XXX: should be locked */ + driUpdateTextureLRU( (driTextureObject *) t ); + } + + imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; + return GL_TRUE; +} + +static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; + GLint Width, Height; + + Width = tObj->Image[0][t->base.firstLevel]->Width - 1; + Height = tObj->Image[0][t->base.firstLevel]->Height - 1; + + I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); + t->Setup[I810_TEXREG_MCS] &= ~MCS_NORMALIZED_COORDS; + t->Setup[I810_TEXREG_MCS] |= MCS_UPDATE_NORMALIZED; + t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_EXACT | + (Height << MI2_HEIGHT_SHIFT) | Width); + + return GL_TRUE; +} + +static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; + GLint log2Width, log2Height; + + + log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; + log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; + + I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); + t->Setup[I810_TEXREG_MCS] |= MCS_NORMALIZED_COORDS | MCS_UPDATE_NORMALIZED; + t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_LOG2 | + (log2Height << MI2_HEIGHT_SHIFT) | log2Width); + + return GL_TRUE; +} + +static void disable_tex( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + + imesa->CurrentTexObj[unit] = 0; + imesa->TexEnvImageFmt[unit] = 0; + imesa->dirty &= ~(I810_UPLOAD_TEX0<<unit); + +} + +/** + * Update hardware state for a texture unit. + * + * \todo + * 1D textures should be supported! Just use a 2D texture with the second + * texture coordinate value fixed at 0.0. + */ +static void i810UpdateTexUnit( GLcontext *ctx, GLuint unit, + int * next_color_stage, int * next_alpha_stage ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLboolean ret; + + switch(texUnit->_ReallyEnabled) { + case TEXTURE_2D_BIT: + ret = enable_tex_common( ctx, unit); + ret &= enable_tex_2d(ctx, unit); + if (ret == GL_FALSE) { + FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); + } + break; + case TEXTURE_RECT_BIT: + ret = enable_tex_common( ctx, unit); + ret &= enable_tex_rect(ctx, unit); + if (ret == GL_FALSE) { + FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); + } + break; + case 0: + disable_tex(ctx, unit); + break; + } + + + if (!i810UpdateTexEnvCombine( ctx, unit, + next_color_stage, next_alpha_stage )) { + FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); + } + + return; +} + + +void i810UpdateTextureState( GLcontext *ctx ) +{ + static const unsigned color_pass[3] = { + GFX_OP_MAP_COLOR_STAGES | MC_STAGE_0 | MC_UPDATE_DEST | MC_DEST_CURRENT + | MC_UPDATE_ARG1 | (MC_ARG_ITERATED_COLOR << MC_ARG1_SHIFT) + | MC_UPDATE_ARG2 | (MC_ARG_ONE << MC_ARG2_SHIFT) + | MC_UPDATE_OP | MC_OP_ARG1, + GFX_OP_MAP_COLOR_STAGES | MC_STAGE_1 | MC_UPDATE_DEST | MC_DEST_CURRENT + | MC_UPDATE_ARG1 | (MC_ARG_CURRENT_COLOR << MC_ARG1_SHIFT) + | MC_UPDATE_ARG2 | (MC_ARG_ONE << MC_ARG2_SHIFT) + | MC_UPDATE_OP | MC_OP_ARG1, + GFX_OP_MAP_COLOR_STAGES | MC_STAGE_2 | MC_UPDATE_DEST | MC_DEST_CURRENT + | MC_UPDATE_ARG1 | (MC_ARG_CURRENT_COLOR << MC_ARG1_SHIFT) + | MC_UPDATE_ARG2 | (MC_ARG_ONE << MC_ARG2_SHIFT) + | MC_UPDATE_OP | MC_OP_ARG1 + }; + static const unsigned alpha_pass[3] = { + GFX_OP_MAP_ALPHA_STAGES | MA_STAGE_0 + | MA_UPDATE_ARG1 | (MA_ARG_ITERATED_ALPHA << MA_ARG1_SHIFT) + | MA_UPDATE_ARG2 | (MA_ARG_ITERATED_ALPHA << MA_ARG2_SHIFT) + | MA_UPDATE_OP | MA_OP_ARG1, + GFX_OP_MAP_ALPHA_STAGES | MA_STAGE_1 + | MA_UPDATE_ARG1 | (MA_ARG_CURRENT_ALPHA << MA_ARG1_SHIFT) + | MA_UPDATE_ARG2 | (MA_ARG_CURRENT_ALPHA << MA_ARG2_SHIFT) + | MA_UPDATE_OP | MA_OP_ARG1, + GFX_OP_MAP_ALPHA_STAGES | MA_STAGE_2 + | MA_UPDATE_ARG1 | (MA_ARG_CURRENT_ALPHA << MA_ARG1_SHIFT) + | MA_UPDATE_ARG2 | (MA_ARG_CURRENT_ALPHA << MA_ARG2_SHIFT) + | MA_UPDATE_OP | MA_OP_ARG1 + }; + i810ContextPtr imesa = I810_CONTEXT(ctx); + int next_color_stage = 0; + int next_alpha_stage = 0; + + + /* fprintf(stderr, "%s\n", __FUNCTION__); */ + FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_FALSE ); + + i810UpdateTexUnit( ctx, 0, & next_color_stage, & next_alpha_stage ); + i810UpdateTexUnit( ctx, 1, & next_color_stage, & next_alpha_stage ); + + /* There needs to be at least one combine stage emitted that just moves + * the incoming primary color to the current color register. In addition, + * there number be the same number of color and alpha stages emitted. + * Finally, if there are less than 3 combine stages, a MC_OP_DISABLE stage + * must be emitted. + */ + + while ( (next_color_stage == 0) || + (next_color_stage < next_alpha_stage) ) { + set_color_stage( color_pass[ next_color_stage ], next_color_stage, + imesa ); + next_color_stage++; + } + + assert( next_color_stage <= 3 ); + + while ( next_alpha_stage < next_color_stage ) { + set_alpha_stage( alpha_pass[ next_alpha_stage ], next_alpha_stage, + imesa ); + next_alpha_stage++; + } + + assert( next_alpha_stage <= 3 ); + assert( next_color_stage == next_alpha_stage ); + + if ( next_color_stage < 3 ) { + const unsigned color = GFX_OP_MAP_COLOR_STAGES + | (next_color_stage << MC_STAGE_SHIFT) + | MC_UPDATE_DEST | MC_DEST_CURRENT + | MC_UPDATE_ARG1 | (MC_ARG_ONE << MC_ARG1_SHIFT) + | MC_UPDATE_ARG2 | (MC_ARG_ONE << MC_ARG2_SHIFT) + | MC_UPDATE_OP | (MC_OP_DISABLE); + + const unsigned alpha = GFX_OP_MAP_ALPHA_STAGES + | (next_color_stage << MC_STAGE_SHIFT) + | MA_UPDATE_ARG1 | (MA_ARG_CURRENT_ALPHA << MA_ARG1_SHIFT) + | MA_UPDATE_ARG2 | (MA_ARG_CURRENT_ALPHA << MA_ARG2_SHIFT) + | MA_UPDATE_OP | (MA_OP_ARG1); + + set_color_stage( color, next_color_stage, imesa ); + set_alpha_stage( alpha, next_alpha_stage, imesa ); + } +} |