Merge branch '7.8'
[mesa.git] / src / gallium / auxiliary / draw / draw_pipe_vbuf.c
index 9153bc2f8652b81959722b112989e74390577f5c..abbf6247ab824897a222811af2632740ebe5f97b 100644 (file)
  * \file
  * Vertex buffer drawing stage.
  * 
- * \author José Fonseca <jrfonsec@tungstengraphics.com>
+ * \author Jose Fonseca <jrfonsec@tungstengraphics.com>
  * \author Keith Whitwell <keith@tungstengraphics.com>
  */
 
 
-#include "pipe/p_debug.h"
+#include "util/u_debug.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
@@ -93,7 +93,6 @@ vbuf_stage( struct draw_stage *stage )
 }
 
 
-static void vbuf_flush_indices( struct vbuf_stage *vbuf );
 static void vbuf_flush_vertices( struct vbuf_stage *vbuf );
 static void vbuf_alloc_vertices( struct vbuf_stage *vbuf );
 
@@ -109,13 +108,12 @@ overflow( void *map, void *ptr, unsigned bytes, unsigned bufsz )
 static INLINE void 
 check_space( struct vbuf_stage *vbuf, unsigned nr )
 {
-   if (vbuf->nr_vertices + nr > vbuf->max_vertices ) {
-      vbuf_flush_vertices(vbuf);
-      vbuf_alloc_vertices(vbuf);
+   if (vbuf->nr_vertices + nr > vbuf->max_vertices ||
+       vbuf->nr_indices + nr > vbuf->max_indices)
+   {
+      vbuf_flush_vertices( vbuf );
+      vbuf_alloc_vertices( vbuf );
    }
-
-   if (vbuf->nr_indices + nr > vbuf->max_indices )
-      vbuf_flush_indices(vbuf);
 }
 
 
@@ -139,8 +137,8 @@ emit_vertex( struct vbuf_stage *vbuf,
        */
       /* 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, vbuf->vertex_ptr);
+      vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0, ~0);
+      vbuf->translate->run(vbuf->translate, 0, 1, 0, vbuf->vertex_ptr);
 
       if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
       
@@ -161,8 +159,19 @@ vbuf_tri( struct draw_stage *stage,
 
    check_space( vbuf, 3 );
 
-   for (i = 0; i < 3; i++) {
-      vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
+   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] );
+      }
    }
 }
 
@@ -202,7 +211,7 @@ vbuf_point( struct draw_stage *stage,
  * will be flushed if needed and a new one allocated.
  */
 static void
-vbuf_set_prim( struct vbuf_stage *vbuf, uint prim )
+vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
 {
    struct translate_key hw_key;
    unsigned dst_offset;
@@ -217,11 +226,7 @@ vbuf_set_prim( struct vbuf_stage *vbuf, uint prim )
     * state change.
     */
    vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
-
-   if (vbuf->vertex_size != vbuf->vinfo->size * sizeof(float)) {
-      vbuf_flush_vertices(vbuf);
-      vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
-   }
+   vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
 
    /* Translate from pipeline vertices to hw vertices.
     */
@@ -230,46 +235,25 @@ vbuf_set_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;
       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;
 
@@ -287,15 +271,15 @@ vbuf_set_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;
 
    /* Allocate new buffer?
     */
-   if (!vbuf->vertices)
-      vbuf_alloc_vertices(vbuf);
+   assert(vbuf->vertices == NULL);
+   vbuf_alloc_vertices(vbuf);
 }
 
 
@@ -305,9 +289,9 @@ vbuf_first_tri( struct draw_stage *stage,
 {
    struct vbuf_stage *vbuf = vbuf_stage( stage );
 
-   vbuf_flush_indices( vbuf );   
+   vbuf_flush_vertices( vbuf );
+   vbuf_start_prim(vbuf, PIPE_PRIM_TRIANGLES);
    stage->tri = vbuf_tri;
-   vbuf_set_prim(vbuf, PIPE_PRIM_TRIANGLES);
    stage->tri( stage, prim );
 }
 
@@ -318,9 +302,9 @@ vbuf_first_line( struct draw_stage *stage,
 {
    struct vbuf_stage *vbuf = vbuf_stage( stage );
 
-   vbuf_flush_indices( vbuf );
+   vbuf_flush_vertices( vbuf );
+   vbuf_start_prim(vbuf, PIPE_PRIM_LINES);
    stage->line = vbuf_line;
-   vbuf_set_prim(vbuf, PIPE_PRIM_LINES);
    stage->line( stage, prim );
 }
 
@@ -331,53 +315,42 @@ vbuf_first_point( struct draw_stage *stage,
 {
    struct vbuf_stage *vbuf = vbuf_stage( stage );
 
-   vbuf_flush_indices( vbuf );
+   vbuf_flush_vertices(vbuf);
+   vbuf_start_prim(vbuf, PIPE_PRIM_POINTS);
    stage->point = vbuf_point;
-   vbuf_set_prim(vbuf, PIPE_PRIM_POINTS);
    stage->point( stage, prim );
 }
 
 
-static void 
-vbuf_flush_indices( struct vbuf_stage *vbuf ) 
-{
-   if(!vbuf->nr_indices)
-      return;
-   
-   assert((uint) (vbuf->vertex_ptr - vbuf->vertices) == 
-          vbuf->nr_vertices * vbuf->vertex_size / sizeof(unsigned));
-
-   vbuf->render->draw(vbuf->render, vbuf->indices, vbuf->nr_indices);
-   
-   vbuf->nr_indices = 0;
-}
-
 
 /**
  * Flush existing vertex buffer and allocate a new one.
- * 
- * XXX: We separate flush-on-index-full and flush-on-vb-full, but may 
- * raise issues uploading vertices if the hardware wants to flush when
- * we flush.
  */
 static void 
 vbuf_flush_vertices( struct vbuf_stage *vbuf )
 {
-   if(vbuf->vertices) {      
-      vbuf_flush_indices(vbuf);
-      
+   if(vbuf->vertices) {
+
+      vbuf->render->unmap_vertices( vbuf->render, 0, vbuf->nr_vertices - 1 );
+
+      if (vbuf->nr_indices) 
+      {
+         vbuf->render->draw(vbuf->render, 
+                            vbuf->indices, 
+                            vbuf->nr_indices );
+   
+         vbuf->nr_indices = 0;
+      }
+     
       /* Reset temporary vertices ids */
       if(vbuf->nr_vertices)
         draw_reset_vertex_ids( vbuf->stage.draw );
       
       /* Free the vertex buffer */
-      vbuf->render->release_vertices(vbuf->render,
-                                     vbuf->vertices,
-                                     vbuf->vertex_size,
-                                     vbuf->nr_vertices);
+      vbuf->render->release_vertices( vbuf->render );
+
       vbuf->max_vertices = vbuf->nr_vertices = 0;
       vbuf->vertex_ptr = vbuf->vertices = NULL;
-      
    }
 }
    
@@ -402,9 +375,12 @@ vbuf_alloc_vertices( struct vbuf_stage *vbuf )
     * and it will flush itself if necessary to do so.  If this does
     * fail, we are basically without usable hardware.
     */
-   vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render,
-                                                            (ushort) vbuf->vertex_size,
-                                                            (ushort) vbuf->max_vertices);
+   vbuf->render->allocate_vertices(vbuf->render,
+                                   (ushort) vbuf->vertex_size,
+                                   (ushort) vbuf->max_vertices);
+
+   vbuf->vertices = (uint *) vbuf->render->map_vertices( vbuf->render );
+   
    vbuf->vertex_ptr = vbuf->vertices;
 }
 
@@ -415,14 +391,11 @@ vbuf_flush( struct draw_stage *stage, unsigned flags )
 {
    struct vbuf_stage *vbuf = vbuf_stage( stage );
 
-   vbuf_flush_indices( vbuf );
+   vbuf_flush_vertices( vbuf );
 
    stage->point = vbuf_first_point;
    stage->line = vbuf_first_line;
    stage->tri = vbuf_first_tri;
-
-   if (flags & DRAW_FLUSH_BACKEND)
-      vbuf_flush_vertices( vbuf );
 }
 
 
@@ -463,6 +436,7 @@ struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
       goto fail;
    
    vbuf->stage.draw = draw;
+   vbuf->stage.name = "vbuf";
    vbuf->stage.point = vbuf_first_point;
    vbuf->stage.line = vbuf_first_line;
    vbuf->stage.tri = vbuf_first_tri;