Пример #1
0
static void offset_tri( struct draw_stage *stage,
			struct prim_header *header )
{
   struct prim_header tmp;

   tmp.det = header->det;
   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);

   do_offset_tri( stage, &tmp );
}
static void flatshade_tri_2( struct draw_stage *stage,
                             struct prim_header *header )
{
   struct prim_header tmp;

   tmp.det = header->det;
   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] = header->v[2];

   copy_colors2(stage, tmp.v[0], tmp.v[1], tmp.v[2]);
   
   stage->next->tri( stage->next, &tmp );
}
Пример #3
0
static void
emit_segment(struct draw_stage *stage, struct prim_header *header,
             float t0, float t1)
{
   struct vertex_header *v0new = dup_vert(stage, header->v[0], 0);
   struct vertex_header *v1new = dup_vert(stage, header->v[1], 1);
   struct prim_header newprim = *header;

   if (t0 > 0.0) {
      screen_interp( stage->draw, v0new, t0, header->v[0], header->v[1] );
      newprim.v[0] = v0new;
   }

   if (t1 < 1.0) {
      screen_interp( stage->draw, v1new, t1, header->v[0], header->v[1] );
      newprim.v[1] = v1new;
   }

   stage->next->line( stage->next, &newprim );
}
static void flatshade_line_1( struct draw_stage *stage,
                              struct prim_header *header )
{
   struct prim_header tmp;

   tmp.v[0] = dup_vert(stage, header->v[0], 0);
   tmp.v[1] = header->v[1];

   copy_colors(stage, tmp.v[0], tmp.v[1]);
   
   stage->next->line( stage->next, &tmp );
}
Пример #5
0
/**
 * Copy back color(s) to front color(s).
 */
static INLINE struct vertex_header *
copy_bfc( struct twoside_stage *twoside, 
          const struct vertex_header *v,
          unsigned idx )
{   
   struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx );
   
   if (twoside->attrib_back0) {
      COPY_4FV(tmp->data[twoside->attrib_front0],
               tmp->data[twoside->attrib_back0]);
   }
   if (twoside->attrib_back1) {
      COPY_4FV(tmp->data[twoside->attrib_front1],
               tmp->data[twoside->attrib_back1]);
   }

   return tmp;
}
Пример #6
0
/* Clip a triangle against the viewport and user clip planes.
 */
