Fix pow <small> and a very stypid bug with dummy srcs(0 equals to tmp0.x)</small...
[mesa.git] / src / mesa / main / texenvprogram.c
index 8cd8a8630eb8bc2dc54fb5cc82328a6ea9366a83..04738b019b61c9e216743c51240d8bafd50d3ee6 100644 (file)
 
 #include "shader/program.h"
 #include "shader/program_instruction.h"
-#include "shader/arbfragparse.h"
 
+#define MAX_INSTRUCTIONS 100
 
 #define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
 
 struct mode_opt {
-   unsigned Source:4;
-   unsigned Operand:3;
+   GLuint Source:4;
+   GLuint Operand:3;
 };
 
 struct state_key {
-   GLuint enabled_units;
-   unsigned separate_specular:1;
-   unsigned fog_enabled:1;
-   unsigned fog_mode:2;
+   GLbitfield enabled_units;
+   GLuint separate_specular:1;
+   GLuint fog_enabled:1;
+   GLuint fog_mode:2;
 
    struct {
-      unsigned enabled:1;
-      unsigned source_index:3;
-      unsigned ScaleShiftRGB:2;
-      unsigned ScaleShiftA:2;
+      GLuint enabled:1;
+      GLuint source_index:3;   /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
+      GLuint ScaleShiftRGB:2;
+      GLuint ScaleShiftA:2;
 
-      unsigned NumArgsRGB:2;
-      unsigned ModeRGB:4;
+      GLuint NumArgsRGB:2;
+      GLuint ModeRGB:4;
       struct mode_opt OptRGB[3];
 
-      unsigned NumArgsA:2;
-      unsigned ModeA:4;
+      GLuint NumArgsA:2;
+      GLuint ModeA:4;
       struct mode_opt OptA[3];
    } unit[8];
 };
@@ -181,7 +181,12 @@ static GLuint translate_tex_src_bit( GLbitfield bit )
    }
 }
 
