diff options
Diffstat (limited to 'src/mesa/main/texenvprogram.c')
-rw-r--r-- | src/mesa/main/texenvprogram.c | 223 |
1 files changed, 142 insertions, 81 deletions
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 64b2ab6c135..af51a206a56 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -2,6 +2,7 @@ * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. + * Copyright 2009 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -28,6 +29,7 @@ #include "glheader.h" #include "macros.h" #include "enums.h" +#include "shader/program.h" #include "shader/prog_parameter.h" #include "shader/prog_cache.h" #include "shader/prog_instruction.h" @@ -36,16 +38,44 @@ #include "shader/programopt.h" #include "texenvprogram.h" + +#define MAX_TERMS 4 + + +/* + * Note on texture units: + * + * The number of texture units supported by fixed-function fragment + * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS. + * That's because there's a one-to-one correspondence between texture + * coordinates and samplers in fixed-function processing. + * + * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS + * sets of texcoords, so is fixed-function fragment processing. + * + * We can safely use ctx->Const.MaxTextureUnits for loop bounds. + */ + + +struct texenvprog_cache_item +{ + GLuint hash; + void *key; + struct gl_fragment_program *data; + struct texenvprog_cache_item *next; +}; + + /** * Up to nine instructions per tex unit, plus fog, specular color. */ -#define MAX_INSTRUCTIONS ((MAX_TEXTURE_UNITS * 9) + 12) +#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 9) + 12) #define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM) struct mode_opt { - GLubyte Source:4; - GLubyte Operand:3; + GLuint Source:4; + GLuint Operand:3; }; struct state_key { @@ -59,16 +89,17 @@ struct state_key { struct { GLuint enabled:1; GLuint source_index:3; /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */ + GLuint shadow:1; GLuint ScaleShiftRGB:2; GLuint ScaleShiftA:2; - GLuint NumArgsRGB:2; + GLuint NumArgsRGB:3; GLuint ModeRGB:4; - GLuint NumArgsA:2; - GLuint ModeA:4; + struct mode_opt OptRGB[MAX_TERMS]; - struct mode_opt OptRGB[3]; - struct mode_opt OptA[3]; + GLuint NumArgsA:3; + GLuint ModeA:4; + struct mode_opt OptA[MAX_TERMS]; } unit[8]; }; @@ -104,7 +135,9 @@ static GLuint translate_operand( GLenum operand ) case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA; case GL_ZERO: return OPR_ZERO; case GL_ONE: return OPR_ONE; - default: return OPR_UNKNOWN; + default: + assert(0); + return OPR_UNKNOWN; } } @@ -120,6 +153,7 @@ static GLuint translate_operand( GLenum operand ) #define SRC_CONSTANT 9 #define SRC_PRIMARY_COLOR 10 #define SRC_PREVIOUS 11 +#define SRC_ZERO 12 #define SRC_UNKNOWN 15 static GLuint translate_source( GLenum src ) @@ -137,32 +171,49 @@ static GLuint translate_source( GLenum src ) case GL_CONSTANT: return SRC_CONSTANT; case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR; case GL_PREVIOUS: return SRC_PREVIOUS; - default: return SRC_UNKNOWN; + case GL_ZERO: + return SRC_ZERO; + default: + assert(0); + return SRC_UNKNOWN; } } -#define MODE_REPLACE 0 -#define MODE_MODULATE 1 -#define MODE_ADD 2 -#define MODE_ADD_SIGNED 3 -#define MODE_INTERPOLATE 4 -#define MODE_SUBTRACT 5 -#define MODE_DOT3_RGB 6 -#define MODE_DOT3_RGB_EXT 7 -#define MODE_DOT3_RGBA 8 -#define MODE_DOT3_RGBA_EXT 9 -#define MODE_MODULATE_ADD_ATI 10 -#define MODE_MODULATE_SIGNED_ADD_ATI 11 -#define MODE_MODULATE_SUBTRACT_ATI 12 -#define MODE_UNKNOWN 15 - -static GLuint translate_mode( GLenum mode ) +#define MODE_REPLACE 0 /* r = a0 */ +#define MODE_MODULATE 1 /* r = a0 * a1 */ +#define MODE_ADD 2 /* r = a0 + a1 */ +#define MODE_ADD_SIGNED 3 /* r = a0 + a1 - 0.5 */ +#define MODE_INTERPOLATE 4 /* r = a0 * a2 + a1 * (1 - a2) */ +#define MODE_SUBTRACT 5 /* r = a0 - a1 */ +#define MODE_DOT3_RGB 6 /* r = a0 . a1 */ +#define MODE_DOT3_RGB_EXT 7 /* r = a0 . a1 */ +#define MODE_DOT3_RGBA 8 /* r = a0 . a1 */ +#define MODE_DOT3_RGBA_EXT 9 /* r = a0 . a1 */ +#define MODE_MODULATE_ADD_ATI 10 /* r = a0 * a2 + a1 */ +#define MODE_MODULATE_SIGNED_ADD_ATI 11 /* r = a0 * a2 + a1 - 0.5 */ +#define MODE_MODULATE_SUBTRACT_ATI 12 /* r = a0 * a2 - a1 */ +#define MODE_ADD_PRODUCTS 13 /* r = a0 * a1 + a2 * a3 */ +#define MODE_ADD_PRODUCTS_SIGNED 14 /* r = a0 * a1 + a2 * a3 - 0.5 */ +#define MODE_UNKNOWN 15 + +/** + * Translate GL combiner state into a MODE_x value + */ +static GLuint translate_mode( GLenum envMode, GLenum mode ) { switch (mode) { case GL_REPLACE: return MODE_REPLACE; case GL_MODULATE: return MODE_MODULATE; - case GL_ADD: return MODE_ADD; - case GL_ADD_SIGNED: return MODE_ADD_SIGNED; + case GL_ADD: + if (envMode == GL_COMBINE4_NV) + return MODE_ADD_PRODUCTS; + else + return MODE_ADD; + case GL_ADD_SIGNED: + if (envMode == GL_COMBINE4_NV) + return MODE_ADD_PRODUCTS_SIGNED; + else + return MODE_ADD_SIGNED; case GL_INTERPOLATE: return MODE_INTERPOLATE; case GL_SUBTRACT: return MODE_SUBTRACT; case GL_DOT3_RGB: return MODE_DOT3_RGB; @@ -172,7 +223,9 @@ static GLuint translate_mode( GLenum mode ) case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI; case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI; case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI; - default: return MODE_UNKNOWN; + default: + assert(0); + return MODE_UNKNOWN; } } @@ -182,14 +235,16 @@ static GLuint translate_tex_src_bit( GLbitfield bit ) /* make sure number of switch cases is correct */ assert(NUM_TEXTURE_TARGETS == 7); switch (bit) { - case TEXTURE_1D_BIT: return TEXTURE_1D_INDEX; - case TEXTURE_2D_BIT: return TEXTURE_2D_INDEX; - case TEXTURE_3D_BIT: return TEXTURE_3D_INDEX; - case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX; - case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX; - case TEXTURE_1D_ARRAY_BIT: return TEXTURE_1D_ARRAY_INDEX; - case TEXTURE_2D_ARRAY_BIT: return TEXTURE_2D_ARRAY_INDEX; - default: return TEXTURE_UNKNOWN_INDEX; + case TEXTURE_1D_BIT: return TEXTURE_1D_INDEX; + case TEXTURE_2D_BIT: return TEXTURE_2D_INDEX; + case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX; + case TEXTURE_3D_BIT: return TEXTURE_3D_INDEX; + case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX; + case TEXTURE_1D_ARRAY_BIT: return TEXTURE_1D_ARRAY_INDEX; + case TEXTURE_2D_ARRAY_BIT: return TEXTURE_2D_ARRAY_INDEX; + default: + assert(0); + return TEXTURE_UNKNOWN_INDEX; } } @@ -301,12 +356,15 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) memset(key, 0, sizeof(*key)); - for (i=0;i<MAX_TEXTURE_UNITS;i++) { + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; - - if (!texUnit->_ReallyEnabled) + GLenum format; + + if (!texUnit->_ReallyEnabled || !texUnit->Enabled) continue; + format = texUnit->_Current->Image[0][texUnit->_Current->BaseLevel]->_BaseFormat; + key->unit[i].enabled = 1; key->enabled_units |= (1<<i); key->nr_enabled_units = i+1; @@ -314,19 +372,22 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) key->unit[i].source_index = translate_tex_src_bit(texUnit->_ReallyEnabled); + key->unit[i].shadow = ((texUnit->_Current->CompareMode == GL_COMPARE_R_TO_TEXTURE) && + ((format == GL_DEPTH_COMPONENT) || + (format == GL_DEPTH_STENCIL_EXT))); key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB; key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA; key->unit[i].ModeRGB = - translate_mode(texUnit->_CurrentCombine->ModeRGB); + translate_mode(texUnit->EnvMode, texUnit->_CurrentCombine->ModeRGB); key->unit[i].ModeA = - translate_mode(texUnit->_CurrentCombine->ModeA); + translate_mode(texUnit->EnvMode, texUnit->_CurrentCombine->ModeA); key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB; key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA; - for (j=0;j<3;j++) { + for (j = 0; j < MAX_TERMS; j++) { key->unit[i].OptRGB[j].Operand = translate_operand(texUnit->_CurrentCombine->OperandRGB[j]); key->unit[i].OptA[j].Operand = @@ -398,7 +459,7 @@ struct texenv_fragment_program { GLbitfield temp_in_use; /**< Tracks temporary regs which are in use. */ GLboolean error; - struct ureg src_texture[MAX_TEXTURE_UNITS]; + struct ureg src_texture[MAX_TEXTURE_COORD_UNITS]; /* Reg containing each texture unit's sampled texture color, * else undef. */ @@ -615,7 +676,7 @@ emit_op(struct texenv_fragment_program *p, { GLuint nr = p->program->Base.NumInstructions++; struct prog_instruction *inst = &p->program->Base.Instructions[nr]; - + assert(nr < MAX_INSTRUCTIONS); _mesa_init_instructions(inst, 1); @@ -788,12 +849,17 @@ static struct ureg get_source( struct texenv_fragment_program *p, case SRC_PRIMARY_COLOR: return register_input(p, FRAG_ATTRIB_COL0); + case SRC_ZERO: + return get_zero(p); + case SRC_PREVIOUS: - default: if (is_undef(p->src_previous)) return register_input(p, FRAG_ATTRIB_COL0); else return p->src_previous; + + default: + assert(0); } } @@ -834,7 +900,9 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p, case OPR_ONE: return get_one(p); case OPR_SRC_COLOR: + return src; default: + assert(0); return src; } } @@ -883,10 +951,12 @@ static struct ureg emit_combine( struct texenv_fragment_program *p, GLuint mode, const struct mode_opt *opt) { - struct ureg src[3]; + struct ureg src[MAX_TERMS]; struct ureg tmp, half; GLuint i; + assert(nr <= MAX_TERMS); + tmp = undef; /* silence warning (bug 5318) */ for (i = 0; i < nr; i++) @@ -962,7 +1032,26 @@ static struct ureg emit_combine( struct texenv_fragment_program *p, /* Arg0 * Arg2 - Arg1 */ emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) ); return dest; + case MODE_ADD_PRODUCTS: + /* Arg0 * Arg1 + Arg2 * Arg3 */ + { + struct ureg tmp0 = get_temp(p); + emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef ); + emit_arith( p, OPCODE_MAD, dest, mask, saturate, src[2], src[3], tmp0 ); + } + return dest; + case MODE_ADD_PRODUCTS_SIGNED: + /* Arg0 * Arg1 + Arg2 * Arg3 - 0.5 */ + { + struct ureg tmp0 = get_temp(p); + half = get_half(p); + emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef ); + emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[2], src[3], tmp0 ); + emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef ); + } + return dest; default: + assert(0); return src[0]; } } @@ -1084,6 +1173,10 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit ) p->src_texture[unit] = emit_texld( p, OPCODE_TXP, tmp, WRITEMASK_XYZW, unit, dim, texcoord ); + + if (p->state->unit[unit].shadow) + p->program->Base.ShadowSamplers |= 1 << unit; + p->program->Base.SamplersUsed |= (1 << unit); /* This identity mapping should already be in place * (see _mesa_init_program_struct()) but let's be safe. @@ -1115,6 +1208,7 @@ static GLboolean load_texenv_source( struct texenv_fragment_program *p, break; default: + /* not a texture src - do nothing */ break; } @@ -1179,7 +1273,7 @@ create_new_program(GLcontext *ctx, struct state_key *key, p.program->Base.InputsRead = 0; p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR; - for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++) + for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) p.src_texture[unit] = undef; p.src_previous = undef; @@ -1311,36 +1405,3 @@ _mesa_get_fixed_func_fragment_program(GLcontext *ctx) return prog; } - - - -/** - * If _MaintainTexEnvProgram is set we'll generate a fragment program that - * implements the current texture env/combine mode. - * This function generates that program and puts it into effect. - */ -void -_mesa_UpdateTexEnvProgram( GLcontext *ctx ) -{ - const struct gl_fragment_program *prev = ctx->FragmentProgram._Current; - - ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram); - - /* If a conventional fragment program/shader isn't in effect... */ - if (!ctx->FragmentProgram._Enabled && - (!ctx->Shader.CurrentProgram || - !ctx->Shader.CurrentProgram->FragmentProgram) ) { - - ctx->FragmentProgram._Current - = ctx->FragmentProgram._TexEnvProgram - = _mesa_get_fixed_func_fragment_program(ctx); - } - - /* Tell the driver about the change. Could define a new target for - * this? - */ - if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) { - ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, - (struct gl_program *) ctx->FragmentProgram._Current); - } -} |