draw_pipe_vbuf.c File Reference

Vertex buffer drawing stage. More...

Include dependency graph for draw_pipe_vbuf.c:

Go to the source code of this file.

Data Structures

struct  vbuf_stage
 Vertex buffer emit stage. More...

Functions

static struct vbuf_stagevbuf_stage (struct draw_stage *stage)
 Basically a cast wrapper.
static void vbuf_flush_indices (struct vbuf_stage *vbuf)
static void vbuf_flush_vertices (struct vbuf_stage *vbuf)
 Flush existing vertex buffer and allocate a new one.
static void vbuf_alloc_vertices (struct vbuf_stage *vbuf)
static boolean overflow (void *map, void *ptr, unsigned bytes, unsigned bufsz)
static void check_space (struct vbuf_stage *vbuf, unsigned nr)
static ushort emit_vertex (struct vbuf_stage *vbuf, struct vertex_header *vertex)
 Extract the needed fields from post-transformed vertex and emit a hardware(driver) vertex.
static void vbuf_tri (struct draw_stage *stage, struct prim_header *prim)
static void vbuf_line (struct draw_stage *stage, struct prim_header *prim)
static void vbuf_point (struct draw_stage *stage, struct prim_header *prim)
static void vbuf_set_prim (struct vbuf_stage *vbuf, uint prim)
 Set the prim type for subsequent vertices.
static void vbuf_first_tri (struct draw_stage *stage, struct prim_header *prim)
static void vbuf_first_line (struct draw_stage *stage, struct prim_header *prim)
static void vbuf_first_point (struct draw_stage *stage, struct prim_header *prim)
static void vbuf_flush (struct draw_stage *stage, unsigned flags)
static void vbuf_reset_stipple_counter (struct draw_stage *stage)
static void vbuf_destroy (struct draw_stage *stage)
struct draw_stagedraw_vbuf_stage (struct draw_context *draw, struct vbuf_render *render)
 Create a new primitive vbuf/render stage.


Detailed Description

Vertex buffer drawing stage.

Author:
José Fonseca <jrfonsec@tungstengraphics.com>

Keith Whitwell <keith@tungstengraphics.com>

Definition in file draw_pipe_vbuf.c.


Function Documentation

static void check_space ( struct vbuf_stage vbuf,
unsigned  nr 
) [static]

Definition at line 110 of file draw_pipe_vbuf.c.

References vbuf_stage::max_indices, vbuf_stage::max_vertices, vbuf_stage::nr_indices, vbuf_stage::nr_vertices, vbuf_alloc_vertices(), vbuf_flush_indices(), and vbuf_flush_vertices().

00111 {
00112    if (vbuf->nr_vertices + nr > vbuf->max_vertices ) {
00113       vbuf_flush_vertices(vbuf);
00114       vbuf_alloc_vertices(vbuf);
00115    }
00116 
00117    if (vbuf->nr_indices + nr > vbuf->max_indices )
00118       vbuf_flush_indices(vbuf);
00119 }

struct draw_stage* draw_vbuf_stage ( struct draw_context draw,
struct vbuf_render render 
) [read]

Create a new primitive vbuf/render stage.

Definition at line 455 of file draw_pipe_vbuf.c.

References align_malloc(), vbuf_stage::cache, CALLOC_STRUCT, draw_stage::destroy, draw_stage::draw, draw_stage::flush, vbuf_stage::indices, draw_stage::line, MAX2, vbuf_render::max_indices, vbuf_stage::max_indices, draw_stage::point, vbuf_stage::render, draw_stage::reset_stipple_counter, vbuf_stage::stage, translate_cache_create(), draw_stage::tri, UNDEFINED_VERTEX_ID, vbuf_destroy(), vbuf_first_line(), vbuf_first_point(), vbuf_first_tri(), vbuf_flush(), vbuf_reset_stipple_counter(), vbuf_stage::vertex_ptr, and vbuf_stage::vertices.

