X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fdraw%2Fdraw_pt_fetch_emit.c;h=4a1f3b095361e6046d64678796837fc36bfaebc5;hb=d25709df1d5d9dccdeb173b33a57018004fe849c;hp=0806076956d9ce5cb8c9a3e1b23b0d7baf03ee7e;hpb=a8a5376406cabf5aa6a44f7d37f5f8abbb4adf56;p=mesa.git diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index 0806076956d..4a1f3b09536 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -36,6 +36,8 @@ #include "draw/draw_vbuf.h" #include "draw/draw_vertex.h" #include "draw/draw_pt.h" +#include "translate/translate.h" +#include "translate/translate_cache.h" /* The simplest 'middle end' in the new vertex code. * @@ -72,107 +74,31 @@ struct fetch_emit_middle_end { struct draw_pt_middle_end base; struct draw_context *draw; - - struct { - const ubyte *ptr; - unsigned pitch; - void (*fetch)( const void *from, float *attrib); - void (*emit)( const float *attrib, float **out ); - } fetch[PIPE_MAX_ATTRIBS]; - unsigned nr_fetch; - unsigned hw_vertex_size; -}; - - - -static void fetch_R32_FLOAT( const void *from, - float *attrib ) -{ - float *f = (float *) from; - attrib[0] = f[0]; - attrib[1] = 0.0; - attrib[2] = 0.0; - attrib[3] = 1.0; -} - - -static void emit_R32_FLOAT( const float *attrib, - float **out ) -{ - (*out)[0] = attrib[0]; - (*out) += 1; -} - -static void emit_R32G32_FLOAT( const float *attrib, - float **out ) -{ - (*out)[0] = attrib[0]; - (*out)[1] = attrib[1]; - (*out) += 2; -} - -static void emit_R32G32B32_FLOAT( const float *attrib, - float **out ) -{ - (*out)[0] = attrib[0]; - (*out)[1] = attrib[1]; - (*out)[2] = attrib[2]; - (*out) += 3; -} - -static void emit_R32G32B32A32_FLOAT( const float *attrib, - float **out ) -{ - (*out)[0] = attrib[0]; - (*out)[1] = attrib[1]; - (*out)[2] = attrib[2]; - (*out)[3] = attrib[3]; - (*out) += 4; -} + struct translate *translate; + const struct vertex_info *vinfo; + /* Cache point size somewhere it's address won't change: + */ + float point_size; -/** - * General-purpose fetch from user's vertex arrays, emit to driver's - * vertex buffer. - * - * XXX this is totally temporary. - */ -static void -fetch_store_general( struct fetch_emit_middle_end *feme, - void *out_ptr, - const unsigned *fetch_elts, - unsigned count ) -{ - float *out = (float *)out_ptr; - struct vbuf_render *render = feme->draw->render; - uint i, j; + struct translate_cache *cache; +}; - for (i = 0; i < count; i++) { - unsigned elt = fetch_elts[i] & ~DRAW_PT_FLAG_MASK; - - for (j = 0; j < feme->nr_fetch; j++) { - float attrib[4]; - const ubyte *from = (feme->fetch[j].ptr + - feme->fetch[j].pitch * elt); - - feme->fetch[j].fetch( from, attrib ); - feme->fetch[j].emit( attrib, &out ); - } - } -} static void fetch_emit_prepare( struct draw_pt_middle_end *middle, - unsigned prim ) + unsigned prim, + unsigned opt, + unsigned *max_vertices ) { - static const float zero = 0; struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; const struct vertex_info *vinfo; - unsigned i; + unsigned i, dst_offset; boolean ok; + struct translate_key key; ok = draw->render->set_primitive( draw->render, @@ -184,55 +110,105 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle, /* Must do this after set_primitive() above: */ - vinfo = draw->render->get_vertex_info(draw->render); + vinfo = feme->vinfo = draw->render->get_vertex_info(draw->render); + + - for (i = 0; i < vinfo->num_attribs; i++) { - unsigned src_element = vinfo->src_index[i]; - unsigned src_buffer = draw->vertex_element[src_element].vertex_buffer_index; - - feme->fetch[i].ptr = ((const ubyte *)draw->user.vbuffer[src_buffer] + - draw->vertex_buffer[src_buffer].buffer_offset + - draw->vertex_element[src_element].src_offset); + /* Transform from API vertices to HW vertices, skipping the + * pipeline_vertex intermediate step. + */ + dst_offset = 0; + memset(&key, 0, sizeof(key)); - feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch; - - feme->fetch[i].fetch = draw_get_fetch_func(draw->vertex_element[src_element].src_format); + for (i = 0; i < vinfo->num_attribs; i++) { + const struct pipe_vertex_element *src = &draw->pt.vertex_element[vinfo->src_index[i]]; + unsigned emit_sz = 0; + unsigned input_format = src->src_format; + unsigned input_buffer = src->vertex_buffer_index; + unsigned input_offset = src->src_offset; + unsigned output_format; switch (vinfo->emit[i]) { case EMIT_4F: - feme->fetch[i].emit = emit_R32G32B32A32_FLOAT; + output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + emit_sz = 4 * sizeof(float); break; case EMIT_3F: - feme->fetch[i].emit = emit_R32G32B32_FLOAT; + output_format = PIPE_FORMAT_R32G32B32_FLOAT; + emit_sz = 3 * sizeof(float); break; case EMIT_2F: - feme->fetch[i].emit = emit_R32G32_FLOAT; + output_format = PIPE_FORMAT_R32G32_FLOAT; + emit_sz = 2 * sizeof(float); break; case EMIT_1F: - feme->fetch[i].emit = emit_R32_FLOAT; - break; - case EMIT_HEADER: - feme->fetch[i].ptr = (const ubyte *)&zero; - feme->fetch[i].pitch = 0; - feme->fetch[i].fetch = fetch_R32_FLOAT; - feme->fetch[i].emit = emit_R32_FLOAT; + output_format = PIPE_FORMAT_R32_FLOAT; + emit_sz = 1 * sizeof(float); break; case EMIT_1F_PSIZE: - feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size; - feme->fetch[i].pitch = 0; - feme->fetch[i].fetch = fetch_R32_FLOAT; - feme->fetch[i].emit = emit_R32_FLOAT; + input_format = PIPE_FORMAT_R32_FLOAT; + input_buffer = draw->pt.nr_vertex_buffers; + input_offset = 0; + output_format = PIPE_FORMAT_R32_FLOAT; + emit_sz = 1 * sizeof(float); break; default: assert(0); - feme->fetch[i].emit = NULL; - break; + output_format = PIPE_FORMAT_NONE; + emit_sz = 0; + continue; } + + key.element[i].input_format = input_format; + key.element[i].input_buffer = input_buffer; + key.element[i].input_offset = input_offset; + key.element[i].output_format = output_format; + key.element[i].output_offset = dst_offset; + + dst_offset += emit_sz; } - feme->nr_fetch = vinfo->num_attribs; - feme->hw_vertex_size = vinfo->size * 4; + key.nr_elements = vinfo->num_attribs; + key.output_stride = vinfo->size * 4; + + /* Don't bother with caching at this stage: + */ + if (!feme->translate || + translate_key_compare(&feme->translate->key, &key) != 0) + { + translate_key_sanitize(&key); + feme->translate = translate_cache_find(feme->cache, + &key); + + + feme->translate->set_buffer(feme->translate, + draw->pt.nr_vertex_buffers, + &feme->point_size, + 0); + } + + feme->point_size = draw->rasterizer->point_size; + + for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { + feme->translate->set_buffer(feme->translate, + i, + ((char *)draw->pt.user.vbuffer[i] + + draw->pt.vertex_buffer[i].buffer_offset), + draw->pt.vertex_buffer[i].pitch ); + } + + *max_vertices = (draw->render->max_vertex_buffer_bytes / + (vinfo->size * 4)); + + /* Return an even number of verts. + * This prevents "parity" errors when splitting long triangle strips which + * can lead to front/back culling mix-ups. + * Every other triangle in a strip has an alternate front/back orientation + * so splitting at an odd position can cause the orientation of subsequent + * triangles to get reversed. + */ + *max_vertices = *max_vertices & ~1; } @@ -249,8 +225,12 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, struct draw_context *draw = feme->draw; void *hw_verts; + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + hw_verts = draw->render->allocate_vertices( draw->render, - (ushort)feme->hw_vertex_size, + (ushort)feme->translate->key.output_stride, (ushort)fetch_count ); if (!hw_verts) { assert(0); @@ -260,10 +240,19 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, /* Single routine to fetch vertices and emit HW verts. */ - fetch_store_general( feme, - hw_verts, - fetch_elts, - fetch_count ); + feme->translate->run_elts( feme->translate, + fetch_elts, + fetch_count, + hw_verts ); + + if (0) { + unsigned i; + for (i = 0; i < fetch_count; i++) { + debug_printf("\n\nvertex %d:\n", i); + draw_dump_emitted_vertex( feme->vinfo, + (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i ); + } + } /* XXX: Draw arrays path to avoid re-emitting index list again and * again. @@ -276,12 +265,112 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, */ draw->render->release_vertices( draw->render, hw_verts, - feme->hw_vertex_size, + feme->translate->key.output_stride, fetch_count ); } +static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count ) +{ + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + struct draw_context *draw = feme->draw; + void *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)count ); + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices and emit HW verts. + */ + feme->translate->run( feme->translate, + start, + count, + hw_verts ); + + if (0) { + unsigned i; + for (i = 0; i < count; i++) { + debug_printf("\n\nvertex %d:\n", i); + draw_dump_emitted_vertex( feme->vinfo, + (const uint8_t *)hw_verts + feme->vinfo->size * 4 * i ); + } + } + + /* XXX: Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw_arrays( draw->render, + 0, /*start*/ + count ); + + /* Done -- that was easy, wasn't it: + */ + draw->render->release_vertices( draw->render, + hw_verts, + feme->translate->key.output_stride, + count ); + +} + + +static void fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle, + unsigned start, + unsigned count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + struct draw_context *draw = feme->draw; + void *hw_verts; + + /* XXX: need to flush to get prim_vbuf.c to release its allocation?? + */ + draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)count ); + if (!hw_verts) { + assert(0); + return; + } + + /* Single routine to fetch vertices and emit HW verts. + */ + feme->translate->run( feme->translate, + start, + count, + hw_verts ); + + /* XXX: Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw( draw->render, + draw_elts, + draw_count ); + + /* Done -- that was easy, wasn't it: + */ + draw->render->release_vertices( draw->render, + hw_verts, + feme->translate->key.output_stride, + count ); + +} + + + static void fetch_emit_finish( struct draw_pt_middle_end *middle ) { @@ -290,6 +379,11 @@ static void fetch_emit_finish( struct draw_pt_middle_end *middle ) static void fetch_emit_destroy( struct draw_pt_middle_end *middle ) { + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + + if (feme->cache) + translate_cache_destroy(feme->cache); + FREE(middle); } @@ -297,11 +391,21 @@ static void fetch_emit_destroy( struct draw_pt_middle_end *middle ) struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ) { struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end ); - - fetch_emit->base.prepare = fetch_emit_prepare; - fetch_emit->base.run = fetch_emit_run; - fetch_emit->base.finish = fetch_emit_finish; - fetch_emit->base.destroy = fetch_emit_destroy; + if (fetch_emit == NULL) + return NULL; + + fetch_emit->cache = translate_cache_create(); + if (!fetch_emit->cache) { + FREE(fetch_emit); + return NULL; + } + + fetch_emit->base.prepare = fetch_emit_prepare; + fetch_emit->base.run = fetch_emit_run; + fetch_emit->base.run_linear = fetch_emit_run_linear; + fetch_emit->base.run_linear_elts = fetch_emit_run_linear_elts; + fetch_emit->base.finish = fetch_emit_finish; + fetch_emit->base.destroy = fetch_emit_destroy; fetch_emit->draw = draw;