diff options
Diffstat (limited to 'src/mesa/main/ffvertex_prog.c')
-rw-r--r-- | src/mesa/main/ffvertex_prog.c | 536 |
1 files changed, 217 insertions, 319 deletions
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c index cc1b44de64..356476e35a 100644 --- a/src/mesa/main/ffvertex_prog.c +++ b/src/mesa/main/ffvertex_prog.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * 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 @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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. - * + * **************************************************************************/ /** @@ -46,32 +46,33 @@ #include "shader/prog_statevars.h" +/** Max of number of lights and texture coord units */ +#define NUM_UNITS MAX2(MAX_TEXTURE_COORD_UNITS, MAX_LIGHTS) + struct state_key { + unsigned light_color_material_mask:12; unsigned light_global_enabled:1; unsigned light_local_viewer:1; unsigned light_twoside:1; - unsigned light_color_material:1; - unsigned light_color_material_mask:12; - unsigned light_material_mask:12; unsigned material_shininess_is_zero:1; - unsigned need_eye_coords:1; unsigned normalize:1; unsigned rescale_normals:1; + unsigned fog_source_is_depth:1; - unsigned tnl_do_vertex_fog:1; unsigned separate_specular:1; - unsigned fog_mode:2; unsigned point_attenuated:1; unsigned point_array:1; unsigned texture_enabled_global:1; unsigned fragprog_inputs_read:12; + unsigned varying_vp_inputs; + struct { unsigned light_enabled:1; unsigned light_eyepos3_is_zero:1; unsigned light_spotcutoff_is_180:1; - unsigned light_attenuated:1; + unsigned light_attenuated:1; unsigned texunit_really_enabled:1; unsigned texmat_enabled:1; unsigned texgen_enabled:4; @@ -79,27 +80,10 @@ struct state_key { unsigned texgen_mode1:4; unsigned texgen_mode2:4; unsigned texgen_mode3:4; - } unit[8]; + } unit[NUM_UNITS]; }; - -#define FOG_NONE 0 -#define FOG_LINEAR 1 -#define FOG_EXP 2 -#define FOG_EXP2 3 - -static GLuint translate_fog_mode( GLenum mode ) -{ - switch (mode) { - case GL_LINEAR: return FOG_LINEAR; - case GL_EXP: return FOG_EXP; - case GL_EXP2: return FOG_EXP2; - default: return FOG_NONE; - } -} - - #define TXG_NONE 0 #define TXG_OBJ_LINEAR 1 #define TXG_EYE_LINEAR 2 @@ -123,42 +107,6 @@ static GLuint translate_texgen( GLboolean enabled, GLenum mode ) } -/** - * Returns bitmask of flags indicating which materials are set per-vertex - * in the current VB. - * XXX get these from the VBO... - */ -static GLbitfield -tnl_get_per_vertex_materials(GLcontext *ctx) -{ - GLbitfield mask = 0x0; -#if 0 - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - - for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) - if (VB->AttribPtr[i] && VB->AttribPtr[i]->stride) - mask |= 1 << (i - _TNL_FIRST_MAT); -#endif - return mask; -} - - -/** - * Should fog be computed per-vertex? - */ -static GLboolean -tnl_get_per_vertex_fog(GLcontext *ctx) -{ -#if 0 - TNLcontext *tnl = TNL_CONTEXT(ctx); - return tnl->_DoVertexFog; -#else - return GL_FALSE; -#endif -} - static GLboolean check_active_shininess( GLcontext *ctx, const struct state_key *key, @@ -166,10 +114,11 @@ static GLboolean check_active_shininess( GLcontext *ctx, { GLuint bit = 1 << (MAT_ATTRIB_FRONT_SHININESS + side); - if (key->light_color_material_mask & bit) + if ((key->varying_vp_inputs & VERT_BIT_COLOR0) && + (key->light_color_material_mask & bit)) return GL_TRUE; - if (key->light_material_mask & bit) + if (key->varying_vp_inputs & (bit << 16)) return GL_TRUE; if (ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS + side][0] != 0.0F) @@ -194,6 +143,7 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) key->need_eye_coords = ctx->_NeedEyeCoords; key->fragprog_inputs_read = fp->Base.InputsRead; + key->varying_vp_inputs = ctx->varying_vp_inputs; if (ctx->RenderMode == GL_FEEDBACK) { /* make sure the vertprog emits color and tex0 */ @@ -213,12 +163,9 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) key->light_twoside = 1; if (ctx->Light.ColorMaterialEnabled) { - key->light_color_material = 1; key->light_color_material_mask = ctx->Light.ColorMaterialBitmask; } - key->light_material_mask = tnl_get_per_vertex_materials(ctx); - for (i = 0; i < MAX_LIGHTS; i++) { struct gl_light *light = &ctx->Light.Light[i]; @@ -227,7 +174,7 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) if (light->EyePosition[3] == 0.0) key->unit[i].light_eyepos3_is_zero = 1; - + if (light->SpotCutoff == 180.0) key->unit[i].light_spotcutoff_is_180 = 1; @@ -256,12 +203,8 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) if (ctx->Transform.RescaleNormals) key->rescale_normals = 1; - key->fog_mode = translate_fog_mode(fp->FogOption); - if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) key->fog_source_is_depth = 1; - - key->tnl_do_vertex_fog = tnl_get_per_vertex_fog(ctx); if (ctx->Point._Attenuated) key->point_attenuated = 1; @@ -275,52 +218,46 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) ctx->Texture._TexMatEnabled || ctx->Texture._EnabledUnits) key->texture_enabled_global = 1; - + for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; if (texUnit->_ReallyEnabled) key->unit[i].texunit_really_enabled = 1; - if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) + if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) key->unit[i].texmat_enabled = 1; - + if (texUnit->TexGenEnabled) { key->unit[i].texgen_enabled = 1; - - key->unit[i].texgen_mode0 = + + key->unit[i].texgen_mode0 = translate_texgen( texUnit->TexGenEnabled & (1<<0), - texUnit->GenModeS ); - key->unit[i].texgen_mode1 = + texUnit->GenS.Mode ); + key->unit[i].texgen_mode1 = translate_texgen( texUnit->TexGenEnabled & (1<<1), - texUnit->GenModeT ); - key->unit[i].texgen_mode2 = + texUnit->GenT.Mode ); + key->unit[i].texgen_mode2 = translate_texgen( texUnit->TexGenEnabled & (1<<2), - texUnit->GenModeR ); - key->unit[i].texgen_mode3 = + texUnit->GenR.Mode ); + key->unit[i].texgen_mode3 = translate_texgen( texUnit->TexGenEnabled & (1<<3), - texUnit->GenModeQ ); + texUnit->GenQ.Mode ); } } } - + /* Very useful debugging tool - produces annotated listing of * generated program with line/function references for each * instruction back into this file: */ #define DISASSEM 0 -/* Should be tunable by the driver - do we want to do matrix - * multiplications with DP4's or with MUL/MAD's? SSE works better - * with the latter, drivers may differ. - */ -#define PREFER_DP4 0 - /* Use uregs to represent registers internally, translate to Mesa's - * expected formats on emit. + * expected formats on emit. * * NOTE: These are passed by value extensively in this file rather * than as usual by pointer reference. If this disturbs you, try @@ -345,10 +282,11 @@ struct tnl_program { const struct state_key *state; struct gl_vertex_program *program; GLint max_inst; /** number of instructions allocated for program */ - + GLboolean mvp_with_dp4; + GLuint temp_in_use; GLuint temp_reserved; - + struct ureg eye_position; struct ureg eye_position_z; struct ureg eye_position_normalized; @@ -360,7 +298,7 @@ struct tnl_program { }; -static const struct ureg undef = { +static const struct ureg undef = { PROGRAM_UNDEFINED, 0, 0, @@ -395,7 +333,7 @@ static struct ureg negate( struct ureg reg ) { reg.negate ^= 1; return reg; -} +} static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w ) @@ -404,7 +342,6 @@ static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w ) GET_SWZ(reg.swz, y), GET_SWZ(reg.swz, z), GET_SWZ(reg.swz, w)); - return reg; } @@ -447,20 +384,52 @@ static void release_temp( struct tnl_program *p, struct ureg reg ) } } - static void release_temps( struct tnl_program *p ) { p->temp_in_use = p->temp_reserved; } +static struct ureg register_param5(struct tnl_program *p, + GLint s0, + GLint s1, + GLint s2, + GLint s3, + GLint s4) +{ + gl_state_index tokens[STATE_LENGTH]; + GLint idx; + tokens[0] = s0; + tokens[1] = s1; + tokens[2] = s2; + tokens[3] = s3; + tokens[4] = s4; + idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens ); + return make_ureg(PROGRAM_STATE_VAR, idx); +} + + +#define register_param1(p,s0) register_param5(p,s0,0,0,0,0) +#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0) +#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0) +#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0) + + + /** * \param input one of VERT_ATTRIB_x tokens. */ static struct ureg register_input( struct tnl_program *p, GLuint input ) { - p->program->Base.InputsRead |= (1<<input); - return make_ureg(PROGRAM_INPUT, input); + assert(input < 32); + + if (p->state->varying_vp_inputs & (1<<input)) { + p->program->Base.InputsRead |= (1<<input); + return make_ureg(PROGRAM_INPUT, input); + } + else { + return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, input ); + } } @@ -474,7 +443,7 @@ static struct ureg register_output( struct tnl_program *p, GLuint output ) } -static struct ureg register_const4f( struct tnl_program *p, +static struct ureg register_const4f( struct tnl_program *p, GLfloat s0, GLfloat s1, GLfloat s2, @@ -493,7 +462,6 @@ static struct ureg register_const4f( struct tnl_program *p, return make_ureg(PROGRAM_CONSTANT, idx); } - #define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1) #define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0) #define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1) @@ -507,38 +475,12 @@ static GLboolean is_undef( struct ureg reg ) static struct ureg get_identity_param( struct tnl_program *p ) { - if (is_undef(p->identity)) + if (is_undef(p->identity)) p->identity = register_const4f(p, 0,0,0,1); return p->identity; } - -static struct ureg register_param5(struct tnl_program *p, - GLint s0, - GLint s1, - GLint s2, - GLint s3, - GLint s4) -{ - gl_state_index tokens[STATE_LENGTH]; - GLint idx; - tokens[0] = s0; - tokens[1] = s1; - tokens[2] = s2; - tokens[3] = s3; - tokens[4] = s4; - idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens ); - return make_ureg(PROGRAM_STATE_VAR, idx); -} - - -#define register_param1(p,s0) register_param5(p,s0,0,0,0,0) -#define register_param2(p,s0,s1) register_param5(p,s0,s1,0,0,0) -#define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0) -#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0) - - static void register_matrix_param5( struct tnl_program *p, GLint s0, /* modelview, projection, etc */ GLint s1, /* texture matrix number */ @@ -552,7 +494,7 @@ static void register_matrix_param5( struct tnl_program *p, /* This is a bit sad as the support is there to pull the whole * matrix out in one go: */ - for (i = 0; i <= s3 - s2; i++) + for (i = 0; i <= s3 - s2; i++) matrix[i] = register_param5( p, s0, s1, i, i, s4 ); } @@ -563,9 +505,8 @@ static void emit_arg( struct prog_src_register *src, src->File = reg.file; src->Index = reg.idx; src->Swizzle = reg.swz; - src->NegateBase = reg.negate ? NEGATE_XYZW : 0; + src->Negate = reg.negate ? NEGATE_XYZW : NEGATE_NONE; src->Abs = 0; - src->NegateAbs = 0; src->RelAddr = 0; /* Check that bitfield sizes aren't exceeded */ ASSERT(src->Index == reg.idx); @@ -578,7 +519,7 @@ static void emit_dst( struct prog_dst_register *dst, dst->File = reg.file; dst->Index = reg.idx; /* allow zero as a shorthand for xyzw */ - dst->WriteMask = mask ? mask : WRITEMASK_XYZW; + dst->WriteMask = mask ? mask : WRITEMASK_XYZW; dst->CondMask = COND_TR; /* always pass cond test */ dst->CondSwizzle = SWIZZLE_NOOP; dst->CondSrc = 0; @@ -593,12 +534,12 @@ static void debug_insn( struct prog_instruction *inst, const char *fn, { if (DISASSEM) { static const char *last_fn; - + if (fn != last_fn) { last_fn = fn; _mesa_printf("%s:\n", fn); } - + _mesa_printf("%d:\t", line); _mesa_print_instruction(inst); } @@ -617,7 +558,7 @@ static void emit_op3fn(struct tnl_program *p, { GLuint nr; struct prog_instruction *inst; - + assert((GLint) p->program->Base.NumInstructions <= p->max_inst); if (p->program->Base.NumInstructions == p->max_inst) { @@ -642,17 +583,16 @@ static void emit_op3fn(struct tnl_program *p, p->program->Base.Instructions = newInst; } - + nr = p->program->Base.NumInstructions++; inst = &p->program->Base.Instructions[nr]; - inst->Opcode = (enum prog_opcode) op; - inst->StringPos = 0; + inst->Opcode = (enum prog_opcode) op; inst->Data = 0; - + emit_arg( &inst->SrcReg[0], src0 ); emit_arg( &inst->SrcReg[1], src1 ); - emit_arg( &inst->SrcReg[2], src2 ); + emit_arg( &inst->SrcReg[2], src2 ); emit_dst( &inst->DstReg, dest, mask ); @@ -672,7 +612,7 @@ static void emit_op3fn(struct tnl_program *p, static struct ureg make_temp( struct tnl_program *p, struct ureg reg ) { - if (reg.file == PROGRAM_TEMPORARY && + if (reg.file == PROGRAM_TEMPORARY && !(p->temp_reserved & (1<<reg.idx))) return reg; else { @@ -753,24 +693,24 @@ static void emit_normalize_vec3( struct tnl_program *p, } -static void emit_passthrough( struct tnl_program *p, +static void emit_passthrough( struct tnl_program *p, GLuint input, GLuint output ) { struct ureg out = register_output(p, output); - emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input)); + emit_op1(p, OPCODE_MOV, out, 0, register_input(p, input)); } static struct ureg get_eye_position( struct tnl_program *p ) { if (is_undef(p->eye_position)) { - struct ureg pos = register_input( p, VERT_ATTRIB_POS ); + struct ureg pos = register_input( p, VERT_ATTRIB_POS ); struct ureg modelview[4]; p->eye_position = reserve_temp(p); - if (PREFER_DP4) { + if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 0, modelview ); @@ -783,18 +723,18 @@ static struct ureg get_eye_position( struct tnl_program *p ) emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos); } } - + return p->eye_position; } static struct ureg get_eye_position_z( struct tnl_program *p ) { - if (!is_undef(p->eye_position)) + if (!is_undef(p->eye_position)) return swizzle1(p->eye_position, Z); if (is_undef(p->eye_position_z)) { - struct ureg pos = register_input( p, VERT_ATTRIB_POS ); + struct ureg pos = register_input( p, VERT_ATTRIB_POS ); struct ureg modelview[4]; p->eye_position_z = reserve_temp(p); @@ -804,10 +744,10 @@ static struct ureg get_eye_position_z( struct tnl_program *p ) emit_op2(p, OPCODE_DP4, p->eye_position_z, 0, pos, modelview[2]); } - + return p->eye_position_z; } - + static struct ureg get_eye_position_normalized( struct tnl_program *p ) { @@ -816,7 +756,7 @@ static struct ureg get_eye_position_normalized( struct tnl_program *p ) p->eye_position_normalized = reserve_temp(p); emit_normalize_vec3(p, p->eye_position_normalized, eye); } - + return p->eye_position_normalized; } @@ -830,7 +770,7 @@ static struct ureg get_transformed_normal( struct tnl_program *p ) { p->transformed_normal = register_input(p, VERT_ATTRIB_NORMAL ); } - else if (is_undef(p->transformed_normal)) + else if (is_undef(p->transformed_normal)) { struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL ); struct ureg mvinv[3]; @@ -861,7 +801,7 @@ static struct ureg get_transformed_normal( struct tnl_program *p ) emit_op2( p, OPCODE_MUL, transformed_normal, 0, normal, rescale ); normal = transformed_normal; } - + assert(normal.file == PROGRAM_TEMPORARY); p->transformed_normal = normal; } @@ -872,17 +812,17 @@ static struct ureg get_transformed_normal( struct tnl_program *p ) static void build_hpos( struct tnl_program *p ) { - struct ureg pos = register_input( p, VERT_ATTRIB_POS ); + struct ureg pos = register_input( p, VERT_ATTRIB_POS ); struct ureg hpos = register_output( p, VERT_RESULT_HPOS ); struct ureg mvp[4]; - if (PREFER_DP4) { - register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, + if (p->mvp_with_dp4) { + register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, 0, mvp ); emit_matrix_transform_vec4( p, hpos, mvp, pos ); } else { - register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, + register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, STATE_MATRIX_TRANSPOSE, mvp ); emit_transpose_matrix_transform_vec4( p, hpos, mvp, pos ); } @@ -891,8 +831,7 @@ static void build_hpos( struct tnl_program *p ) static GLuint material_attrib( GLuint side, GLuint property ) { - return ((property - STATE_AMBIENT) * 2 + - side); + return (property - STATE_AMBIENT) * 2 + side; } @@ -904,27 +843,28 @@ static void set_material_flags( struct tnl_program *p ) p->color_materials = 0; p->materials = 0; - if (p->state->light_color_material) { - p->materials = + if (p->state->varying_vp_inputs & VERT_BIT_COLOR0) { + p->materials = p->color_materials = p->state->light_color_material_mask; } - p->materials |= p->state->light_material_mask; + p->materials |= (p->state->varying_vp_inputs >> 16); } -/* XXX temporary!!! */ -#define _TNL_ATTRIB_MAT_FRONT_AMBIENT 32 - -static struct ureg get_material( struct tnl_program *p, GLuint side, +static struct ureg get_material( struct tnl_program *p, GLuint side, GLuint property ) { GLuint attrib = material_attrib(side, property); if (p->color_materials & (1<<attrib)) return register_input(p, VERT_ATTRIB_COLOR0); - else if (p->materials & (1<<attrib)) - return register_input( p, attrib + _TNL_ATTRIB_MAT_FRONT_AMBIENT ); + else if (p->materials & (1<<attrib)) { + /* Put material values in the GENERIC slots -- they are not used + * for anything in fixed function mode. + */ + return register_input( p, attrib + VERT_ATTRIB_GENERIC0 ); + } else return register_param3( p, STATE_MATERIAL, side, property ); } @@ -953,7 +893,7 @@ static struct ureg get_scenecolor( struct tnl_program *p, GLuint side ) struct ureg material_ambient = get_material(p, side, STATE_AMBIENT); struct ureg material_diffuse = get_material(p, side, STATE_DIFFUSE); struct ureg tmp = make_temp(p, material_diffuse); - emit_op3(p, OPCODE_MAD, tmp, WRITEMASK_XYZ, lm_ambient, + emit_op3(p, OPCODE_MAD, tmp, WRITEMASK_XYZ, lm_ambient, material_ambient, material_emission); return tmp; } @@ -962,16 +902,16 @@ static struct ureg get_scenecolor( struct tnl_program *p, GLuint side ) } -static struct ureg get_lightprod( struct tnl_program *p, GLuint light, +static struct ureg get_lightprod( struct tnl_program *p, GLuint light, GLuint side, GLuint property ) { GLuint attrib = material_attrib(side, property); if (p->materials & (1<<attrib)) { - struct ureg light_value = + struct ureg light_value = register_param3(p, STATE_LIGHT, light, property); struct ureg material_value = get_material(p, side, property); struct ureg tmp = get_temp(p); - emit_op2(p, OPCODE_MUL, tmp, 0, light_value, material_value); + emit_op2(p, OPCODE_MUL, tmp, 0, light_value, material_value); return tmp; } else @@ -980,7 +920,7 @@ static struct ureg get_lightprod( struct tnl_program *p, GLuint light, static struct ureg calculate_light_attenuation( struct tnl_program *p, - GLuint i, + GLuint i, struct ureg VPpli, struct ureg dist ) { @@ -1008,28 +948,28 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p, /* Calculate distance attenuation: */ if (p->state->unit[i].light_attenuated) { - /* 1/d,d,d,1/d */ - emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist); + emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist); /* 1,d,d*d,1/d */ - emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y)); + emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y)); /* 1/dist-atten */ - emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist); + emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist); if (!p->state->unit[i].light_spotcutoff_is_180) { /* dist-atten */ - emit_op1(p, OPCODE_RCP, dist, 0, dist); + emit_op1(p, OPCODE_RCP, dist, 0, dist); /* spot-atten * dist-atten */ - emit_op2(p, OPCODE_MUL, att, 0, dist, att); - } else { + emit_op2(p, OPCODE_MUL, att, 0, dist, att); + } + else { /* dist-atten */ - emit_op1(p, OPCODE_RCP, att, 0, dist); + emit_op1(p, OPCODE_RCP, att, 0, dist); } } return att; } - + /** * Compute: @@ -1048,7 +988,7 @@ static void emit_degenerate_lit( struct tnl_program *p, /* MAX lit, id, dots; */ - emit_op2(p, OPCODE_MAX, lit, WRITEMASK_XYZW, id, dots); + emit_op2(p, OPCODE_MAX, lit, WRITEMASK_XYZW, id, dots); /* result[2] = (in > 0 ? 1 : 0) * SLT lit.z, id.z, dots; # lit.z = (0 < dots.z) ? 1 : 0 @@ -1075,22 +1015,22 @@ static void build_lighting( struct tnl_program *p ) /* * NOTE: - * dot.x = dot(normal, VPpli) - * dot.y = dot(normal, halfAngle) - * dot.z = back.shininess - * dot.w = front.shininess + * dots.x = dot(normal, VPpli) + * dots.y = dot(normal, halfAngle) + * dots.z = back.shininess + * dots.w = front.shininess */ - for (i = 0; i < MAX_LIGHTS; i++) + for (i = 0; i < MAX_LIGHTS; i++) if (p->state->unit[i].light_enabled) nr_lights++; - + set_material_flags(p); { if (!p->state->material_shininess_is_zero) { struct ureg shininess = get_material(p, 0, STATE_SHININESS); - emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); + emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); release_temp(p, shininess); } @@ -1099,13 +1039,15 @@ static void build_lighting( struct tnl_program *p ) _col1 = make_temp(p, get_identity_param(p)); else _col1 = _col0; - } if (twoside) { if (!p->state->material_shininess_is_zero) { + /* Note that we negate the back-face specular exponent here. + * The negation will be un-done later in the back-face code below. + */ struct ureg shininess = get_material(p, 1, STATE_SHININESS); - emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, + emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, negate(swizzle1(shininess,X))); release_temp(p, shininess); } @@ -1133,12 +1075,12 @@ static void build_lighting( struct tnl_program *p ) struct ureg res0 = register_output( p, VERT_RESULT_BFC0 ); emit_op1(p, OPCODE_MOV, res0, 0, _bfc0); } - + if (twoside && separate) { struct ureg res1 = register_output( p, VERT_RESULT_BFC1 ); emit_op1(p, OPCODE_MOV, res1, 0, _bfc1); } - + if (nr_lights == 0) { release_temps(p); return; @@ -1148,39 +1090,40 @@ static void build_lighting( struct tnl_program *p ) if (p->state->unit[i].light_enabled) { struct ureg half = undef; struct ureg att = undef, VPpli = undef; - + count++; if (p->state->unit[i].light_eyepos3_is_zero) { /* Can used precomputed constants in this case. * Attenuation never applies to infinite lights. */ - VPpli = register_param3(p, STATE_INTERNAL, - STATE_LIGHT_POSITION_NORMALIZED, i); - + VPpli = register_param3(p, STATE_INTERNAL, + STATE_LIGHT_POSITION_NORMALIZED, i); + if (!p->state->material_shininess_is_zero) { if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); half = get_temp(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); emit_normalize_vec3(p, half, half); - } else { - half = register_param3(p, STATE_INTERNAL, + } + else { + half = register_param3(p, STATE_INTERNAL, STATE_LIGHT_HALF_VECTOR, i); } } - } + } else { - struct ureg Ppli = register_param3(p, STATE_INTERNAL, - STATE_LIGHT_POSITION, i); + struct ureg Ppli = register_param3(p, STATE_INTERNAL, + STATE_LIGHT_POSITION, i); struct ureg V = get_eye_position(p); struct ureg dist = get_temp(p); - VPpli = get_temp(p); - + VPpli = get_temp(p); + /* Calculate VPpli vector */ - emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); + emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); /* Normalize VPpli. The dist value also used in * attenuation below. @@ -1190,7 +1133,7 @@ static void build_lighting( struct tnl_program *p ) emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist); /* Calculate attenuation: - */ + */ if (!p->state->unit[i].light_spotcutoff_is_180 || p->state->unit[i].light_attenuated) { att = calculate_light_attenuation(p, i, VPpli, dist); @@ -1206,7 +1149,7 @@ static void build_lighting( struct tnl_program *p ) emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); } else { - struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); + struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir); } @@ -1248,7 +1191,8 @@ static void build_lighting( struct tnl_program *p ) res0 = _col0; res1 = register_output( p, VERT_RESULT_COL0 ); } - } else { + } + else { mask0 = 0; mask1 = 0; res0 = _col0; @@ -1260,12 +1204,12 @@ static void build_lighting( struct tnl_program *p ) emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_MUL, lit, 0, lit, att); emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0); - } + } else if (!p->state->material_shininess_is_zero) { /* there's a non-zero specular term */ emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0); - } + } else { /* no attenutation, no specular */ emit_degenerate_lit(p, lit, dots); @@ -1274,7 +1218,7 @@ static void build_lighting( struct tnl_program *p ) emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1); - + release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); @@ -1288,7 +1232,7 @@ static void build_lighting( struct tnl_program *p ) struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; - + if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; @@ -1302,13 +1246,19 @@ static void build_lighting( struct tnl_program *p ) res0 = _bfc0; res1 = register_output( p, VERT_RESULT_BFC0 ); } - } else { + } + else { res0 = _bfc0; res1 = _bfc1; mask0 = 0; mask1 = 0; } + /* For the back face we need to negate the X and Y component + * dot products. dots.Z has the negated back-face specular + * exponent. We swizzle that into the W position. This + * negation makes the back-face specular term positive again. + */ dots = negate(swizzle(dots,X,Y,W,Z)); if (!is_undef(att)) { @@ -1318,8 +1268,8 @@ static void build_lighting( struct tnl_program *p ) } else if (!p->state->material_shininess_is_zero) { emit_op1(p, OPCODE_LIT, lit, 0, dots); - emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); - } + emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); /**/ + } else { emit_degenerate_lit(p, lit, dots); emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); @@ -1327,8 +1277,10 @@ static void build_lighting( struct tnl_program *p ) emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1); - /* restore negate flag for next lighting */ - dots = negate(dots); + /* restore dots to its original state for subsequent lights + * by negating and swizzling again. + */ + dots = negate(swizzle(dots,X,Y,W,Z)); release_temp(p, ambient); release_temp(p, diffuse); @@ -1357,52 +1309,12 @@ static void build_fog( struct tnl_program *p ) input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X); } - if (p->state->fog_mode && p->state->tnl_do_vertex_fog) { - struct ureg params = register_param2(p, STATE_INTERNAL, - STATE_FOG_PARAMS_OPTIMIZED); - struct ureg tmp = get_temp(p); - GLboolean useabs = (p->state->fog_mode != FOG_EXP2); - - if (useabs) { - emit_op1(p, OPCODE_ABS, tmp, 0, input); - } - - switch (p->state->fog_mode) { - case FOG_LINEAR: { - struct ureg id = get_identity_param(p); - emit_op3(p, OPCODE_MAD, tmp, 0, useabs ? tmp : input, - swizzle1(params,X), swizzle1(params,Y)); - emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */ - emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W)); - break; - } - case FOG_EXP: - emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input, - swizzle1(params,Z)); - emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp)); - break; - case FOG_EXP2: - emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W)); - emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp); - emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp)); - break; - } - - release_temp(p, tmp); - } - else { - /* results = incoming fog coords (compute fog per-fragment later) - * - * KW: Is it really necessary to do anything in this case? - * BP: Yes, we always need to compute the absolute value, unless - * we want to push that down into the fragment program... - */ - GLboolean useabs = GL_TRUE; - emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, WRITEMASK_X, input); - } + /* result.fog = {abs(f),0,0,1}; */ + emit_op1(p, OPCODE_ABS, fog, WRITEMASK_X, input); + emit_op1(p, OPCODE_MOV, fog, WRITEMASK_YZW, get_identity_param(p)); } - + static void build_reflect_texgen( struct tnl_program *p, struct ureg dest, GLuint writemask ) @@ -1412,9 +1324,9 @@ static void build_reflect_texgen( struct tnl_program *p, struct ureg tmp = get_temp(p); /* n.u */ - emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat); + emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat); /* 2n.u */ - emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp); + emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp); /* (-2n.u)n + u */ emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat); @@ -1443,22 +1355,22 @@ static void build_sphere_texgen( struct tnl_program *p, */ /* n.u */ - emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat); + emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat); /* 2n.u */ - emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp); + emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp); /* (-2n.u)n + u */ - emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat); + emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat); /* r + 0,0,1 */ - emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z)); + emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z)); /* rx^2 + ry^2 + (rz+1)^2 */ - emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp); + emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp); /* 2/m */ - emit_op1(p, OPCODE_RSQ, tmp, 0, tmp); + emit_op1(p, OPCODE_RSQ, tmp, 0, tmp); /* 1/m */ - emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half); + emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half); /* r/m + 1/2 */ - emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half); - + emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half); + release_temp(p, tmp); release_temp(p, r); release_temp(p, inv_m); @@ -1473,10 +1385,10 @@ static void build_texture_transform( struct tnl_program *p ) if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i))) continue; - - if (p->state->unit[i].texgen_enabled || + + if (p->state->unit[i].texgen_enabled || p->state->unit[i].texmat_enabled) { - + GLuint texmat_enabled = p->state->unit[i].texmat_enabled; struct ureg out = register_output(p, VERT_RESULT_TEX0 + i); struct ureg out_texgen = undef; @@ -1487,8 +1399,8 @@ static void build_texture_transform( struct tnl_program *p ) GLuint reflect_mask = 0; GLuint normal_mask = 0; GLuint modes[4]; - - if (texmat_enabled) + + if (texmat_enabled) out_texgen = get_temp(p); else out_texgen = out; @@ -1502,31 +1414,31 @@ static void build_texture_transform( struct tnl_program *p ) switch (modes[j]) { case TXG_OBJ_LINEAR: { struct ureg obj = register_input(p, VERT_ATTRIB_POS); - struct ureg plane = + struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_OBJECT_S + j); - emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, + emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, obj, plane ); break; } case TXG_EYE_LINEAR: { struct ureg eye = get_eye_position(p); - struct ureg plane = - register_param3(p, STATE_TEXGEN, i, + struct ureg plane = + register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_EYE_S + j); - emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, + emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, eye, plane ); break; } - case TXG_SPHERE_MAP: + case TXG_SPHERE_MAP: sphere_mask |= WRITEMASK_X << j; break; case TXG_REFLECTION_MAP: reflect_mask |= WRITEMASK_X << j; break; - case TXG_NORMAL_MAP: + case TXG_NORMAL_MAP: normal_mask |= WRITEMASK_X << j; break; case TXG_NONE: @@ -1555,10 +1467,10 @@ static void build_texture_transform( struct tnl_program *p ) if (texmat_enabled) { struct ureg texmat[4]; - struct ureg in = (!is_undef(out_texgen) ? - out_texgen : + struct ureg in = (!is_undef(out_texgen) ? + out_texgen : register_input(p, VERT_ATTRIB_TEX0+i)); - if (PREFER_DP4) { + if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, 0, texmat ); emit_matrix_transform_vec4( p, out, texmat, in ); @@ -1571,7 +1483,7 @@ static void build_texture_transform( struct tnl_program *p ) } release_temps(p); - } + } else { emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i); } @@ -1618,17 +1530,6 @@ static void build_atten_pointsize( struct tnl_program *p ) /** - * Emit constant point size. - */ -static void build_constant_pointsize( struct tnl_program *p ) -{ - struct ureg state_size = register_param1(p, STATE_POINT_SIZE); - struct ureg out = register_output(p, VERT_RESULT_PSIZ); - emit_op1(p, OPCODE_MOV, out, WRITEMASK_X, state_size); -} - - -/** * Pass-though per-vertex point size, from user's point size array. */ static void build_array_pointsize( struct tnl_program *p ) @@ -1640,7 +1541,8 @@ static void build_array_pointsize( struct tnl_program *p ) static void build_tnl_program( struct tnl_program *p ) -{ /* Emit the program, starting with modelviewproject: +{ + /* Emit the program, starting with modelviewproject: */ build_hpos(p); @@ -1658,8 +1560,7 @@ static void build_tnl_program( struct tnl_program *p ) } } - if ((p->state->fragprog_inputs_read & FRAG_BIT_FOGC) || - p->state->fog_mode != FOG_NONE) + if (p->state->fragprog_inputs_read & FRAG_BIT_FOGC) build_fog(p); if (p->state->fragprog_inputs_read & FRAG_BITS_TEX_ANY) @@ -1669,12 +1570,6 @@ static void build_tnl_program( struct tnl_program *p ) build_atten_pointsize(p); else if (p->state->point_array) build_array_pointsize(p); -#if 0 - else - build_constant_pointsize(p); -#else - (void) build_constant_pointsize; -#endif /* Finish up: */ @@ -1691,6 +1586,7 @@ static void build_tnl_program( struct tnl_program *p ) static void create_new_program( const struct state_key *key, struct gl_vertex_program *program, + GLboolean mvp_with_dp4, GLuint max_temps) { struct tnl_program p; @@ -1704,7 +1600,8 @@ create_new_program( const struct state_key *key, p.transformed_normal = undef; p.identity = undef; p.temp_in_use = 0; - + p.mvp_with_dp4 = mvp_with_dp4; + if (max_temps >= sizeof(int) * 8) p.temp_reserved = 0; else @@ -1747,23 +1644,24 @@ _mesa_get_fixed_func_vertex_program(GLcontext *ctx) */ prog = (struct gl_vertex_program *) _mesa_search_program_cache(ctx->VertexProgram.Cache, &key, sizeof(key)); - + if (!prog) { /* OK, we'll have to build a new one */ if (0) _mesa_printf("Build new TNL program\n"); - + prog = (struct gl_vertex_program *) - ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); + ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); if (!prog) return NULL; create_new_program( &key, prog, + ctx->mvp_with_dp4, ctx->Const.VertexProgram.MaxTemps ); #if 0 if (ctx->Driver.ProgramStringNotify) - ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB, + ctx->Driver.ProgramStringNotify( ctx, GL_VERTEX_PROGRAM_ARB, &prog->Base ); #endif _mesa_program_cache_insert(ctx, ctx->VertexProgram.Cache, |