diff options
author | Ben Skeggs <[email protected]> | 2008-04-04 20:30:29 +1000 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2008-04-04 20:30:29 +1000 |
commit | e902d9091c048531cf76b1d9d034fb865b1a0f6e (patch) | |
tree | 6594c42173c215b9b17ac904a7d05a1568d53d31 /src/gallium | |
parent | bc67533f29abe578e2306be2a24db392a0c62fc4 (diff) | |
parent | 7a7bce7b24ea4f63faa1d5bfe3f71d09b412c838 (diff) |
Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/auxiliary/draw/Makefile | 1 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/SConscript | 1 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_private.h | 6 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.c | 26 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.h | 7 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_fetch_emit.c | 98 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c | 391 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_vcache.c | 17 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_vertex_fetch.c | 4 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_wide_point.c | 33 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/p_tile.c | 72 | ||||
-rw-r--r-- | src/gallium/drivers/cell/spu/spu_main.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/cell/spu/spu_main.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/cell/spu/spu_texture.c | 50 | ||||
-rw-r--r-- | src/gallium/include/pipe/p_state.h | 3 | ||||
-rw-r--r-- | src/gallium/winsys/xlib/SConscript | 2 |
16 files changed, 600 insertions, 116 deletions
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile index a0db2e4555e..b28e516396e 100644 --- a/src/gallium/auxiliary/draw/Makefile +++ b/src/gallium/auxiliary/draw/Makefile @@ -18,6 +18,7 @@ C_SOURCES = \ draw_pt.c \ draw_pt_vcache.c \ draw_pt_fetch_emit.c \ + draw_pt_fetch_pipeline.c \ draw_pt_elts.c \ draw_prim.c \ draw_pstipple.c \ diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript index 981225a8c2c..9ca41974412 100644 --- a/src/gallium/auxiliary/draw/SConscript +++ b/src/gallium/auxiliary/draw/SConscript @@ -17,6 +17,7 @@ draw = env.ConvenienceLibrary( 'draw_pt.c', 'draw_pt_vcache.c', 'draw_pt_fetch_emit.c', + 'draw_pt_fetch_pipeline.c', 'draw_pt_elts.c', 'draw_prim.c', 'draw_pstipple.c', diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 9a9b25297f1..0c9f9c2e036 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -160,6 +160,11 @@ struct draw_vertex_shader { /* Internal function for vertex fetch. */ typedef void (*fetch_func)(const void *ptr, float *attrib); + +fetch_func draw_get_fetch_func( enum pipe_format format ); + + + typedef void (*full_fetch_func)( struct draw_context *draw, struct tgsi_exec_machine *machine, const unsigned *elts, @@ -211,6 +216,7 @@ struct draw_context struct { struct draw_pt_middle_end *fetch_emit; + struct draw_pt_middle_end *fetch_pipeline; struct draw_pt_middle_end *fetch_shade_emit; struct draw_pt_middle_end *fetch_shade_cliptest_pipeline_or_emit; } middle; diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 2ea96c686da..f59fb86f781 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -73,7 +73,6 @@ draw_pt_arrays(struct draw_context *draw, */ -#if 0 if (!cliptest && !pipeline && !shading) { /* This is the 'passthrough' path: */ @@ -81,6 +80,14 @@ draw_pt_arrays(struct draw_context *draw, */ middle = draw->pt.middle.fetch_emit; } + else if (!cliptest && !shading) { + /* This is the 'passthrough' path targetting the pipeline backend. + */ + /* Fetch user verts, emit pipeline verts, run pipeline: + */ + middle = draw->pt.middle.fetch_pipeline; + } +#if 0 else if (!cliptest && !pipeline) { /* Fetch user verts, run vertex shader, emit hw verts: */ @@ -117,10 +124,9 @@ draw_pt_arrays(struct draw_context *draw, middle = draw->pt.middle.fetch_shade_cliptest_pipeline; } #else - if (cliptest || pipeline || shading) + else { return FALSE; - - middle = draw->pt.middle.fetch_emit; + } #endif @@ -171,10 +177,9 @@ draw_pt_arrays(struct draw_context *draw, */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); - frontend->prepare( frontend, middle ); + frontend->prepare( frontend, prim, middle ); frontend->run( frontend, - prim, draw_pt_elt_func( draw ), draw_pt_elt_ptr( draw, start ), count ); @@ -191,6 +196,10 @@ boolean draw_pt_init( struct draw_context *draw ) if (!draw->pt.middle.fetch_emit) return FALSE; + draw->pt.middle.fetch_pipeline = draw_pt_fetch_pipeline( draw ); + if (!draw->pt.middle.fetch_pipeline) + return FALSE; + draw->pt.front.vcache = draw_pt_vcache( draw ); if (!draw->pt.front.vcache) return FALSE; @@ -206,6 +215,11 @@ void draw_pt_destroy( struct draw_context *draw ) draw->pt.middle.fetch_emit = NULL; } + if (draw->pt.middle.fetch_pipeline) { + draw->pt.middle.fetch_pipeline->destroy( draw->pt.middle.fetch_pipeline ); + draw->pt.middle.fetch_pipeline = NULL; + } + if (draw->pt.front.vcache) { draw->pt.front.vcache->destroy( draw->pt.front.vcache ); draw->pt.front.vcache = NULL; diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index f8786160799..800072c5115 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -53,10 +53,10 @@ struct draw_context; */ struct draw_pt_front_end { void (*prepare)( struct draw_pt_front_end *, + unsigned prim, struct draw_pt_middle_end * ); void (*run)( struct draw_pt_front_end *, - unsigned prim, pt_elt_func elt_func, const void *elt_ptr, unsigned count ); @@ -79,10 +79,10 @@ struct draw_pt_front_end { * Currenly only using the passthrough version. */ struct draw_pt_middle_end { - void (*prepare)( struct draw_pt_middle_end * ); + void (*prepare)( struct draw_pt_middle_end *, + unsigned prim ); void (*run)( struct draw_pt_middle_end *, - unsigned prim, const unsigned *fetch_elts, unsigned fetch_count, const ushort *draw_elts, @@ -112,6 +112,7 @@ const void *draw_pt_elt_ptr( struct draw_context *draw, */ struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw ); struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ); +struct draw_pt_middle_end *draw_pt_fetch_pipeline( struct draw_context *draw ); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index 9b098bc173f..39f0b40838f 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -85,45 +85,6 @@ struct fetch_emit_middle_end { }; -static void fetch_B8G8R8A8_UNORM( const void *from, - float *attrib ) -{ - ubyte *ub = (ubyte *) from; - attrib[2] = UBYTE_TO_FLOAT(ub[0]); - attrib[1] = UBYTE_TO_FLOAT(ub[1]); - attrib[0] = UBYTE_TO_FLOAT(ub[2]); - attrib[3] = UBYTE_TO_FLOAT(ub[3]); -} - -static void fetch_R32G32B32A32_FLOAT( const void *from, - float *attrib ) -{ - float *f = (float *) from; - attrib[0] = f[0]; - attrib[1] = f[1]; - attrib[2] = f[2]; - attrib[3] = f[3]; -} - -static void fetch_R32G32B32_FLOAT( const void *from, - float *attrib ) -{ - float *f = (float *) from; - attrib[0] = f[0]; - attrib[1] = f[1]; - attrib[2] = f[2]; - attrib[3] = 1.0; -} - -static void fetch_R32G32_FLOAT( const void *from, - float *attrib ) -{ - float *f = (float *) from; - attrib[0] = f[0]; - attrib[1] = f[1]; - attrib[2] = 0.0; - attrib[3] = 1.0; -} static void fetch_R32_FLOAT( const void *from, float *attrib ) @@ -203,16 +164,29 @@ fetch_store_general( struct fetch_emit_middle_end *feme, -static void fetch_emit_prepare( struct draw_pt_middle_end *middle ) +static void fetch_emit_prepare( struct draw_pt_middle_end *middle, + unsigned prim ) { 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 = draw->render->get_vertex_info(draw->render); - unsigned nr_attrs = vinfo->num_attribs; + const struct vertex_info *vinfo; unsigned i; + boolean ok; + + + ok = draw->render->set_primitive( draw->render, + prim ); + if (!ok) { + assert(0); + return; + } + + /* Must do this after set_primitive() above: + */ + vinfo = draw->render->get_vertex_info(draw->render); - for (i = 0; i < nr_attrs; i++) { + 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; @@ -222,28 +196,9 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle ) feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch; - switch (draw->vertex_element[src_element].src_format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - feme->fetch[i].fetch = fetch_B8G8R8A8_UNORM; - break; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - feme->fetch[i].fetch = fetch_R32G32B32A32_FLOAT; - break; - case PIPE_FORMAT_R32G32B32_FLOAT: - feme->fetch[i].fetch = fetch_R32G32B32_FLOAT; - break; - case PIPE_FORMAT_R32G32_FLOAT: - feme->fetch[i].fetch = fetch_R32G32_FLOAT; - break; - case PIPE_FORMAT_R32_FLOAT: - feme->fetch[i].fetch = fetch_R32_FLOAT; - break; - default: - assert(0); - feme->fetch[i].fetch = NULL; - break; - } - + feme->fetch[i].fetch = draw_get_fetch_func(draw->vertex_element[src_element].src_format); + + switch (vinfo->emit[i]) { case EMIT_4F: feme->fetch[i].emit = emit_R32G32B32A32_FLOAT; @@ -268,6 +223,7 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle ) feme->fetch[i].pitch = 0; feme->fetch[i].fetch = fetch_R32_FLOAT; feme->fetch[i].emit = emit_R32_FLOAT; + break; default: assert(0); feme->fetch[i].emit = NULL; @@ -275,7 +231,7 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle ) } } - feme->nr_fetch = nr_attrs; + feme->nr_fetch = vinfo->num_attribs; feme->hw_vertex_size = vinfo->size * 4; } @@ -284,7 +240,6 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle ) static void fetch_emit_run( struct draw_pt_middle_end *middle, - unsigned prim, const unsigned *fetch_elts, unsigned fetch_count, const ushort *draw_elts, @@ -293,16 +248,7 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; void *hw_verts; - boolean ok; - ok = draw->render->set_primitive( draw->render, - prim ); - if (!ok) { - assert(0); - return; - } - - hw_verts = draw->render->allocate_vertices( draw->render, (ushort)feme->hw_vertex_size, (ushort)fetch_count ); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c new file mode 100644 index 00000000000..94e7d01be4b --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c @@ -0,0 +1,391 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_vertex.h" +#include "draw/draw_pt.h" + +/* The simplest 'middle end' in the new vertex code. + * + * The responsibilities of a middle end are to: + * - perform vertex fetch using + * - draw vertex element/buffer state + * - a list of fetch indices we received as an input + * - run the vertex shader + * - cliptest, + * - clip coord calculation + * - viewport transformation + * - if necessary, run the primitive pipeline, passing it: + * - a linear array of vertex_header vertices constructed here + * - a set of draw indices we received as an input + * - otherwise, drive the hw backend, + * - allocate space for hardware format vertices + * - translate the vertex-shader output vertices to hw format + * - calling the backend draw functions. + * + * For convenience, we provide a helper function to drive the hardware + * backend given similar inputs to those required to run the pipeline. + * + * In the case of passthrough mode, many of these actions are disabled + * or noops, so we end up doing: + * + * - perform vertex fetch + * - drive the hw backend + * + * IE, basically just vertex fetch to post-vs-format vertices, + * followed by a call to the backend helper function. + */ + + +struct fetch_pipeline_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 pipeline_vertex_size; + unsigned prim; +}; + + +static void fetch_NULL( const void *from, + float *attrib ) +{ +} + + + +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; +} + +static void emit_header( const float *attrib, + float **out ) +{ + (*out)[0] = 0; + (*out)[1] = 0; + (*out)[2] = 0; + (*out)[3] = 0; + (*out)[3] = 1; + (*out) += 5; +} + +/** + * 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_pipeline_middle_end *fpme, + void *out_ptr, + const unsigned *fetch_elts, + unsigned count ) +{ + float *out = (float *)out_ptr; + uint i, j; + + for (i = 0; i < count; i++) { + unsigned elt = fetch_elts[i]; + + for (j = 0; j < fpme->nr_fetch; j++) { + float attrib[4]; + const ubyte *from = (fpme->fetch[j].ptr + + fpme->fetch[j].pitch * elt); + + fpme->fetch[j].fetch( from, attrib ); + fpme->fetch[j].emit( attrib, &out ); + } + } +} + + +/* We aren't running a vertex shader, but are running the pipeline. + * That means the vertices we need to build look like: + * + * dw0: vertex header (zero?) + * dw1: clip coord 0 + * dw2: clip coord 1 + * dw3: clip coord 2 + * dw4: clip coord 4 + * dw5: screen coord 0 + * dw6: screen coord 0 + * dw7: screen coord 0 + * dw8: screen coord 0 + * dw9: other attribs... + * + */ +static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle, + unsigned prim ) +{ + static const float zero = 0; + struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; + struct draw_context *draw = fpme->draw; + unsigned i, nr = 0; + + fpme->prim = prim; + + /* Emit the vertex header and empty clipspace coord field: + */ + { + fpme->fetch[nr].ptr = NULL; + fpme->fetch[nr].pitch = 0; + fpme->fetch[nr].fetch = fetch_NULL; + fpme->fetch[nr].emit = emit_header; + nr++; + } + + + /* Need to look at vertex shader inputs (we know it is a + * passthrough shader, so these define the outputs too). If we + * were running a shader, we'd still be looking at the inputs at + * this point. + */ + for (i = 0; i < draw->vertex_shader->info.num_inputs; i++) { + unsigned buf = draw->vertex_element[i].vertex_buffer_index; + enum pipe_format format = draw->vertex_element[i].src_format; + + fpme->fetch[nr].ptr = ((const ubyte *) draw->user.vbuffer[buf] + + draw->vertex_buffer[buf].buffer_offset + + draw->vertex_element[i].src_offset); + + fpme->fetch[nr].pitch = draw->vertex_buffer[buf].pitch; + fpme->fetch[nr].fetch = draw_get_fetch_func( format ); + + /* Always do this -- somewhat redundant... + */ + fpme->fetch[nr].emit = emit_R32G32B32A32_FLOAT; + nr++; + } + + fpme->nr_fetch = nr; + fpme->pipeline_vertex_size = (5 + (nr-1) * 4) * sizeof(float); +} + + + +/** + * Add a point to the primitive queue. + * \param i0 index into user's vertex arrays + */ +static void do_point( struct draw_context *draw, + const char *v0 ) +{ + struct prim_header prim; + + prim.reset_line_stipple = 0; + prim.edgeflags = 1; + prim.pad = 0; + prim.v[0] = (struct vertex_header *)v0; + + draw->pipeline.first->point( draw->pipeline.first, &prim ); +} + + +/** + * Add a line to the primitive queue. + * \param i0 index into user's vertex arrays + * \param i1 index into user's vertex arrays + */ +static void do_line( struct draw_context *draw, + const char *v0, + const char *v1 ) +{ + struct prim_header prim; + + prim.reset_line_stipple = 1; /* fixme */ + prim.edgeflags = 1; + prim.pad = 0; + prim.v[0] = (struct vertex_header *)v0; + prim.v[1] = (struct vertex_header *)v1; + + draw->pipeline.first->line( draw->pipeline.first, &prim ); +} + +/** + * Add a triangle to the primitive queue. + */ +static void do_triangle( struct draw_context *draw, + char *v0, + char *v1, + char *v2 ) +{ + struct prim_header prim; + +// _mesa_printf("tri %d %d %d\n", i0, i1, i2); + prim.reset_line_stipple = 1; + prim.edgeflags = ~0; + prim.pad = 0; + prim.v[0] = (struct vertex_header *)v0; + prim.v[1] = (struct vertex_header *)v1; + prim.v[2] = (struct vertex_header *)v2; + + draw->pipeline.first->tri( draw->pipeline.first, &prim ); +} + + +static void run_pipeline( struct fetch_pipeline_middle_end *fpme, + char *verts, + const ushort *elts, + unsigned count ) +{ + struct draw_context *draw = fpme->draw; + unsigned stride = fpme->pipeline_vertex_size; + unsigned i; + + switch (fpme->prim) { + case PIPE_PRIM_POINTS: + for (i = 0; i < count; i++) + do_point( draw, + verts + stride * elts[i] ); + break; + case PIPE_PRIM_LINES: + for (i = 0; i+1 < count; i += 2) + do_line( draw, + verts + stride * elts[i+0], + verts + stride * elts[i+1]); + break; + case PIPE_PRIM_TRIANGLES: + for (i = 0; i+2 < count; i += 3) + do_triangle( draw, + verts + stride * elts[i+0], + verts + stride * elts[i+1], + verts + stride * elts[i+2]); + break; + } +} + + + + +static void fetch_pipeline_run( struct draw_pt_middle_end *middle, + const unsigned *fetch_elts, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle; + struct draw_context *draw = fpme->draw; + char *pipeline_verts; + + pipeline_verts = MALLOC( fpme->pipeline_vertex_size * + fetch_count ); + if (!pipeline_verts) { + assert(0); + return; + } + + + /* Single routine to fetch vertices and emit pipeline verts. + */ + fetch_store_general( fpme, + pipeline_verts, + fetch_elts, + fetch_count ); + + + run_pipeline( fpme, + pipeline_verts, + draw_elts, + draw_count ); + + + /* Done -- that was easy, wasn't it: + */ + FREE( pipeline_verts ); +} + + + +static void fetch_pipeline_finish( struct draw_pt_middle_end *middle ) +{ + /* nothing to do */ +} + +static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle ) +{ + FREE(middle); +} + + +struct draw_pt_middle_end *draw_pt_fetch_pipeline( struct draw_context *draw ) +{ + struct fetch_pipeline_middle_end *fetch_pipeline = CALLOC_STRUCT( fetch_pipeline_middle_end ); + + fetch_pipeline->base.prepare = fetch_pipeline_prepare; + fetch_pipeline->base.run = fetch_pipeline_run; + fetch_pipeline->base.finish = fetch_pipeline_finish; + fetch_pipeline->base.destroy = fetch_pipeline_destroy; + + fetch_pipeline->draw = draw; + + return &fetch_pipeline->base; +} + diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index 16ffedf580c..5a068761df9 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -59,6 +59,8 @@ struct vcache_frontend { const void *elt_ptr; struct draw_pt_middle_end *middle; + + unsigned input_prim; unsigned output_prim; }; @@ -77,7 +79,6 @@ static void vcache_flush( struct vcache_frontend *vcache ) if (vcache->draw_count) { vcache->middle->run( vcache->middle, - vcache->output_prim, vcache->fetch_elts, vcache->fetch_count, vcache->draw_elts, @@ -173,7 +174,6 @@ static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { static void vcache_run_pv2( struct draw_pt_front_end *frontend, - unsigned prim, pt_elt_func get_elt, const void *elts, unsigned count ) @@ -185,9 +185,8 @@ static void vcache_run_pv2( struct draw_pt_front_end *frontend, */ vcache->elt_func = get_elt; vcache->elt_ptr = elts; - vcache->output_prim = reduced_prim[prim]; - switch (prim) { + switch (vcache->input_prim) { case PIPE_PRIM_POINTS: for (i = 0; i < count; i ++) { vcache_point( vcache, @@ -304,7 +303,6 @@ static void vcache_run_pv2( struct draw_pt_front_end *frontend, static void vcache_run_pv0( struct draw_pt_front_end *frontend, - unsigned prim, pt_elt_func get_elt, const void *elts, unsigned count ) @@ -316,9 +314,8 @@ static void vcache_run_pv0( struct draw_pt_front_end *frontend, */ vcache->elt_func = get_elt; vcache->elt_ptr = elts; - vcache->output_prim = reduced_prim[prim]; - switch (prim) { + switch (vcache->input_prim) { case PIPE_PRIM_POINTS: for (i = 0; i < count; i ++) { vcache_point( vcache, @@ -389,6 +386,7 @@ static void vcache_run_pv0( struct draw_pt_front_end *frontend, } static void vcache_prepare( struct draw_pt_front_end *frontend, + unsigned prim, struct draw_pt_middle_end *middle ) { struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; @@ -398,8 +396,11 @@ static void vcache_prepare( struct draw_pt_front_end *frontend, else vcache->base.run = vcache_run_pv2; + vcache->input_prim = prim; + vcache->output_prim = reduced_prim[prim]; + vcache->middle = middle; - middle->prepare( middle ); + middle->prepare( middle, vcache->output_prim ); } diff --git a/src/gallium/auxiliary/draw/draw_vertex_fetch.c b/src/gallium/auxiliary/draw/draw_vertex_fetch.c index 11f99babf65..9041041006e 100644 --- a/src/gallium/auxiliary/draw/draw_vertex_fetch.c +++ b/src/gallium/auxiliary/draw/draw_vertex_fetch.c @@ -166,7 +166,7 @@ fetch_B8G8R8A8_UNORM(const void *ptr, float *attrib) } -static fetch_func get_fetch_func( enum pipe_format format ) +fetch_func draw_get_fetch_func( enum pipe_format format ) { #if 0 { @@ -502,7 +502,7 @@ void draw_update_vertex_fetch( struct draw_context *draw ) draw->vertex_element[i].src_offset; draw->vertex_fetch.pitch[i] = draw->vertex_buffer[buf].pitch; - draw->vertex_fetch.fetch[i] = get_fetch_func( format ); + draw->vertex_fetch.fetch[i] = draw_get_fetch_func( format ); } draw->vertex_fetch.nr_attrs = nr_attrs; diff --git a/src/gallium/auxiliary/draw/draw_wide_point.c b/src/gallium/auxiliary/draw/draw_wide_point.c index c53f7e6cb37..6fc7c9fcd7a 100644 --- a/src/gallium/auxiliary/draw/draw_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_wide_point.c @@ -38,6 +38,11 @@ struct widepoint_stage { struct draw_stage stage; float half_point_size; + float point_size_min; + float point_size_max; + + float xbias; + float ybias; uint texcoord_slot[PIPE_MAX_SHADER_OUTPUTS]; uint texcoord_mode[PIPE_MAX_SHADER_OUTPUTS]; @@ -124,20 +129,26 @@ static void widepoint_point( struct draw_stage *stage, float *pos2 = v2->data[0]; float *pos3 = v3->data[0]; - const float xbias = 0.0, ybias = -0.125; - /* point size is either per-vertex or fixed size */ if (wide->psize_slot >= 0) { - half_size = 0.5f * header->v[0]->data[wide->psize_slot][0]; + half_size = header->v[0]->data[wide->psize_slot][0]; + + /* XXX: temporary -- do this in the vertex shader?? + */ + half_size = CLAMP(half_size, + wide->point_size_min, + wide->point_size_max); + + half_size *= 0.5f; } else { half_size = wide->half_point_size; } - left_adj = -half_size + xbias; - right_adj = half_size + xbias; - bot_adj = half_size + ybias; - top_adj = -half_size + ybias; + left_adj = -half_size + wide->xbias; + right_adj = half_size + wide->xbias; + bot_adj = half_size + wide->ybias; + top_adj = -half_size + wide->ybias; pos0[0] += left_adj; pos0[1] += top_adj; @@ -182,6 +193,14 @@ static void widepoint_first_point( struct draw_stage *stage, struct draw_context *draw = stage->draw; wide->half_point_size = 0.5f * draw->rasterizer->point_size; + wide->point_size_min = draw->rasterizer->point_size_min; + wide->point_size_max = draw->rasterizer->point_size_max; + wide->xbias = 0.0; + wide->ybias = 0.0; + + if (draw->rasterizer->gl_rasterization_rules) { + wide->ybias = -0.125; + } /* XXX we won't know the real size if it's computed by the vertex shader! */ if ((draw->rasterizer->point_size > draw->wide_point_threshold) || diff --git a/src/gallium/auxiliary/util/p_tile.c b/src/gallium/auxiliary/util/p_tile.c index 287d7839812..520da5cecd5 100644 --- a/src/gallium/auxiliary/util/p_tile.c +++ b/src/gallium/auxiliary/util/p_tile.c @@ -560,6 +560,70 @@ z24s8_get_tile_rgba(unsigned *src, } +/*** PIPE_FORMAT_YCBCR / PIPE_FORMAT_YCBCR_REV ***/ + +/** + * Convert YCbCr (or YCrCb) to RGBA. + */ +static void +ycbcr_get_tile_rgba(ushort *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride, + boolean rev) +{ + const float scale = 1.0f / 255.0f; + unsigned i, j; + + /* we're assuming we're being asked for an even number of texels */ + assert((w & 1) == 0); + + for (i = 0; i < h; i++) { + float *pRow = p; + /* do two texels at a time */ + for (j = 0; j < w; j += 2, src += 2) { + const ushort t0 = src[0]; + const ushort t1 = src[1]; + const ubyte y0 = (t0 >> 8) & 0xff; /* luminance */ + const ubyte y1 = (t1 >> 8) & 0xff; /* luminance */ + ubyte cb, cr; + float r, g, b; + + if (rev) { + cb = t1 & 0xff; /* chroma U */ + cr = t0 & 0xff; /* chroma V */ + } + else { + cb = t0 & 0xff; /* chroma U */ + cr = t1 & 0xff; /* chroma V */ + } + + /* even pixel: y0,cr,cb */ + r = 1.164f * (y0-16) + 1.596f * (cr-128); + g = 1.164f * (y0-16) - 0.813f * (cr-128) - 0.391f * (cb-128); + b = 1.164f * (y0-16) + 2.018f * (cb-128); + pRow[0] = r * scale; + pRow[1] = g * scale; + pRow[2] = b * scale; + pRow[3] = 1.0f; + pRow += 4; + + /* odd pixel: use y1,cr,cb */ + r = 1.164f * (y1-16) + 1.596f * (cr-128); + g = 1.164f * (y1-16) - 0.813f * (cr-128) - 0.391f * (cb-128); + b = 1.164f * (y1-16) + 2.018f * (cb-128); + pRow[0] = r * scale; + pRow[1] = g * scale; + pRow[2] = b * scale; + pRow[3] = 1.0f; + pRow += 4; + + } + p += dst_stride; + } +} + + void pipe_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps, @@ -622,6 +686,14 @@ pipe_get_tile_rgba(struct pipe_context *pipe, case PIPE_FORMAT_Z24S8_UNORM: z24s8_get_tile_rgba((unsigned *) packed, w, h, p, dst_stride); break; + case PIPE_FORMAT_YCBCR: + assert((x & 1) == 0); + ycbcr_get_tile_rgba((ushort *) packed, w, h, p, dst_stride, FALSE); + break; + case PIPE_FORMAT_YCBCR_REV: + assert((x & 1) == 0); + ycbcr_get_tile_rgba((ushort *) packed, w, h, p, dst_stride, TRUE); + break; default: assert(0); } diff --git a/src/gallium/drivers/cell/spu/spu_main.c b/src/gallium/drivers/cell/spu/spu_main.c index 1ab1c40379a..e04ffeb9b16 100644 --- a/src/gallium/drivers/cell/spu/spu_main.c +++ b/src/gallium/drivers/cell/spu/spu_main.c @@ -343,6 +343,8 @@ cmd_state_texture(const struct cell_command_texture *texture) spu.texture[unit].width = width; spu.texture[unit].height = height; + spu.texture[unit].tiles_per_row = width / TILE_SIZE; + spu.texture[unit].tex_size = (vector float) { width, height, 0.0, 0.0}; spu.texture[unit].tex_size_mask = (vector unsigned int) { width - 1, height - 1, 0, 0 }; diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h index e9e39cbeab3..e962e1426c6 100644 --- a/src/gallium/drivers/cell/spu/spu_main.h +++ b/src/gallium/drivers/cell/spu/spu_main.h @@ -105,7 +105,8 @@ struct spu_framebuffer { struct spu_texture { void *start; - uint width, height; + ushort width, height; + ushort tiles_per_row; vector float tex_size; vector unsigned int tex_size_mask; /**< == int(size - 1) */ vector unsigned int tex_size_x_mask; /**< == int(size - 1) */ diff --git a/src/gallium/drivers/cell/spu/spu_texture.c b/src/gallium/drivers/cell/spu/spu_texture.c index ceab2469803..5051774f00c 100644 --- a/src/gallium/drivers/cell/spu/spu_texture.c +++ b/src/gallium/drivers/cell/spu/spu_texture.c @@ -48,25 +48,45 @@ invalidate_tex_cache(void) } +/** + * XXX look into getting texels for all four pixels in a quad at once. + */ static uint get_texel(uint unit, vec_uint4 coordinate) { + /* + * XXX we could do the "/ TILE_SIZE" and "% TILE_SIZE" operations as + * SIMD since X and Y are already in a SIMD register. + */ + const unsigned texture_ea = (uintptr_t) spu.texture[unit].start; + ushort x = spu_extract(coordinate, 0); + ushort y = spu_extract(coordinate, 1); + unsigned tile_offset = sizeof(tile_t) + * ((y / TILE_SIZE * spu.texture[unit].tiles_per_row) + (x / TILE_SIZE)); + ushort texel_offset = (ushort) 4 + * (ushort) (((ushort) (y % TILE_SIZE) * (ushort) TILE_SIZE) + (x % TILE_SIZE)); vec_uint4 tmp; - unsigned x = spu_extract(coordinate, 0); - unsigned y = spu_extract(coordinate, 1); - const unsigned tiles_per_row = spu.texture[unit].width / TILE_SIZE; - unsigned tile_offset = sizeof(tile_t) * ((y / TILE_SIZE * tiles_per_row) - + (x / TILE_SIZE)); - unsigned texel_offset = 4 * (((y % TILE_SIZE) * TILE_SIZE) - + (x % TILE_SIZE)); spu_dcache_fetch_unaligned((qword *) & tmp, - spu.texture[unit].start + tile_offset + texel_offset, + texture_ea + tile_offset + texel_offset, 4); return spu_extract(tmp, 0); } +/** + * Get four texels from locations (x[0], y[0]), (x[1], y[1]) ... + * + * NOTE: in the typical case of bilinear filtering, the four texels + * are in a 2x2 group so we could get by with just two dcache fetches + * (two side-by-side texels per fetch). But when bilinear filtering + * wraps around a texture edge, we'll probably need code like we have + * now. + * FURTHERMORE: since we're rasterizing a quad of 2x2 pixels at a time, + * it's quite likely that the four pixels in a quad will need some of the + * same texels. So look into doing texture fetches for four pixels at + * a time. + */ static void get_four_texels(uint unit, vec_uint4 x, vec_uint4 y, vec_uint4 *texels) { @@ -76,7 +96,7 @@ get_four_texels(uint unit, vec_uint4 x, vec_uint4 y, vec_uint4 *texels) const qword offset_x = si_andi((qword) x, 0x1f); const qword offset_y = si_andi((qword) y, 0x1f); - const qword tiles_per_row = (qword) spu_splats(spu.texture[unit].width / TILE_SIZE); + const qword tiles_per_row = (qword) spu_splats(spu.texture[unit].tiles_per_row); const qword tile_size = (qword) spu_splats(sizeof(tile_t)); qword tile_offset = si_mpya((qword) tile_y, tiles_per_row, (qword) tile_x); @@ -97,9 +117,9 @@ get_four_texels(uint unit, vec_uint4 x, vec_uint4 y, vec_uint4 *texels) texture_ea + spu_extract(offset, 3), 4); } + /** * Get texture sample at texcoord. - * XXX this is extremely primitive for now. */ vector float sample_texture_nearest(uint unit, vector float texcoord) @@ -126,17 +146,25 @@ sample_texture_bilinear(uint unit, vector float texcoord) vec_uint4 texels[4]; + /* setup texcoords for quad: + * +-----+-----+ + * |x0,y0|x1,y1| + * +-----+-----+ + * |x2,y2|x3,y3| + * +-----+-----+ + */ vec_uint4 x = spu_splats(spu_extract(itc, 0)); vec_uint4 y = spu_splats(spu_extract(itc, 1)); - x = spu_add(x, offset_x); y = spu_add(y, offset_y); + /* GL_REPEAT wrap mode: */ x = spu_and(x, spu.texture[unit].tex_size_x_mask); y = spu_and(y, spu.texture[unit].tex_size_y_mask); get_four_texels(unit, x, y, texels); + /* integer A8R8G8B8 to float texel conversion */ vector float texel00 = spu_unpack_A8R8G8B8(spu_extract(texels[0], 0)); vector float texel01 = spu_unpack_A8R8G8B8(spu_extract(texels[1], 0)); vector float texel10 = spu_unpack_A8R8G8B8(spu_extract(texels[2], 0)); diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index a73028814e3..3593446e1c4 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -115,9 +115,12 @@ struct pipe_rasterizer_state still needed though, to indicate inputs/outputs */ unsigned origin_lower_left:1; /**< Is (0,0) the lower-left corner? */ unsigned flatshade_first:1; /**< take color attribute from the first vertex of a primitive */ + unsigned gl_rasterization_rules:1; /**< enable tweaks for GL rasterization? */ float line_width; float point_size; /**< used when no per-vertex size */ + float point_size_min; /* XXX - temporary, will go away */ + float point_size_max; /* XXX - temporary, will go away */ float offset_units; float offset_scale; ubyte sprite_coord_mode[PIPE_MAX_SHADER_OUTPUTS]; /**< PIPE_SPRITE_COORD_ */ diff --git a/src/gallium/winsys/xlib/SConscript b/src/gallium/winsys/xlib/SConscript index c38b5be52c8..218b89285f7 100644 --- a/src/gallium/winsys/xlib/SConscript +++ b/src/gallium/winsys/xlib/SConscript @@ -22,8 +22,6 @@ sources = [ drivers = [ softpipe, - i915simple, - i965simple, ] # TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions |