Ejemplo n.º 1
0
void
draw_aapoint_prepare_outputs(struct draw_context *draw,
                             struct draw_stage *stage)
{
   struct aapoint_stage *aapoint = aapoint_stage(stage);
   const struct pipe_rasterizer_state *rast = draw->rasterizer;

   /* update vertex attrib info */
   aapoint->pos_slot = draw_current_shader_position_output(draw);

   if (!rast->point_smooth)
      return;

   /* allocate the extra post-transformed vertex attribute */
   aapoint->tex_slot = draw_alloc_extra_vertex_attrib(draw,
                                                      TGSI_SEMANTIC_GENERIC,
                                                      aapoint->fs->generic_attrib);
   assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */

   /* find psize slot in post-transform vertex */
   aapoint->psize_slot = -1;
   if (draw->rasterizer->point_size_per_vertex) {
      const struct tgsi_shader_info *info = draw_get_shader_info(draw);
      uint i;
      /* find PSIZ vertex output */
      for (i = 0; i < info->num_outputs; i++) {
         if (info->output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
            aapoint->psize_slot = i;
            break;
         }
      }
   }
}
Ejemplo n.º 2
0
void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos)
{
   struct draw_context *draw = emit->draw;

   emit->use_pre_clip_pos = use_pre_clip_pos;
   emit->has_so = draw_has_so(draw);
   if (use_pre_clip_pos)
      emit->pos_idx = draw_current_shader_position_output(draw);

   /* if we have a state with outputs make sure we have
    * buffers to output to */
   if (emit->has_so) {
      boolean has_valid_buffer = FALSE;
      unsigned i;
      for (i = 0; i < draw->so.num_targets; ++i) {
         if (draw->so.targets[i]) {
            has_valid_buffer = TRUE;
            break;
         }
      }
      emit->has_so = has_valid_buffer;
   }

   if (!emit->has_so)
      return;

   /* XXX: need to flush to get prim_vbuf.c to release its allocation??
    */
   draw_do_flush( draw, DRAW_FLUSH_BACKEND );
}
Ejemplo n.º 3
0
static void
stipple_line(struct draw_stage *stage, struct prim_header *header)
{
   struct stipple_stage *stipple = stipple_stage(stage);
   struct vertex_header *v0 = header->v[0];
   struct vertex_header *v1 = header->v[1];
   const unsigned pos = draw_current_shader_position_output(stage->draw);
   const float *pos0 = v0->data[pos];
   const float *pos1 = v1->data[pos];
   float start = 0;
   bool state = 0;

   float x0 = pos0[0];
   float x1 = pos1[0];
   float y0 = pos0[1];
   float y1 = pos1[1];

   float length;
   int i;

   if (stipple->smooth) {
      float dx = x1 - x0;
      float dy = y1 - y0;
      length = sqrtf(dx*dx + dy*dy);
   } else {
      float dx = x0 > x1 ? x0 - x1 : x1 - x0;
      float dy = y0 > y1 ? y0 - y1 : y1 - y0;
      length = MAX2(dx, dy);
   }

   if (header->flags & DRAW_PIPE_RESET_STIPPLE)
      stipple->counter = 0;

   /* XXX ToDo: instead of iterating pixel-by-pixel, use a look-up table.
    */
   for (i = 0; i < length; i++) {
      bool result = stipple_test((int)stipple->counter + i,
                                 (ushort)stipple->pattern, stipple->factor);
      if (result != state) {
         /* changing from "off" to "on" or vice versa */
         if (state) {
            if (start != i) {
               /* finishing an "on" segment */
               emit_segment(stage, header, start / length, i / length);
            }
         }
         else {
            /* starting an "on" segment */
            start = (float)i;
         }
         state = result;
      }
   }

   if (state && start < length)
      emit_segment(stage, header, start / length, 1.0);

   stipple->counter += length;
}
Ejemplo n.º 4
0
static void
aapoint_first_point(struct draw_stage *stage, struct prim_header *header)
{
   auto struct aapoint_stage *aapoint = aapoint_stage(stage);
   struct draw_context *draw = stage->draw;
   struct pipe_context *pipe = draw->pipe;
   const struct pipe_rasterizer_state *rast = draw->rasterizer;
   void *r;

   assert(draw->rasterizer->point_smooth);

   if (draw->rasterizer->point_size <= 2.0)
      aapoint->radius = 1.0;
   else
      aapoint->radius = 0.5f * draw->rasterizer->point_size;

   /*
    * Bind (generate) our fragprog.
    */
   bind_aapoint_fragment_shader(aapoint);

   /* update vertex attrib info */
   aapoint->tex_slot = draw_current_shader_outputs(draw);
   assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */

   aapoint->pos_slot = draw_current_shader_position_output(draw);

   draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
   draw->extra_shader_outputs.semantic_index = aapoint->fs->generic_attrib;
   draw->extra_shader_outputs.slot = aapoint->tex_slot;

   /* find psize slot in post-transform vertex */
   aapoint->psize_slot = -1;
   if (draw->rasterizer->point_size_per_vertex) {
      /* find PSIZ vertex output */
      const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
      uint i;
      for (i = 0; i < vs->info.num_outputs; i++) {
         if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
            aapoint->psize_slot = i;
            break;
         }
      }
   }

   draw->suspend_flushing = TRUE;

   /* Disable triangle culling, stippling, unfilled mode etc. */
   r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade);
   pipe->bind_rasterizer_state(pipe, r);

   draw->suspend_flushing = FALSE;

   /* now really draw first point */
   stage->point = aapoint_point;
   stage->point(stage, header);
}
Ejemplo n.º 5
0
static void
aaline_first_line(struct draw_stage *stage, struct prim_header *header)
{
   auto struct aaline_stage *aaline = aaline_stage(stage);
   struct draw_context *draw = stage->draw;
   struct pipe_context *pipe = draw->pipe;
   const struct pipe_rasterizer_state *rast = draw->rasterizer;
   uint num_samplers;
   void *r;

   assert(draw->rasterizer->line_smooth);

   if (draw->rasterizer->line_width <= 2.2)
      aaline->half_line_width = 1.1f;
   else
      aaline->half_line_width = 0.5f * draw->rasterizer->line_width;

   /*
    * Bind (generate) our fragprog, sampler and texture
    */
   if (!bind_aaline_fragment_shader(aaline)) {
      stage->line = draw_pipe_passthrough_line;
      stage->line(stage, header);
      return;
   }

   /* update vertex attrib info */
   aaline->tex_slot = draw_current_shader_outputs(draw);
   aaline->pos_slot = draw_current_shader_position_output(draw);;

   /* allocate the extra post-transformed vertex attribute */
   (void) draw_alloc_extra_vertex_attrib(draw, TGSI_SEMANTIC_GENERIC,
                                         aaline->fs->generic_attrib);

   /* how many samplers? */
   /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
   num_samplers = MAX2(aaline->num_sampler_views, aaline->num_samplers);
   num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1);

   aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso;
   pipe_sampler_view_reference(&aaline->state.sampler_views[aaline->fs->sampler_unit],
                               aaline->sampler_view);

   draw->suspend_flushing = TRUE;
   aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler);
   aaline->driver_set_sampler_views(pipe, num_samplers, aaline->state.sampler_views);

   /* Disable triangle culling, stippling, unfilled mode etc. */
   r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade);
   pipe->bind_rasterizer_state(pipe, r);

   draw->suspend_flushing = FALSE;

   /* now really draw first line */
   stage->line = aaline_line;
   stage->line(stage, header);
}
Ejemplo n.º 6
0
/**
 * Checks whether the specifed triangle is empty and if it is returns
 * true, otherwise returns false.
 * Triangle is considered null/empty if it's area is qual to zero.
 */
