svga: implement user index buffers
[mesa.git] / src / gallium / drivers / svga / svga_pipe_draw.c
index 303d4565cdb7648b9a5f26138b023f7ed19a452e..bbd443049507da7dcbaa0bb0b655c780fc7189e4 100644 (file)
@@ -25,6 +25,7 @@
 
 
 #include "util/u_format.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_prim.h"
 #include "util/u_prim_restart.h"
@@ -39,6 +40,7 @@
 #include "svga_draw.h"
 #include "svga_shader.h"
 #include "svga_state.h"
+#include "svga_surface.h"
 #include "svga_swtnl.h"
 #include "svga_debug.h"
 #include "svga_resource_buffer.h"
@@ -50,7 +52,7 @@ retry_draw_range_elements( struct svga_context *svga,
                            int index_bias,
                            unsigned min_index,
                            unsigned max_index,
-                           unsigned prim,
+                           enum pipe_prim_type prim,
                            unsigned start,
                            unsigned count,
                            unsigned start_instance,
@@ -59,6 +61,8 @@ retry_draw_range_elements( struct svga_context *svga,
 {
    enum pipe_error ret = PIPE_OK;
 
+   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWELEMENTS);
+
    svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
 
    ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
@@ -81,32 +85,36 @@ retry_draw_range_elements( struct svga_context *svga,
    if (ret != PIPE_OK)
       goto retry;
 
-   return PIPE_OK;
+   goto done;
 
 retry:
    svga_context_flush( svga, NULL );
 
    if (do_retry)
    {
-      return retry_draw_range_elements( svga,
-                                        index_buffer, index_size, index_bias,
-                                        min_index, max_index,
-                                        prim, start, count,
-                                        start_instance, instance_count, FALSE );
+      ret = retry_draw_range_elements(svga,
+                                      index_buffer, index_size, index_bias,
+                                      min_index, max_index,
+                                      prim, start, count,
+                                      start_instance, instance_count, FALSE);
    }
 
+done:
+   SVGA_STATS_TIME_POP(svga_sws(svga));
    return ret;
 }
 
 
 static enum pipe_error
 retry_draw_arrays( struct svga_context *svga,
-                   unsigned prim, unsigned start, unsigned count,
+                   enum pipe_prim_type prim, unsigned start, unsigned count,
                    unsigned start_instance, unsigned instance_count,
                    boolean do_retry )
 {
    enum pipe_error ret;
 
+   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWARRAYS);
+
    svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
 
    ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
@@ -126,18 +134,20 @@ retry_draw_arrays( struct svga_context *svga,
    if (ret != PIPE_OK)
       goto retry;
 
-   return PIPE_OK;
+   goto done;
 
 retry:
    if (ret == PIPE_ERROR_OUT_OF_MEMORY && do_retry)
    {
       svga_context_flush( svga, NULL );
 
-      return retry_draw_arrays(svga, prim, start, count,
-                               start_instance, instance_count,
-                               FALSE );
+      ret = retry_draw_arrays(svga, prim, start, count,
+                              start_instance, instance_count,
+                              FALSE);
    }
 
+done:
+   SVGA_STATS_TIME_POP(svga_sws(svga));
    return ret;
 }
 
@@ -177,11 +187,21 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    enum pipe_error ret = 0;
    boolean needed_swtnl;
 
-   svga->num_draw_calls++;  /* for SVGA_QUERY_DRAW_CALLS */
+   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWVBO);
+
+   svga->hud.num_draw_calls++;  /* for SVGA_QUERY_NUM_DRAW_CALLS */
 
    if (u_reduced_prim(info->mode) == PIPE_PRIM_TRIANGLES &&
        svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK)
+      goto done;
+
+   /* Upload a user index buffer. */
+   struct pipe_index_buffer ibuffer_saved = {};
+   if (info->indexed && svga->curr.ib.user_buffer &&
+       !util_save_and_upload_index_buffer(pipe, info, &svga->curr.ib,
+                                          &ibuffer_saved)) {
       return;
+   }
 
    /*
     * Mark currently bound target surfaces as dirty
@@ -202,24 +222,18 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
       r = util_draw_vbo_without_prim_restart(pipe, &svga->curr.ib, info);
       assert(r == PIPE_OK);
       (void) r;
-      return;
+      goto done;
    }
 
    if (!u_trim_pipe_prim( info->mode, &count ))
-      return;
+      goto done;
 
    needed_swtnl = svga->state.sw.need_swtnl;
 
    svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );
 
-#ifdef DEBUG
-   if (svga->curr.vs->base.id == svga->debug.disable_shader ||
-       svga->curr.fs->base.id == svga->debug.disable_shader)
-      return;
-#endif
-
    if (svga->state.sw.need_swtnl) {
-      svga->num_fallbacks++;  /* for SVGA_QUERY_FALLBACKS */
+      svga->hud.num_fallbacks++;  /* for SVGA_QUERY_NUM_FALLBACKS */
       if (!needed_swtnl) {
          /*
           * We're switching from HW to SW TNL.  SW TNL will require mapping all
@@ -270,6 +284,12 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
       svga_hwtnl_flush_retry( svga );
       svga_context_flush(svga, NULL);
    }
+
+done:
+   if (info->indexed && ibuffer_saved.user_buffer)
+      pipe->set_index_buffer(pipe, &ibuffer_saved);
+
+   SVGA_STATS_TIME_POP(svga_sws(svga));
 }