static void
do_clip_tri( struct draw_stage *stage, 
	     struct prim_header *header,
	     unsigned clipmask )
{
   struct clip_stage *clipper = clip_stage( stage );
   struct vertex_header *a[MAX_CLIPPED_VERTICES];
   struct vertex_header *b[MAX_CLIPPED_VERTICES];
   struct vertex_header **inlist = a;
   struct vertex_header **outlist = b;
   unsigned tmpnr = 0;
   unsigned n = 3;
   unsigned i;
   boolean aEdges[MAX_CLIPPED_VERTICES];
   boolean bEdges[MAX_CLIPPED_VERTICES];
   boolean *inEdges = aEdges;
   boolean *outEdges = bEdges;

   inlist[0] = header->v[0];
   inlist[1] = header->v[1];
   inlist[2] = header->v[2];

   /*
    * Note: at this point we can't just use the per-vertex edge flags.
    * We have to observe the edge flag bits set in header->flags which
    * were set during primitive decomposition.  Put those flags into
    * an edge flags array which parallels the vertex array.
    * Later, in the 'unfilled' pipeline stage we'll draw the edge if both
    * the header.flags bit is set AND the per-vertex edgeflag field is set.
    */
   inEdges[0] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_0);
   inEdges[1] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_1);
   inEdges[2] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_2);

   while (clipmask && n >= 3) {
      const unsigned plane_idx = ffs(clipmask)-1;
      const boolean is_user_clip_plane = plane_idx >= 6;
      const float *plane = clipper->plane[plane_idx];
      struct vertex_header *vert_prev = inlist[0];
      boolean *edge_prev = &inEdges[0];
      float dp_prev = dot4( vert_prev->clip, plane );
      unsigned outcount = 0;

      clipmask &= ~(1<<plane_idx);

      assert(n < MAX_CLIPPED_VERTICES);
      if (n >= MAX_CLIPPED_VERTICES)
         return;
      inlist[n] = inlist[0]; /* prevent rotation of vertices */
      inEdges[n] = inEdges[0];

      for (i = 1; i <= n; i++) {
	 struct vertex_header *vert = inlist[i];
         boolean *edge = &inEdges[i];

	 float dp = dot4( vert->clip, plane );

	 if (!IS_NEGATIVE(dp_prev)) {
            assert(outcount < MAX_CLIPPED_VERTICES);
            if (outcount >= MAX_CLIPPED_VERTICES)
               return;
            outEdges[outcount] = *edge_prev;
	    outlist[outcount++] = vert_prev;
	 }

	 if (DIFFERENT_SIGNS(dp, dp_prev)) {
	    struct vertex_header *new_vert;
            boolean *new_edge;

            assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
            if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
               return;
            new_vert = clipper->stage.tmp[tmpnr++];

            assert(outcount < MAX_CLIPPED_VERTICES);
            if (outcount >= MAX_CLIPPED_VERTICES)
               return;

            new_edge = &outEdges[outcount];
	    outlist[outcount++] = new_vert;

	    if (IS_NEGATIVE(dp)) {
	       /* Going out of bounds.  Avoid division by zero as we
		* know dp != dp_prev from DIFFERENT_SIGNS, above.
		*/
	       float t = dp / (dp - dp_prev);
	       interp( clipper, new_vert, t, vert, vert_prev );
	       
	       /* Whether or not to set edge flag for the new vert depends
                * on whether it's a user-defined clipping plane.  We're
                * copying NVIDIA's behaviour here.
		*/
               if (is_user_clip_plane) {
                  /* we want to see an edge along the clip plane */
                  *new_edge = TRUE;
                  new_vert->edgeflag = TRUE;
               }
               else {
                  /* we don't want to see an edge along the frustum clip plane */
                  *new_edge = *edge_prev;
                  new_vert->edgeflag = FALSE;
               }
	    }
            else {
	       /* Coming back in.
		*/
	       float t = dp_prev / (dp_prev - dp);
	       interp( clipper, new_vert, t, vert_prev, vert );

	       /* Copy starting vert's edgeflag:
		*/
	       new_vert->edgeflag = vert_prev->edgeflag;
               *new_edge = *edge_prev;
	    }
	 }

	 vert_prev = vert;
         edge_prev = edge;
	 dp_prev = dp;
      }

      /* swap in/out lists */
      {
	 struct vertex_header **tmp = inlist;
	 inlist = outlist;
	 outlist = tmp;
	 n = outcount;
      }
      {
         boolean *tmp = inEdges;
         inEdges = outEdges;
         outEdges = tmp;
      }

   }

   /* If flat-shading, copy provoking vertex color to polygon vertex[0]
    */
   if (n >= 3) {
      if (clipper->flat) {
         if (stage->draw->rasterizer->flatshade_first) {
            if (inlist[0] != header->v[0]) {
               assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
               if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
                  return;
               inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
               copy_colors(stage, inlist[0], header->v[0]);
            }
         }
         else {
            if (inlist[0] != header->v[2]) {
               assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
               if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
                  return;
               inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
               copy_colors(stage, inlist[0], header->v[2]);
            }
         }
      }
      
      /* Emit the polygon as triangles to the setup stage:
       */
      emit_poly( stage, inlist, inEdges, n, header );
   }
}
Пример #7
0
/**
 * Draw an AA point by drawing a quad.
 */