00457 {
00458    struct vbuf_stage *vbuf = CALLOC_STRUCT(vbuf_stage);
00459    if (vbuf == NULL)
00460       goto fail;
00461    
00462    vbuf->stage.draw = draw;
00463    vbuf->stage.point = vbuf_first_point;
00464    vbuf->stage.line = vbuf_first_line;
00465    vbuf->stage.tri = vbuf_first_tri;
00466    vbuf->stage.flush = vbuf_flush;
00467    vbuf->stage.reset_stipple_counter = vbuf_reset_stipple_counter;
00468    vbuf->stage.destroy = vbuf_destroy;
00469    
00470    vbuf->render = render;
00471    vbuf->max_indices = MAX2(render->max_indices, UNDEFINED_VERTEX_ID-1);
00472 
00473    vbuf->indices = (ushort *) align_malloc( vbuf->max_indices * 
00474                                             sizeof(vbuf->indices[0]), 
00475                                             16 );
00476    if (!vbuf->indices)
00477       goto fail;
00478 
00479    vbuf->cache = translate_cache_create();
00480    if (!vbuf->cache) 
00481       goto fail;
00482       
00483    
00484    vbuf->vertices = NULL;
00485    vbuf->vertex_ptr = vbuf->vertices;
00486    
00487    return &vbuf->stage;
00488 
00489  fail:
00490    if (vbuf)
00491       vbuf_destroy(&vbuf->stage);
00492    
00493    return NULL;
00494 }

static ushort emit_vertex ( struct vbuf_stage vbuf,
struct vertex_header vertex 
) [static]

Extract the needed fields from post-transformed vertex and emit a hardware(driver) vertex.

Recall that the vertices are constructed by the 'draw' module and have a couple of slots at the beginning (1-dword header, 4-dword clip pos) that we ignore here. We only use the vertex->data[] fields.

Definition at line 132 of file draw_pipe_vbuf.c.

References vertex_header::data, draw_dump_emitted_vertex(), vbuf_stage::nr_vertices, translate::set_buffer, vbuf_stage::translate, UNDEFINED_VERTEX_ID, vertex_header::vertex_id, vbuf_stage::vertex_ptr, vbuf_stage::vertex_size, and vbuf_stage::vinfo.

00134 {
00135    if(vertex->vertex_id == UNDEFINED_VERTEX_ID) {      
00136       /* Hmm - vertices are emitted one at a time - better make sure
00137        * set_buffer is efficient.  Consider a special one-shot mode for
00138        * translate.
00139        */
00140       /* Note: we really do want data[0] here, not data[pos]: 
00141        */
00142       vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0);
00143       vbuf->translate->run(vbuf->translate, 0, 1, vbuf->vertex_ptr);
00144 
00145       if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
00146       
00147       vbuf->vertex_ptr += vbuf->vertex_size/4;
00148       vertex->vertex_id = vbuf->nr_vertices++;
00149    }
00150 
00151    return (ushort)vertex->vertex_id;
00152 }

static boolean overflow ( void *  map,
void *  ptr,
unsigned  bytes,
unsigned  bufsz 
) [static]

Definition at line 102 of file draw_pipe_vbuf.c.

00103 {
00104    unsigned long used = (unsigned long) ((char *)ptr - (char *)map);
00105    return (used + bytes) > bufsz;
00106 }

static void vbuf_alloc_vertices ( struct vbuf_stage vbuf  )  [static]

Definition at line 386 of file draw_pipe_vbuf.c.

References vbuf_render::allocate_vertices, assert, vbuf_render::max_vertex_buffer_bytes, vbuf_stage::max_vertices, vbuf_stage::nr_indices, vbuf_stage::render, vbuf_stage::vertex_ptr, vbuf_stage::vertex_size, and vbuf_stage::vertices.

00387 {
00388    assert(!vbuf->nr_indices);
00389    assert(!vbuf->vertices);
00390    
00391    /* Allocate a new vertex buffer */
00392    vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
00393 
00394    /* even number */
00395    vbuf->max_vertices = vbuf->max_vertices & ~1;
00396 
00397    /* Must always succeed -- driver gives us a
00398     * 'max_vertex_buffer_bytes' which it guarantees it can allocate,
00399     * and it will flush itself if necessary to do so.  If this does
00400     * fail, we are basically without usable hardware.
00401     */
00402    vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render,
00403                                                              (ushort) vbuf->vertex_size,
00404                                                              (ushort) vbuf->max_vertices);
00405    vbuf->vertex_ptr = vbuf->vertices;
00406 }

static void vbuf_destroy ( struct draw_stage stage  )  [static]

