radeonsi: fix user fence space when MCBP is enabled
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_emit.c
index 4fb53276bbeab5f14c2275ab4e0c8fcb61b93a26..984c76fdf9452b7059ec0fe3f38ede7e9bea37cd 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2008 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.
@@ -33,6 +33,7 @@
 #include "draw/draw_pt.h"
 #include "translate/translate.h"
 #include "translate/translate_cache.h"
+#include "util/u_prim.h"
 
 struct pt_emit {
    struct draw_context *draw;
@@ -43,40 +44,38 @@ struct pt_emit {
    unsigned prim;
 
    const struct vertex_info *vinfo;
+
+   float zero4[4];
+
 };
 
-void draw_pt_emit_prepare( struct pt_emit *emit,
-                          unsigned prim,
-                           unsigned *max_vertices )
+
+void
+draw_pt_emit_prepare(struct pt_emit *emit,
+                     unsigned prim,
+                     unsigned *max_vertices)
 {
    struct draw_context *draw = emit->draw;
    const struct vertex_info *vinfo;
    unsigned dst_offset;
    struct translate_key hw_key;
    unsigned i;
-   boolean ok;
-   
-   /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 
-    */
-   draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
+   /* XXX: need to flush to get prim_vbuf.c to release its allocation??
+    */
+   draw_do_flush(draw, DRAW_FLUSH_BACKEND);
 
    /* XXX: may need to defensively reset this later on as clipping can
     * clobber this state in the render backend.
     */
    emit->prim = prim;
 
-   ok = draw->render->set_primitive(draw->render, emit->prim);
-   if (!ok) {
-      assert(0);
-      return;
-   }
+   draw->render->set_primitive(draw->render, emit->prim);
 
    /* Must do this after set_primitive() above:
     */
    emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
 
-
    /* Translate from pipeline vertices to hw vertices.
     */
    dst_offset = 0;
@@ -84,42 +83,22 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
       unsigned emit_sz = 0;
       unsigned src_buffer = 0;
       unsigned output_format;
-      unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );
-
-
-         
-      switch (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);
-        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;
+      unsigned src_offset = vinfo->attrib[i].src_index * 4 * sizeof(float);
+
+      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
+      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);
+
+      /* doesn't handle EMIT_OMIT */
+      assert(emit_sz != 0);
+
+      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
+         src_buffer = 1;
+         src_offset = 0;
+      }
+      else if (vinfo->attrib[i].src_index == DRAW_ATTR_NONEXIST) {
+         /* elements which don't exist will get assigned zeros */
+         src_buffer = 2;
+         src_offset = 0;
       }
 
       hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
@@ -137,162 +116,177 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
    hw_key.output_stride = vinfo->size * 4;
 
    if (!emit->translate ||
-       translate_key_compare(&emit->translate->key, &hw_key) != 0)
-   {
+       translate_key_compare(&emit->translate->key, &hw_key) != 0) {
       translate_key_sanitize(&hw_key);
       emit->translate = translate_cache_find(emit->cache, &hw_key);
-   }
 
-   *max_vertices = (draw->render->max_vertex_buffer_bytes / 
-                    (vinfo->size * 4));
+      emit->translate->set_buffer(emit->translate, 2, &emit->zero4[0], 0, ~0);
+   }
 
-   /* even number */
-   *max_vertices = *max_vertices & ~1;
+   if (!vinfo->size)
+      *max_vertices = 0;
+   else
+      *max_vertices = (draw->render->max_vertex_buffer_bytes /
+                       (vinfo->size * 4));
 }
 
 
-void draw_pt_emit( struct pt_emit *emit,
-                  const float (*vertex_data)[4],
-                  unsigned vertex_count,
-                  unsigned stride,
-                  const ushort *elts,
-                  unsigned count )
+void
+draw_pt_emit(struct pt_emit *emit,
+             const struct draw_vertex_info *vert_info,
+             const struct draw_prim_info *prim_info)
 {
+   const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
+   unsigned vertex_count = vert_info->count;
+   unsigned stride = vert_info->stride;
+   const ushort *elts = prim_info->elts;
    struct draw_context *draw = emit->draw;
    struct translate *translate = emit->translate;
    struct vbuf_render *render = draw->render;
+   unsigned start, i;
    void *hw_verts;
 
-   /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 
+   /* XXX: need to flush to get prim_vbuf.c to release its allocation??
     */
-   draw_do_flush( draw, DRAW_FLUSH_BACKEND );
+   draw_do_flush(draw, DRAW_FLUSH_BACKEND);
 
    if (vertex_count == 0)
       return;
 
-   if (vertex_count >= UNDEFINED_VERTEX_ID) {
-      assert(0);
-      return;
-   }
-
    /* XXX: and work out some way to coordinate the render primitive
     * between vbuf.c and here...
     */
-   if (!draw->render->set_primitive(draw->render, emit->prim)) {
-      assert(0);
-      return;
-   }
+   render->set_primitive(draw->render, prim_info->prim);
 
+   assert(vertex_count <= 65535);
    render->allocate_vertices(render,
                              (ushort)translate->key.output_stride,
                              (ushort)vertex_count);
 
-   hw_verts = render->map_vertices( render );
+   hw_verts = render->map_vertices(render);
    if (!hw_verts) {
-      assert(0);
+      debug_warn_once("map of vertex buffer failed (out of memory?)");
       return;
    }
 
-   translate->set_buffer(translate, 
-                        0, 
-                        vertex_data,
-                        stride );
+   translate->set_buffer(translate,
+                         0,
+                         vertex_data,
+                         stride,
+                         ~0);
 
-   translate->set_buffer(translate, 
-                        1, 
-                        &draw->rasterizer->point_size,
-                        0);
+   translate->set_buffer(translate,
+                         1,
+                         &draw->rasterizer->point_size,
+                         0,
+                         ~0);
 
-   translate->run( translate,
-                  0, 
-                  vertex_count,
-                   draw->instance_id,
-                  hw_verts );
+   /* fetch/translate vertex attribs to fill hw_verts[] */
+   translate->run(translate,
+                  0,
+                  vertex_count,
+                  0,
+                  0,
+                  hw_verts);
 
-   render->unmap_vertices( render, 
-                           0, 
-                           vertex_count - 1 );
+   render->unmap_vertices(render, 0, vertex_count - 1);
 
-   render->draw(render,
-               elts,
-               count);
+   for (start = i = 0;
+        i < prim_info->primitive_count;
+        start += prim_info->primitive_lengths[i], i++)
+   {
+      render->draw_elements(render,
+                            elts + start,
+                            prim_info->primitive_lengths[i]);
+   }
 
    render->release_vertices(render);
 }
 
 
