failover: queiten compiler warnings
[mesa.git] / src / gallium / drivers / i915simple / i915_prim_vbuf.c
index 9d5f609220aa383dfcc465c5cc07991cef2f43a3..a8e97e7c306ed5d69c001c89c566d2ae0e71dc2f 100644 (file)
  */
 
 
+#include "draw/draw_context.h"
 #include "draw/draw_vbuf.h"
 #include "pipe/p_debug.h"
-#include "pipe/p_util.h"
 #include "pipe/p_inlines.h"
 #include "pipe/p_winsys.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
 
 #include "i915_context.h"
 #include "i915_reg.h"
@@ -62,8 +64,21 @@ struct i915_vbuf_render {
    /** Vertex size in bytes */
    unsigned vertex_size;
 
+   /** Software primitive */
+   unsigned prim;
+
    /** Hardware primitive */
    unsigned hwprim;
+
+   /** Genereate a vertex list */
+   unsigned fallback;
+
+   /* Stuff for the vbo */
+   struct pipe_buffer *vbo;
+   size_t vbo_size;
+   size_t vbo_offset;
+   void *vbo_ptr;
+   size_t vbo_alloc_size;
 };
 
 
@@ -95,48 +110,297 @@ i915_vbuf_render_get_vertex_info( struct vbuf_render *render )
 
 static void *
 i915_vbuf_render_allocate_vertices( struct vbuf_render *render,
-                                   ushort vertex_size,
-                                   ushort nr_vertices )
+                                    ushort vertex_size,
+                                    ushort nr_vertices )
 {
    struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
    struct i915_context *i915 = i915_render->i915;
-   struct pipe_winsys *winsys = i915->pipe.winsys;
+   struct pipe_screen *screen = i915->pipe.screen;
    size_t size = (size_t)vertex_size * (size_t)nr_vertices;
 
    /* FIXME: handle failure */
    assert(!i915->vbo);
-   i915->vbo = winsys->buffer_create(winsys, 64, I915_BUFFER_USAGE_LIT_VERTEX,
-                                     size);
-   
+
+   if (i915_render->vbo_size > size + i915_render->vbo_offset && !i915->vbo_flushed) {
+   } else {
+      i915->vbo_flushed = 0;
+      pipe_buffer_reference(screen, &i915_render->vbo, NULL);
+   }
+
+   if (!i915_render->vbo) {
+      i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size);
+      i915_render->vbo_offset = 0;
+      i915_render->vbo = pipe_buffer_create(screen,
+                                            64,
+                                            I915_BUFFER_USAGE_LIT_VERTEX,
+                                            i915_render->vbo_size);
+      i915_render->vbo_ptr = pipe_buffer_map(screen,
+                                             i915_render->vbo,
+                                             PIPE_BUFFER_USAGE_CPU_WRITE);
+      pipe_buffer_unmap(screen, i915_render->vbo);
+   }
+
+   i915->vbo = i915_render->vbo;
+   i915->vbo_offset = i915_render->vbo_offset;
    i915->dirty |= I915_NEW_VBO;
-   
-   return winsys->buffer_map(winsys, 
-                             i915->vbo, 
-                             PIPE_BUFFER_USAGE_CPU_WRITE);
+
+   return (unsigned char *)i915_render->vbo_ptr + i915->vbo_offset;
 }
 
 