static void
aapoint_point(struct draw_stage *stage, struct prim_header *header)
{
   const struct aapoint_stage *aapoint = aapoint_stage(stage);
   struct prim_header tri;
   struct vertex_header *v[4];
   const uint tex_slot = aapoint->tex_slot;
   const uint pos_slot = aapoint->pos_slot;
   float radius, *pos, *tex;
   uint i;
   float k;

   if (aapoint->psize_slot >= 0) {
      radius = 0.5f * header->v[0]->data[aapoint->psize_slot][0];
   }
   else {
      radius = aapoint->radius;
   }

   /*
    * Note: the texcoords (generic attrib, really) we use are special:
    * The S and T components simply vary from -1 to +1.
    * The R component is k, below.
    * The Q component is 1.0 and will used as a handy constant in the
    * fragment shader.
    */

   /*
    * k is the threshold distance from the point's center at which
    * we begin alpha attenuation (the coverage value).
    * Operating within a unit circle, we'll compute the fragment's
    * distance 'd' from the center point using the texcoords.
    * IF d > 1.0 THEN
    *    KILL fragment
    * ELSE IF d > k THEN
    *    compute coverage in [0,1] proportional to d in [k, 1].
    * ELSE
    *    coverage = 1.0;  // full coverage
    * ENDIF
    *
    * Note: the ELSEIF and ELSE clauses are actually implemented with CMP to
    * avoid using IF/ELSE/ENDIF TGSI opcodes.
    */

#if !NORMALIZE
   k = 1.0f / radius;
   k = 1.0f - 2.0f * k + k * k;
#else
   k = 1.0f - 1.0f / radius;
#endif

   /* allocate/dup new verts */
   for (i = 0; i < 4; i++) {
      v[i] = dup_vert(stage, header->v[0], i);
   }

   /* new verts */
   pos = v[0]->data[pos_slot];
   pos[0] -= radius;
   pos[1] -= radius;

   pos = v[1]->data[pos_slot];
   pos[0] += radius;
   pos[1] -= radius;

   pos = v[2]->data[pos_slot];
   pos[0] += radius;
   pos[1] += radius;

   pos = v[3]->data[pos_slot];
   pos[0] -= radius;
   pos[1] += radius;

   /* new texcoords */
   tex = v[0]->data[tex_slot];
   ASSIGN_4V(tex, -1, -1, k, 1);

   tex = v[1]->data[tex_slot];
   ASSIGN_4V(tex,  1, -1, k, 1);

   tex = v[2]->data[tex_slot];
   ASSIGN_4V(tex,  1,  1, k, 1);

   tex = v[3]->data[tex_slot];
   ASSIGN_4V(tex, -1,  1, k, 1);

   /* emit 2 tris for the quad strip */
   tri.v[0] = v[0];
   tri.v[1] = v[1];
   tri.v[2] = v[2];
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v[0];
   tri.v[1] = v[2];
   tri.v[2] = v[3];
   stage->next->tri( stage->next, &tri );
}
Пример #8
0
/**
 * Draw a wide line by drawing a quad (two triangles).
 */
static void wideline_line( struct draw_stage *stage,
                           struct prim_header *header )
{
   /*const struct wideline_stage *wide = wideline_stage(stage);*/
   const unsigned pos = draw_current_shader_position_output(stage->draw);
   const float half_width = 0.5f * stage->draw->rasterizer->line_width;

   struct prim_header tri;

   struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
   struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
   struct vertex_header *v2 = dup_vert(stage, header->v[1], 2);
   struct vertex_header *v3 = dup_vert(stage, header->v[1], 3);

   float *pos0 = v0->data[pos];
   float *pos1 = v1->data[pos];
   float *pos2 = v2->data[pos];
   float *pos3 = v3->data[pos];

   const float dx = fabsf(pos0[0] - pos2[0]);
   const float dy = fabsf(pos0[1] - pos2[1]);

   const boolean half_pixel_center =
      stage->draw->rasterizer->half_pixel_center;

   /* small tweak to meet GL specification */
   const float bias = half_pixel_center ? 0.125f : 0.0f;

   /*
    * Draw wide line as a quad (two tris) by "stretching" the line along
    * X or Y.
    * We need to tweak coords in several ways to be conformant here.
    */

   if (dx > dy) {
      /* x-major line */
      pos0[1] = pos0[1] - half_width - bias;
      pos1[1] = pos1[1] + half_width - bias;
      pos2[1] = pos2[1] - half_width - bias;
      pos3[1] = pos3[1] + half_width - bias;
      if (half_pixel_center) {
         if (pos0[0] < pos2[0]) {
            /* left to right line */
            pos0[0] -= 0.5f;
            pos1[0] -= 0.5f;
            pos2[0] -= 0.5f;
            pos3[0] -= 0.5f;
         }
         else {
            /* right to left line */
            pos0[0] += 0.5f;
            pos1[0] += 0.5f;
            pos2[0] += 0.5f;
            pos3[0] += 0.5f;
         }
      }
   }
   else {
      /* y-major line */
      pos0[0] = pos0[0] - half_width + bias;
      pos1[0] = pos1[0] + half_width + bias;
      pos2[0] = pos2[0] - half_width + bias;
      pos3[0] = pos3[0] + half_width + bias;
      if (half_pixel_center) {
         if (pos0[1] < pos2[1]) {
            /* top to bottom line */
            pos0[1] -= 0.5f;
            pos1[1] -= 0.5f;
            pos2[1] -= 0.5f;
            pos3[1] -= 0.5f;
         }
         else {
            /* bottom to top line */
            pos0[1] += 0.5f;
            pos1[1] += 0.5f;
            pos2[1] += 0.5f;
            pos3[1] += 0.5f;
         }
      }
   }

   tri.det = header->det;  /* only the sign matters */
   tri.v[0] = v0;
   tri.v[1] = v2;
   tri.v[2] = v3;
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v0;
   tri.v[1] = v3;
   tri.v[2] = v1;
   stage->next->tri( stage->next, &tri );
}
Пример #9
0
/**
 * Draw a wide line by drawing a quad, using geometry which will
 * fullfill GL's antialiased line requirements.
 */
