Пример #1
0
static boolean
vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx)
{
   struct nv30_screen *screen = r->nv30->screen;
   struct nv30_fragprog *fp = r->nv30->fragprog.program;
   struct vertex_info *vinfo = &r->vertex_info;
   enum pipe_format format;
   uint emit = EMIT_OMIT;
   uint result = *idx;

   if (sem == TGSI_SEMANTIC_GENERIC) {
      uint num_texcoords = (screen->eng3d->oclass < NV40_3D_CLASS) ? 8 : 10;
      for (result = 0; result < num_texcoords; result++) {
         if (fp->texcoord[result] == *idx + 8) {
            sem = TGSI_SEMANTIC_TEXCOORD;
            emit = vroute[sem].emit;
            break;
         }
      }
   } else {
      emit = vroute[sem].emit;
   }

   if (emit == EMIT_OMIT)
      return FALSE;

   draw_emit_vertex_attr(vinfo, emit, vroute[sem].interp, attrib);
   format = draw_translate_vinfo_format(emit);

   r->vtxfmt[attrib] = nv30_vtxfmt(&screen->base.base, format)->hw;
   r->vtxptr[attrib] = vinfo->size;
   vinfo->size += draw_translate_vinfo_size(emit);

   if (screen->eng3d->oclass < NV40_3D_CLASS) {
      r->vtxprog[attrib][0] = 0x001f38d8;
      r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9);
      r->vtxprog[attrib][2] = 0x0836106c;
      r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2;
   } else {
      r->vtxprog[attrib][0] = 0x401f9c6c;
      r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8);
      r->vtxprog[attrib][2] = 0x8106c083;
      r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2;
   }

   if (result < 8)
      *idx = vroute[sem].ow40 << result;
   else {
      assert(sem == TGSI_SEMANTIC_TEXCOORD);
      *idx = 0x00001000 << (result - 8);
   }
   return TRUE;
}
Пример #2
0
/**
 * Compute the size of a vertex, in dwords/floats, to update the
 * vinfo->size field.
 */