-void draw_pt_emit_linear(struct pt_emit *emit,
-                         const float (*vertex_data)[4],
-                         unsigned stride,
-                         unsigned count)
+void
+draw_pt_emit_linear(struct pt_emit *emit,
+                    const struct draw_vertex_info *vert_info,
+                    const struct draw_prim_info *prim_info)
 {
+   const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
+   unsigned stride = vert_info->stride;
+   unsigned count = vert_info->count;
    struct draw_context *draw = emit->draw;
    struct translate *translate = emit->translate;
    struct vbuf_render *render = draw->render;
    void *hw_verts;
+   unsigned start, i;
 
 #if 0
    debug_printf("Linear emit\n");
 #endif
-   /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 
+   /* XXX: need to flush to get prim_vbuf.c to release its allocation??
     */
-   draw_do_flush( draw, DRAW_FLUSH_BACKEND );
-
-   if (count >= UNDEFINED_VERTEX_ID)
-      goto fail;
+   draw_do_flush(draw, DRAW_FLUSH_BACKEND);
 
    /* XXX: and work out some way to coordinate the render primitive
     * between vbuf.c and here...
     */
-   if (!draw->render->set_primitive(draw->render, emit->prim)) 
-      goto fail;
+   render->set_primitive(draw->render, prim_info->prim);
 
+   assert(count <= 65535);
    if (!render->allocate_vertices(render,
                                   (ushort)translate->key.output_stride,
                                   (ushort)count))
       goto fail;
 
-   hw_verts = render->map_vertices( render );
+   hw_verts = render->map_vertices(render);
    if (!hw_verts)
       goto fail;
 
    translate->set_buffer(translate, 0,
-                        vertex_data, stride);
+                         vertex_data, stride, count - 1);
 
    translate->set_buffer(translate, 1,
-                        &draw->rasterizer->point_size,
-                        0);
+                         &draw->rasterizer->point_size,
+                         0, ~0);
 
    translate->run(translate,
                   0,
                   count,
-                  draw->instance_id,
+                  0,
+                  0,
                   hw_verts);
 
    if (0) {
       unsigned i;
       for (i = 0; i < count; i++) {
          debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);
-         draw_dump_emitted_vertex( emit->vinfo, 
-                                   (const uint8_t *)hw_verts + 
-                                   translate->key.output_stride * i );
+         draw_dump_emitted_vertex(emit->vinfo,
+                                  (const uint8_t *)hw_verts +
+                                  translate->key.output_stride * i);
       }
    }
 
-   render->unmap_vertices( render, 0, count - 1 );
+   render->unmap_vertices(render, 0, count - 1);
 
-   render->draw_arrays(render, 0, count);
+   for (start = i = 0;
+        i < prim_info->primitive_count;
+        start += prim_info->primitive_lengths[i], i++)
+   {
+      render->draw_arrays(render,
+                          start,
+                          prim_info->primitive_lengths[i]);
+   }
 
    render->release_vertices(render);
 
    return;
 
 fail:
-   assert(0);
+   debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");
    return;
 }
 
-struct pt_emit *draw_pt_emit_create( struct draw_context *draw )
+
+struct pt_emit *
+draw_pt_emit_create(struct draw_context *draw)
 {
    struct pt_emit *emit = CALLOC_STRUCT(pt_emit);
    if (!emit)
@@ -305,10 +299,14 @@ struct pt_emit *draw_pt_emit_create( struct draw_context *draw )
       return NULL;
    }
 
+   emit->zero4[0] = emit->zero4[1] = emit->zero4[2] = emit->zero4[3] = 0.0f;
+
    return emit;
 }
 
-void draw_pt_emit_destroy( struct pt_emit *emit )
+
+void
+draw_pt_emit_destroy(struct pt_emit *emit)
 {
    if (emit->cache)
       translate_cache_destroy(emit->cache);