static inline boolean
is_tri_null(struct draw_context *draw, const struct prim_header *header)
{
   const unsigned pos_attr = draw_current_shader_position_output(draw);
   float x1 = header->v[1]->data[pos_attr][0] - header->v[0]->data[pos_attr][0];
   float y1 = header->v[1]->data[pos_attr][1] - header->v[0]->data[pos_attr][1];
   float z1 = header->v[1]->data[pos_attr][2] - header->v[0]->data[pos_attr][2];

   float x2 = header->v[2]->data[pos_attr][0] - header->v[0]->data[pos_attr][0];
   float y2 = header->v[2]->data[pos_attr][1] - header->v[0]->data[pos_attr][1];
   float z2 = header->v[2]->data[pos_attr][2] - header->v[0]->data[pos_attr][2];

   float vx = y1 * z2 - z1 * y2;
   float vy = x1 * z2 - z1 * x2;
   float vz = x1 * y2 - y1 * x2;

   return (vx*vx  + vy*vy + vz*vz) == 0.f;
}
Ejemplo n.º 7
0
void
draw_aaline_prepare_outputs(struct draw_context *draw,
                            struct draw_stage *stage)
{
   struct aaline_stage *aaline = aaline_stage(stage);
   const struct pipe_rasterizer_state *rast = draw->rasterizer;