static void
aaline_line(struct draw_stage *stage, struct prim_header *header)
{
   const struct aaline_stage *aaline = aaline_stage(stage);
   const float half_width = aaline->half_line_width;
   struct prim_header tri;
   struct vertex_header *v[8];
   uint texPos = aaline->tex_slot;
   uint posPos = aaline->pos_slot;
   float *pos, *tex;
   float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0];
   float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1];
   double a = atan2(dy, dx);
   float c_a = (float) cos(a), s_a = (float) sin(a);
   uint i;

   /* XXX the ends of lines aren't quite perfect yet, but probably passable */
   dx = 0.5F * half_width;
   dy = half_width;

   /* allocate/dup new verts */
   for (i = 0; i < 8; i++) {
      v[i] = dup_vert(stage, header->v[i/4], i);
   }

   /*
    * Quad strip for line from v0 to v1 (*=endpoints):
    *
    *  1   3                     5   7
    *  +---+---------------------+---+
    *  |                             |
    *  | *v0                     v1* |
    *  |                             |
    *  +---+---------------------+---+
    *  0   2                     4   6
    */

   /* new verts */
   pos = v[0]->data[posPos];
   pos[0] += (-dx * c_a -  dy * s_a);
   pos[1] += (-dx * s_a +  dy * c_a);

   pos = v[1]->data[posPos];
   pos[0] += (-dx * c_a - -dy * s_a);
   pos[1] += (-dx * s_a + -dy * c_a);

   pos = v[2]->data[posPos];
   pos[0] += ( dx * c_a -  dy * s_a);
   pos[1] += ( dx * s_a +  dy * c_a);

   pos = v[3]->data[posPos];
   pos[0] += ( dx * c_a - -dy * s_a);
   pos[1] += ( dx * s_a + -dy * c_a);

   pos = v[4]->data[posPos];
   pos[0] += (-dx * c_a -  dy * s_a);
   pos[1] += (-dx * s_a +  dy * c_a);

   pos = v[5]->data[posPos];
   pos[0] += (-dx * c_a - -dy * s_a);
   pos[1] += (-dx * s_a + -dy * c_a);

   pos = v[6]->data[posPos];
   pos[0] += ( dx * c_a -  dy * s_a);
   pos[1] += ( dx * s_a +  dy * c_a);

   pos = v[7]->data[posPos];
   pos[0] += ( dx * c_a - -dy * s_a);
   pos[1] += ( dx * s_a + -dy * c_a);

   /* new texcoords */
   tex = v[0]->data[texPos];
   ASSIGN_4V(tex, 0, 0, 0, 1);

   tex = v[1]->data[texPos];
   ASSIGN_4V(tex, 0, 1, 0, 1);

   tex = v[2]->data[texPos];
   ASSIGN_4V(tex, .5, 0, 0, 1);

   tex = v[3]->data[texPos];
   ASSIGN_4V(tex, .5, 1, 0, 1);

   tex = v[4]->data[texPos];
   ASSIGN_4V(tex, .5, 0, 0, 1);

   tex = v[5]->data[texPos];
   ASSIGN_4V(tex, .5, 1, 0, 1);

   tex = v[6]->data[texPos];
   ASSIGN_4V(tex, 1, 0, 0, 1);

   tex = v[7]->data[texPos];
   ASSIGN_4V(tex, 1, 1, 0, 1);

   /* emit 6 tris for the quad strip */
   tri.v[0] = v[2];  tri.v[1] = v[1];  tri.v[2] = v[0];
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v[3];  tri.v[1] = v[1];  tri.v[2] = v[2];
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v[4];  tri.v[1] = v[3];  tri.v[2] = v[2];
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v[5];  tri.v[1] = v[3];  tri.v[2] = v[4];
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v[6];  tri.v[1] = v[5];  tri.v[2] = v[4];
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v[7];  tri.v[1] = v[5];  tri.v[2] = v[6];
   stage->next->tri( stage->next, &tri );
}
Пример #10
0
/* Clip a triangle against the viewport and user clip planes.
 */
