draw/sample: add support for indirect images
[mesa.git] / src / gallium / auxiliary / draw / draw_pt.c
index ccde371ffcd7ee4ce7a12d04c521bce0788aaae8..0ea1f14c1e0eef159f0ba694209c91c22cb0ffd4 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2007 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
  /*
   * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Keith Whitwell <keithw@vmware.com>
   */
 
 #include "draw/draw_context.h"
 #include "draw/draw_gs.h"
+#include "draw/draw_tess.h"
 #include "draw/draw_private.h"
 #include "draw/draw_pt.h"
 #include "draw/draw_vbuf.h"
@@ -39,7 +40,7 @@
 #include "tgsi/tgsi_dump.h"
 #include "util/u_math.h"
 #include "util/u_prim.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
 #include "util/u_draw.h"
 
 
@@ -66,16 +67,24 @@ draw_pt_arrays(struct draw_context *draw,
     */
    {
       unsigned first, incr;
-      draw_pt_split_prim(prim, &first, &incr);
+
+      if (prim == PIPE_PRIM_PATCHES) {
+         first = draw->pt.vertices_per_patch;
+         incr = draw->pt.vertices_per_patch;
+      } else
+         draw_pt_split_prim(prim, &first, &incr);
       count = draw_pt_trim_count(count, first, incr);
       if (count < first)
          return TRUE;
    }
 
    if (!draw->force_passthrough) {
-      unsigned gs_out_prim = (draw->gs.geometry_shader ? 
-                              draw->gs.geometry_shader->output_primitive :
-                              prim);
+      unsigned out_prim = prim;
+
+      if (draw->gs.geometry_shader)
+         out_prim = draw->gs.geometry_shader->output_primitive;
+      else if (draw->tes.tess_eval_shader)
+         out_prim = get_tes_output_prim(draw->tes.tess_eval_shader);
 
       if (!draw->render) {
          opt |= PT_PIPELINE;
@@ -83,7 +92,7 @@ draw_pt_arrays(struct draw_context *draw,
 
       if (draw_need_pipeline(draw,
                              draw->rasterizer,
-                             gs_out_prim)) {
+                             out_prim)) {
          opt |= PT_PIPELINE;
       }
 
@@ -109,7 +118,7 @@ draw_pt_arrays(struct draw_context *draw,
 
    frontend = draw->pt.frontend;
 
-   if (frontend ) {
+   if (frontend) {
       if (draw->pt.prim != prim || draw->pt.opt != opt) {
          /* In certain conditions switching primitives requires us to flush
           * and validate the different stages. One example is when smooth
@@ -191,7 +200,7 @@ boolean draw_pt_init( struct draw_context *draw )
    if (!draw->pt.middle.general)
       return FALSE;
 
-#if HAVE_LLVM
+#ifdef LLVM_AVAILABLE
    if (draw->llvm)
       draw->pt.middle.llvm = draw_pt_fetch_pipeline_or_emit_llvm( draw );
 #endif
@@ -416,7 +425,7 @@ draw_pt_arrays_restart(struct draw_context *draw,
    }
    else {
       /* Non-indexed prims (draw_arrays).
-       * Primitive restart should have been handled in the state tracker.
+       * Primitive restart should have been handled in gallium frontends.
        */
       draw_pt_arrays(draw, prim, start, count);
    }
@@ -431,17 +440,20 @@ draw_pt_arrays_restart(struct draw_context *draw,
  */
 static void
 resolve_draw_info(const struct pipe_draw_info *raw_info,
-                  struct pipe_draw_info *info)
+                  struct pipe_draw_info *info,
+                  struct pipe_vertex_buffer *vertex_buffer)
 {
    memcpy(info, raw_info, sizeof(struct pipe_draw_info));
 
    if (raw_info->count_from_stream_output) {
       struct draw_so_target *target =
          (struct draw_so_target *)info->count_from_stream_output;
-      info->count = target->emitted_vertices;
+      assert(vertex_buffer != NULL);
+      info->count = vertex_buffer->stride == 0 ? 0 :
+                       target->internal_offset / vertex_buffer->stride;
 
       /* Stream output draw can not be indexed */
-      debug_assert(!info->indexed);
+      debug_assert(!info->index_size);
       info->max_index = info->count - 1;
    }
 }
@@ -462,16 +474,18 @@ draw_vbo(struct draw_context *draw,
    unsigned fpstate = util_fpstate_get();
    struct pipe_draw_info resolved_info;
 
+   if (info->instance_count == 0)
+      return;
+
    /* Make sure that denorms are treated like zeros. This is 
     * the behavior required by D3D10. OpenGL doesn't care.
     */
    util_fpstate_set_denorms_to_zero(fpstate);
 
-   resolve_draw_info(info, &resolved_info);
+   resolve_draw_info(info, &resolved_info, &(draw->pt.vertex_buffer[0]));
    info = &resolved_info;
 
-   assert(info->instance_count > 0);
-   if (info->indexed)
+   if (info->index_size)
       assert(draw->pt.user.elts);
 
    count = info->count;
@@ -479,7 +493,10 @@ draw_vbo(struct draw_context *draw,
    draw->pt.user.eltBias = info->index_bias;
    draw->pt.user.min_index = info->min_index;
    draw->pt.user.max_index = info->max_index;
-   draw->pt.user.eltSize = info->indexed ? draw->pt.user.eltSizeIB : 0;
+   draw->pt.user.eltSize = info->index_size ? draw->pt.user.eltSizeIB : 0;
+   draw->pt.user.drawid = info->drawid;
+
+   draw->pt.vertices_per_patch = info->vertices_per_patch;
 
    if (0)
       debug_printf("draw_vbo(mode=%u start=%u count=%u):\n",
@@ -517,12 +534,12 @@ draw_vbo(struct draw_context *draw,
                                      draw->pt.vertex_element,
                                      draw->pt.nr_vertex_elements,
                                      info);
-#if HAVE_LLVM
+#ifdef LLVM_AVAILABLE
    if (!draw->llvm)
 #endif
    {
       if (index_limit == 0) {
-      /* one of the buffers is too small to do any valid drawing */
+         /* one of the buffers is too small to do any valid drawing */
          debug_warning("draw: VBO too small to draw anything\n");
          util_fpstate_set(fpstate);
          return;
@@ -535,18 +552,20 @@ draw_vbo(struct draw_context *draw,
    }
 
    draw->pt.max_index = index_limit - 1;
+   draw->start_index = info->start;
 
    /*
     * TODO: We could use draw->pt.max_index to further narrow
-    * the min_index/max_index hints given by the state tracker.
+    * the min_index/max_index hints given by gallium frontends.
     */
 
    for (instance = 0; instance < info->instance_count; instance++) {
-      draw->instance_id = instance + info->start_instance;
+      unsigned instance_idx = instance + info->start_instance;
       draw->start_instance = info->start_instance;
+      draw->instance_id = instance;
       /* check for overflow */
-      if (draw->instance_id < instance ||
-          draw->instance_id < info->start_instance) {
+      if (instance_idx < instance ||
+          instance_idx < draw->start_instance) {
          /* if we overflown just set the instance id to the max */
          draw->instance_id = 0xffffffff;
       }