void
draw_compute_vertex_size(struct vertex_info *vinfo)
{
   uint i;

   vinfo->size = 0;
   for (i = 0; i < vinfo->num_attribs; i++)
      vinfo->size += draw_translate_vinfo_size(vinfo->attrib[i].emit);

   assert(vinfo->size % 4 == 0);
   /* in dwords */
   vinfo->size /= 4;
}
Пример #3
0
void
draw_pt_emit_prepare(struct pt_emit *emit,
                     unsigned prim,
                     unsigned *max_vertices)
{
   struct draw_context *draw = emit->draw;
   const struct vertex_info *vinfo;
   unsigned dst_offset;
   struct translate_key hw_key;
   unsigned i;

   /* XXX: need to flush to get prim_vbuf.c to release its allocation??
    */
   draw_do_flush( draw, DRAW_FLUSH_BACKEND );

   /* XXX: may need to defensively reset this later on as clipping can
    * clobber this state in the render backend.
    */
   emit->prim = prim;

   draw->render->set_primitive(draw->render, emit->prim);

   /* Must do this after set_primitive() above:
    */
   emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);

   /* Translate from pipeline vertices to hw vertices.
    */
   dst_offset = 0;
   for (i = 0; i < vinfo->num_attribs; i++) {
      unsigned emit_sz = 0;
      unsigned src_buffer = 0;
      unsigned output_format;
      unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );

      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);

      /* doesn't handle EMIT_OMIT */
      assert(emit_sz != 0);

      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
	 src_buffer = 1;
	 src_offset = 0;
      }

      hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
      hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      hw_key.element[i].input_buffer = src_buffer;
      hw_key.element[i].input_offset = src_offset;
      hw_key.element[i].instance_divisor = 0;
      hw_key.element[i].output_format = output_format;
      hw_key.element[i].output_offset = dst_offset;

      dst_offset += emit_sz;
   }

   hw_key.nr_elements = vinfo->num_attribs;
   hw_key.output_stride = vinfo->size * 4;

   if (!emit->translate ||
       translate_key_compare(&emit->translate->key, &hw_key) != 0) {
      translate_key_sanitize(&hw_key);
      emit->translate = translate_cache_find(emit->cache, &hw_key);
   }

   *max_vertices = (draw->render->max_vertex_buffer_bytes /
                    (vinfo->size * 4));
}
static void fse_prepare( struct draw_pt_middle_end *middle,
                         unsigned prim,
                         unsigned opt,
                         unsigned *max_vertices )
{
   struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
   struct draw_context *draw = fse->draw;
   unsigned num_vs_inputs = draw->vs.vertex_shader->info.num_inputs;
   const struct vertex_info *vinfo;
   unsigned i;
   unsigned nr_vbs = 0;

   /* Can't support geometry shader on this path.
    */
   assert(!draw->gs.geometry_shader);

   if (!draw->render->set_primitive( draw->render,
                                     prim )) {
      assert(0);
      return;
   }

   /* Must do this after set_primitive() above:
    */
   fse->vinfo = vinfo = draw->render->get_vertex_info(draw->render);


   fse->key.output_stride = vinfo->size * 4;
   fse->key.nr_outputs = vinfo->num_attribs;
   fse->key.nr_inputs = num_vs_inputs;

   fse->key.nr_elements = MAX2(fse->key.nr_outputs,     /* outputs - translate to hw format */
                               fse->key.nr_inputs);     /* inputs - fetch from api format */

   fse->key.viewport = !draw->identity_viewport;
   fse->key.clip = draw->clip_xy || draw->clip_z || draw->clip_user;
   fse->key.const_vbuffers = 0;

   memset(fse->key.element, 0, 
          fse->key.nr_elements * sizeof(fse->key.element[0]));

   for (i = 0; i < num_vs_inputs; i++) {
      const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
      fse->key.element[i].in.format = src->src_format;

      /* Consider ignoring these, ie make generated programs
       * independent of this state:
       */
      fse->key.element[i].in.buffer = src->vertex_buffer_index;
      fse->key.element[i].in.offset = src->src_offset;
      nr_vbs = MAX2(nr_vbs, src->vertex_buffer_index + 1);
   }
   
   for (i = 0; i < 5 && i < nr_vbs; i++) {
      if (draw->pt.vertex_buffer[i].stride == 0)
         fse->key.const_vbuffers |= (1<<i);
   }

   if (0) debug_printf("%s: lookup const_vbuffers: %x\n", __FUNCTION__, fse->key.const_vbuffers);
   
   {
      unsigned dst_offset = 0;

      for (i = 0; i < vinfo->num_attribs; i++) {
         unsigned emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);

         /* doesn't handle EMIT_OMIT */
         assert(emit_sz != 0);

         /* The elements in the key correspond to vertex shader output
          * numbers, not to positions in the hw vertex description --
          * that's handled by the output_offset field.
          */
         fse->key.element[i].out.format = vinfo->attrib[i].emit;
         fse->key.element[i].out.vs_output = vinfo->attrib[i].src_index;
         fse->key.element[i].out.offset = dst_offset;
      
         dst_offset += emit_sz;
         assert(fse->key.output_stride >= dst_offset);
      }
   }

   
   fse->active = draw_vs_lookup_varient( draw->vs.vertex_shader, 
                                         &fse->key );

   if (!fse->active) {
      assert(0);
      return ;
   }

   if (0) debug_printf("%s: found const_vbuffers: %x\n", __FUNCTION__, 
                       fse->active->key.const_vbuffers);

   /* Now set buffer pointers:
    */
   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
      fse->active->set_buffer( fse->active, 
                               i, 
                               ((const ubyte *) draw->pt.user.vbuffer[i] + 
                                draw->pt.vertex_buffer[i].buffer_offset),
                              draw->pt.vertex_buffer[i].stride,
                              draw->pt.vertex_buffer[i].max_index );
   }

   *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                    (vinfo->size * 4));

   /* Probably need to do this somewhere (or fix exec shader not to
    * need it):
    */
   if (1) {
      struct draw_vertex_shader *vs = draw->vs.vertex_shader;
      vs->prepare(vs, draw);
   }
}
Пример #5
0
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
                                unsigned prim,
				unsigned opt,
                                unsigned *max_vertices )
{
   struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
   struct draw_context *draw = feme->draw;
   const struct vertex_info *vinfo;
   unsigned i, dst_offset;
   boolean ok;
   struct translate_key key;

   unsigned gs_out_prim = (draw->gs.geometry_shader ? 
                           draw->gs.geometry_shader->output_primitive :
                           prim);



   ok = draw->render->set_primitive( draw->render, 
                                     gs_out_prim );
   if (!ok) {
      assert(0);
      return;
   }
   
   /* Must do this after set_primitive() above:
    */
   vinfo = feme->vinfo = draw->render->get_vertex_info(draw->render);
   
   

   /* Transform from API vertices to HW vertices, skipping the
    * pipeline_vertex intermediate step.
    */
   dst_offset = 0;
   memset(&key, 0, sizeof(key));

   for (i = 0; i < vinfo->num_attribs; i++) {
      const struct pipe_vertex_element *src = &draw->pt.vertex_element[vinfo->attrib[i].src_index];

      unsigned emit_sz = 0;
      unsigned input_format = src->src_format;
      unsigned input_buffer = src->vertex_buffer_index;
      unsigned input_offset = src->src_offset;
      unsigned output_format;

      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);

      if (vinfo->attrib[i].emit == EMIT_OMIT)
	 continue;

      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
	 input_format = PIPE_FORMAT_R32_FLOAT;
	 input_buffer = draw->pt.nr_vertex_buffers;
	 input_offset = 0;
      }

      key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
      key.element[i].input_format = input_format;
      key.element[i].input_buffer = input_buffer;
      key.element[i].input_offset = input_offset;
      key.element[i].instance_divisor = src->instance_divisor;
      key.element[i].output_format = output_format;
      key.element[i].output_offset = dst_offset;
      
      dst_offset += emit_sz;
   }

   key.nr_elements = vinfo->num_attribs;
   key.output_stride = vinfo->size * 4;

   /* Don't bother with caching at this stage:
    */
   if (!feme->translate ||
       translate_key_compare(&feme->translate->key, &key) != 0) 
   {
      translate_key_sanitize(&key);
      feme->translate = translate_cache_find(feme->cache,
                                             &key);


      feme->translate->set_buffer(feme->translate, 
				  draw->pt.nr_vertex_buffers, 
				  &feme->point_size,
				  0,
				  ~0);
   }
   
   feme->point_size = draw->rasterizer->point_size;

   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
      feme->translate->set_buffer(feme->translate, 
                                  i, 
                                  ((char *)draw->pt.user.vbuffer[i] + 
                                   draw->pt.vertex_buffer[i].buffer_offset),
                                  draw->pt.vertex_buffer[i].stride,
                                  draw->pt.max_index);
   }

   *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                    (vinfo->size * 4));
}
Пример #6
0
/**
 * Set the prim type for subsequent vertices.
 * This may result in a new vertex size.  The existing vbuffer (if any)
 * will be flushed if needed and a new one allocated.
 */