   /* update vertex attrib info */
   aaline->pos_slot = draw_current_shader_position_output(draw);;

   if (!rast->line_smooth)
      return;

   /* allocate the extra post-transformed vertex attribute */
   aaline->tex_slot = draw_alloc_extra_vertex_attrib(draw,
                                                     TGSI_SEMANTIC_GENERIC,
                                                     aaline->fs->generic_attrib);
}
Ejemplo n.º 8
0
/**
 * Offset tri Z.  Some hardware can handle this, but not usually when
 * doing unfilled rendering.
 */
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[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];
   float ey = v0[1] - v2[1];
   float ez = v0[2] - v2[2];
   float fx = v1[0] - v2[0];
   float fy = v1[1] - v2[1];
   float fz = v1[2] - v2[2];

   /* (a,b) = cross(e,f).xy */
   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 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.
    */
   v0[2] = CLAMP(v0[2] + zoffset, 0.0f, 1.0f);
   v1[2] = CLAMP(v1[2] + zoffset, 0.0f, 1.0f);
   v2[2] = CLAMP(v2[2] + zoffset, 0.0f, 1.0f);

   stage->next->tri( stage->next, header );
}
Ejemplo n.º 9
0
/* Interpolate between two vertices to produce a third.  
 */
static void interp( const struct clip_stage *clip,
		    struct vertex_header *dst,
		    float t,
		    const struct vertex_header *out, 
		    const struct vertex_header *in )
{
   const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw);
   const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
   unsigned j;

   /* Vertex header.
    */
   dst->clipmask = 0;
   dst->edgeflag = 0;        /* will get overwritten later */
   dst->pad = 0;
   dst->vertex_id = UNDEFINED_VERTEX_ID;

   /* Interpolate the clip-space coords.
    */
   interp_attr(dst->clip, t, in->clip, out->clip);

   /* Do the projective divide and viewport transformation to get
    * new window coordinates:
    */
   {
      const float *pos = dst->clip;
      const float *scale = clip->stage.draw->viewport.scale;
      const float *trans = clip->stage.draw->viewport.translate;
      const float oow = 1.0f / pos[3];

      dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0];
      dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1];
      dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2];
      dst->data[pos_attr][3] = oow;
   }

   /* Other attributes
    */
   for (j = 0; j < nr_attrs; j++) {
      if (j != pos_attr)
         interp_attr(dst->data[j], t, in->data[j], out->data[j]);
   }
}
static void
llvm_pipeline_generic(struct draw_pt_middle_end *middle,
                      const struct draw_fetch_info *fetch_info,
                      const struct draw_prim_info *in_prim_info)
{
   struct llvm_middle_end *fpme = llvm_middle_end(middle);
   struct draw_context *draw = fpme->draw;
   struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
   struct draw_prim_info gs_prim_info;
   struct draw_vertex_info llvm_vert_info;
   struct draw_vertex_info gs_vert_info;
   struct draw_vertex_info *vert_info;
   struct draw_prim_info ia_prim_info;
   struct draw_vertex_info ia_vert_info;
   const struct draw_prim_info *prim_info = in_prim_info;
   boolean free_prim_info = FALSE;
   unsigned opt = fpme->opt;
   unsigned clipped = 0;

   llvm_vert_info.count = fetch_info->count;
   llvm_vert_info.vertex_size = fpme->vertex_size;
   llvm_vert_info.stride = fpme->vertex_size;
   llvm_vert_info.verts = (struct vertex_header *)
      MALLOC(fpme->vertex_size *
             align(fetch_info->count, lp_native_vector_width / 32));
   if (!llvm_vert_info.verts) {
      assert(0);
      return;
   }

   if (draw->collect_statistics) {
      draw->statistics.ia_vertices += prim_info->count;
      draw->statistics.ia_primitives +=
         u_decomposed_prims_for_vertices(prim_info->prim, prim_info->count);
      draw->statistics.vs_invocations += fetch_info->count;
   }

   if (fetch_info->linear)
      clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context,
                                       llvm_vert_info.verts,
                                       draw->pt.user.vbuffer,
                                       fetch_info->start,
                                       fetch_info->count,
                                       fpme->vertex_size,
                                       draw->pt.vertex_buffer,
                                       draw->instance_id,
                                       draw->start_index,
                                       draw->start_instance);
   else
      clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
                                            llvm_vert_info.verts,
                                            draw->pt.user.vbuffer,
                                            fetch_info->elts,
                                            draw->pt.user.eltMax,
                                            fetch_info->count,
                                            fpme->vertex_size,
                                            draw->pt.vertex_buffer,
                                            draw->instance_id,
                                            draw->pt.user.eltBias,
                                            draw->start_instance);

   /* Finished with fetch and vs:
    */
   fetch_info = NULL;
   vert_info = &llvm_vert_info;

   if ((opt & PT_SHADE) && gshader) {
      struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
      draw_geometry_shader_run(gshader,
                               draw->pt.user.gs_constants,
                               draw->pt.user.gs_constants_size,
                               vert_info,
                               prim_info,
                               &vshader->info,
                               &gs_vert_info,
                               &gs_prim_info);

      FREE(vert_info->verts);
      vert_info = &gs_vert_info;
      prim_info = &gs_prim_info;
   } else {
      if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
         draw_prim_assembler_run(draw, prim_info, vert_info,
                                 &ia_prim_info, &ia_vert_info);

         if (ia_vert_info.count) {
            FREE(vert_info->verts);
            vert_info = &ia_vert_info;
            prim_info = &ia_prim_info;
            free_prim_info = TRUE;
         }
      }
   }
   if (prim_info->count == 0) {
      debug_printf("GS/IA didn't emit any vertices!\n");

      FREE(vert_info->verts);
      if (free_prim_info) {
         FREE(prim_info->primitive_lengths);
      }
      return;
   }

   /* stream output needs to be done before clipping */
   draw_pt_so_emit( fpme->so_emit, vert_info, prim_info );

   draw_stats_clipper_primitives(draw, prim_info);

   /*
    * if there's no position, need to stop now, or the latter stages
    * will try to access non-existent position output.
    */
   if (draw_current_shader_position_output(draw) != -1) {
      if ((opt & PT_SHADE) && gshader) {
         clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info );
      }
      if (clipped) {
         opt |= PT_PIPELINE;
      }

      /* Do we need to run the pipeline? Now will come here if clipped
       */
      if (opt & PT_PIPELINE) {
         pipeline( fpme, vert_info, prim_info );
      }
      else {
         emit( fpme->emit, vert_info, prim_info );
      }
   }
   FREE(vert_info->verts);
   if (free_prim_info) {
      FREE(prim_info->primitive_lengths);
   }
}
Ejemplo n.º 11
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 );
}
Ejemplo n.º 12
0
/**
 * Offset tri Z.  Some hardware can handle this, but not usually when
 * doing unfilled rendering.
 */
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[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];
   float ey = v0[1] - v2[1];
   float ez = v0[2] - v2[2];
   float fx = v1[0] - v2[0];
   float fy = v1[1] - v2[1];
   float fz = v1[2] - v2[2];

   /* (a,b) = cross(e,f).xy */
   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 zoffset, mult;

   mult = MAX2(dzdx, dzdy) * offset->scale;

   if (stage->draw->floating_point_depth) {
      float bias;
      union fi maxz;
      maxz.f = MAX3(v0[2], v1[2], v2[2]);
      /* just do the math directly on shifted number */
      maxz.ui &= 0xff << 23;
      maxz.i -= 23 << 23;
      /* Clamping to zero means mrd will be zero for very small numbers,
       * but specs do not indicate this should be prevented by clamping
       * mrd to smallest normal number instead. */
      maxz.i = MAX2(maxz.i, 0);

      bias = offset->units * maxz.f;
      zoffset = bias + mult;
   } else {
      zoffset = offset->units + mult;
   }

   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.
    */
   v0[2] = CLAMP(v0[2] + zoffset, 0.0f, 1.0f);
   v1[2] = CLAMP(v1[2] + zoffset, 0.0f, 1.0f);
   v2[2] = CLAMP(v2[2] + zoffset, 0.0f, 1.0f);

   stage->next->tri( stage->next, header );
}
Ejemplo n.º 13
0
static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
                                    const struct draw_fetch_info *fetch_info,
                                    const struct draw_prim_info *prim_info )
{
   struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
   struct draw_context *draw = fpme->draw;
   struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
   struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
   struct draw_prim_info gs_prim_info;
   struct draw_vertex_info fetched_vert_info;
   struct draw_vertex_info vs_vert_info;
   struct draw_vertex_info gs_vert_info;
   struct draw_vertex_info *vert_info;
   unsigned opt = fpme->opt;

   fetched_vert_info.count = fetch_info->count;
   fetched_vert_info.vertex_size = fpme->vertex_size;
   fetched_vert_info.stride = fpme->vertex_size;
   fetched_vert_info.verts =
      (struct vertex_header *)MALLOC(fpme->vertex_size *
                                     align(fetch_info->count,  4));
   if (!fetched_vert_info.verts) {
      assert(0);
      return;
   }

   /* Fetch into our vertex buffer.
    */
   fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );

   /* Finished with fetch:
    */
   fetch_info = NULL;
   vert_info = &fetched_vert_info;

   /* Run the shader, note that this overwrites the data[] parts of
    * the pipeline verts.
    */
   if (fpme->opt & PT_SHADE) {
      draw_vertex_shader_run(vshader,
                             draw->pt.user.vs_constants,
                             draw->pt.user.vs_constants_size,
                             vert_info,
                             &vs_vert_info);

      FREE(vert_info->verts);
      vert_info = &vs_vert_info;
   }

   if ((fpme->opt & PT_SHADE) && gshader) {
      draw_geometry_shader_run(gshader,
                               draw->pt.user.gs_constants,
                               draw->pt.user.gs_constants_size,
                               vert_info,
                               prim_info,
                               &gs_vert_info,
                               &gs_prim_info);

      FREE(vert_info->verts);
      vert_info = &gs_vert_info;
      prim_info = &gs_prim_info;
   }


   /* Stream output needs to be done before clipping.
    *
    * XXX: Stream output surely needs to respect the prim_info->elt
    *      lists.
    */
   draw_pt_so_emit( fpme->so_emit, vert_info, prim_info );

   /*
    * if there's no position, need to stop now, or the latter stages
    * will try to access non-existent position output.
    */
   if (draw_current_shader_position_output(draw) != -1) {

      if (draw_pt_post_vs_run( fpme->post_vs, vert_info ))
      {
         opt |= PT_PIPELINE;
      }

      /* Do we need to run the pipeline?
       */
      if (opt & PT_PIPELINE) {
         pipeline( fpme, vert_info, prim_info );
      }
      else {
         emit( fpme->emit, vert_info, prim_info );
      }
   }
   FREE(vert_info->verts);
}
Ejemplo n.º 14
0
/* Interpolate between two vertices to produce a third.  
 */
