/** Vertex size in bytes */
unsigned vertex_size;
+ /** Software primitive */
+ unsigned prim;
+
/** Hardware primitive */
unsigned hwprim;
+
+ /** Genereate a vertex list */
+ unsigned fallback;
};
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;
assert(!i915->vbo);
i915->vbo = winsys->buffer_create(winsys, 64, I915_BUFFER_USAGE_LIT_VERTEX,
size);
-
+
i915->dirty |= I915_NEW_VBO;
-
+
return winsys->buffer_map(winsys,
i915->vbo,
PIPE_BUFFER_USAGE_CPU_WRITE);
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;
+ i915_render->fallback = 0;
return TRUE;
case PIPE_PRIM_LINES:
i915_render->hwprim = PRIM3D_LINELIST;
+ i915_render->fallback = 0;
+ 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_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;
default:
/* Actually, can handle a lot more just fine... Fixme.
}
+
+/**
+ * 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_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_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;
+ struct pipe_winsys *winsys = i915->pipe.winsys;
+ unsigned nr_indices;
+
+ winsys->buffer_unmap( winsys, i915->vbo );
+ 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 (!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 );
+
+ 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:
+ winsys->buffer_map( winsys, i915->vbo, PIPE_BUFFER_USAGE_CPU_WRITE );
+}
+
+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] & 0x0FFF) | ((indices[i+1] & 0x0FFF) << 16) );
+ }
+ if (i < nr_indices) {
+ OUT_BATCH( indices[i] & 0x0FFF );
+ }
+ break;
+ case PIPE_PRIM_QUADS:
+ for (i = 0; i + 3 < nr_indices; i += 4) {
+ OUT_BATCH( (indices[i+0] & 0x0FFF) | (indices[i+1] & 0x0FFF) << 16 );
+ OUT_BATCH( (indices[i+3] & 0x0FFF) | (indices[i+1] & 0x0FFF) << 16 );
+ OUT_BATCH( (indices[i+2] & 0x0FFF) | (indices[i+3] & 0x0FFF) << 16 );
+ }
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 0; i + 3 < nr_indices; i += 2) {
+ OUT_BATCH( (indices[i+0] & 0x0FFF) | (indices[i+1] & 0x0FFF) << 16 );
+ OUT_BATCH( (indices[i+3] & 0x0FFF) | (indices[i+2] & 0x0FFF) << 16 );
+ OUT_BATCH( (indices[i+0] & 0x0FFF) | (indices[i+3] & 0x0FFF) << 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_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,
const ushort *indices,
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
struct i915_context *i915 = i915_render->i915;
- unsigned i;
+ struct pipe_winsys *winsys = i915->pipe.winsys;
+ unsigned save_nr_indices;
+
+ save_nr_indices = nr_indices;
+ nr_indices = draw_calc_nr_indices( nr_indices, i915_render->fallback );
assert(nr_indices);
+ winsys->buffer_unmap( winsys, i915->vbo );
- /* 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 );
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:
+ winsys->buffer_map( winsys, i915->vbo, PIPE_BUFFER_USAGE_CPU_WRITE );
+ return;
}
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;
render->destroy(render);
return NULL;
}
-
+ draw_set_render(i915->draw, render);
+
return stage;
}