draw: add map/unmap directives for swtnl driver interface

Previously draw module asked for a pointer into (mapped) vertex data,
which it would incrementally fill and emit draw commands against.  This
was hard for the drivers to deal with, especially in the case where a
draw command would force a flush and thus an unmap of the vertex data.

With this change, the draw module explicitly maps & then unmaps vertex
data prior to emitting draw commands.
This commit is contained in:
Keith Whitwell 2009-02-17 12:07:09 +00:00
parent c5c383596d
commit befa4ff50e
7 changed files with 172 additions and 178 deletions

View file

@ -93,7 +93,6 @@ vbuf_stage( struct draw_stage *stage )
}
static void vbuf_flush_indices( struct vbuf_stage *vbuf );
static void vbuf_flush_vertices( struct vbuf_stage *vbuf );
static void vbuf_alloc_vertices( struct vbuf_stage *vbuf );
@ -109,13 +108,12 @@ overflow( void *map, void *ptr, unsigned bytes, unsigned bufsz )
static INLINE void
check_space( struct vbuf_stage *vbuf, unsigned nr )
{
if (vbuf->nr_vertices + nr > vbuf->max_vertices ) {
vbuf_flush_vertices(vbuf);
vbuf_alloc_vertices(vbuf);
if (vbuf->nr_vertices + nr > vbuf->max_vertices ||
vbuf->nr_indices + nr > vbuf->max_indices)
{
vbuf_flush_vertices( vbuf );
vbuf_alloc_vertices( vbuf );
}
if (vbuf->nr_indices + nr > vbuf->max_indices )
vbuf_flush_indices(vbuf);
}
@ -202,7 +200,7 @@ vbuf_point( struct draw_stage *stage,
* will be flushed if needed and a new one allocated.
*/
static void
vbuf_set_prim( struct vbuf_stage *vbuf, uint prim )
vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
{
struct translate_key hw_key;
unsigned dst_offset;
@ -217,11 +215,7 @@ vbuf_set_prim( struct vbuf_stage *vbuf, uint prim )
* state change.
*/
vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
if (vbuf->vertex_size != vbuf->vinfo->size * sizeof(float)) {
vbuf_flush_vertices(vbuf);
vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
}
vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
/* Translate from pipeline vertices to hw vertices.
*/
@ -294,8 +288,8 @@ vbuf_set_prim( struct vbuf_stage *vbuf, uint prim )
/* Allocate new buffer?
*/
if (!vbuf->vertices)
vbuf_alloc_vertices(vbuf);
assert(vbuf->vertices == NULL);
vbuf_alloc_vertices(vbuf);
}
@ -305,9 +299,9 @@ vbuf_first_tri( struct draw_stage *stage,
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
vbuf_flush_indices( vbuf );
vbuf_flush_vertices( vbuf );
vbuf_start_prim(vbuf, PIPE_PRIM_TRIANGLES);
stage->tri = vbuf_tri;
vbuf_set_prim(vbuf, PIPE_PRIM_TRIANGLES);
stage->tri( stage, prim );
}
@ -318,9 +312,9 @@ vbuf_first_line( struct draw_stage *stage,
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
vbuf_flush_indices( vbuf );
vbuf_flush_vertices( vbuf );
vbuf_start_prim(vbuf, PIPE_PRIM_LINES);
stage->line = vbuf_line;
vbuf_set_prim(vbuf, PIPE_PRIM_LINES);
stage->line( stage, prim );
}
@ -331,53 +325,42 @@ vbuf_first_point( struct draw_stage *stage,
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
vbuf_flush_indices( vbuf );
vbuf_flush_vertices(vbuf);
vbuf_start_prim(vbuf, PIPE_PRIM_POINTS);
stage->point = vbuf_point;
vbuf_set_prim(vbuf, PIPE_PRIM_POINTS);
stage->point( stage, prim );
}
static void
vbuf_flush_indices( struct vbuf_stage *vbuf )
{
if(!vbuf->nr_indices)
return;
assert((uint) (vbuf->vertex_ptr - vbuf->vertices) ==
vbuf->nr_vertices * vbuf->vertex_size / sizeof(unsigned));
vbuf->render->draw(vbuf->render, vbuf->indices, vbuf->nr_indices);
vbuf->nr_indices = 0;
}
/**
* Flush existing vertex buffer and allocate a new one.
*
* XXX: We separate flush-on-index-full and flush-on-vb-full, but may
* raise issues uploading vertices if the hardware wants to flush when
* we flush.
*/
static void
vbuf_flush_vertices( struct vbuf_stage *vbuf )
{
if(vbuf->vertices) {
vbuf_flush_indices(vbuf);
if(vbuf->vertices) {
vbuf->render->unmap_vertices( vbuf->render, 0, vbuf->nr_vertices );
if (vbuf->nr_indices)
{
vbuf->render->draw(vbuf->render,
vbuf->indices,
vbuf->nr_indices );
vbuf->nr_indices = 0;
}
/* Reset temporary vertices ids */
if(vbuf->nr_vertices)
draw_reset_vertex_ids( vbuf->stage.draw );
/* Free the vertex buffer */
vbuf->render->release_vertices(vbuf->render,
vbuf->vertices,
vbuf->vertex_size,
vbuf->nr_vertices);
vbuf->render->release_vertices( vbuf->render );
vbuf->max_vertices = vbuf->nr_vertices = 0;
vbuf->vertex_ptr = vbuf->vertices = NULL;
}
}
@ -402,9 +385,12 @@ vbuf_alloc_vertices( struct vbuf_stage *vbuf )
* and it will flush itself if necessary to do so. If this does
* fail, we are basically without usable hardware.
*/
vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render,
(ushort) vbuf->vertex_size,
(ushort) vbuf->max_vertices);
vbuf->render->allocate_vertices(vbuf->render,
(ushort) vbuf->vertex_size,
(ushort) vbuf->max_vertices);
vbuf->vertices = (uint *) vbuf->render->map_vertices( vbuf->render );
vbuf->vertex_ptr = vbuf->vertices;
}
@ -415,14 +401,11 @@ vbuf_flush( struct draw_stage *stage, unsigned flags )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
vbuf_flush_indices( vbuf );
vbuf_flush_vertices( vbuf );
stage->point = vbuf_first_point;
stage->line = vbuf_first_line;
stage->tri = vbuf_first_tri;
if (flags & DRAW_FLUSH_BACKEND)
vbuf_flush_vertices( vbuf );
}

