i965: Correct build_lighting in i965 driver according to
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vs_tnl.c
index 35adc4846a0744aa7d899f7a338daf65f0c7aa82..2ed80dc36e964a19d33fc7668bb5a22e8e519f80 100644 (file)
@@ -1000,13 +1000,19 @@ static void build_lighting( struct tnl_program *p )
                                               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.
@@ -1038,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:
@@ -1154,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);
    }
@@ -1171,26 +1180,30 @@ static void build_fog( struct tnl_program *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_op3(p, OPCODE_MAD, tmp, 0, tmp, swizzle1(params,X), swizzle1(params,Y));
+        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,Z));
+        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,W));
-        emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp); 
+        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 {
@@ -1198,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);
    }
 }