-static void 
+static boolean
 i915_vbuf_render_set_primitive( struct vbuf_render *render, 
                                 unsigned prim )
 {
    struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
-   
+   i915_render->prim = prim;
+
    switch(prim) {
    case PIPE_PRIM_POINTS:
       i915_render->hwprim = PRIM3D_POINTLIST;
-      break;
+      i915_render->fallback = 0;
+      return TRUE;
    case PIPE_PRIM_LINES:
       i915_render->hwprim = PRIM3D_LINELIST;
-      break;
+      i915_render->fallback = 0;
+      return TRUE;
+   case PIPE_PRIM_LINE_LOOP:
+      i915_render->hwprim = PRIM3D_LINELIST;
+      i915_render->fallback = PIPE_PRIM_LINE_LOOP;
+      return TRUE;
+   case PIPE_PRIM_LINE_STRIP:
+      i915_render->hwprim = PRIM3D_LINESTRIP;
+      i915_render->fallback = 0;
+      return TRUE;
    case PIPE_PRIM_TRIANGLES:
       i915_render->hwprim = PRIM3D_TRILIST;
+      i915_render->fallback = 0;
+      return TRUE;
+   case PIPE_PRIM_TRIANGLE_STRIP:
+      i915_render->hwprim = PRIM3D_TRISTRIP;
+      i915_render->fallback = 0;
+      return TRUE;
+   case PIPE_PRIM_TRIANGLE_FAN:
+      i915_render->hwprim = PRIM3D_TRIFAN;
+      i915_render->fallback = 0;
+      return TRUE;
+   case PIPE_PRIM_QUADS:
+      i915_render->hwprim = PRIM3D_TRILIST;
+      i915_render->fallback = PIPE_PRIM_QUADS;
+      return TRUE;
+   case PIPE_PRIM_QUAD_STRIP:
+      i915_render->hwprim = PRIM3D_TRILIST;
+      i915_render->fallback = PIPE_PRIM_QUAD_STRIP;
+      return TRUE;
+   case PIPE_PRIM_POLYGON:
+      i915_render->hwprim = PRIM3D_POLY;
+      i915_render->fallback = 0;
+      return TRUE;
+   default:
+      /* FIXME: Actually, can handle a lot more just fine... */
+      return FALSE;
+   }
+}
+
+
+
+/**
+ * Used for fallbacks in draw_arrays
+ */
+static void
+draw_arrays_generate_indices( struct vbuf_render *render,
+                              unsigned start, uint nr,
+                              unsigned type )
+{
+   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+   struct i915_context *i915 = i915_render->i915;
+   unsigned i;
+   unsigned end = start + nr;
+   switch(type) {
+   case 0:
+      for (i = start; i+1 < end; i += 2)
+        OUT_BATCH( (i+0) | (i+1) << 16 );
+      if (i < end)
+        OUT_BATCH( i );
+      break;
+   case PIPE_PRIM_LINE_LOOP:
+      if (nr >= 2) {
+        for (i = start + 1; i < end; i++)
+           OUT_BATCH( (i-0) | (i+0) << 16 );
+        OUT_BATCH( (i-0) | (  start) << 16 );
+      }
+      break;
+   case PIPE_PRIM_QUADS:
+      for (i = start; i + 3 < end; i += 4) {
+        OUT_BATCH( (i+0) | (i+1) << 16 );
+        OUT_BATCH( (i+3) | (i+1) << 16 );
+        OUT_BATCH( (i+2) | (i+3) << 16 );
+      }
+      break;
+   case PIPE_PRIM_QUAD_STRIP:
+      for (i = start; i + 3 < end; i += 2) {
+        OUT_BATCH( (i+0) | (i+1) << 16 );
+        OUT_BATCH( (i+3) | (i+2) << 16 );
+        OUT_BATCH( (i+0) | (i+3) << 16 );
+      }
       break;
    default:
       assert(0);
    }
 }
 