View file

@ -173,9 +173,7 @@ void draw_pt_emit( struct pt_emit *emit,
void draw_pt_emit_linear( struct pt_emit *emit,
const float (*vertex_data)[4],
unsigned vertex_count,
unsigned stride,
unsigned start,
unsigned count );
void draw_pt_emit_destroy( struct pt_emit *emit );

View file

@ -178,9 +178,11 @@ void draw_pt_emit( struct pt_emit *emit,
return;
}
hw_verts = render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)vertex_count);
render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)vertex_count);
hw_verts = render->map_vertices( render );
if (!hw_verts) {
assert(0);
return;
@ -201,22 +203,21 @@ void draw_pt_emit( struct pt_emit *emit,
vertex_count,
hw_verts );
render->unmap_vertices( render,
0,
vertex_count );
render->draw(render,
elts,
count);
render->release_vertices(render,
hw_verts,
translate->key.output_stride,
vertex_count);
render->release_vertices(render);
}
void draw_pt_emit_linear(struct pt_emit *emit,
const float (*vertex_data)[4],
unsigned vertex_count,
unsigned stride,
unsigned start,
unsigned count)
{
struct draw_context *draw = emit->draw;
@ -231,26 +232,23 @@ void draw_pt_emit_linear(struct pt_emit *emit,
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
if (count >= UNDEFINED_VERTEX_ID) {
assert(0);
return;
}
if (count >= UNDEFINED_VERTEX_ID)
goto fail;
/* 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;
}
if (!draw->render->set_primitive(draw->render, emit->prim))
goto fail;
hw_verts = render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)count);
if (!hw_verts) {
assert(0);
return;
}
if (!render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)count))
goto fail;
hw_verts = render->map_vertices( render );
if (!hw_verts)
goto fail;
translate->set_buffer(translate, 0,
vertex_data, stride);
@ -261,12 +259,12 @@ void draw_pt_emit_linear(struct pt_emit *emit,
translate->run(translate,
0,
vertex_count,
count,
hw_verts);
if (0) {
unsigned i;
for (i = 0; i < vertex_count; 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 +
@ -274,13 +272,17 @@ void draw_pt_emit_linear(struct pt_emit *emit,
}
}
render->unmap_vertices( render, 0, count );
render->draw_arrays(render, start, count);
render->draw_arrays(render, 0, count);
render->release_vertices(render,
hw_verts,
translate->key.output_stride,
vertex_count);
render->release_vertices(render);
return;
fail:
assert(0);
return;
}
struct pt_emit *draw_pt_emit_create( struct draw_context *draw )

View file

@ -234,9 +234,11 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
return;
}
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)fetch_count );
draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)fetch_count );
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts) {
assert(0);
return;
@ -259,6 +261,10 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
}
}
draw->render->unmap_vertices( draw->render,
0,
(ushort)fetch_count );
/* XXX: Draw arrays path to avoid re-emitting index list again and
* again.
*/
@ -268,10 +274,7 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
/* Done -- that was easy, wasn't it:
*/
draw->render->release_vertices( draw->render,
hw_verts,
feme->translate->key.output_stride,
fetch_count );
draw->render->release_vertices( draw->render );
}
@ -288,18 +291,17 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
if (count >= UNDEFINED_VERTEX_ID) {
assert(0);
return;
}
if (count >= UNDEFINED_VERTEX_ID)
goto fail;
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)count );
if (!hw_verts) {
assert(0);
return;
}
if (!draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)count ))
goto fail;
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
goto fail;
/* Single routine to fetch vertices and emit HW verts.
*/
@ -317,20 +319,21 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
}
}
draw->render->unmap_vertices( draw->render, 0, count );
/* XXX: Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_arrays( draw->render,
0, /*start*/
count );
draw->render->draw_arrays( draw->render, 0, count );
/* Done -- that was easy, wasn't it:
*/
draw->render->release_vertices( draw->render,
hw_verts,
feme->translate->key.output_stride,
count );
draw->render->release_vertices( draw->render );
return;
fail:
assert(0);
return;
}
@ -351,9 +354,12 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
if (count >= UNDEFINED_VERTEX_ID)
return FALSE;
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)count );
if (!draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)count ))
return FALSE;
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
return FALSE;
@ -364,6 +370,8 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
count,
hw_verts );
draw->render->unmap_vertices( draw->render, 0, (ushort)count );
/* XXX: Draw arrays path to avoid re-emitting index list again and
* again.
*/
@ -373,10 +381,7 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
/* Done -- that was easy, wasn't it:
*/
draw->render->release_vertices( draw->render,
hw_verts,
feme->translate->key.output_stride,
count );
draw->render->release_vertices( draw->render );
return TRUE;
}

