Implement instanced indexed draw.
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch.c
index 100117a9aef6c13958ea57af6dba81610c95c142..f88a839f61e9fd286ea5c2a0a125c27e7349c57f 100644 (file)
@@ -25,7 +25,8 @@
  *
  **************************************************************************/
 
-#include "pipe/p_util.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
 #include "draw/draw_context.h"
 #include "draw/draw_private.h"
 #include "draw/draw_vbuf.h"
@@ -41,11 +42,11 @@ struct pt_fetch {
    struct translate *translate;
 
    unsigned vertex_size;
-   boolean need_edgeflags;
 
    struct translate_cache *cache;
 };
 
+
 /* Perform the fetch from API vertex elements & vertex buffers, to a
  * contiguous set of float[4] attributes as required for the
  * vertex_shader->run_linear() method.
@@ -56,9 +57,11 @@ struct pt_fetch {
  *
  */
 void draw_pt_fetch_prepare( struct pt_fetch *fetch,
+                            unsigned vs_input_count,
                            unsigned vertex_size )
 {
    struct draw_context *draw = fetch->draw;
+   unsigned nr_inputs;
    unsigned i, nr = 0;
    unsigned dst_offset = 0;
    struct translate_key key;
@@ -78,6 +81,7 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       key.element[nr].input_format = PIPE_FORMAT_R32_FLOAT;
       key.element[nr].input_buffer = draw->pt.nr_vertex_buffers;
       key.element[nr].input_offset = 0;
+      key.element[nr].instance_divisor = 0;
       key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
       key.element[nr].output_offset = dst_offset;
       dst_offset += 1 * sizeof(float);
@@ -89,11 +93,15 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       dst_offset += 4 * sizeof(float);
    }
       
+   assert( draw->pt.nr_vertex_elements >= vs_input_count );
+
+   nr_inputs = MIN2( vs_input_count, draw->pt.nr_vertex_elements );
 
-   for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
+   for (i = 0; i < nr_inputs; i++) {
       key.element[nr].input_format = draw->pt.vertex_element[i].src_format;
       key.element[nr].input_buffer = draw->pt.vertex_element[i].vertex_buffer_index;
       key.element[nr].input_offset = draw->pt.vertex_element[i].src_offset;
+      key.element[nr].instance_divisor = draw->pt.vertex_element[i].instance_divisor;
       key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
       key.element[nr].output_offset = dst_offset;
 
@@ -114,7 +122,12 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       fetch->translate = translate_cache_find(fetch->cache, &key);
 
       {
-        static struct vertex_header vh = { 0, 1, 0, 0xffff };
+         static struct vertex_header vh = { 0,
+                                            1,
+                                            0,
+                                            UNDEFINED_VERTEX_ID,
+                                            { .0f, .0f, .0f, .0f } };
+
         fetch->translate->set_buffer(fetch->translate,
                                      draw->pt.nr_vertex_buffers,
                                      &vh,
@@ -122,9 +135,6 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       }
    }
 
-   fetch->need_edgeflags = ((draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
-                             draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) &&
-                            draw->pt.user.edgeflag);
 }
 
 
@@ -144,25 +154,40 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
                            i, 
                            ((char *)draw->pt.user.vbuffer[i] + 
                             draw->pt.vertex_buffer[i].buffer_offset),
-                           draw->pt.vertex_buffer[i].pitch );
+                           draw->pt.vertex_buffer[i].stride );
    }
 
    translate->run_elts( translate,
                        elts, 
                        count,
+                        draw->instance_id,
                        verts );
 
-   /* Edgeflags are hard to fit into a translate program, populate
-    * them separately if required.  In the setup above they are
-    * defaulted to one, so only need this if there is reason to change
-    * that default:
-    */
-   if (fetch->need_edgeflags) {
-      for (i = 0; i < count; i++) {
-         struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
-         vh->edgeflag = draw_pt_get_edgeflag( draw, elts[i] );
-      }
+}
+
+
+void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
+                               unsigned start,
+                               unsigned count,
+                               char *verts )
+{
+   struct draw_context *draw = fetch->draw;
+   struct translate *translate = fetch->translate;
+   unsigned i;
+
+   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
+      translate->set_buffer(translate,
+                           i,
+                           ((char *)draw->pt.user.vbuffer[i] +
+                            draw->pt.vertex_buffer[i].buffer_offset),
+                           draw->pt.vertex_buffer[i].stride );
    }
+
+   translate->run( translate,
+                   start,
+                   count,
+                   draw->instance_id,
+                   verts );
 }
 
 
@@ -184,7 +209,8 @@ struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw )
 
 void draw_pt_fetch_destroy( struct pt_fetch *fetch )
 {
-   translate_cache_destroy(fetch->cache);
+   if (fetch->cache)
+      translate_cache_destroy(fetch->cache);
 
    FREE(fetch);
 }