+static unsigned
+draw_arrays_calc_nr_indices( uint nr, unsigned type )
+{
+   switch (type) {
+   case 0:
+      return nr;
+   case PIPE_PRIM_LINE_LOOP:
+      if (nr >= 2)
+        return nr * 2;
+      else
+        return 0;
+   case PIPE_PRIM_QUADS:
+      return (nr / 4) * 6;
+   case PIPE_PRIM_QUAD_STRIP:
+      return ((nr - 2) / 2) * 6;
+   default:
+      assert(0);
+      return 0;
+   }
+}
+
+static void
+draw_arrays_fallback( struct vbuf_render *render,
+                      unsigned start,
+                      uint nr )
+{
+   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+   struct i915_context *i915 = i915_render->i915;
+   unsigned nr_indices;
+
+   if (i915->dirty)
+      i915_update_derived( i915 );
+
+   if (i915->hardware_dirty)
+      i915_emit_hardware_state( i915 );
+
+   nr_indices = draw_arrays_calc_nr_indices( nr, i915_render->fallback );
+   if (!nr_indices)
+      return;
+
+   if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
+      FLUSH_BATCH(NULL);
+
+      /* Make sure state is re-emitted after a flush:
+       */
+      i915_update_derived( i915 );
+      i915_emit_hardware_state( i915 );
+      i915->vbo_flushed = 1;
+
+      if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
+        assert(0);
+        goto out;
+      }
+   }
+   OUT_BATCH( _3DPRIMITIVE |
+             PRIM_INDIRECT |
+             i915_render->hwprim |
+             PRIM_INDIRECT_ELTS |
+             nr_indices );
+
+   draw_arrays_generate_indices( render, start, nr, i915_render->fallback );
+
+out:
+   return;
+}
+
+static void
+i915_vbuf_render_draw_arrays( struct vbuf_render *render,
+                              unsigned start,
+                              uint nr )
+{
+   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+
+   if (i915_render->fallback) {
+      draw_arrays_fallback( render, start, nr );
+      return;
+   }
+
+   /* JB: TODO submit direct cmds */
+   draw_arrays_fallback( render, start, nr );
+}
+
+/**
+ * Used for normal and fallback emitting of indices
+ * If type is zero normal operation assumed.
+ */
+static void
+draw_generate_indices( struct vbuf_render *render,
+                       const ushort *indices,
+                       uint nr_indices,
+                       unsigned type )
+{
+   struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+   struct i915_context *i915 = i915_render->i915;
+   unsigned i;
+
+   switch(type) {
+   case 0:
+      for (i = 0; i + 1 < nr_indices; i += 2) {
+        OUT_BATCH( indices[i] | indices[i+1] << 16 );
+      }
+      if (i < nr_indices) {
+        OUT_BATCH( indices[i] );
+      }
+      break;
+   case PIPE_PRIM_LINE_LOOP:
+      if (nr_indices >= 2) {
+        for (i = 1; i < nr_indices; i++)
+           OUT_BATCH( indices[i-1] | indices[i] << 16 );
+        OUT_BATCH( indices[i-1] | indices[0] << 16 );
+      }
+      break;
+   case PIPE_PRIM_QUADS:
+      for (i = 0; i + 3 < nr_indices; i += 4) {
+        OUT_BATCH( indices[i+0] | indices[i+1] << 16 );
+        OUT_BATCH( indices[i+3] | indices[i+1] << 16 );
+        OUT_BATCH( indices[i+2] | indices[i+3] << 16 );
+      }
+      break;
+   case PIPE_PRIM_QUAD_STRIP:
+      for (i = 0; i + 3 < nr_indices; i += 2) {
+        OUT_BATCH( indices[i+0] | indices[i+1] << 16 );
+        OUT_BATCH( indices[i+3] | indices[i+2] << 16 );
+        OUT_BATCH( indices[i+0] | indices[i+3] << 16 );
+      }
+      break;
+   default:
+      assert(0);
+      break;
+   }
+}
+
+static unsigned
+draw_calc_nr_indices( uint nr_indices, unsigned type )
+{
+   switch (type) {
+   case 0:
+      return nr_indices;
+   case PIPE_PRIM_LINE_LOOP:
+      if (nr_indices >= 2)
+        return nr_indices * 2;
+      else
+        return 0;
+   case PIPE_PRIM_QUADS:
+      return (nr_indices / 4) * 6;
+   case PIPE_PRIM_QUAD_STRIP:
+      return ((nr_indices - 2) / 2) * 6;
+   default:
+      assert(0);
+      return 0;
+   }
+}
 
 static void 
 i915_vbuf_render_draw( struct vbuf_render *render,
@@ -145,13 +409,14 @@ i915_vbuf_render_draw( struct vbuf_render *render,
 {
    struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
    struct i915_context *i915 = i915_render->i915;
-   unsigned i;
+   unsigned save_nr_indices;
 
-   assert(nr_indices);
+   save_nr_indices = nr_indices;
+
+   nr_indices = draw_calc_nr_indices( nr_indices, i915_render->fallback );
+   if (!nr_indices)
+      return;
 
-   /* this seems to be bogus, since we validate state right after this */
-   /*assert((i915->dirty & ~I915_NEW_VBO) == 0);*/
-   
    if (i915->dirty)
       i915_update_derived( i915 );
 
@@ -159,31 +424,32 @@ i915_vbuf_render_draw( struct vbuf_render *render,
       i915_emit_hardware_state( i915 );
 
    if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
-      FLUSH_BATCH();
+      FLUSH_BATCH(NULL);
 
       /* Make sure state is re-emitted after a flush: 
        */
       i915_update_derived( i915 );
       i915_emit_hardware_state( i915 );
+      i915->vbo_flushed = 1;
 
       if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
         assert(0);
-        return;
+     goto out;
       }
    }
 
    OUT_BATCH( _3DPRIMITIVE |
-              PRIM_INDIRECT |
-              i915_render->hwprim |
-             PRIM_INDIRECT_ELTS |
-             nr_indices );
-   for (i = 0; i + 1 < nr_indices; i += 2) {
-      OUT_BATCH( indices[i] |
-                 (indices[i + 1] << 16) );
-   }
-   if (i < nr_indices) {
-      OUT_BATCH( indices[i] );
-   }
+             PRIM_INDIRECT |
+             i915_render->hwprim |
+             PRIM_INDIRECT_ELTS |
+             nr_indices );
+   draw_generate_indices( render,
+                         indices,
+                         save_nr_indices,
+                         i915_render->fallback );
+
+out:
+   return;
 }
 
 
