tgsi/ureg: make the dst register match the src indirection
[mesa.git] / src / gallium / auxiliary / draw / draw_pipe_offset.c
index c1dc21cd3293567f51f8eb567a5302e396b4e3a4..3578525051f463f74dd4e440d60b4de5628be0e8 100644 (file)
@@ -32,7 +32,8 @@
  * \author  Brian Paul
  */
 
-#include "pipe/p_util.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
 #include "draw_pipe.h"
 
 
@@ -42,6 +43,7 @@ struct offset_stage {
 
    float scale;
    float units;
+   float clamp;
 };
 
 
@@ -62,14 +64,15 @@ static INLINE struct offset_stage *offset_stage( struct draw_stage *stage )
 static void do_offset_tri( struct draw_stage *stage,
                           struct prim_header *header )
 {
+   const unsigned pos = draw_current_shader_position_output(stage->draw);
    struct offset_stage *offset = offset_stage(stage);   
    float inv_det = 1.0f / header->det;
 
    /* Window coords:
     */
-   float *v0 = header->v[0]->data[0];
-   float *v1 = header->v[1]->data[0];
-   float *v2 = header->v[2]->data[0];
+   float *v0 = header->v[0]->data[pos];
+   float *v1 = header->v[1]->data[pos];
+   float *v2 = header->v[2]->data[pos];
 
    /* edge vectors e = v0 - v2, f = v1 - v2 */
    float ex = v0[0] - v2[0];
@@ -83,11 +86,15 @@ static void do_offset_tri( struct draw_stage *stage,
    float a = ey*fz - ez*fy;
    float b = ez*fx - ex*fz;
 
-   float dzdx = FABSF(a * inv_det);
-   float dzdy = FABSF(b * inv_det);
+   float dzdx = fabsf(a * inv_det);
+   float dzdy = fabsf(b * inv_det);
 
    float zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale;
 
+   if (offset->clamp)
+      zoffset = (offset->clamp < 0.0f) ? MAX2(zoffset, offset->clamp) :
+                                         MIN2(zoffset, offset->clamp);
+
    /*
     * Note: we're applying the offset and clamping per-vertex.
     * Ideally, the offset is applied per-fragment prior to fragment shading.
@@ -106,7 +113,8 @@ static void offset_tri( struct draw_stage *stage,
    struct prim_header tmp;
 
    tmp.det = header->det;
-   tmp.edgeflags = header->edgeflags;
+   tmp.flags = header->flags;
+   tmp.pad = header->pad;
    tmp.v[0] = dup_vert(stage, header->v[0], 0);
    tmp.v[1] = dup_vert(stage, header->v[1], 1);
    tmp.v[2] = dup_vert(stage, header->v[2], 2);
@@ -119,10 +127,44 @@ static void offset_first_tri( struct draw_stage *stage,
                              struct prim_header *header )
 {
    struct offset_stage *offset = offset_stage(stage);
-   float mrd = 1.0f / 65535.0f; /* XXX this depends on depthbuffer bits! */
+   const struct pipe_rasterizer_state *rast = stage->draw->rasterizer;
+   unsigned fill_mode = rast->fill_front;
+   boolean do_offset;
+
+   if (rast->fill_back != rast->fill_front) {
+      /* Need to check for back-facing triangle */
+      boolean ccw = header->det < 0.0f;
+      if (ccw != rast->front_ccw)
+         fill_mode = rast->fill_back;
+   }
+
+   /* Now determine if we need to do offsetting for the point/line/fill mode */
+   switch (fill_mode) {
+   case PIPE_POLYGON_MODE_FILL:
+      do_offset = rast->offset_tri;
+      break;
+   case PIPE_POLYGON_MODE_LINE:
+      do_offset = rast->offset_line;
+      break;
+   case PIPE_POLYGON_MODE_POINT:
+      do_offset = rast->offset_point;
+      break;
+   default:
+      assert(!"invalid fill_mode in offset_first_tri()");
+      do_offset = rast->offset_tri;
+   }
+
+   if (do_offset) {
+      offset->scale = rast->offset_scale;
+      offset->clamp = rast->offset_clamp;
+      offset->units = (float) (rast->offset_units * stage->draw->mrd);
+   }
+   else {
+      offset->scale = 0.0f;
+      offset->clamp = 0.0f;
+      offset->units = 0.0f;
+   }
 
-   offset->units = stage->draw->rasterizer->offset_units * mrd;
-   offset->scale = stage->draw->rasterizer->offset_scale;
 
    stage->tri = offset_tri;
    stage->tri( stage, header );
@@ -158,10 +200,11 @@ static void offset_destroy( struct draw_stage *stage )
 struct draw_stage *draw_offset_stage( struct draw_context *draw )
 {
    struct offset_stage *offset = CALLOC_STRUCT(offset_stage);
-
-   draw_alloc_temp_verts( &offset->stage, 3 );
+   if (offset == NULL)
+      goto fail;
 
    offset->stage.draw = draw;
+   offset->stage.name = "offset";
    offset->stage.next = NULL;
    offset->stage.point = draw_pipe_passthrough_point;
    offset->stage.line = draw_pipe_passthrough_line;
@@ -170,5 +213,14 @@ struct draw_stage *draw_offset_stage( struct draw_context *draw )
    offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
    offset->stage.destroy = offset_destroy;
 
+   if (!draw_alloc_temp_verts( &offset->stage, 3 ))
+      goto fail;
+
    return &offset->stage;
+
+fail:
+   if (offset)
+      offset->stage.destroy( &offset->stage );
+
+   return NULL;
 }