summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2008-04-04 20:30:29 +1000
committerBen Skeggs <[email protected]>2008-04-04 20:30:29 +1000
commite902d9091c048531cf76b1d9d034fb865b1a0f6e (patch)
tree6594c42173c215b9b17ac904a7d05a1568d53d31 /src/gallium
parentbc67533f29abe578e2306be2a24db392a0c62fc4 (diff)
parent7a7bce7b24ea4f63faa1d5bfe3f71d09b412c838 (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/Makefile1
-rw-r--r--src/gallium/auxiliary/draw/SConscript1
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c26
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h7
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c98
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c391
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c17
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex_fetch.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_wide_point.c33
-rw-r--r--src/gallium/auxiliary/util/p_tile.c72
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.c2
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.h3
-rw-r--r--src/gallium/drivers/cell/spu/spu_texture.c50
-rw-r--r--src/gallium/include/pipe/p_state.h3
-rw-r--r--src/gallium/winsys/xlib/SConscript2
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