@@ -195,11 +461,13 @@ i915_vbuf_render_release_vertices( struct vbuf_render *render,
 {
    struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
    struct i915_context *i915 = i915_render->i915;
-   struct pipe_winsys *winsys = i915->pipe.winsys;
+   size_t size = (size_t)vertex_size * (size_t)vertices_used;
 
    assert(i915->vbo);
-   winsys->buffer_unmap(winsys, i915->vbo);
-   pipe_buffer_reference(winsys, &i915->vbo, NULL);
+
+   i915_render->vbo_offset += size;
+   i915->vbo = NULL;
+   i915->dirty |= I915_NEW_VBO;
 }
 
 
@@ -218,6 +486,7 @@ static struct vbuf_render *
 i915_vbuf_render_create( struct i915_context *i915 )
 {
    struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render);
+   struct pipe_screen *screen = i915->pipe.screen;
 
    i915_render->i915 = i915;
    
@@ -227,14 +496,27 @@ i915_vbuf_render_create( struct i915_context *i915 )
     * batch buffer.
     */
    i915_render->base.max_indices = 16*1024;
-   
+
    i915_render->base.get_vertex_info = i915_vbuf_render_get_vertex_info;
    i915_render->base.allocate_vertices = i915_vbuf_render_allocate_vertices;
    i915_render->base.set_primitive = i915_vbuf_render_set_primitive;
    i915_render->base.draw = i915_vbuf_render_draw;
+   i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays;
    i915_render->base.release_vertices = i915_vbuf_render_release_vertices;
    i915_render->base.destroy = i915_vbuf_render_destroy;
-   
+
+   i915_render->vbo_alloc_size = 128 * 4096;
+   i915_render->vbo_size = i915_render->vbo_alloc_size;
+   i915_render->vbo_offset = 0;
+   i915_render->vbo = pipe_buffer_create(screen,
+                                         64,
+                                         I915_BUFFER_USAGE_LIT_VERTEX,
+                                         i915_render->vbo_size);
+   i915_render->vbo_ptr = pipe_buffer_map(screen,
+                                          i915_render->vbo,
+                                          PIPE_BUFFER_USAGE_CPU_WRITE);
+   pipe_buffer_unmap(screen, i915_render->vbo);
+
    return &i915_render->base;
 }
 
@@ -256,6 +538,8 @@ struct draw_stage *i915_draw_vbuf_stage( struct i915_context *i915 )
       render->destroy(render);
       return NULL;
    }
-    
+   /** TODO JB: this shouldn't be here */
+   draw_set_render(i915->draw, render);
+
    return stage;
 }