-static struct state_key *make_state_key( GLcontext *ctx )
+/**
+ * Examine current texture environment state and generate a unique
+ * key to identify it.
+ */
+static struct state_key *
+make_state_key(GLcontext *ctx)
 {
    struct state_key *key = CALLOC_STRUCT(state_key);
    GLuint i, j;
@@ -264,10 +269,6 @@ const static struct ureg undef = {
    0
 };
 
-#define X    0
-#define Y    1
-#define Z    2
-#define W    3
 
 /* State used to build the fragment program:
  */
@@ -276,14 +277,9 @@ struct texenv_fragment_program {
    GLcontext *ctx;
    struct state_key *state;
 
-   GLuint alu_temps;           /* Track texture indirections, see spec. */
-   GLuint temps_output;                /* Track texture indirections, see spec. */
-
-   GLuint temp_in_use;         /* Tracks temporary regs which are in
-                                * use.
-                                */
-
-
+   GLbitfield alu_temps;       /* Track texture indirections, see spec. */
+   GLbitfield temps_output;    /* Track texture indirections, see spec. */
+   GLbitfield temp_in_use;     /* Tracks temporary regs which are in use. */
    GLboolean error;
 
    struct ureg src_texture[MAX_TEXTURE_UNITS];   
@@ -428,7 +424,7 @@ static struct ureg register_param6( struct texenv_fragment_program *p,
    tokens[3] = s3;
    tokens[4] = s4;
    tokens[5] = s5;
-   idx = _mesa_add_state_reference( p->program->Parameters, tokens );
+   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
    return make_ureg(PROGRAM_STATE_VAR, idx);
 }
 
@@ -441,7 +437,7 @@ static struct ureg register_param6( struct texenv_fragment_program *p,
 
 static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
 {
-   p->program->InputsRead |= (1<<input);
+   p->program->Base.InputsRead |= (1 << input);
    return make_ureg(PROGRAM_INPUT, input);
 }
 
@@ -469,25 +465,25 @@ static void emit_dst( struct prog_dst_register *dst,
 
 static struct prog_instruction *
 emit_op(struct texenv_fragment_program *p,
-       GLuint op,
+       enum prog_opcode op,
        struct ureg dest,
        GLuint mask,
-       GLuint saturate,
+       GLboolean saturate,
        struct ureg src0,
        struct ureg src1,
        struct ureg src2 )
 {
    GLuint nr = p->program->Base.NumInstructions++;
-   struct prog_instruction *inst = &p->program->Instructions[nr];
+   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
       
-   _mesa_memset(inst, 0, sizeof(*inst));
+   _mesa_init_instruction(inst);
    inst->Opcode = op;
    
    emit_arg( &inst->SrcReg[0], src0 );
    emit_arg( &inst->SrcReg[1], src1 );
    emit_arg( &inst->SrcReg[2], src2 );
    
-   inst->Saturate = saturate;
+   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
 
    emit_dst( &inst->DstReg, dest, mask );
 
@@ -501,10 +497,10 @@ emit_op(struct texenv_fragment_program *p,
    
 
 static struct ureg emit_arith( struct texenv_fragment_program *p,
-                              GLuint op,
+                              enum prog_opcode op,
                               struct ureg dest,
                               GLuint mask,
-                              GLuint saturate,
+                              GLboolean saturate,
                               struct ureg src0,
                               struct ureg src1,
                               struct ureg src2 )
@@ -530,7 +526,7 @@ static struct ureg emit_arith( struct texenv_fragment_program *p,
 }
 
 static struct ureg emit_texld( struct texenv_fragment_program *p,
-                              GLuint op,
+                              enum prog_opcode op,
                               struct ureg dest,
                               GLuint destmask,
                               GLuint tex_unit,
@@ -539,7 +535,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
 {
    struct prog_instruction *inst = emit_op( p, op, 
                                          dest, destmask, 
-                                         0,            /* don't saturate? */
+                                         GL_FALSE,     /* don't saturate? */
                                          coord,        /* arg 0? */
                                          undef,
                                          undef);
@@ -577,7 +573,7 @@ static struct ureg register_const4f( struct texenv_fragment_program *p,
    values[1] = s1;
    values[2] = s2;
    values[3] = s3;
-   idx = _mesa_add_unnamed_constant( p->program->Parameters, values );
+   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values );
    return make_ureg(PROGRAM_STATE_VAR, idx);
 }
 
@@ -587,8 +583,6 @@ static struct ureg register_const4f( struct texenv_fragment_program *p,
 #define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
 
 
-
-
 static struct ureg get_one( struct texenv_fragment_program *p )
 {
    if (is_undef(p->one)) 
@@ -611,9 +605,6 @@ static struct ureg get_zero( struct texenv_fragment_program *p )
 }
 
 
-
-
-
 static void program_error( struct texenv_fragment_program *p, const char *msg )
 {
    _mesa_problem(NULL, msg);
@@ -677,7 +668,7 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p,
       if (mask == WRITEMASK_W)
         return src;
       else
-        return swizzle1( src, W );
+        return swizzle1( src, SWIZZLE_W );
    case OPR_ONE_MINUS_SRC_ALPHA: 
       /* Get unused tmp,
        * Emit tmp = 1.0 - arg.wwww
@@ -685,7 +676,7 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p,
       arg = get_temp(p);
       one = get_one(p);
       return emit_arith(p, OPCODE_SUB, arg, mask, 0,
-                       one, swizzle1(src, W), undef);
+                       one, swizzle1(src, SWIZZLE_W), undef);
    case OPR_ZERO:
       return get_zero(p);
    case OPR_ONE:
@@ -698,7 +689,7 @@ static struct ureg emit_combine_source( struct texenv_fragment_program *p,
 
 static GLboolean args_match( struct state_key *key, GLuint unit )
 {
-   int i, nr = key->unit[unit].NumArgsRGB;
+   GLuint i, nr = key->unit[unit].NumArgsRGB;
 
    for (i = 0 ; i < nr ; i++) {
       if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source) 
@@ -734,7 +725,7 @@ static GLboolean args_match( struct state_key *key, GLuint unit )
 static struct ureg emit_combine( struct texenv_fragment_program *p,
                                 struct ureg dest,
                                 GLuint mask,
-                                GLuint saturate,
+                                GLboolean saturate,
                                 GLuint unit,
                                 GLuint nr,
                                 GLuint mode,
@@ -742,7 +733,9 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
 {
    struct ureg src[3];
    struct ureg tmp, half;
-   int i;
+   GLuint i;
+
+   tmp = undef; /* silence warning (bug 5318) */
 
    for (i = 0; i < nr; i++)
       src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
@@ -822,10 +815,14 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
 }
 
 
-static struct ureg emit_texenv( struct texenv_fragment_program *p, int unit )
+/**
+ * Generate instructions for one texture unit's env/combiner mode.
+ */
+static struct ureg
+emit_texenv(struct texenv_fragment_program *p, GLuint unit)
 {
    struct state_key *key = p->state;
-   GLuint saturate = (unit < p->last_tex_stage);
+   GLboolean saturate = (unit < p->last_tex_stage);
    GLuint rgb_shift, alpha_shift;
    struct ureg out, shift;
    struct ureg dest;
@@ -915,7 +912,9 @@ static struct ureg emit_texenv( struct texenv_fragment_program *p, int unit )
 }
 
 
-
+/**
+ * Generate instruction for getting a texture source term.
+ */
 static void load_texture( struct texenv_fragment_program *p, GLuint unit )
 {
    if (is_undef(p->src_texture[unit])) {
@@ -962,7 +961,12 @@ static GLboolean load_texenv_source( struct texenv_fragment_program *p,
    return GL_TRUE;
 }
 
-static GLboolean load_texunit_sources( struct texenv_fragment_program *p, int unit )
+
+/**
+ * Generate instructions for loading all texture source terms.
+ */
+static GLboolean
+load_texunit_sources( struct texenv_fragment_program *p, int unit )
 {
    struct state_key *key = p->state;
    int i, nr = key->unit[unit].NumArgsRGB;
@@ -974,8 +978,14 @@ static GLboolean load_texunit_sources( struct texenv_fragment_program *p, int un
    return GL_TRUE;
 }
 
-static void create_new_program(struct state_key *key, GLcontext *ctx,
-                              struct fragment_program *program)
+
+/**
+ * Generate a new fragment program which implements the context's
+ * current texture env/combine mode.
+ */
+static void
+create_new_program(struct state_key *key, GLcontext *ctx,
+                   struct fragment_program *program)
 {
    struct texenv_fragment_program p;
    GLuint unit;
@@ -986,7 +996,8 @@ static void create_new_program(struct state_key *key, GLcontext *ctx,
    p.state = key;
    p.program = program;
 
-   p.program->Instructions = MALLOC(sizeof(struct prog_instruction) * 100);
+   p.program->Base.Instructions =
+      (struct prog_instruction*) _mesa_malloc(sizeof(struct prog_instruction) * MAX_INSTRUCTIONS);
    p.program->Base.NumInstructions = 0;
    p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
    p.program->NumTexIndirections = 1;  /* correct? */
@@ -997,10 +1008,10 @@ static void create_new_program(struct state_key *key, GLcontext *ctx,
       p.program->Base.NumTemporaries =
       p.program->Base.NumParameters =
       p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
-   p.program->Parameters = _mesa_new_parameter_list();
+   p.program->Base.Parameters = _mesa_new_parameter_list();
 
-   p.program->InputsRead = 0;
-   p.program->OutputsWritten = 1 << FRAG_RESULT_COLR;
+   p.program->Base.InputsRead = 0;
+   p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
 
    for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++)
       p.src_texture[unit] = undef;
@@ -1067,6 +1078,7 @@ static void create_new_program(struct state_key *key, GLcontext *ctx,
    if (p.program->NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
       program_error(&p, "Exceeded max ALU instructions");
 
+   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
 
    /* Notify driver the fragment program has (actually) changed.
     */
@@ -1076,15 +1088,13 @@ static void create_new_program(struct state_key *key, GLcontext *ctx,
                                          &p.program->Base );
 
       if (DISASSEM) {
-        _mesa_print_program(p.program->NumTexInstructions + p.program->NumAluInstructions,
-                            p.program->Instructions);
+        _mesa_print_program(&p.program->Base);
         _mesa_printf("\n");
       }
-      
    }
-
 }
 
+
 static void *search_cache( struct texenvprog_cache *cache,
                           GLuint hash,
                           const void *key,
@@ -1105,7 +1115,7 @@ static void cache_item( struct texenvprog_cache **cache,
                        void *key,
                        void *data )
 {
-   struct texenvprog_cache *c = MALLOC(sizeof(*c));
+   struct texenvprog_cache *c = CALLOC_STRUCT(texenvprog_cache);
    c->hash = hash;
    c->key = key;
    c->data = data;
@@ -1141,7 +1151,7 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
         search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key));
        
       if (!ctx->_TexEnvProgram) {
-        if (1) _mesa_printf("Building new texenv proggy for key %x\n", hash);
+        if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash);
                
         ctx->FragmentProgram._Current = ctx->_TexEnvProgram = 
            (struct fragment_program *) 
@@ -1151,8 +1161,8 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
 
         cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram);
       } else {
-        FREE(key);
-        if (1) _mesa_printf("Found existing texenv program for key %x\n", hash);
+        _mesa_free(key);
+        if (0) _mesa_printf("Found existing texenv program for key %x\n", hash);
       }
    } 
    else {
@@ -1162,9 +1172,10 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
    /* Tell the driver about the change.  Could define a new target for
     * this?
     */
-   if (ctx->FragmentProgram._Current != prev)
-      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, (struct program *)
-                             ctx->FragmentProgram._Current);   
+   if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
+      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
+                             (struct program *) ctx->FragmentProgram._Current);
+   }
 }
 
 void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
@@ -1173,9 +1184,8 @@ void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
 
    for (a = ctx->Texture.env_fp_cache; a; a = tmp) {
       tmp = a->next;
-      FREE(a->key);
-      FREE(a->data);
-      FREE(a);
+      _mesa_free(a->key);
+      ctx->Driver.DeleteProgram(ctx, (struct program *) a->data);
+      _mesa_free(a);
    }
 }
-