static void
vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
{
   struct translate_key hw_key;
   unsigned dst_offset;
   unsigned i;
   const struct vertex_info *vinfo;

   vbuf->render->set_primitive(vbuf->render, prim);

   /* Must do this after set_primitive() above:
    * 
    * XXX: need some state managment to track when this needs to be
    * recalculated.  The driver should tell us whether there was a
    * state change.
    */
   vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
   vinfo = vbuf->vinfo;
   vbuf->vertex_size = vinfo->size * sizeof(float);

   /* Translate from pipeline vertices to hw vertices.
    */
   dst_offset = 0;

   for (i = 0; i < vinfo->num_attribs; i++) {
      unsigned emit_sz = 0;
      unsigned src_buffer = 0;
      enum pipe_format output_format;
      unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );

      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);

      /* doesn't handle EMIT_OMIT */
      assert(emit_sz != 0);

      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
         src_buffer = 1;
         src_offset = 0;
      }
      else if (vinfo->attrib[i].src_index == DRAW_ATTR_NONEXIST) {
         /* elements which don't exist will get assigned zeros */
         src_buffer = 2;
         src_offset = 0;
      }

      hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
      hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      hw_key.element[i].input_buffer = src_buffer;
      hw_key.element[i].input_offset = src_offset;
      hw_key.element[i].instance_divisor = 0;
      hw_key.element[i].output_format = output_format;
      hw_key.element[i].output_offset = dst_offset;

      dst_offset += emit_sz;
   }

   hw_key.nr_elements = vinfo->num_attribs;
   hw_key.output_stride = vbuf->vertex_size;

   /* Don't bother with caching at this stage:
    */
   if (!vbuf->translate ||
       translate_key_compare(&vbuf->translate->key, &hw_key) != 0) 
   {
      translate_key_sanitize(&hw_key);
      vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);

      vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0, ~0);
      vbuf->translate->set_buffer(vbuf->translate, 2, &vbuf->zero4[0], 0, ~0);
   }

   vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;

   /* Allocate new buffer?
    */
   assert(vbuf->vertices == NULL);
   vbuf_alloc_vertices(vbuf);
}