Definition at line 435 of file draw_pipe_vbuf.c.

References align_free(), vbuf_stage::cache, vbuf_render::destroy, FREE, vbuf_stage::indices, vbuf_stage::render, translate_cache_destroy(), and vbuf_stage().

00436 {
00437    struct vbuf_stage *vbuf = vbuf_stage( stage );
00438 
00439    if(vbuf->indices)
00440       align_free( vbuf->indices );
00441    
00442    if (vbuf->render)
00443       vbuf->render->destroy( vbuf->render );
00444 
00445    if (vbuf->cache)
00446       translate_cache_destroy(vbuf->cache);
00447 
00448    FREE( stage );
00449 }

static void vbuf_first_line ( struct draw_stage stage,
struct prim_header prim 
) [static]

Definition at line 316 of file draw_pipe_vbuf.c.

References draw_stage::line, PIPE_PRIM_LINES, vbuf_flush_indices(), vbuf_line(), vbuf_set_prim(), and vbuf_stage().

00318 {
00319    struct vbuf_stage *vbuf = vbuf_stage( stage );
00320 
00321    vbuf_flush_indices( vbuf );
00322    stage->line = vbuf_line;
00323    vbuf_set_prim(vbuf, PIPE_PRIM_LINES);
00324    stage->line( stage, prim );
00325 }

static void vbuf_first_point ( struct draw_stage stage,
struct prim_header prim 
) [static]

Definition at line 329 of file draw_pipe_vbuf.c.

References PIPE_PRIM_POINTS, draw_stage::point, vbuf_flush_indices(), vbuf_point(), vbuf_set_prim(), and vbuf_stage().

00331 {
00332    struct vbuf_stage *vbuf = vbuf_stage( stage );
00333 
00334    vbuf_flush_indices( vbuf );
00335    stage->point = vbuf_point;
00336    vbuf_set_prim(vbuf, PIPE_PRIM_POINTS);
00337    stage->point( stage, prim );
00338 }

static void vbuf_first_tri ( struct draw_stage stage,
struct prim_header prim 
) [static]

Definition at line 303 of file draw_pipe_vbuf.c.

References PIPE_PRIM_TRIANGLES, draw_stage::tri, vbuf_flush_indices(), vbuf_set_prim(), vbuf_stage(), and vbuf_tri().

00305 {
00306    struct vbuf_stage *vbuf = vbuf_stage( stage );
00307 
00308    vbuf_flush_indices( vbuf );   
00309    stage->tri = vbuf_tri;
00310    vbuf_set_prim(vbuf, PIPE_PRIM_TRIANGLES);
00311    stage->tri( stage, prim );
00312 }

static void vbuf_flush ( struct draw_stage stage,
unsigned  flags 
) [static]

Definition at line 411 of file draw_pipe_vbuf.c.

References DRAW_FLUSH_BACKEND, draw_stage::line, draw_stage::point, draw_stage::tri, vbuf_first_line(), vbuf_first_point(), vbuf_first_tri(), vbuf_flush_indices(), vbuf_flush_vertices(), and vbuf_stage().

00412 {
00413    struct vbuf_stage *vbuf = vbuf_stage( stage );
00414 
00415    vbuf_flush_indices( vbuf );
00416 
00417    stage->point = vbuf_first_point;
00418    stage->line = vbuf_first_line;
00419    stage->tri = vbuf_first_tri;
00420 
00421    if (flags & DRAW_FLUSH_BACKEND)
00422       vbuf_flush_vertices( vbuf );
00423 }

static void vbuf_flush_indices ( struct vbuf_stage vbuf  )  [static]

Definition at line 342 of file draw_pipe_vbuf.c.

References assert, vbuf_render::draw, vbuf_stage::indices, vbuf_stage::nr_indices, vbuf_stage::nr_vertices, vbuf_stage::render, vbuf_stage::vertex_ptr, vbuf_stage::vertex_size, and vbuf_stage::vertices.

00343 {
00344    if(!vbuf->nr_indices)
00345       return;
00346    
00347    assert((uint) (vbuf->vertex_ptr - vbuf->vertices) == 
00348           vbuf->nr_vertices * vbuf->vertex_size / sizeof(unsigned));
00349 
00350    vbuf->render->draw(vbuf->render, vbuf->indices, vbuf->nr_indices);
00351    
00352    vbuf->nr_indices = 0;
00353 }

