From 47b29f511a8e917c65536fde90397d54d2ad23d3 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Wed, 4 May 2005 11:44:44 +0000 Subject: Add a facility to route all rasterization through a fragment program which is automatically generated to match the current texture environment state. Introduces a new value ctx->FragmentProgram._Active which is true when either _Enabled is true or there is such a fragment program ready to run. To test out on a driver running the software rasterizer, set MESA_TEX_PROG=t in the environment. It goes without saying that performance is lower for the software rasterizer in this mode. --- src/mesa/main/context.c | 3 + src/mesa/main/mtypes.h | 5 + src/mesa/main/state.c | 13 ++ src/mesa/main/texenvprogram.c | 254 +++++++++++++++----------------------- src/mesa/main/texenvprogram.h | 39 ++++++ src/mesa/sources | 1 + src/mesa/swrast/s_aalinetemp.h | 4 +- src/mesa/swrast/s_context.c | 20 +-- src/mesa/swrast/s_fragprog_to_c.c | 2 +- src/mesa/swrast/s_nvfragprog.c | 4 +- src/mesa/swrast/s_pointtemp.h | 2 +- src/mesa/swrast/s_span.c | 20 +-- src/mesa/swrast/s_triangle.c | 4 +- src/mesa/tnl/t_vp_build.c | 27 +++- 14 files changed, 213 insertions(+), 185 deletions(-) create mode 100644 src/mesa/main/texenvprogram.h diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index acf5cc7d8bc..087cc64c336 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1602,6 +1602,9 @@ _mesa_initialize_context( GLcontext *ctx, ctx->TnlModule.SwapCount = 0; #endif + ctx->_MaintainTexEnvProgram = (_mesa_getenv("MESA_TEX_PROG") != NULL); + ctx->_MaintainTnlProgram = (_mesa_getenv("MESA_TNL_PROG") != NULL); + return GL_TRUE; } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 4ece984f38d..b50bf0e4f1a 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1829,7 +1829,9 @@ struct gl_fragment_program_state { GLboolean Enabled; /* GL_VERTEX_PROGRAM_NV */ GLboolean _Enabled; /* Really enabled? */ + GLboolean _Active; /* Really really enabled? */ struct fragment_program *Current; /* ptr to currently bound program */ + struct fragment_program *_Current; /* ptr to currently active program */ struct fp_machine Machine; /* machine state */ GLfloat Parameters[MAX_NV_FRAGMENT_PROGRAM_PARAMS][4]; /* Env params */ @@ -2652,6 +2654,9 @@ struct __GLcontextRec struct fragment_program _TexEnvProgram; /**< Texture state as fragment program */ struct vertex_program _TnlProgram; /**< Fixed func TNL state as vertex program */ + GLboolean _MaintainTexEnvProgram; + GLboolean _MaintainTnlProgram; + struct gl_occlusion_state Occlusion; /**< GL_ARB_occlusion_query */ struct gl_shader_objects_state ShaderObjects; /* GL_ARB_shader_objects */ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 3cb90447013..540d3ce993c 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -933,6 +933,14 @@ update_program(GLcontext *ctx) && ctx->FragmentProgram.Current->Instructions; ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled && ctx->ATIFragmentShader.Current->Instructions; + + ctx->FragmentProgram._Current = ctx->FragmentProgram.Current; + ctx->FragmentProgram._Active = ctx->FragmentProgram._Enabled; + + if (ctx->_MaintainTexEnvProgram && !ctx->FragmentProgram._Enabled) { + ctx->FragmentProgram._Current = &ctx->_TexEnvProgram; + ctx->FragmentProgram._Active = GL_TRUE; + } } @@ -984,6 +992,11 @@ _mesa_update_state( GLcontext *ctx ) if (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) update_arrays( ctx ); + if (ctx->_MaintainTexEnvProgram) { + if (new_state & (_NEW_TEXTURE | _DD_NEW_SEPARATE_SPECULAR)) + _mesa_UpdateTexEnvProgram(ctx); + } + /* ctx->_NeedEyeCoords is now up to date. * * If the truth value of this variable has changed, update for the diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 448c577b795..187526e6775 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -37,7 +37,7 @@ #include "shader/arbfragparse.h" -#define DISASSEM 1 +#define DISASSEM 0 /* Use uregs to represent registers internally, translate to Mesa's * expected formats on emit. @@ -76,30 +76,17 @@ const static struct ureg undef = { #define Z 2 #define W 3 -#define MAX_CONSTANT 32 - /* State used to build the fragment program: */ struct texenv_fragment_program { - struct fragment_program *prog; + struct fragment_program *program; GLcontext *ctx; - GLfloat constant[MAX_CONSTANT][4]; - GLuint constant_flags[MAX_CONSTANT]; - GLuint nr_constants; - GLuint temp_flag; /* Tracks temporary regs which are in * use. */ - struct { - GLuint reg; /* Hardware constant idx */ - const GLfloat *values; /* Pointer to tracked values */ - } param[MAX_CONSTANT]; - GLuint nr_params; - - GLboolean error; struct ureg src_texture; /* Reg containing sampled texture color, @@ -167,22 +154,40 @@ static void release_temps( struct texenv_fragment_program *p ) } -static struct ureg emit_decl( struct texenv_fragment_program *p, - GLuint type, GLuint nr ) +static struct ureg register_param6( struct texenv_fragment_program *p, + GLint s0, + GLint s1, + GLint s2, + GLint s3, + GLint s4, + GLint s5) { - struct ureg reg = make_ureg(type, nr); + GLint tokens[6]; + GLuint idx; + tokens[0] = s0; + tokens[1] = s1; + tokens[2] = s2; + tokens[3] = s3; + tokens[4] = s4; + tokens[5] = s5; + idx = _mesa_add_state_reference( p->program->Parameters, tokens ); + return make_ureg(PROGRAM_STATE_VAR, idx); +} - if (type == PROGRAM_INPUT) { - p->prog->InputsRead |= 1<program->InputsRead |= (1<prog->Base.NumInstructions++; - struct fp_instruction *inst = &p->prog->Instructions[nr]; + GLuint nr = p->program->Base.NumInstructions++; + struct fp_instruction *inst = &p->program->Instructions[nr]; memset(inst, 0, sizeof(*inst)); inst->Opcode = op; - if (!is_undef(src0)) emit_arg( &inst->SrcReg[0], src0 ); - if (!is_undef(src1)) emit_arg( &inst->SrcReg[1], src1 ); - if (!is_undef(src2)) emit_arg( &inst->SrcReg[2], src2 ); + emit_arg( &inst->SrcReg[0], src0 ); + emit_arg( &inst->SrcReg[1], src1 ); + emit_arg( &inst->SrcReg[2], src2 ); inst->Saturate = saturate; @@ -233,17 +238,17 @@ emit_op(struct texenv_fragment_program *p, static struct ureg emit_arith( struct texenv_fragment_program *p, - GLuint op, - struct ureg dest, - GLuint mask, - GLuint saturate, - struct ureg src0, - struct ureg src1, - struct ureg src2 ) + GLuint op, + struct ureg dest, + GLuint mask, + GLuint saturate, + struct ureg src0, + struct ureg src1, + struct ureg src2 ) { emit_op(p, op, dest, mask, saturate, src0, src1, src2); - p->prog->NumAluInstructions++; + p->program->NumAluInstructions++; return dest; } @@ -265,99 +270,39 @@ static struct ureg emit_texld( struct texenv_fragment_program *p, inst->TexSrcIdx = tex_idx; inst->TexSrcUnit = tex_unit; - p->prog->NumTexInstructions++; + p->program->NumTexInstructions++; if (coord.file != PROGRAM_INPUT && - (coord.idx < VERT_ATTRIB_TEX0 || - coord.idx > VERT_ATTRIB_TEX7)) { - p->prog->NumTexIndirections++; + (coord.idx < FRAG_ATTRIB_TEX0 || + coord.idx > FRAG_ATTRIB_TEX7)) { + p->program->NumTexIndirections++; } return dest; } -static struct ureg emit_const1f( struct texenv_fragment_program *p, GLfloat c0 ) -{ - GLint reg, idx; - - for (reg = 0; reg < MAX_CONSTANT; reg++) { - for (idx = 0; idx < 4; idx++) { - if (!(p->constant_flags[reg] & (1<constant[reg][idx] == c0) { - p->constant[reg][idx] = c0; - p->constant_flags[reg] |= 1< p->nr_constants) p->nr_constants = reg+1; - return swizzle1(make_ureg(PROGRAM_LOCAL_PARAM, reg),idx); - } - } - } - - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); - p->error = 1; - return undef; -} - -static struct ureg emit_const2f( struct texenv_fragment_program *p, - GLfloat c0, GLfloat c1 ) +static struct ureg register_const4f( struct texenv_fragment_program *p, + GLfloat s0, + GLfloat s1, + GLfloat s2, + GLfloat s3) { - GLint reg, idx; - - for (reg = 0; reg < MAX_CONSTANT; reg++) { - if (p->constant_flags[reg] == 0xf) - continue; - for (idx = 0; idx < 3; idx++) { - if (!(p->constant_flags[reg] & (3<constant[reg][idx] = c0; - p->constant[reg][idx+1] = c1; - p->constant_flags[reg] |= 3< p->nr_constants) p->nr_constants = reg+1; - return swizzle(make_ureg(PROGRAM_LOCAL_PARAM, reg),idx,idx+1,idx,idx+1); - } - } - } - - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); - p->error = 1; - return undef; + GLfloat values[4]; + GLuint idx; + values[0] = s0; + values[1] = s1; + values[2] = s2; + values[3] = s3; + idx = _mesa_add_unnamed_constant( p->program->Parameters, values ); + return make_ureg(PROGRAM_STATE_VAR, idx); } +#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1) +#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1) +#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1) -static struct ureg emit_const4f( struct texenv_fragment_program *p, - GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3 ) -{ - GLint reg; - - for (reg = 0; reg < MAX_CONSTANT; reg++) { - if (p->constant_flags[reg] == 0xf && - p->constant[reg][0] == c0 && - p->constant[reg][1] == c1 && - p->constant[reg][2] == c2 && - p->constant[reg][3] == c3) { - return make_ureg(PROGRAM_LOCAL_PARAM, reg); - } - else if (p->constant_flags[reg] == 0) { - p->constant[reg][0] = c0; - p->constant[reg][1] = c1; - p->constant[reg][2] = c2; - p->constant[reg][3] = c3; - p->constant_flags[reg] = 0xf; - if (reg+1 > p->nr_constants) p->nr_constants = reg+1; - return make_ureg(PROGRAM_LOCAL_PARAM, reg); - } - } - - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); - p->error = 1; - return undef; -} - - -static struct ureg emit_const4fv( struct texenv_fragment_program *p, const GLfloat *c ) -{ - return emit_const4f( p, c[0], c[1], c[2], c[3] ); -} @@ -393,9 +338,7 @@ static struct ureg get_source( struct texenv_fragment_program *p, if (is_undef(p->src_texture)) { GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled); - struct ureg texcoord = emit_decl(p, - PROGRAM_INPUT, - VERT_ATTRIB_TEX0+unit); + struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit); struct ureg tmp = get_temp( p ); /* TODO: Use D0_MASK_XY where possible. @@ -420,14 +363,15 @@ static struct ureg get_source( struct texenv_fragment_program *p, } case GL_CONSTANT: - return emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor ); + return register_param2(p, STATE_TEXENV_COLOR, unit); case GL_PRIMARY_COLOR: - return emit_decl(p, PROGRAM_INPUT, VERT_ATTRIB_COLOR0); + return register_input(p, FRAG_ATTRIB_COL0); case GL_PREVIOUS: default: - return emit_decl(p, - p->src_previous.file, - p->src_previous.idx); + if (is_undef(p->src_previous)) + return register_input(p, FRAG_ATTRIB_COL0); + else + return p->src_previous; } } @@ -448,7 +392,7 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p, * Emit tmp = 1.0 - arg.xyzw */ arg = get_temp( p ); - one = emit_const1f(p, 1); + one = register_const1f(p, 1.0); return emit_arith( p, FP_OPCODE_SUB, arg, mask, 0, one, src, undef); case GL_SRC_ALPHA: @@ -461,7 +405,7 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p, * Emit tmp = 1.0 - arg.wwww */ arg = get_temp( p ); - one = emit_const1f(p, 1); + one = register_const1f(p, 1.0); return emit_arith( p, FP_OPCODE_SUB, arg, mask, 0, one, swizzle1(src, W), undef); case GL_SRC_COLOR: @@ -559,7 +503,7 @@ static struct ureg emit_combine( struct texenv_fragment_program *p, /* tmp = arg0 + arg1 * result = tmp + -.5 */ - tmp = emit_const1f(p, .5); + tmp = register_const1f(p, .5); tmp = swizzle1(tmp,X); emit_arith( p, FP_OPCODE_ADD, dest, mask, 0, src[0], src[1], undef ); emit_arith( p, FP_OPCODE_SUB, dest, mask, saturate, dest, tmp, undef ); @@ -578,8 +522,8 @@ static struct ureg emit_combine( struct texenv_fragment_program *p, case GL_DOT3_RGB: { struct ureg tmp0 = get_temp( p ); struct ureg tmp1 = get_temp( p ); - struct ureg neg1 = emit_const1f(p, -1); - struct ureg two = emit_const1f(p, 2); + struct ureg neg1 = register_const1f(p, -1); + struct ureg two = register_const1f(p, 2); /* tmp0 = 2*src0 - 1 * tmp1 = 2*src1 - 1 @@ -610,7 +554,7 @@ static struct ureg get_dest( struct texenv_fragment_program *p, int unit ) else if (unit != p->last_tex_stage) return get_temp( p ); else - return make_ureg(PROGRAM_OUTPUT, VERT_ATTRIB_COLOR0); + return make_ureg(PROGRAM_OUTPUT, FRAG_OUTPUT_COLR); } @@ -684,11 +628,11 @@ static struct ureg emit_texenv( struct texenv_fragment_program *p, int unit ) */ if (alpha_shift || rgb_shift) { if (rgb_shift == alpha_shift) { - shift = emit_const1f(p, 1<FragmentProgram._Enabled) + return; + p.ctx = ctx; - p.prog = &ctx->_TexEnvProgram; + p.program = &ctx->_TexEnvProgram; - if (p.prog->Instructions == NULL) { - p.prog->Instructions = MALLOC(sizeof(struct fp_instruction) * 100); + if (p.program->Instructions == NULL) { + p.program->Instructions = MALLOC(sizeof(struct fp_instruction) * 100); } - p.prog->Base.NumInstructions = 0; - p.prog->NumTexIndirections = 1; /* correct? */ - p.prog->NumTexInstructions = 0; - p.prog->NumAluInstructions = 0; - - memset( p.constant_flags, 0, sizeof(p.constant_flags) ); + p.program->Base.NumInstructions = 0; + p.program->NumTexIndirections = 1; /* correct? */ + p.program->NumTexInstructions = 0; + p.program->NumAluInstructions = 0; p.src_texture = undef; - p.src_previous = make_ureg(PROGRAM_INPUT, VERT_ATTRIB_COLOR0); + p.src_previous = undef; p.last_tex_stage = 0; if (ctx->Texture._EnabledUnits) { @@ -738,12 +683,12 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx ) } cf = get_source( &p, GL_PREVIOUS, 0 ); - out = make_ureg( PROGRAM_OUTPUT, VERT_ATTRIB_COLOR0 ); + out = make_ureg( PROGRAM_OUTPUT, FRAG_OUTPUT_COLR ); if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { /* Emit specular add. */ - struct ureg s = emit_decl(&p, PROGRAM_INPUT, VERT_ATTRIB_COLOR1); + struct ureg s = register_input(&p, FRAG_ATTRIB_COL1); emit_arith( &p, FP_OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef ); } else if (memcmp(&cf, &out, sizeof(cf)) != 0) { @@ -753,18 +698,23 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx ) emit_arith( &p, FP_OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef ); } - if (p.prog->NumTexIndirections > ctx->Const.MaxFragmentProgramTexIndirections) + /* Finish up: + */ + emit_arith( &p, FP_OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef); + + + if (p.program->NumTexIndirections > ctx->Const.MaxFragmentProgramTexIndirections) program_error(&p, "Exceeded max nr indirect texture lookups"); - if (p.prog->NumTexInstructions > ctx->Const.MaxFragmentProgramTexInstructions) + if (p.program->NumTexInstructions > ctx->Const.MaxFragmentProgramTexInstructions) program_error(&p, "Exceeded max TEX instructions"); - if (p.prog->NumAluInstructions > ctx->Const.MaxFragmentProgramAluInstructions) + if (p.program->NumAluInstructions > ctx->Const.MaxFragmentProgramAluInstructions) program_error(&p, "Exceeded max ALU instructions"); #if DISASSEM - _mesa_debug_fp_inst(p.prog->NumTexInstructions + p.prog->NumAluInstructions, - p.prog->Instructions); + _mesa_debug_fp_inst(p.program->NumTexInstructions + p.program->NumAluInstructions, + p.program->Instructions); _mesa_printf("\n"); #endif } diff --git a/src/mesa/main/texenvprogram.h b/src/mesa/main/texenvprogram.h new file mode 100644 index 00000000000..bca05d00e05 --- /dev/null +++ b/src/mesa/main/texenvprogram.h @@ -0,0 +1,39 @@ +/** + * \file texenvprogram.h + * Texture state management. + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef TEXENVPROGRAM_H +#define TEXENVPROGRAM_H + + +#include "mtypes.h" + +extern void _mesa_UpdateTexEnvProgram( GLcontext *ctx ); + +#endif diff --git a/src/mesa/sources b/src/mesa/sources index e461840a9ef..54cd290524a 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -46,6 +46,7 @@ MAIN_SOURCES = \ main/texcompress.c \ main/texcompress_s3tc.c \ main/texcompress_fxt1.c \ + main/texenvprogram.c \ main/texformat.c \ main/teximage.c \ main/texobj.c \ diff --git a/src/mesa/swrast/s_aalinetemp.h b/src/mesa/swrast/s_aalinetemp.h index aa78ef7b596..4a1e1ebda2a 100644 --- a/src/mesa/swrast/s_aalinetemp.h +++ b/src/mesa/swrast/s_aalinetemp.h @@ -80,7 +80,7 @@ NAME(plot)(GLcontext *ctx, struct LineInfo *line, int ix, int iy) #ifdef DO_TEX { GLfloat invQ; - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { invQ = 1.0F; } else { @@ -100,7 +100,7 @@ NAME(plot)(GLcontext *ctx, struct LineInfo *line, int ix, int iy) for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled) { GLfloat invQ; - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { invQ = 1.0F; } else { diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c index b923f0a673e..f6dcdbb9644 100644 --- a/src/mesa/swrast/s_context.c +++ b/src/mesa/swrast/s_context.c @@ -104,7 +104,7 @@ _swrast_update_rasterflags( GLcontext *ctx ) rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */ } - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { rasterMask |= FRAGPROG_BIT; } @@ -161,7 +161,7 @@ _swrast_update_fog_hint( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); swrast->_PreferPixelFog = (!swrast->AllowVertexFog || - ctx->FragmentProgram._Enabled || + ctx->FragmentProgram._Active || (ctx->Hint.Fog == GL_NICEST && swrast->AllowPixelFog)); } @@ -202,10 +202,10 @@ _swrast_update_fog_state( GLcontext *ctx ) /* determine if fog is needed, and if so, which fog mode */ swrast->_FogEnabled = GL_FALSE; - if (ctx->FragmentProgram._Enabled) { - if (ctx->FragmentProgram.Current->Base.Target==GL_FRAGMENT_PROGRAM_ARB) { + if (ctx->FragmentProgram._Active) { + if (ctx->FragmentProgram._Current->Base.Target==GL_FRAGMENT_PROGRAM_ARB) { const struct fragment_program *p - = (struct fragment_program *) ctx->FragmentProgram.Current; + = (struct fragment_program *) ctx->FragmentProgram._Current; if (p->FogOption != GL_NONE) { swrast->_FogEnabled = GL_TRUE; swrast->_FogMode = p->FogOption; @@ -226,8 +226,8 @@ _swrast_update_fog_state( GLcontext *ctx ) static void _swrast_update_fragment_program( GLcontext *ctx ) { - if (ctx->FragmentProgram._Enabled) { - struct fragment_program *program = ctx->FragmentProgram.Current; + if (ctx->FragmentProgram._Active) { + struct fragment_program *program = ctx->FragmentProgram._Current; _mesa_load_state_parameters(ctx, program->Parameters); } } @@ -295,7 +295,7 @@ _swrast_validate_triangle( GLcontext *ctx, if (ctx->Texture._EnabledUnits == 0 && NEED_SECONDARY_COLOR(ctx) - && !ctx->FragmentProgram._Enabled) { + && !ctx->FragmentProgram._Active) { /* separate specular color, but no texture */ swrast->SpecTriangle = swrast->Triangle; swrast->Triangle = _swrast_add_spec_terms_triangle; @@ -318,7 +318,7 @@ _swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) if (ctx->Texture._EnabledUnits == 0 && NEED_SECONDARY_COLOR(ctx) - && !ctx->FragmentProgram._Enabled) { + && !ctx->FragmentProgram._Active) { swrast->SpecLine = swrast->Line; swrast->Line = _swrast_add_spec_terms_line; } @@ -341,7 +341,7 @@ _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 ) if (ctx->Texture._EnabledUnits == 0 && NEED_SECONDARY_COLOR(ctx) - && !ctx->FragmentProgram._Enabled) { + && !ctx->FragmentProgram._Active) { swrast->SpecPoint = swrast->Point; swrast->Point = _swrast_add_spec_terms_point; } diff --git a/src/mesa/swrast/s_fragprog_to_c.c b/src/mesa/swrast/s_fragprog_to_c.c index fa669693307..1953e8c73cc 100644 --- a/src/mesa/swrast/s_fragprog_to_c.c +++ b/src/mesa/swrast/s_fragprog_to_c.c @@ -808,7 +808,7 @@ static void translate_program( struct fragment_program *p ) void _swrast_translate_program( GLcontext *ctx ) { - struct fragment_program *p = ctx->FragmentProgram.Current; + struct fragment_program *p = ctx->FragmentProgram._Current; if (p) { p->c_strlen = 0; diff --git a/src/mesa/swrast/s_nvfragprog.c b/src/mesa/swrast/s_nvfragprog.c index 2fea568cc90..51d36c0a2b5 100644 --- a/src/mesa/swrast/s_nvfragprog.c +++ b/src/mesa/swrast/s_nvfragprog.c @@ -1410,7 +1410,7 @@ init_machine( GLcontext *ctx, struct fp_machine *machine, void _swrast_exec_fragment_program( GLcontext *ctx, struct sw_span *span ) { - const struct fragment_program *program = ctx->FragmentProgram.Current; + const struct fragment_program *program = ctx->FragmentProgram._Current; GLuint i; ctx->_CurrentProgram = GL_FRAGMENT_PROGRAM_ARB; /* or NV, doesn't matter */ @@ -1418,7 +1418,7 @@ _swrast_exec_fragment_program( GLcontext *ctx, struct sw_span *span ) for (i = 0; i < span->end; i++) { if (span->array->mask[i]) { init_machine(ctx, &ctx->FragmentProgram.Machine, - ctx->FragmentProgram.Current, span, i); + ctx->FragmentProgram._Current, span, i); #ifdef USE_TCC if (!_swrast_execute_codegen_program(ctx, program, ~0, diff --git a/src/mesa/swrast/s_pointtemp.h b/src/mesa/swrast/s_pointtemp.h index ef48d239ec4..b0c110f3007 100644 --- a/src/mesa/swrast/s_pointtemp.h +++ b/src/mesa/swrast/s_pointtemp.h @@ -120,7 +120,7 @@ NAME ( GLcontext *ctx, const SWvertex *vert ) #endif #if FLAGS & TEXTURE span->arrayMask |= SPAN_TEXTURE; - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { /* Don't divide texture s,t,r by q (use TXP to do that) */ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { if (ctx->Texture._EnabledCoordUnits & (1 << u)) { diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index a541b66ceb5..e6afee1eaa0 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -128,7 +128,7 @@ _swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span ) GLuint i; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { const GLfloat *tc = ctx->Current.RasterTexCoords[i]; - if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled) { + if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled) { COPY_4V(span->tex[i], tc); } else if (tc[3] > 0.0F) { @@ -406,7 +406,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) if (obj) { const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; needLambda = (obj->MinFilter != obj->MagFilter) - || ctx->FragmentProgram._Enabled; + || ctx->FragmentProgram._Active; texW = img->WidthScale; texH = img->HeightScale; } @@ -431,7 +431,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) GLfloat r = span->tex[u][2]; GLfloat q = span->tex[u][3]; GLuint i; - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->dwdx; GLfloat w = span->w; @@ -482,7 +482,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) GLfloat r = span->tex[u][2]; GLfloat q = span->tex[u][3]; GLuint i; - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->dwdx; GLfloat w = span->w; @@ -540,7 +540,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) if (obj) { const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; needLambda = (obj->MinFilter != obj->MagFilter) - || ctx->FragmentProgram._Enabled; + || ctx->FragmentProgram._Active; texW = (GLfloat) img->WidthScale; texH = (GLfloat) img->HeightScale; } @@ -565,7 +565,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) GLfloat r = span->tex[0][2]; GLfloat q = span->tex[0][3]; GLuint i; - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->dwdx; GLfloat w = span->w; @@ -616,7 +616,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) GLfloat r = span->tex[0][2]; GLfloat q = span->tex[0][3]; GLuint i; - if (ctx->FragmentProgram._Enabled) { + if (ctx->FragmentProgram._Active) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->dwdx; GLfloat w = span->w; @@ -1174,7 +1174,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) interpolate_fog(ctx, span); /* Compute fragment colors with fragment program or texture lookups */ - if (ctx->FragmentProgram._Enabled) + if (ctx->FragmentProgram._Active) /* XXX interpolate depth values here??? */ _swrast_exec_fragment_program( ctx, span ); else if (ctx->ATIFragmentShader._Enabled) @@ -1252,7 +1252,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) if (span->interpMask & SPAN_FOG) interpolate_fog(ctx, span); - if (ctx->FragmentProgram._Enabled) + if (ctx->FragmentProgram._Active) _swrast_exec_fragment_program( ctx, span ); else if (ctx->ATIFragmentShader._Enabled) _swrast_exec_fragment_shader( ctx, span ); @@ -1262,7 +1262,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) ASSERT(span->arrayMask & SPAN_RGBA); - if (!ctx->FragmentProgram._Enabled) { + if (!ctx->FragmentProgram._Active) { /* Add base and specular colors */ if (ctx->Fog.ColorSumEnabled || (ctx->Light.Enabled && diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c index c236e525709..4533980455e 100644 --- a/src/mesa/swrast/s_triangle.c +++ b/src/mesa/swrast/s_triangle.c @@ -1075,7 +1075,7 @@ _swrast_choose_triangle( GLcontext *ctx ) } } - if (ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Enabled) { + if (ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Active) { /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ const struct gl_texture_object *texObj2D; const struct gl_texture_image *texImg; @@ -1090,7 +1090,7 @@ _swrast_choose_triangle( GLcontext *ctx ) /* First see if we can use an optimized 2-D texture function */ if (ctx->Texture._EnabledCoordUnits == 0x1 - && !ctx->FragmentProgram._Enabled + && !ctx->FragmentProgram._Active && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT && texObj2D->WrapS == GL_REPEAT && texObj2D->WrapT == GL_REPEAT diff --git a/src/mesa/tnl/t_vp_build.c b/src/mesa/tnl/t_vp_build.c index eefede7913c..9034fc77121 100644 --- a/src/mesa/tnl/t_vp_build.c +++ b/src/mesa/tnl/t_vp_build.c @@ -367,6 +367,10 @@ static void emit_matrix_transform_vec4( struct tnl_program *p, emit_op2(p, VP_OPCODE_DP4, dest, WRITEMASK_W, src, mat[3]); } +/* This version is much easier to implement if writemasks are not + * supported natively on the target or (like SSE), the target doesn't + * have a clean/obvious dotproduct implementation. + */ static void emit_transpose_matrix_transform_vec4( struct tnl_program *p, struct ureg dest, const struct ureg *mat, @@ -692,14 +696,12 @@ static void build_lighting( struct tnl_program *p ) count++; if (light->EyePosition[3] == 0) { - /* Can used precomputed constants in this case: + /* Can used precomputed constants in this case. + * Attenuation never applies to infinite lights. */ VPpli = register_param3(p, STATE_LIGHT, i, STATE_POSITION_NORMALIZED); half = register_param3(p, STATE_LIGHT, i, STATE_HALF); - - /* Spot attenuation maybe applies to this case? Could - * precompute if so? */ } else { struct ureg Ppli = register_param3(p, STATE_LIGHT, i, @@ -767,7 +769,7 @@ static void build_lighting( struct tnl_program *p ) if (!is_undef(att)) emit_op2(p, VP_OPCODE_MUL, lit, 0, lit, att); - + if (count == nr_lights) { if (separate) { res0 = register_output( p, VERT_RESULT_COL0 ); @@ -1082,9 +1084,15 @@ static void build_pointsize( struct tnl_program *p ) } +static void build_passthrough( struct tnl_program *p, GLuint inputs ) +{ +} + + void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx ) { + TNLcontext *tnl = TNL_CONTEXT(ctx); struct tnl_program p; if (ctx->VertexProgram._Enabled) @@ -1136,6 +1144,15 @@ void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx ) if (ctx->Point._Attenuated) build_pointsize(&p); + /* Is there a need to copy inputs to outputs? The software + * implementation might do this more efficiently by just assigning + * the missing results to point at input arrays. + */ + if (/* tnl->vp_copy_inputs && */ + (tnl->render_inputs & ~p.program->OutputsWritten)) { + build_passthrough(&p, tnl->render_inputs); + } + /* Finish up: */ -- cgit v1.2.3