fix issues when using mixed-mode pos-invariant vp and ff tnl (bug #9856)
authorRoland Scheidegger <sroland@tungstengraphics.com>
Mon, 5 Feb 2007 20:29:25 +0000 (21:29 +0100)
committerRoland Scheidegger <sroland@tungstengraphics.com>
Mon, 5 Feb 2007 20:29:25 +0000 (21:29 +0100)
ARB_vp requires vertex transformation to be invariant to fixed function tnl
if the position_invariant option is used. So the same function needs to be
used, otherwise z-fighting artifacts may happen with applications which rely
on the results being really the same due to precision issues when dealing with
floating point values (may not be a problem when using a non-optimizing
compiler strictly following IEEE rules).

src/mesa/tnl/t_vb_arbprogram.c

index 524472a7772d27fee17a622f5063e3cc5026401d..4c8f967fdffc85fbd6261a58450883a61686fc72 100644 (file)
@@ -1249,8 +1249,7 @@ run_arb_vertex_program(GLcontext *ctx, struct tnl_pipeline_stage *stage)
    m->nr_inputs = m->nr_outputs = 0;
 
    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
-      if (program->Base.InputsRead & (1<<i) ||
-         (i == VERT_ATTRIB_POS && program->IsPositionInvariant)) {
+      if (program->Base.InputsRead & (1<<i)) {
         GLuint j = m->nr_inputs++;
         m->input[j].idx = i;
         m->input[j].data = (GLfloat *)m->VB->AttribPtr[i]->data;
@@ -1258,16 +1257,15 @@ run_arb_vertex_program(GLcontext *ctx, struct tnl_pipeline_stage *stage)
         m->input[j].size = m->VB->AttribPtr[i]->size;
         ASSIGN_4V(m->File[0][REG_IN0 + i], 0, 0, 0, 1);
       }
-   }     
+   }
 
    for (i = 0; i < VERT_RESULT_MAX; i++) {
-      if (program->Base.OutputsWritten & (1 << i) ||
-         (i == VERT_RESULT_HPOS && program->IsPositionInvariant)) {
+      if (program->Base.OutputsWritten & (1 << i)) {
         GLuint j = m->nr_outputs++;
         m->output[j].idx = i;
         m->output[j].data = (GLfloat *)m->attribs[i].data;
       }
-   }     
+   }
 
 
    /* Run the actual program:
@@ -1297,15 +1295,6 @@ run_arb_vertex_program(GLcontext *ctx, struct tnl_pipeline_stage *stage)
         }
       }
 
-      /* If the program is position invariant, multiply the input position
-       * by the MVP matrix and store in the vertex position result register.
-       */
-      if (program->IsPositionInvariant) {
-        TRANSFORM_POINT( m->File[0][REG_OUT0+0], 
-                         ctx->_ModelProjectMatrix.m, 
-                         m->File[0][REG_IN0+0]);
-      }
-
       for (j = 0; j < m->nr_outputs; j++) {
         GLuint idx = REG_OUT0 + m->output[j].idx;
         m->output[j].data[0] = m->File[0][idx][0];
@@ -1327,15 +1316,39 @@ run_arb_vertex_program(GLcontext *ctx, struct tnl_pipeline_stage *stage)
     * TODO: 2) Integrate t_vertex.c so that we just go straight ahead
     * and build machine vertices here.
     */
-   VB->ClipPtr = &m->attribs[VERT_RESULT_HPOS];
-   VB->ClipPtr->count = VB->Count;
 
    /* XXX There seems to be confusion between using the VERT_ATTRIB_*
     * values vs _TNL_ATTRIB_* tokens here:
     */
    outputs = program->Base.OutputsWritten;
-   if (program->IsPositionInvariant) 
-      outputs |= (1<<VERT_RESULT_HPOS);
+
+   if (program->IsPositionInvariant) {
+      /* We need the exact same transform as in the fixed function path here
+         to guarantee invariance, depending on compiler optimization flags results
+         could be different otherwise */
+      VB->ClipPtr = TransformRaw( &m->attribs[0],
+                                 &ctx->_ModelProjectMatrix,
+                                 m->VB->AttribPtr[0] );
+
+      /* Drivers expect this to be clean to element 4...
+       */
+      switch (VB->ClipPtr->size) {
+      case 1:
+        /* impossible */
+      case 2:
+        _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+        /* fall-through */
+      case 3:
+        _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+        /* fall-through */
+      case 4:
+        break;
+      }
+   }
+   else {
+      VB->ClipPtr = &m->attribs[VERT_RESULT_HPOS];
+      VB->ClipPtr->count = VB->Count;
+   }
 
    if (outputs & (1<<VERT_RESULT_COL0)) {
       VB->ColorPtr[0] =