static void vbuf_flush_vertices ( struct vbuf_stage vbuf  )  [static]

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.

Definition at line 364 of file draw_pipe_vbuf.c.

References draw_stage::draw, draw_reset_vertex_ids(), vbuf_stage::max_vertices, vbuf_stage::nr_vertices, vbuf_render::release_vertices, vbuf_stage::render, vbuf_stage::stage, vbuf_flush_indices(), vbuf_stage::vertex_ptr, vbuf_stage::vertex_size, and vbuf_stage::vertices.

00365 {
00366    if(vbuf->vertices) {      
00367       vbuf_flush_indices(vbuf);
00368       
00369       /* Reset temporary vertices ids */
00370       if(vbuf->nr_vertices)
00371          draw_reset_vertex_ids( vbuf->stage.draw );
00372       
00373       /* Free the vertex buffer */
00374       vbuf->render->release_vertices(vbuf->render,
00375                                      vbuf->vertices,
00376                                      vbuf->vertex_size,
00377                                      vbuf->nr_vertices);
00378       vbuf->max_vertices = vbuf->nr_vertices = 0;
00379       vbuf->vertex_ptr = vbuf->vertices = NULL;
00380       
00381    }
00382 }

static void vbuf_line ( struct draw_stage stage,
struct prim_header prim 
) [static]

Definition at line 171 of file draw_pipe_vbuf.c.

References check_space(), emit_vertex(), vbuf_stage::indices, vbuf_stage::nr_indices, prim_header::v, and vbuf_stage().

00173 {
00174    struct vbuf_stage *vbuf = vbuf_stage( stage );
00175    unsigned i;
00176 
00177    check_space( vbuf, 2 );
00178 
00179    for (i = 0; i < 2; i++) {
00180       vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
00181    }   
00182 }

static void vbuf_point ( struct draw_stage stage,
struct prim_header prim 
) [static]

Definition at line 186 of file draw_pipe_vbuf.c.

References check_space(), emit_vertex(), vbuf_stage::indices, vbuf_stage::nr_indices, prim_header::v, and vbuf_stage().

00188 {
00189    struct vbuf_stage *vbuf = vbuf_stage( stage );
00190 
00191    check_space( vbuf, 1 );
00192 
00193    vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] );
00194 }

static void vbuf_reset_stipple_counter ( struct draw_stage stage  )  [static]

Definition at line 427 of file draw_pipe_vbuf.c.

00428 {
00429    /* XXX: Need to do something here for hardware with linestipple.
00430     */
00431    (void) stage;
00432 }

static void vbuf_set_prim ( struct vbuf_stage vbuf,
uint  prim 
) [static]

Set the prim type for subsequent vertices.

This may result in a new vertex size. The existing vbuffer (if any) will be flushed if needed and a new one allocated.

Definition at line 205 of file draw_pipe_vbuf.c.

References assert, vertex_info::attrib, vbuf_stage::cache, draw_stage::draw, translate_key::element, vertex_info::emit, EMIT_1F, EMIT_1F_PSIZE, EMIT_2F, EMIT_3F, EMIT_4F, EMIT_4UB, vbuf_render::get_vertex_info, translate_element::input_buffer, translate_element::input_format, translate_element::input_offset, translate::key, translate_key::nr_elements, vertex_info::num_attribs, translate_element::output_format, translate_element::output_offset, translate_key::output_stride, PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_NONE, PIPE_FORMAT_R32_FLOAT, PIPE_FORMAT_R32G32_FLOAT, PIPE_FORMAT_R32G32B32_FLOAT, PIPE_FORMAT_R32G32B32A32_FLOAT, pipe_rasterizer_state::point_size, vbuf_stage::point_size, draw_context::rasterizer, vbuf_stage::render, translate::set_buffer, vbuf_render::set_primitive, vertex_info::size, vertex_info::src_index, vbuf_stage::stage, vbuf_stage::translate, translate_cache_find(), translate_key_compare(), translate_key_sanitize(), vbuf_alloc_vertices(), vbuf_flush_vertices(), vbuf_stage::vertex_size, vbuf_stage::vertices, and vbuf_stage::vinfo.

