i965: Correct build_lighting in i965 driver according to
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vs_tnl.c
index 0d61092247ab0b61ef992a8f7de6c85a421c40bf..2ed80dc36e964a19d33fc7668bb5a22e8e519f80 100644 (file)
 #include "glheader.h"
 #include "macros.h"
 #include "enums.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
 #include "brw_vs.h"
 #include "brw_state.h"
 
-#include "shader/program.h"
-#include "shader/program_instruction.h"
-#include "shader/arbprogparse.h"
 
 struct state_key {
    unsigned light_global_enabled:1;
@@ -398,11 +397,14 @@ static struct ureg register_const4f( struct tnl_program *p,
 {
    GLfloat values[4];
    GLint idx;
+   GLuint swizzle;
    values[0] = s0;
    values[1] = s1;
    values[2] = s2;
    values[3] = s3;
-   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4 );
+   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
+                                     &swizzle);
+   /* XXX what about swizzle? */
    return make_ureg(PROGRAM_STATE_VAR, idx);
 }
 
@@ -424,40 +426,37 @@ static struct ureg get_identity_param( struct tnl_program *p )
    return p->identity;
 }
 
-static struct ureg register_param6( struct tnl_program *p, 
-                                  GLint s0,
-                                  GLint s1,
-                                  GLint s2,
-                                  GLint s3,
-                                  GLint s4,
-                                  GLint s5)
+static struct ureg register_param5( struct tnl_program *p, 
+                                    GLint s0,
+                                    GLint s1,
+                                    GLint s2,
+                                    GLint s3,
+                                    GLint s4)
 {
-   GLint tokens[6];
+   gl_state_index tokens[STATE_LENGTH];
    GLint 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->Base.Parameters, tokens );
    return make_ureg(PROGRAM_STATE_VAR, idx);
 }
 
 
-#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)
+#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_param6( struct tnl_program *p,
-                                   GLint s0,
-                                   GLint s1,
-                                   GLint s2,
-                                   GLint s3,
-                                   GLint s4,
-                                   GLint s5,
+static void register_matrix_param5( struct tnl_program *p,
+                                   GLint s0, /* matrix name */
+                                   GLint s1, /* texture matrix number */
+                                   GLint s2, /* first row */
+                                   GLint s3, /* last row */
+                                   GLint s4, /* modifier */
                                    struct ureg *matrix )
 {
    GLint i;
@@ -465,8 +464,8 @@ static void register_matrix_param6( 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 <= s4 - s3; i++) 
-      matrix[i] = register_param6( p, s0, s1, s2, i, i, s5 );
+   for (i = 0; i <= s3 - s2; i++) 
+      matrix[i] = register_param5( p, s0, s1, i, i, s4 );
 }
 
 
@@ -650,13 +649,13 @@ static struct ureg get_eye_position( struct tnl_program *p )
       p->eye_position = reserve_temp(p);
 
       if (PREFER_DP4) {
-        register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3, 
-                                STATE_MATRIX, modelview );
+        register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 
+                                0, modelview );
 
         emit_matrix_transform_vec4(p, p->eye_position, modelview, pos);
       }
       else {
-        register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 3, 
+        register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 
                                 STATE_MATRIX_TRANSPOSE, modelview );
 
         emit_transpose_matrix_transform_vec4(p, p->eye_position, modelview, pos);
@@ -710,7 +709,7 @@ static struct ureg get_eye_normal( struct tnl_program *p )
       struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
       struct ureg mvinv[3];
 
-      register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 0, 2,
+      register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
                              STATE_MATRIX_INVTRANS, mvinv );
 
       p->eye_normal = reserve_temp(p);
@@ -745,12 +744,12 @@ static void build_hpos( struct tnl_program *p )
    struct ureg mvp[4];
 
    if (PREFER_DP4) {
-      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 0, 0, 3, 
-                             STATE_MATRIX, mvp );
+      register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3, 
+                             0, mvp );
       emit_matrix_transform_vec4( p, hpos, mvp, pos );
    }
    else {
-      register_matrix_param6( p, STATE_MATRIX, STATE_MVP, 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 );
    }
@@ -850,14 +849,13 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
    /* Calculate spot attenuation:
     */
    if (!p->state->unit[i].light_spotcutoff_is_180) {
-      struct ureg spot_dir = register_param3(p, STATE_LIGHT, i,
-                                            STATE_SPOT_DIRECTION);
+      struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
+                                                 STATE_SPOT_DIR_NORMALIZED, i);
       struct ureg spot = get_temp(p);
       struct ureg slt = get_temp(p);
-              
-      emit_normalize_vec3( p, spot, spot_dir ); /* XXX: precompute! */
-      emit_op2(p, OPCODE_DP3, spot, 0, ureg_negate(VPpli), spot);
-      emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir,W), spot);
+
+      emit_op2(p, OPCODE_DP3, spot, 0, ureg_negate(VPpli), spot_dir_norm);
+      emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot);
       emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
       emit_op2(p, OPCODE_MUL, att, 0, slt, spot);
 