static void
do_clip_tri( struct draw_stage *stage, 
	     struct prim_header *header,
	     unsigned clipmask )
{
   struct clipper *clipper = clipper_stage( stage );
   struct vertex_header *a[MAX_CLIPPED_VERTICES];
   struct vertex_header *b[MAX_CLIPPED_VERTICES];
   struct vertex_header **inlist = a;
   struct vertex_header **outlist = b;
   unsigned tmpnr = 0;
   unsigned n = 3;
   unsigned i;

   inlist[0] = header->v[0];
   inlist[1] = header->v[1];
   inlist[2] = header->v[2];

   while (clipmask && n >= 3) {
      const unsigned plane_idx = ffs(clipmask)-1;
      const float *plane = clipper->plane[plane_idx];
      struct vertex_header *vert_prev = inlist[0];
      float dp_prev = dot4( vert_prev->clip, plane );
      unsigned outcount = 0;

      clipmask &= ~(1<<plane_idx);

      inlist[n] = inlist[0]; /* prevent rotation of vertices */

      for (i = 1; i <= n; i++) {
	 struct vertex_header *vert = inlist[i];

	 float dp = dot4( vert->clip, plane );

	 if (!IS_NEGATIVE(dp_prev)) {
	    outlist[outcount++] = vert_prev;
	 }

	 if (DIFFERENT_SIGNS(dp, dp_prev)) {
	    struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++];
	    outlist[outcount++] = new_vert;

	    if (IS_NEGATIVE(dp)) {
	       /* Going out of bounds.  Avoid division by zero as we
		* know dp != dp_prev from DIFFERENT_SIGNS, above.
		*/
	       float t = dp / (dp - dp_prev);
	       interp( clipper, new_vert, t, vert, vert_prev );
	       
	       /* Force edgeflag true in this case:
		*/
	       new_vert->edgeflag = 1;
	    } else {
	       /* Coming back in.
		*/
	       float t = dp_prev / (dp_prev - dp);
	       interp( clipper, new_vert, t, vert_prev, vert );

	       /* Copy starting vert's edgeflag:
		*/
	       new_vert->edgeflag = vert_prev->edgeflag;
	    }
	 }

	 vert_prev = vert;
	 dp_prev = dp;
      }

      {
	 struct vertex_header **tmp = inlist;
	 inlist = outlist;
	 outlist = tmp;
	 n = outcount;
      }
   }

   /* If flat-shading, copy color to new provoking vertex.
    */
   if (clipper->flat && inlist[0] != header->v[2]) {
      if (1) {
	 inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
      }

      copy_colors(stage, inlist[0], header->v[2]);
   }



   /* Emit the polygon as triangles to the setup stage:
    */
   if (n >= 3)
      emit_poly( stage, inlist, n, header );
}
Пример #11
0
/* If there are lots of sprite points (and why wouldn't there be?) it
 * would probably be more sensible to change hardware setup to
 * optimize this rather than doing the whole thing in software like
 * this.
 */
static void widepoint_point( struct draw_stage *stage,
                             struct prim_header *header )
{
   const struct widepoint_stage *wide = widepoint_stage(stage);
   const unsigned pos = draw_current_shader_position_output(stage->draw);
   const boolean sprite = (boolean) stage->draw->rasterizer->point_quad_rasterization;
   float half_size;
   float left_adj, right_adj, bot_adj, top_adj;

   struct prim_header tri;

   /* four dups of original vertex */
   struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
   struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
   struct vertex_header *v2 = dup_vert(stage, header->v[0], 2);
   struct vertex_header *v3 = dup_vert(stage, header->v[0], 3);

   float *pos0 = v0->data[pos];
   float *pos1 = v1->data[pos];
   float *pos2 = v2->data[pos];
   float *pos3 = v3->data[pos];

   /* point size is either per-vertex or fixed size */
   if (wide->psize_slot >= 0) {
      half_size = header->v[0]->data[wide->psize_slot][0];
      half_size *= 0.5f; 
   }
   else {
      half_size = wide->half_point_size;
   }

   left_adj = -half_size + wide->xbias;
   right_adj = half_size + wide->xbias;
   bot_adj = half_size + wide->ybias;
   top_adj = -half_size + wide->ybias;

   pos0[0] += left_adj;
   pos0[1] += top_adj;

   pos1[0] += left_adj;
   pos1[1] += bot_adj;

   pos2[0] += right_adj;
   pos2[1] += top_adj;

   pos3[0] += right_adj;
   pos3[1] += bot_adj;

   if (sprite) {
      static const float tex00[4] = { 0, 0, 0, 1 };
      static const float tex01[4] = { 0, 1, 0, 1 };
      static const float tex11[4] = { 1, 1, 0, 1 };
      static const float tex10[4] = { 1, 0, 0, 1 };
      set_texcoords( wide, v0, tex00 );
      set_texcoords( wide, v1, tex01 );
      set_texcoords( wide, v2, tex10 );
      set_texcoords( wide, v3, tex11 );
   }

   tri.det = header->det;  /* only the sign matters */
   tri.v[0] = v0;
   tri.v[1] = v2;
   tri.v[2] = v3;
   stage->next->tri( stage->next, &tri );

   tri.v[0] = v0;
   tri.v[1] = v3;
   tri.v[2] = v1;
   stage->next->tri( stage->next, &tri );
}