00206 {
00207    struct translate_key hw_key;
00208    unsigned dst_offset;
00209    unsigned i;
00210 
00211    vbuf->render->set_primitive(vbuf->render, prim);
00212 
00213    /* Must do this after set_primitive() above:
00214     * 
00215     * XXX: need some state managment to track when this needs to be
00216     * recalculated.  The driver should tell us whether there was a
00217     * state change.
00218     */
00219    vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
00220 
00221    if (vbuf->vertex_size != vbuf->vinfo->size * sizeof(float)) {
00222       vbuf_flush_vertices(vbuf);
00223       vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
00224    }
00225 
00226    /* Translate from pipeline vertices to hw vertices.
00227     */
00228    dst_offset = 0;
00229 
00230    for (i = 0; i < vbuf->vinfo->num_attribs; i++) {
00231       unsigned emit_sz = 0;
00232       unsigned src_buffer = 0;
00233       unsigned output_format;
00234       unsigned src_offset = (vbuf->vinfo->attrib[i].src_index * 4 * sizeof(float) );
00235 
00236       switch (vbuf->vinfo->attrib[i].emit) {
00237       case EMIT_4F:
00238          output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
00239          emit_sz = 4 * sizeof(float);
00240          break;
00241       case EMIT_3F:
00242          output_format = PIPE_FORMAT_R32G32B32_FLOAT;
00243          emit_sz = 3 * sizeof(float);
00244          break;
00245       case EMIT_2F:
00246          output_format = PIPE_FORMAT_R32G32_FLOAT;
00247          emit_sz = 2 * sizeof(float);
00248          break;
00249       case EMIT_1F:
00250          output_format = PIPE_FORMAT_R32_FLOAT;
00251          emit_sz = 1 * sizeof(float);
00252          break;
00253       case EMIT_1F_PSIZE:
00254          output_format = PIPE_FORMAT_R32_FLOAT;
00255          emit_sz = 1 * sizeof(float);
00256          src_buffer = 1;
00257          src_offset = 0;
00258          break;
00259       case EMIT_4UB:
00260          output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
00261          emit_sz = 4 * sizeof(ubyte);
00262          break;
00263       default:
00264          assert(0);
00265          output_format = PIPE_FORMAT_NONE;
00266          emit_sz = 0;
00267          break;
00268       }
00269       
00270       hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
00271       hw_key.element[i].input_buffer = src_buffer;
00272       hw_key.element[i].input_offset = src_offset;
00273       hw_key.element[i].output_format = output_format;
00274       hw_key.element[i].output_offset = dst_offset;
00275 
00276       dst_offset += emit_sz;
00277    }
00278 
00279    hw_key.nr_elements = vbuf->vinfo->num_attribs;
00280    hw_key.output_stride = vbuf->vinfo->size * 4;
00281 
00282    /* Don't bother with caching at this stage:
00283     */
00284    if (!vbuf->translate ||
00285        translate_key_compare(&vbuf->translate->key, &hw_key) != 0) 
00286    {
00287       translate_key_sanitize(&hw_key);
00288       vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);
00289 
00290       vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0);
00291    }
00292 
00293    vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;
00294 
00295    /* Allocate new buffer?
00296     */
00297    if (!vbuf->vertices)
00298       vbuf_alloc_vertices(vbuf);
00299 }

static struct vbuf_stage* vbuf_stage ( struct draw_stage stage  )  [static, read]

Basically a cast wrapper.

Definition at line 89 of file draw_pipe_vbuf.c.

References assert.

00090 {
00091    assert(stage);
00092    return (struct vbuf_stage *)stage;
00093 }

static void vbuf_tri ( struct draw_stage stage,
struct prim_header prim 
) [static]

Definition at line 156 of file draw_pipe_vbuf.c.

References check_space(), emit_vertex(), vbuf_stage::indices, vbuf_stage::nr_indices, prim_header::v, and vbuf_stage().

00158 {
00159    struct vbuf_stage *vbuf = vbuf_stage( stage );
00160    unsigned i;
00161 
00162    check_space( vbuf, 3 );
00163 
00164    for (i = 0; i < 3; i++) {
00165       vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
00166    }
00167 }


Generated on Tue Sep 29 06:25:20 2009 for Gallium3D by  doxygen 1.5.4