@@ -895,7 +893,7 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
 
 
 /* Need to add some addtional parameters to allow lighting in object
- * space - STATE_SPOT_DIRECTION and STATE_HALF implicitly assume eye
+ * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye
  * space lighting.
  */
 static void build_lighting( struct tnl_program *p )
@@ -988,20 +986,33 @@ static void build_lighting( struct tnl_program *p )
             */
            VPpli = register_param3(p, STATE_LIGHT, i, 
                                    STATE_POSITION_NORMALIZED); 
-           half = register_param3(p, STATE_LIGHT, i, STATE_HALF);
+            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_LIGHT, i, STATE_HALF_VECTOR);
+            }
         } 
         else {
            struct ureg Ppli = register_param3(p, STATE_LIGHT, i, 
                                               STATE_POSITION); 
            struct ureg V = get_eye_position(p);
            struct ureg dist = get_temp(p);
+       struct ureg tmpPpli = get_temp(p);
 
            VPpli = get_temp(p); 
            half = get_temp(p);
+
+       /* In homogeneous object coordinates
+        */
+       emit_op1(p, OPCODE_RCP, dist, 0, swizzle1(Ppli, W));
+       emit_op2(p, OPCODE_MUL, tmpPpli, 0, Ppli, dist);
  
            /* Calulate VPpli vector
             */
-           emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); 
+           emit_op2(p, OPCODE_SUB, VPpli, 0, tmpPpli, V); 
 
            /* Normalize VPpli.  The dist value also used in
             * attenuation below.
@@ -1033,6 +1044,7 @@ static void build_lighting( struct tnl_program *p )
            emit_normalize_vec3(p, half, half);
 
            release_temp(p, dist);
+       release_temp(p, tmpPpli);
         }
 
         /* Calculate dot products:
@@ -1149,7 +1161,9 @@ static void build_fog( struct tnl_program *p )
 {
    struct ureg fog = register_output(p, VERT_RESULT_FOGC);
    struct ureg input;
-   
+   GLuint useabs = p->state->fog_source_is_depth && p->state->fog_option &&
+                  (p->state->fog_option != FOG_EXP2);
+
    if (p->state->fog_source_is_depth) {
       input = swizzle1(get_eye_position(p), Z);
    }
@@ -1159,35 +1173,37 @@ static void build_fog( struct tnl_program *p )
 
    if (p->state->fog_option &&
        p->state->tnl_do_vertex_fog) {
-      struct ureg params = register_param1(p, STATE_FOG_PARAMS);
+      struct ureg params = register_param2(p, STATE_INTERNAL,
+                                          STATE_FOG_PARAMS_OPTIMIZED);
       struct ureg tmp = get_temp(p);
       struct ureg id = get_identity_param(p);
 
       emit_op1(p, OPCODE_MOV, fog, 0, id);
 
+      if (useabs) {
+        emit_op1(p, OPCODE_ABS, tmp, 0, input);
+      }
+
       switch (p->state->fog_option) {
       case FOG_LINEAR: {
-        emit_op1(p, OPCODE_ABS, tmp, 0, input); 
-        emit_op2(p, OPCODE_SUB, tmp, 0, swizzle1(params,Z), tmp); 
-        emit_op2(p, OPCODE_MUL, tmp, 0, tmp, swizzle1(params,W)); 
+        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_op1(p, OPCODE_ABS, tmp, 0, input); 
-        emit_op2(p, OPCODE_MUL, tmp, 0, tmp, swizzle1(params,X)); 
-        emit_op2(p, OPCODE_POW, fog, WRITEMASK_X, 
-                 register_const1f(p, M_E), ureg_negate(tmp)); 
+        emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input,
+                       swizzle1(params,Z));
+        emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, ureg_negate(tmp));
         break;
       case FOG_EXP2:
-        emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,X)); 
-        emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp); 
-        emit_op2(p, OPCODE_POW, fog, WRITEMASK_X, 
-                 register_const1f(p, M_E), ureg_negate(tmp)); 
+        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, ureg_negate(tmp));
         break;
       }
-      
+
       release_temp(p, tmp);
    }
    else {
@@ -1195,7 +1211,7 @@ static void build_fog( struct tnl_program *p )
        *
        * KW:  Is it really necessary to do anything in this case?
        */
-      emit_op1(p, OPCODE_MOV, fog, 0, input);
+      emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, 0, input);
    }
 }
  
@@ -1356,13 +1372,13 @@ static void build_texture_transform( struct tnl_program *p )
                              out_texgen : 
                              register_input(p, VERT_ATTRIB_TEX0+i));
            if (PREFER_DP4) {
-              register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i, 
-                                      0, 3, STATE_MATRIX, texmat );
+              register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
+                                      0, texmat );
               emit_matrix_transform_vec4( p, out, texmat, in );
            }
            else {
-              register_matrix_param6( p, STATE_MATRIX, STATE_TEXTURE, i, 
-                                      0, 3, STATE_MATRIX_TRANSPOSE, texmat );
+              register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
+                                      STATE_MATRIX_TRANSPOSE, texmat );
               emit_transpose_matrix_transform_vec4( p, out, texmat, in );
            }
         }