static void interp( const struct clip_stage *clip,
		    struct vertex_header *dst,
		    float t,
		    const struct vertex_header *out, 
		    const struct vertex_header *in,
                    unsigned viewport_index )
{
   const unsigned nr_attrs = draw_num_shader_outputs(clip->stage.draw);
   const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
   const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
   unsigned j;
   float t_nopersp;

   /* Vertex header.
    */
   dst->clipmask = 0;
   dst->edgeflag = 0;        /* will get overwritten later */
   dst->have_clipdist = in->have_clipdist;
   dst->vertex_id = UNDEFINED_VERTEX_ID;

   /* Interpolate the clip-space coords.
    */
   interp_attr(dst->clip, t, in->clip, out->clip);
   /* interpolate the clip-space position */
   interp_attr(dst->pre_clip_pos, t, in->pre_clip_pos, out->pre_clip_pos);

   /* Do the projective divide and viewport transformation to get
    * new window coordinates:
    */
   {
      const float *pos = dst->pre_clip_pos;
      const float *scale =
         clip->stage.draw->viewports[viewport_index].scale;
      const float *trans =
         clip->stage.draw->viewports[viewport_index].translate;
      const float oow = 1.0f / pos[3];

      dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0];
      dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1];
      dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2];
      dst->data[pos_attr][3] = oow;
   }
   
   /**
    * Compute the t in screen-space instead of 3d space to use
    * for noperspective interpolation.
    *
    * The points can be aligned with the X axis, so in that case try
    * the Y.  When both points are at the same screen position, we can
    * pick whatever value (the interpolated point won't be in front
    * anyway), so just use the 3d t.
    */
   {
      int k;
      t_nopersp = t;
      /* find either in.x != out.x or in.y != out.y */
      for (k = 0; k < 2; k++) {
         if (in->clip[k] != out->clip[k]) {
            /* do divide by W, then compute linear interpolation factor */
            float in_coord = in->clip[k] / in->clip[3];
            float out_coord = out->clip[k] / out->clip[3];
            float dst_coord = dst->clip[k] / dst->clip[3];
            t_nopersp = (dst_coord - out_coord) / (in_coord - out_coord);
            break;
         }
      }
   }

   /* Other attributes
    */
   for (j = 0; j < nr_attrs; j++) {
      if (j != pos_attr && j != clip_attr) {
         if (clip->noperspective_attribs[j])
            interp_attr(dst->data[j], t_nopersp, in->data[j], out->data[j]);
         else
            interp_attr(dst->data[j], t, in->data[j], out->data[j]);
      }
   }
}
Ejemplo n.º 15
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 );
}
static void
llvm_pipeline_generic( struct draw_pt_middle_end *middle,
                       const struct draw_fetch_info *fetch_info,
                       const struct draw_prim_info *prim_info )
{
   struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
   struct draw_context *draw = fpme->draw;
   struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
   struct draw_prim_info gs_prim_info;
   struct draw_vertex_info llvm_vert_info;
   struct draw_vertex_info gs_vert_info;
   struct draw_vertex_info *vert_info;
   unsigned opt = fpme->opt;
   unsigned clipped = 0;

   llvm_vert_info.count = fetch_info->count;
   llvm_vert_info.vertex_size = fpme->vertex_size;
   llvm_vert_info.stride = fpme->vertex_size;
   llvm_vert_info.verts =
      (struct vertex_header *)MALLOC(fpme->vertex_size *
                                     align(fetch_info->count,  lp_native_vector_width / 32));
   if (!llvm_vert_info.verts) {
      assert(0);
      return;
   }

   if (fetch_info->linear)
      clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context,
                                       llvm_vert_info.verts,
                                       (const char **)draw->pt.user.vbuffer,
                                       fetch_info->start,
                                       fetch_info->count,
                                       fpme->vertex_size,
                                       draw->pt.vertex_buffer,
                                       draw->instance_id);
   else
      clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
                                            llvm_vert_info.verts,
                                            (const char **)draw->pt.user.vbuffer,
                                            fetch_info->elts,
                                            fetch_info->count,
                                            fpme->vertex_size,
                                            draw->pt.vertex_buffer,
                                            draw->instance_id);

   /* Finished with fetch and vs:
    */
   fetch_info = NULL;
   vert_info = &llvm_vert_info;


   if ((opt & PT_SHADE) && gshader) {
      struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
      draw_geometry_shader_run(gshader,
                               draw->pt.user.gs_constants,
                               draw->pt.user.gs_constants_size,
                               vert_info,
                               prim_info,
                               &vshader->info,
                               &gs_vert_info,
                               &gs_prim_info);

      FREE(vert_info->verts);
      vert_info = &gs_vert_info;
      prim_info = &gs_prim_info;
   }

   /* stream output needs to be done before clipping */
   draw_pt_so_emit( fpme->so_emit, vert_info, prim_info );

   /*
    * if there's no position, need to stop now, or the latter stages
    * will try to access non-existent position output.
    */
   if (draw_current_shader_position_output(draw) != -1) {
      if ((opt & PT_SHADE) && gshader) {
         clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info );
      }
      if (clipped) {
         opt |= PT_PIPELINE;
      }

      /* Do we need to run the pipeline? Now will come here if clipped
       */
      if (opt & PT_PIPELINE) {
         pipeline( fpme, vert_info, prim_info );
      }
      else {
         emit( fpme->emit, vert_info, prim_info );
      }
   }
   FREE(vert_info->verts);
}