Add a facility to route all rasterization through a fragment program
authorKeith Whitwell <keith@tungstengraphics.com>
Wed, 4 May 2005 11:44:44 +0000 (11:44 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Wed, 4 May 2005 11:44:44 +0000 (11:44 +0000)
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.

14 files changed:
src/mesa/main/context.c
src/mesa/main/mtypes.h
src/mesa/main/state.c
src/mesa/main/texenvprogram.c
src/mesa/main/texenvprogram.h [new file with mode: 0644]
src/mesa/sources
src/mesa/swrast/s_aalinetemp.h
src/mesa/swrast/s_context.c
src/mesa/swrast/s_fragprog_to_c.c
src/mesa/swrast/s_nvfragprog.c
src/mesa/swrast/s_pointtemp.h
src/mesa/swrast/s_span.c
src/mesa/swrast/s_triangle.c
src/mesa/tnl/t_vp_build.c

index acf5cc7..087cc64 100644 (file)
@@ -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;
 }
 
index 4ece984..b50bf0e 100644 (file)
@@ -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 */
index 3cb9044..540d3ce 100644 (file)
@@ -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
index 448c577..187526e 100644 (file)
@@ -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<<nr;
-   }
-   else {
-      /* Other ???
-       */
-   }
 
-   return reg;
+#define register_param1(p,s0)          register_param6(p,s0,0,0,0,0,0)
+#define register_param2(p,s0,s1)       register_param6(p,s0,s1,0,0,0,0)
+#define register_param3(p,s0,s1,s2)    register_param6(p,s0,s1,s2,0,0,0)
+#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
+
+
+static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
+{
+   p->program->InputsRead |= (1<<input);
+   return make_ureg(PROGRAM_INPUT, input);
 }
 
+
 static void emit_arg( struct fp_src_register *reg,
                      struct ureg ureg )
 {
@@ -214,15 +219,15 @@ emit_op(struct texenv_fragment_program *p,
        struct ureg src1,
        struct ureg src2 )
 {
-   GLuint nr = p->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<<idx)) ||
-            p->constant[reg][idx] == c0) {
-           p->constant[reg][idx] = c0;
-           p->constant_flags[reg] |= 1<<idx;
-           if (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<<idx))) {
-           p->constant[reg][idx] = c0;
-           p->constant[reg][idx+1] = c1;
-           p->constant_flags[reg] |= 3<<idx;
-           if (reg+1 > 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<<rgb_shift);
+        shift = register_const1f(p, 1<<rgb_shift);
         shift = swizzle1(shift,X);
       }
       else {
-        shift = emit_const2f(p, 1<<rgb_shift, 1<<alpha_shift);
+        shift = register_const2f(p, 1<<rgb_shift, 1<<alpha_shift);
         shift = swizzle(shift,X,X,X,Y);
       }
       return emit_arith( p, FP_OPCODE_MUL, dest, WRITEMASK_XYZW, 
@@ -704,22 +648,23 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
    GLuint unit;
    struct ureg cf, out;
 
+   if (ctx->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 (file)
index 0000000..bca05d0
--- /dev/null
@@ -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
index e461840..54cd290 100644 (file)
@@ -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 \
index aa78ef7..4a1e1eb 100644 (file)
@@ -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 {
index b923f0a..f6dcdbb 100644 (file)
@@ -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;
    }
index fa66969..1953e8c 100644 (file)
@@ -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;
index 2fea568..51d36c0 100644 (file)
@@ -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,
index ef48d23..b0c110f 100644 (file)
@@ -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)) {
index a541b66..e6afee1 100644 (file)
@@ -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 &&
index c236e52..4533980 100644 (file)
@@ -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
index eefede7..9034fc7 100644 (file)
@@ -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:
     */