draw/translate: fix instancing
[mesa.git] / src / gallium / auxiliary / draw / draw_pipe_vbuf.c
index d40c035240110318a597c4c350e2f11a8cac6863..d3b38eb2df6fa3072ca3a77eb1bbccce4aa916cc 100644 (file)
@@ -130,15 +130,15 @@ static INLINE ushort
 emit_vertex( struct vbuf_stage *vbuf,
              struct vertex_header *vertex )
 {
-   if(vertex->vertex_id == UNDEFINED_VERTEX_ID) {      
+   if (vertex->vertex_id == UNDEFINED_VERTEX_ID && vbuf->vertex_ptr) {
       /* Hmm - vertices are emitted one at a time - better make sure
        * set_buffer is efficient.  Consider a special one-shot mode for
        * translate.
        */
       /* Note: we really do want data[0] here, not data[pos]: 
        */
-      vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0);
-      vbuf->translate->run(vbuf->translate, 0, 1, 0, vbuf->vertex_ptr);
+      vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0, ~0);
+      vbuf->translate->run(vbuf->translate, 0, 1, 0, 0, vbuf->vertex_ptr);
 
       if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
       
@@ -159,19 +159,8 @@ vbuf_tri( struct draw_stage *stage,
 
    check_space( vbuf, 3 );
 
-   if (vbuf->stage.draw->rasterizer->flatshade_first) {
-      /* Put provoking vertex in position expected by the driver.
-       * Emit last provoking vertex in first pos.
-       * Swap verts 0 & 1 to preserve polygon winding.
-       */
-      vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[2] );
-      vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] );
-      vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[1] );
-   }
-   else {
-      for (i = 0; i < 3; i++) {
-         vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
-      }
+   for (i = 0; i < 3; i++) {
+      vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
    }
 }
 
@@ -235,41 +224,18 @@ vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
    for (i = 0; i < vbuf->vinfo->num_attribs; i++) {
       unsigned emit_sz = 0;
       unsigned src_buffer = 0;
-      unsigned output_format;
+      enum pipe_format output_format;
       unsigned src_offset = (vbuf->vinfo->attrib[i].src_index * 4 * sizeof(float) );
 
-      switch (vbuf->vinfo->attrib[i].emit) {
-      case EMIT_4F:
-        output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-        emit_sz = 4 * sizeof(float);
-        break;
-      case EMIT_3F:
-        output_format = PIPE_FORMAT_R32G32B32_FLOAT;
-        emit_sz = 3 * sizeof(float);
-        break;
-      case EMIT_2F:
-        output_format = PIPE_FORMAT_R32G32_FLOAT;
-        emit_sz = 2 * sizeof(float);
-        break;
-      case EMIT_1F:
-        output_format = PIPE_FORMAT_R32_FLOAT;
-        emit_sz = 1 * sizeof(float);
-        break;
-      case EMIT_1F_PSIZE:
-        output_format = PIPE_FORMAT_R32_FLOAT;
-        emit_sz = 1 * sizeof(float);
+      output_format = draw_translate_vinfo_format(vbuf->vinfo->attrib[i].emit);
+      emit_sz = draw_translate_vinfo_size(vbuf->vinfo->attrib[i].emit);
+
+      /* doesn't handle EMIT_OMIT */
+      assert(emit_sz != 0);
+
+      if (vbuf->vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
         src_buffer = 1;
         src_offset = 0;
-        break;
-      case EMIT_4UB:
-        output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
-        emit_sz = 4 * sizeof(ubyte);
-         break;
-      default:
-        assert(0);
-        output_format = PIPE_FORMAT_NONE;
-        emit_sz = 0;
-        break;
       }
 
       hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
@@ -294,7 +260,7 @@ vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
       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);
+      vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0, ~0);
    }
 
    vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;
@@ -358,9 +324,9 @@ vbuf_flush_vertices( struct vbuf_stage *vbuf )
 
       if (vbuf->nr_indices) 
       {
-         vbuf->render->draw(vbuf->render, 
-                            vbuf->indices, 
-                            vbuf->nr_indices );
+         vbuf->render->draw_elements(vbuf->render, 
+                                     vbuf->indices, 
+                                     vbuf->nr_indices );
    
          vbuf->nr_indices = 0;
       }
@@ -375,21 +341,30 @@ vbuf_flush_vertices( struct vbuf_stage *vbuf )
       vbuf->max_vertices = vbuf->nr_vertices = 0;
       vbuf->vertex_ptr = vbuf->vertices = NULL;
    }
+
+   /* Reset point/line/tri function pointers.
+    * If (for example) we transition from points to tris and back to points
+    * again, we need to call the vbuf_first_point() function again to flush
+    * the triangles before drawing more points.  This can happen when drawing
+    * with front polygon mode = filled and back polygon mode = line or point.
+    */
+   vbuf->stage.point = vbuf_first_point;
+   vbuf->stage.line = vbuf_first_line;
+   vbuf->stage.tri = vbuf_first_tri;
 }
    
 
 static void 
 vbuf_alloc_vertices( struct vbuf_stage *vbuf )
 {
-   assert(!vbuf->nr_indices);
-   assert(!vbuf->vertices);
+   if (vbuf->vertex_ptr) {
+      assert(!vbuf->nr_indices);
+      assert(!vbuf->vertices);
+   }
    
    /* Allocate a new vertex buffer */
    vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
 
-   /* even number */
-   vbuf->max_vertices = vbuf->max_vertices & ~1;
-
    if(vbuf->max_vertices >= UNDEFINED_VERTEX_ID)
       vbuf->max_vertices = UNDEFINED_VERTEX_ID - 1;
 
@@ -415,10 +390,6 @@ vbuf_flush( struct draw_stage *stage, unsigned flags )
    struct vbuf_stage *vbuf = vbuf_stage( stage );
 
    vbuf_flush_vertices( vbuf );
-
-   stage->point = vbuf_first_point;
-   stage->line = vbuf_first_line;
-   stage->tri = vbuf_first_tri;
 }
 
 
@@ -468,7 +439,7 @@ struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
    vbuf->stage.destroy = vbuf_destroy;
    
    vbuf->render = render;
-   vbuf->max_indices = MAX2(render->max_indices, UNDEFINED_VERTEX_ID-1);
+   vbuf->max_indices = MIN2(render->max_indices, UNDEFINED_VERTEX_ID-1);
 
    vbuf->indices = (ushort *) align_malloc( vbuf->max_indices * 
                                            sizeof(vbuf->indices[0]),