View file

@ -234,19 +234,17 @@ static void fse_run_linear( struct draw_pt_middle_end *middle,
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
if (count >= UNDEFINED_VERTEX_ID) {
assert(0);
return;
}
if (count >= UNDEFINED_VERTEX_ID)
goto fail;
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)count );
if (!draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)count ))
goto fail;
if (!hw_verts) {
assert(0);
return;
}
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
goto fail;
/* Single routine to fetch vertices, run shader and emit HW verts.
* Clipping is done elsewhere -- either by the API or on hardware,
@ -256,13 +254,7 @@ static void fse_run_linear( struct draw_pt_middle_end *middle,
start, count,
hw_verts );
/* Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_arrays( draw->render,
0,
count );
if (0) {
unsigned i;
for (i = 0; i < count; i++) {
@ -274,12 +266,24 @@ static void fse_run_linear( struct draw_pt_middle_end *middle,
(const uint8_t *)hw_verts + fse->key.output_stride * i );
}
}
draw->render->unmap_vertices( draw->render, 0, (ushort)count );
/* Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_arrays( draw->render,
0,
count );
draw->render->release_vertices( draw->render,
hw_verts,
fse->key.output_stride,
count );
draw->render->release_vertices( draw->render );
return;
fail:
assert(0);
return;
}
@ -298,18 +302,17 @@ fse_run(struct draw_pt_middle_end *middle,
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
if (fetch_count >= UNDEFINED_VERTEX_ID) {
assert(0);
return;
}
if (fetch_count >= UNDEFINED_VERTEX_ID)
goto fail;
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)fetch_count );
if (!hw_verts) {
assert(0);
return;
}
if (!draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)fetch_count ))
goto fail;
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
goto fail;
/* Single routine to fetch vertices, run shader and emit HW verts.
@ -319,9 +322,6 @@ fse_run(struct draw_pt_middle_end *middle,
fetch_count,
hw_verts );
draw->render->draw( draw->render,
draw_elts,
draw_count );
if (0) {
unsigned i;
@ -333,12 +333,19 @@ fse_run(struct draw_pt_middle_end *middle,
}
}
draw->render->unmap_vertices( draw->render, 0, (ushort)fetch_count );
draw->render->draw( draw->render,
draw_elts,
draw_count );
draw->render->release_vertices( draw->render,
hw_verts,
fse->key.output_stride,
fetch_count );
draw->render->release_vertices( draw->render );
return;
fail:
assert(0);
return;
}
@ -360,13 +367,14 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle,
if (count >= UNDEFINED_VERTEX_ID)
return FALSE;
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)count );
if (!hw_verts) {
if (!draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)count ))
return FALSE;
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
return FALSE;
}
/* Single routine to fetch vertices, run shader and emit HW verts.
* Clipping is done elsewhere -- either by the API or on hardware,
@ -382,11 +390,9 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle,
draw_count );
draw->render->unmap_vertices( draw->render, 0, (ushort) count );
draw->render->release_vertices( draw->render,
hw_verts,
fse->key.output_stride,
count );
draw->render->release_vertices( draw->render );
return TRUE;
}

View file

@ -251,9 +251,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
else {
draw_pt_emit_linear( fpme->emit,
(const float (*)[4])pipeline_verts->data,
count,
fpme->vertex_size,
0, /*start*/
count );
}

View file

@ -80,9 +80,14 @@ struct vbuf_render {
* Hardware renderers will use ttm memory, others will just malloc
* something.
*/
void *(*allocate_vertices)( struct vbuf_render *,
ushort vertex_size,
ushort nr_vertices );
boolean (*allocate_vertices)( struct vbuf_render *,
ushort vertex_size,
ushort nr_vertices );
void *(*map_vertices)( struct vbuf_render * );
void (*unmap_vertices)( struct vbuf_render *,
ushort min_index,
ushort max_index );
/**
* Notify the renderer of the current primitive when it changes.
@ -109,10 +114,7 @@ struct vbuf_render {
/**
* Called when vbuf is done with this set of vertices:
*/
void (*release_vertices)( struct vbuf_render *,
void *vertices,
unsigned vertex_size,
unsigned vertices_used );
void (*release_vertices)( struct vbuf_render * );
void (*destroy)( struct vbuf_render * );
};