summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r--src/gallium/auxiliary/draw/Makefile1
-rw-r--r--src/gallium/auxiliary/draw/SConscript1
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c13
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h29
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c65
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c12
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c6
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c243
-rw-r--r--src/gallium/auxiliary/draw/draw_vbuf.c20
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex.c5
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex.h2
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex_cache.c37
-rw-r--r--src/gallium/auxiliary/draw/draw_vertex_shader.c22
-rw-r--r--src/gallium/auxiliary/draw/draw_vf.c56
-rw-r--r--src/gallium/auxiliary/draw/draw_vf.h4
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h33
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_exec.c181
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c48
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_sse.c193
-rw-r--r--src/gallium/auxiliary/pipebuffer/Makefile2
-rw-r--r--src/gallium/auxiliary/pipebuffer/SConscript2
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c81
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr.h27
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c299
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c429
-rw-r--r--src/gallium/auxiliary/rtasm/rtasm_x86sse.c2
-rwxr-xr-xsrc/gallium/auxiliary/tgsi/exec/tgsi_sse2.c291
-rwxr-xr-xsrc/gallium/auxiliary/tgsi/exec/tgsi_sse2.h9
-rw-r--r--src/gallium/auxiliary/tgsi/util/tgsi_dump.c88
-rw-r--r--src/gallium/auxiliary/util/Makefile4
-rw-r--r--src/gallium/auxiliary/util/SConscript1
-rw-r--r--src/gallium/auxiliary/util/p_debug.c7
-rw-r--r--src/gallium/auxiliary/util/p_debug_mem.c71
-rw-r--r--src/gallium/auxiliary/util/u_double_list.h8
-rw-r--r--src/gallium/auxiliary/util/u_snprintf.c16
-rw-r--r--src/gallium/auxiliary/util/u_string.h63
-rw-r--r--src/gallium/auxiliary/util/u_time.c152
-rw-r--r--src/gallium/auxiliary/util/u_time.h99
39 files changed, 2034 insertions, 590 deletions
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
index 28262a92c6..5ab3cfe5ce 100644
--- a/src/gallium/auxiliary/draw/Makefile
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -19,6 +19,7 @@ C_SOURCES = \
draw_pt_vcache.c \
draw_pt_fetch_emit.c \
draw_pt_fetch_pipeline.c \
+ draw_pt_fetch_shade_pipeline.c \
draw_pt_pipeline.c \
draw_pt_elts.c \
draw_prim.c \
diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript
index 52107912f5..a7fb5dbd61 100644
--- a/src/gallium/auxiliary/draw/SConscript
+++ b/src/gallium/auxiliary/draw/SConscript
@@ -18,6 +18,7 @@ draw = env.ConvenienceLibrary(
'draw_pt_vcache.c',
'draw_pt_fetch_emit.c',
'draw_pt_fetch_pipeline.c',
+ 'draw_pt_fetch_shade_pipeline.c',
'draw_pt_pipeline.c',
'draw_pt_elts.c',
'draw_prim.c',
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index b3c65c90d6..0c314f6e1d 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -49,6 +49,8 @@ struct draw_context *draw_create( void )
draw->use_sse = FALSE;
#endif
+ draw->use_pt_shaders = GETENV( "GALLIUM_PT_SHADERS" ) != NULL;
+
/* create pipeline stages */
draw->pipeline.wide_line = draw_wide_line_stage( draw );
draw->pipeline.wide_point = draw_wide_point_stage( draw );
@@ -86,14 +88,11 @@ struct draw_context *draw_create( void )
/* Statically allocate maximum sized vertices for the cache - could be cleverer...
*/
{
- uint i;
- const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
- char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16);
+ char *tmp = align_malloc(VS_QUEUE_LENGTH * MAX_VERTEX_ALLOCATION, 16);
if (!tmp)
goto fail;
- for (i = 0; i < Elements(draw->vs.queue); i++)
- draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size);
+ draw->vs.vertex_cache = tmp;
}
draw->shader_queue_flush = draw_vertex_shader_queue_flush;
@@ -156,8 +155,8 @@ void draw_destroy( struct draw_context *draw )
tgsi_exec_machine_free_data(&draw->machine);
- if (draw->vs.queue[0].vertex)
- align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
+ if (draw->vs.vertex_cache)
+ align_free( draw->vs.vertex_cache ); /* Frees all the vertices. */
/* Not so fast -- we're just borrowing this at the moment.
*
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 4d056f6dba..c8cb96c8ba 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -56,6 +56,8 @@ struct gallivm_cpu_engine;
struct draw_pt_middle_end;
struct draw_pt_front_end;
+#define MAX_SHADER_VERTICES 128
+
/**
* Basic vertex info.
* Carry some useful information around with the vertices in the prim pipe.
@@ -76,6 +78,7 @@ struct vertex_header {
/* XXX This is too large */
#define MAX_VERTEX_SIZE ((2 + PIPE_MAX_SHADER_OUTPUTS) * 4 * sizeof(float))
+#define MAX_VERTEX_ALLOCATION ((MAX_VERTEX_SIZE + 0x0f) & ~0x0f)
@@ -146,12 +149,13 @@ struct draw_vertex_shader {
/* Run the shader - this interface will get cleaned up in the
* future:
*/
- void (*run)( struct draw_vertex_shader *shader,
- struct draw_context *draw,
- const unsigned *elts,
- unsigned count,
- struct vertex_header *vOut[] );
-
+ boolean (*run)( struct draw_vertex_shader *shader,
+ struct draw_context *draw,
+ const unsigned *elts,
+ unsigned count,
+ void *out,
+ unsigned vertex_size);
+
void (*delete)( struct draw_vertex_shader * );
};
@@ -274,6 +278,7 @@ struct draw_context
boolean line_stipple; /**< do line stipple? */
boolean point_sprite; /**< convert points to quads for sprites? */
boolean use_sse;
+ boolean use_pt_shaders; /* temporary flag to switch on pt shader paths */
/* If a prim stage introduces new vertex attributes, they'll be stored here
*/
@@ -319,10 +324,8 @@ struct draw_context
/* Vertex shader queue:
*/
struct {
- struct {
- unsigned elt; /**< index into the user's vertex arrays */
- struct vertex_header *vertex;
- } queue[VS_QUEUE_LENGTH];
+ unsigned elts[VS_QUEUE_LENGTH]; /**< index into the user's vertex arrays */
+ char *vertex_cache;
unsigned queue_nr;
unsigned post_nr;
} vs;
@@ -448,4 +451,10 @@ dot4(const float *a, const float *b)
return result;
}
+static INLINE struct vertex_header *
+draw_header_from_block(char *block, int size, int num)
+{
+ return (struct vertex_header*)(block + num * size);
+}
+
#endif /* DRAW_PRIVATE_H */
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index f59fb86f78..3d2e7bf7b8 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -36,21 +36,25 @@
#include "draw/draw_pt.h"
-/* XXX: Shouldn't those two functions below use the '>' operator???
- */
-
-static boolean too_many_verts( struct draw_context *draw,
- unsigned verts )
+#if 0
+static boolean too_many_elts( struct draw_context *draw,
+ unsigned elts )
{
- return verts < 1024;
+ return elts > (8 * 1024);
}
+#endif
-static boolean too_many_elts( struct draw_context *draw,
- unsigned elts )
+static INLINE unsigned reduced_prim(unsigned prim)
{
- return elts < (16 * 1024);
+ /*FIXME*/
+ return prim;
}
+static INLINE boolean good_prim(unsigned prim)
+{
+ /*FIXME*/
+ return FALSE;
+}
boolean
draw_pt_arrays(struct draw_context *draw,
@@ -64,6 +68,9 @@ draw_pt_arrays(struct draw_context *draw,
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
+ if (!draw->render)
+ return FALSE;
+ /*debug_printf("XXXXXXXXXX needs_pipeline = %d\n", pipeline);*/
/* Overall we do:
* - frontend -- prepare fetch_elts, draw_elts - eg vcache
@@ -72,6 +79,9 @@ draw_pt_arrays(struct draw_context *draw,
* - backend -- the vbuf_render provided by the driver.
*/
+ if (shading && !draw->use_pt_shaders)
+ return FALSE;
+
if (!cliptest && !pipeline && !shading) {
/* This is the 'passthrough' path:
@@ -87,7 +97,6 @@ draw_pt_arrays(struct draw_context *draw,
*/
middle = draw->pt.middle.fetch_pipeline;
}
-#if 0
else if (!cliptest && !pipeline) {
/* Fetch user verts, run vertex shader, emit hw verts:
*/
@@ -111,23 +120,15 @@ draw_pt_arrays(struct draw_context *draw,
*/
middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
}
- else if (!cliptest) {
- /* Fetch user verts, run vertex shader, run pipeline:
- */
- middle = draw->pt.middle.fetch_shade_pipeline;
- }
else {
/* This is what we're currently always doing:
*/
- /* Fetch user verts, run vertex shader, cliptest, run pipeline:
+ /* Fetch user verts, run vertex shader, cliptest, run pipeline
+ * or
+ * Fetch user verts, run vertex shader, run pipeline
*/
- middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
- }
-#else
- else {
- return FALSE;
+ middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
}
-#endif
/* If !pipeline, need to make sure we respect the driver's limited
@@ -143,7 +144,7 @@ draw_pt_arrays(struct draw_context *draw,
frontend = draw->pt.front.vcache;
hw_prim = reduced_prim(prim);
}
-
+#if 0
if (too_many_verts(nr_verts)) {
/* if (is_verts(draw) && can_split(prim)) {
draw = draw_arrays_split;
@@ -153,6 +154,7 @@ draw_pt_arrays(struct draw_context *draw,
hw_prim = reduced_prim(prim);
}
}
+#endif
if (too_many_elts(count)) {
@@ -166,17 +168,13 @@ draw_pt_arrays(struct draw_context *draw,
}
if (!good_prim(hw_prim)) {
- draw = draw->pt.front.vcache;
+ frontend = draw->pt.front.vcache;
}
}
#else
frontend = draw->pt.front.vcache;
#endif
- /* XXX: need to flush to get prim_vbuf.c to release its allocation??
- */
- draw_do_flush( draw, DRAW_FLUSH_BACKEND );
-
frontend->prepare( frontend, prim, middle );
frontend->run( frontend,
@@ -200,6 +198,11 @@ boolean draw_pt_init( struct draw_context *draw )
if (!draw->pt.middle.fetch_pipeline)
return FALSE;
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit =
+ draw_pt_fetch_pipeline_or_emit( draw );
+ if (!draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit)
+ return FALSE;
+
draw->pt.front.vcache = draw_pt_vcache( draw );
if (!draw->pt.front.vcache)
return FALSE;
@@ -220,6 +223,12 @@ void draw_pt_destroy( struct draw_context *draw )
draw->pt.middle.fetch_pipeline = NULL;
}
+ if (draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit) {
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit->destroy(
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit );
+ draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit = 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 590823fd33..48413b648a 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -123,7 +123,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 );
-
+struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
#endif
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index 0806076956..3a26a5d712 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -145,7 +145,6 @@ fetch_store_general( struct fetch_emit_middle_end *feme,
unsigned count )
{
float *out = (float *)out_ptr;
- struct vbuf_render *render = feme->draw->render;
uint i, j;
for (i = 0; i < count; i++) {
@@ -167,7 +166,6 @@ fetch_store_general( struct fetch_emit_middle_end *feme,
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;
@@ -212,12 +210,6 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
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;
- break;
case EMIT_1F_PSIZE:
feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size;
feme->fetch[i].pitch = 0;
@@ -249,6 +241,10 @@ 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)fetch_count );
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
index 4c2a281b29..a70d129c93 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_pipeline.c
@@ -87,7 +87,7 @@ struct fetch_pipeline_middle_end {
};
-
+#if 0
static void emit_R32_FLOAT( const float *attrib,
float **out )
{
@@ -111,7 +111,7 @@ static void emit_R32G32B32_FLOAT( const float *attrib,
(*out)[2] = attrib[2];
(*out) += 3;
}
-
+#endif
static void emit_R32G32B32A32_FLOAT( const float *attrib,
float **out )
{
@@ -211,7 +211,6 @@ fetch_store_general( struct fetch_pipeline_middle_end *fpme,
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;
@@ -264,7 +263,6 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
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 *
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
new file mode 100644
index 0000000000..04b3d2c4cf
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -0,0 +1,243 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+
+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 hw_vertex_size;
+ unsigned prim;
+};
+
+#if 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;
+}
+#endif
+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 fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
+ unsigned prim )
+{
+ struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
+ struct draw_context *draw = fpme->draw;
+ unsigned i, nr = 0;
+ boolean ok;
+ const struct vertex_info *vinfo;
+
+ fpme->prim = prim;
+
+ 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);
+
+ /* 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 = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
+ fpme->pipeline_vertex_size = MAX_VERTEX_ALLOCATION;
+ fpme->hw_vertex_size = vinfo->size * 4;
+}
+
+
+
+
+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;
+ struct draw_vertex_shader *shader = draw->vertex_shader;
+ char *pipeline_verts;
+
+ pipeline_verts = MALLOC(fpme->pipeline_vertex_size *
+ fetch_count);
+
+ if (!pipeline_verts) {
+ assert(0);
+ return;
+ }
+
+
+ /* Shade
+ */
+ shader->prepare(shader, draw);
+ if (shader->run(shader, draw, fetch_elts, fetch_count, pipeline_verts,
+ fpme->pipeline_vertex_size)) {
+ /* Run the pipeline */
+ draw_pt_run_pipeline( fpme->draw,
+ fpme->prim,
+ pipeline_verts,
+ fpme->pipeline_vertex_size,
+ fetch_count,
+ draw_elts,
+ draw_count );
+ } else {
+ unsigned i, j;
+ void *hw_verts;
+ float *out;
+
+ /* 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)fpme->hw_vertex_size,
+ (ushort)fetch_count);
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+ out = (float *)hw_verts;
+ for (i = 0; i < fetch_count; i++) {
+ struct vertex_header *header =
+ (struct vertex_header*)(pipeline_verts + (fpme->pipeline_vertex_size * i));
+
+ for (j = 0; j < fpme->nr_fetch; j++) {
+ float *attrib = header->data[j];
+ /*debug_printf("emiting [%f, %f, %f, %f]\n",
+ attrib[0], attrib[1],
+ attrib[2], attrib[3]);*/
+ fpme->fetch[j].emit(attrib, &out);
+ }
+ }
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw(draw->render,
+ draw_elts,
+ draw_count);
+
+ draw->render->release_vertices(draw->render,
+ hw_verts,
+ fpme->hw_vertex_size,
+ fetch_count);
+ }
+
+
+ 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_or_emit( 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_vbuf.c b/src/gallium/auxiliary/draw/draw_vbuf.c
index f83b441e93..e3216ff711 100644
--- a/src/gallium/auxiliary/draw/draw_vbuf.c
+++ b/src/gallium/auxiliary/draw/draw_vbuf.c
@@ -126,13 +126,6 @@ dump_emitted_vertex(const struct vertex_info *vinfo, const uint8_t *data)
case EMIT_OMIT:
debug_printf("EMIT_OMIT:");
break;
- case EMIT_ALL:
- assert(i == 0);
- assert(j == 0);
- debug_printf("EMIT_ALL:\t");
- for(k = 0; k < vinfo->size*4; ++k)
- debug_printf("%02x ", *data++);
- break;
case EMIT_1F:
debug_printf("EMIT_1F:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
@@ -217,19 +210,6 @@ emit_vertex( struct vbuf_stage *vbuf,
case EMIT_OMIT:
/* no-op */
break;
- case EMIT_ALL:
- /* just copy the whole vertex as-is to the vbuf */
- assert(i == 0);
- assert(j == 0);
- memcpy(vbuf->vertex_ptr, vertex, vinfo->size * 4);
- vbuf->vertex_ptr += vinfo->size;
- count += vinfo->size;
- break;
- case EMIT_HEADER:
- memcpy(vbuf->vertex_ptr, vertex, sizeof(*vertex));
- *vbuf->vertex_ptr += sizeof(*vertex) / 4;
- count += sizeof(*vertex) / 4;
- break;
case EMIT_1F:
*vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
count++;
diff --git a/src/gallium/auxiliary/draw/draw_vertex.c b/src/gallium/auxiliary/draw/draw_vertex.c
index 970adc95e7..168036eee8 100644
--- a/src/gallium/auxiliary/draw/draw_vertex.c
+++ b/src/gallium/auxiliary/draw/draw_vertex.c
@@ -52,9 +52,6 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
switch (vinfo->emit[i]) {
case EMIT_OMIT:
break;
- case EMIT_HEADER:
- vinfo->size += sizeof(struct vertex_header) / 4;
- break;
case EMIT_4UB:
/* fall-through */
case EMIT_1F_PSIZE:
@@ -71,8 +68,6 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
case EMIT_4F:
vinfo->size += 4;
break;
- case EMIT_ALL:
- /* fall-through */
default:
assert(0);
}
diff --git a/src/gallium/auxiliary/draw/draw_vertex.h b/src/gallium/auxiliary/draw/draw_vertex.h
index abd2017ed3..65818463ca 100644
--- a/src/gallium/auxiliary/draw/draw_vertex.h
+++ b/src/gallium/auxiliary/draw/draw_vertex.h
@@ -47,8 +47,6 @@
*/
enum attrib_emit {
EMIT_OMIT, /**< don't emit the attribute */
- EMIT_ALL, /**< emit whole post-xform vertex, w/ header */
- EMIT_HEADER, /**< emit vertex_header struct (XXX temp?) */
EMIT_1F,
EMIT_1F_PSIZE, /**< insert constant point size */
EMIT_2F,
diff --git a/src/gallium/auxiliary/draw/draw_vertex_cache.c b/src/gallium/auxiliary/draw/draw_vertex_cache.c
index c0248979e2..730c18bcb3 100644
--- a/src/gallium/auxiliary/draw/draw_vertex_cache.c
+++ b/src/gallium/auxiliary/draw/draw_vertex_cache.c
@@ -71,25 +71,28 @@ static struct vertex_header *get_vertex( struct draw_context *draw,
/* Cache hit?
*/
if (draw->vcache.idx[slot].in == i) {
-// _mesa_printf("HIT %d %d\n", slot, i);
+ /*debug_printf("HIT %d %d\n", slot, i);*/
assert(draw->vcache.idx[slot].out < draw->vs.queue_nr);
- return draw->vs.queue[draw->vcache.idx[slot].out].vertex;
+ return draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION,
+ draw->vcache.idx[slot].out);
}
/* Otherwise a collision
*/
slot = VCACHE_SIZE + draw->vcache.overflow++;
-// _mesa_printf("XXX %d --> %d\n", i, slot);
+ /*debug_printf("XXX %d --> %d\n", i, slot);*/
}
/* Deal with the cache miss:
*/
{
unsigned out;
-
+ struct vertex_header *header;
+
assert(slot < Elements(draw->vcache.idx));
-// _mesa_printf("NEW %d %d\n", slot, i);
+ /*debug_printf("NEW %d %d\n", slot, i);*/
draw->vcache.idx[slot].in = i;
draw->vcache.idx[slot].out = out = draw->vs.queue_nr++;
draw->vcache.referenced |= (1 << slot);
@@ -99,17 +102,21 @@ static struct vertex_header *get_vertex( struct draw_context *draw,
*/
assert(draw->vs.queue_nr < VS_QUEUE_LENGTH);
- draw->vs.queue[out].elt = i;
- draw->vs.queue[out].vertex->clipmask = 0;
- draw->vs.queue[out].vertex->edgeflag = draw_get_edgeflag(draw, i);
- draw->vs.queue[out].vertex->pad = 0;
- draw->vs.queue[out].vertex->vertex_id = UNDEFINED_VERTEX_ID;
+ header = draw_header_from_block(draw->vs.vertex_cache, MAX_VERTEX_ALLOCATION,
+ out);
+ draw->vs.elts[out] = i;
+ header->clipmask = 0;
+ header->edgeflag = draw_get_edgeflag(draw, i);
+ header->pad = 0;
+ header->vertex_id = UNDEFINED_VERTEX_ID;
/* Need to set the vertex's edge flag here. If we're being called
* by do_ef_triangle(), that function needs edge flag info!
*/
- return draw->vs.queue[draw->vcache.idx[slot].out].vertex;
+ return draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION,
+ draw->vcache.idx[slot].out);
}
}
@@ -142,8 +149,12 @@ void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw )
{
unsigned i;
- for (i = 0; i < draw->vs.post_nr; i++)
- draw->vs.queue[i].vertex->vertex_id = UNDEFINED_VERTEX_ID;
+ for (i = 0; i < draw->vs.post_nr; i++) {
+ struct vertex_header * header =
+ draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION, i);
+ header->vertex_id = UNDEFINED_VERTEX_ID;
+ }
}
diff --git a/src/gallium/auxiliary/draw/draw_vertex_shader.c b/src/gallium/auxiliary/draw/draw_vertex_shader.c
index 133418baca..8572a6d40c 100644
--- a/src/gallium/auxiliary/draw/draw_vertex_shader.c
+++ b/src/gallium/auxiliary/draw/draw_vertex_shader.c
@@ -37,8 +37,6 @@
#include "draw_context.h"
#include "draw_vs.h"
-
-
/**
* Run the vertex shader on all vertices in the vertex queue.
* Called by the draw module when the vertx cache needs to be flushed.
@@ -58,25 +56,25 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)
// fprintf(stderr, "%s %d\n", __FUNCTION__, draw->vs.queue_nr );
/* run vertex shader on vertex cache entries, four per invokation */
- for (i = 0; i < draw->vs.queue_nr; i += 4) {
- struct vertex_header *dests[4];
- unsigned elts[4];
- int j, n = MIN2(4, draw->vs.queue_nr - i);
+ for (i = 0; i < draw->vs.queue_nr; i += MAX_SHADER_VERTICES) {
+ unsigned elts[MAX_SHADER_VERTICES];
+ int j, n = MIN2(MAX_SHADER_VERTICES, draw->vs.queue_nr - i);
+ struct vertex_header *dests =
+ draw_header_from_block(draw->vs.vertex_cache,
+ MAX_VERTEX_ALLOCATION, i);
for (j = 0; j < n; j++) {
- elts[j] = draw->vs.queue[i + j].elt;
- dests[j] = draw->vs.queue[i + j].vertex;
+ elts[j] = draw->vs.elts[i + j];
}
- for ( ; j < 4; j++) {
+ for ( ; j < MAX_SHADER_VERTICES; j++) {
elts[j] = elts[0];
- dests[j] = draw->vs.queue[i + j].vertex;
}
assert(n > 0);
- assert(n <= 4);
+ assert(n <= MAX_SHADER_VERTICES);
- shader->run(shader, draw, elts, n, dests);
+ shader->run(shader, draw, elts, n, dests, MAX_VERTEX_ALLOCATION);
}
draw->vs.post_nr = draw->vs.queue_nr;
diff --git a/src/gallium/auxiliary/draw/draw_vf.c b/src/gallium/auxiliary/draw/draw_vf.c
index 7bb34ace7a..9d0154c50d 100644
--- a/src/gallium/auxiliary/draw/draw_vf.c
+++ b/src/gallium/auxiliary/draw/draw_vf.c
@@ -205,7 +205,7 @@ void draw_vf_set_vertex_info( struct draw_vertex_fetch *vf,
const struct vertex_info *vinfo,
float point_size )
{
- unsigned i, j, k;
+ unsigned i, j;
struct draw_vf_attr *a = vf->attr;
struct draw_vf_attr_map attrs[PIPE_MAX_SHADER_INPUTS];
unsigned count = 0; /* for debug/sanity */
@@ -217,60 +217,6 @@ void draw_vf_set_vertex_info( struct draw_vertex_fetch *vf,
case EMIT_OMIT:
/* no-op */
break;
- case EMIT_ALL: {
- /* just copy the whole vertex as-is to the vbuf */
- unsigned s = vinfo->size;
- assert(i == 0);
- assert(j == 0);
- /* copy the vertex header */
- /* XXX: we actually don't copy the header, just pad it */
- attrs[nr_attrs].attrib = 0;
- attrs[nr_attrs].format = DRAW_EMIT_PAD;
- attrs[nr_attrs].offset = offsetof(struct vertex_header, data);
- s -= offsetof(struct vertex_header, data)/4;
- count += offsetof(struct vertex_header, data)/4;
- nr_attrs++;
- /* copy the vertex data */
- for(k = 0; k < (s & ~0x3); k += 4) {
- attrs[nr_attrs].attrib = k/4;
- attrs[nr_attrs].format = DRAW_EMIT_4F;
- attrs[nr_attrs].offset = 0;
- nr_attrs++;
- count += 4;
- }
- /* tail */
- /* XXX: actually, this shouldn't be needed */
- attrs[nr_attrs].attrib = k/4;
- attrs[nr_attrs].offset = 0;
- switch(s & 0x3) {
- case 0:
- break;
- case 1:
- attrs[nr_attrs].format = DRAW_EMIT_1F;
- nr_attrs++;
- count += 1;
- break;
- case 2:
- attrs[nr_attrs].format = DRAW_EMIT_2F;
- nr_attrs++;
- count += 2;
- break;
- case 3:
- attrs[nr_attrs].format = DRAW_EMIT_3F;
- nr_attrs++;
- count += 3;
- break;
- }
- break;
- }
- case EMIT_HEADER:
- /* XXX emit new DRAW_EMIT_HEADER attribute??? */
- attrs[nr_attrs].attrib = 0;
- attrs[nr_attrs].format = DRAW_EMIT_PAD;
- attrs[nr_attrs].offset = offsetof(struct vertex_header, data);
- count += offsetof(struct vertex_header, data)/4;
- nr_attrs++;
- break;
case EMIT_1F:
attrs[nr_attrs].attrib = j;
attrs[nr_attrs].format = DRAW_EMIT_1F;
diff --git a/src/gallium/auxiliary/draw/draw_vf.h b/src/gallium/auxiliary/draw/draw_vf.h
index 7555d1bd58..0ef98d6257 100644
--- a/src/gallium/auxiliary/draw/draw_vf.h
+++ b/src/gallium/auxiliary/draw/draw_vf.h
@@ -128,9 +128,6 @@ draw_vf_destroy( struct draw_vertex_fetch *vf );
struct draw_vf_attr;
-typedef void (*draw_vf_extract_func)( const struct draw_vf_attr *a,
- float *out,
- const uint8_t *v );
typedef void (*draw_vf_insert_func)( const struct draw_vf_attr *a,
uint8_t *v,
@@ -164,7 +161,6 @@ struct draw_vf_attr
uint8_t *inputptr;
const draw_vf_insert_func *insert;
draw_vf_insert_func do_insert;
- draw_vf_extract_func extract;
};
struct draw_vertex_fetch
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index 4ee7e705e9..33ce1e335e 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -31,6 +31,10 @@
#ifndef DRAW_VS_H
#define DRAW_VS_H
+#include "draw_context.h"
+#include "draw_private.h"
+
+
struct draw_vertex_shader;
struct draw_context;
struct pipe_shader_state;
@@ -47,4 +51,33 @@ struct draw_vertex_shader *
draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *templ);
+
+/* Should be part of the generated shader:
+ */
+static INLINE unsigned
+compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
+{
+ unsigned mask = 0x0;
+ unsigned i;
+
+ /* Do the hardwired planes first:
+ */
+ if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
+ if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
+ if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
+ if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
+ if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
+ if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
+
+ /* Followed by any remaining ones:
+ */
+ for (i = 6; i < nr; i++) {
+ if (dot4(clip, plane[i]) < 0)
+ mask |= (1<<i);
+ }
+
+ return mask;
+}
+
+
#endif
diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
index c6e503686a..5c88c2e24e 100644
--- a/src/gallium/auxiliary/draw/draw_vs_exec.c
+++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
@@ -40,32 +40,7 @@
#include "tgsi/util/tgsi_parse.h"
-
-static INLINE unsigned
-compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
-{
- unsigned mask = 0;
- unsigned i;
-
- /* Do the hardwired planes first:
- */
- if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
- if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
- if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
- if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
- if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
- if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
-
- /* Followed by any remaining ones:
- */
- for (i = 6; i < nr; i++) {
- if (dot4(clip, plane[i]) < 0)
- mask |= (1<<i);
- }
-
- return mask;
-}
-
+#define MAX_TGSI_VERTICES 4
static void
vs_exec_prepare( struct draw_vertex_shader *shader,
@@ -89,22 +64,23 @@ vs_exec_prepare( struct draw_vertex_shader *shader,
* \param count number of vertices to shade [1..4]
* \param vOut array of pointers to four output vertices
*/
-static void
+static boolean
vs_exec_run( struct draw_vertex_shader *shader,
struct draw_context *draw,
const unsigned *elts,
unsigned count,
- struct vertex_header *vOut[] )
+ void *vOut,
+ unsigned vertex_size)
{
struct tgsi_exec_machine *machine = &draw->machine;
- unsigned int j;
+ unsigned int i, j;
+ unsigned int clipped = 0;
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_MAX_ATTRIBS);
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_MAX_ATTRIBS);
const float *scale = draw->viewport.scale;
const float *trans = draw->viewport.translate;
- assert(count <= 4);
assert(draw->vertex_shader->info.output_semantic_name[0]
== TGSI_SEMANTIC_POSITION);
@@ -118,80 +94,87 @@ vs_exec_run( struct draw_vertex_shader *shader,
machine->Outputs = ALIGN16_ASSIGN(outputs);
}
- draw->vertex_fetch.fetch_func( draw, machine, elts, count );
-
- if (!draw->rasterizer->bypass_vs) {
- /* run interpreter */
- tgsi_exec_machine_run( machine );
- }
+ for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
+ unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
+ draw->vertex_fetch.fetch_func( draw, machine, &elts[i], max_vertices );
- /* store machine results */
- for (j = 0; j < count; j++) {
- unsigned slot;
- float x, y, z, w;
-
- /* Handle attr[0] (position) specially:
- *
- * XXX: Computing the clipmask should be done in the vertex
- * program as a set of DP4 instructions appended to the
- * user-provided code.
- */
- x = vOut[j]->clip[0] = machine->Outputs[0].xyzw[0].f[j];
- y = vOut[j]->clip[1] = machine->Outputs[0].xyzw[1].f[j];
- z = vOut[j]->clip[2] = machine->Outputs[0].xyzw[2].f[j];
- w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
-
- if (!draw->rasterizer->bypass_clipping) {
- vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
-
- /* divide by w */
- w = 1.0f / w;
- x *= w;
- y *= w;
- z *= w;
- }
- else {
- vOut[j]->clipmask = 0;
- }
- vOut[j]->edgeflag = 1;
-
- if (!draw->identity_viewport) {
- /* Viewport mapping */
- vOut[j]->data[0][0] = x * scale[0] + trans[0];
- vOut[j]->data[0][1] = y * scale[1] + trans[1];
- vOut[j]->data[0][2] = z * scale[2] + trans[2];
- vOut[j]->data[0][3] = w;
- }
- else {
- vOut[j]->data[0][0] = x;
- vOut[j]->data[0][1] = y;
- vOut[j]->data[0][2] = z;
- vOut[j]->data[0][3] = w;
+ if (!draw->rasterizer->bypass_vs) {
+ /* run interpreter */
+ tgsi_exec_machine_run( machine );
}
- /* Remaining attributes are packed into sequential post-transform
- * vertex attrib slots.
- */
- for (slot = 1; slot < draw->num_vs_outputs; slot++) {
- vOut[j]->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
- vOut[j]->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
- vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
- vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
- }
+ /* store machine results */
+ for (j = 0; j < max_vertices; j++) {
+ unsigned slot;
+ float x, y, z, w;
+ struct vertex_header *out =
+ draw_header_from_block(vOut, vertex_size, i + j);
+
+ /* Handle attr[0] (position) specially:
+ *
+ * XXX: Computing the clipmask should be done in the vertex
+ * program as a set of DP4 instructions appended to the
+ * user-provided code.
+ */
+ x = out->clip[0] = machine->Outputs[0].xyzw[0].f[j];
+ y = out->clip[1] = machine->Outputs[0].xyzw[1].f[j];
+ z = out->clip[2] = machine->Outputs[0].xyzw[2].f[j];
+ w = out->clip[3] = machine->Outputs[0].xyzw[3].f[j];
+
+ if (!draw->rasterizer->bypass_clipping) {
+ out->clipmask = compute_clipmask(out->clip, draw->plane,
+ draw->nr_planes);
+ clipped += out->clipmask;
+
+ /* divide by w */
+ w = 1.0f / w;
+ x *= w;
+ y *= w;
+ z *= w;
+ }
+ else {
+ out->clipmask = 0;
+ }
+ out->edgeflag = 1;
+ out->vertex_id = UNDEFINED_VERTEX_ID;
+
+ if (!draw->identity_viewport) {
+ /* Viewport mapping */
+ out->data[0][0] = x * scale[0] + trans[0];
+ out->data[0][1] = y * scale[1] + trans[1];
+ out->data[0][2] = z * scale[2] + trans[2];
+ out->data[0][3] = w;
+ }
+ else {
+ out->data[0][0] = x;
+ out->data[0][1] = y;
+ out->data[0][2] = z;
+ out->data[0][3] = w;
+ }
+
+ /* Remaining attributes are packed into sequential post-transform
+ * vertex attrib slots.
+ */
+ for (slot = 1; slot < draw->num_vs_outputs; slot++) {
+ out->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
+ out->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
+ out->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
+ out->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ }
#if 0 /*DEBUG*/
- printf("Post xform vert:\n");
- for (slot = 0; slot < draw->num_vs_outputs; slot++) {
- printf("%d: %f %f %f %f\n", slot,
- vOut[j]->data[slot][0],
- vOut[j]->data[slot][1],
- vOut[j]->data[slot][2],
- vOut[j]->data[slot][3]);
- }
-#endif
-
-
- } /* loop over vertices */
+ printf("%d) Post xform vert:\n", i + j);
+ for (slot = 0; slot < draw->num_vs_outputs; slot++) {
+ printf("\t%d: %f %f %f %f\n", slot,
+ out->data[slot][0],
+ out->data[slot][1],
+ out->data[slot][2],
+ out->data[slot][3]);
+ }
+#endif
+ } /* loop over vertices */
+ }
+ return clipped != 0;
}
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
index c8268317ef..73076d2467 100644
--- a/src/gallium/auxiliary/draw/draw_vs_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -50,33 +50,6 @@ struct draw_llvm_vertex_shader {
};
-static INLINE unsigned
-compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
-{
- unsigned mask = 0;
- unsigned i;
-
- /* Do the hardwired planes first:
- */
- if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
- if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
- if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
- if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
- if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
- if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
-
- /* Followed by any remaining ones:
- */
- for (i = 6; i < nr; i++) {
- if (dot4(clip, plane[i]) < 0)
- mask |= (1<<i);
- }
-
- return mask;
-}
-
-
-
static void
vs_llvm_prepare( struct draw_vertex_shader *base,
struct draw_context *draw )
@@ -94,18 +67,19 @@ vs_llvm_prepare( struct draw_vertex_shader *base,
* \param count number of vertices to shade [1..4]
* \param vOut array of pointers to four output vertices
*/
-static void
+static boolean
vs_llvm_run( struct draw_vertex_shader *base,
- struct draw_context *draw,
- const unsigned *elts,
+ struct draw_context *draw,
+ const unsigned *elts,
unsigned count,
- struct vertex_header *vOut[] )
+ void *vOut )
{
- struct draw_llvm_vertex_shader *shader =
+ struct draw_llvm_vertex_shader *shader =
(struct draw_llvm_vertex_shader *)base;
struct tgsi_exec_machine *machine = &draw->machine;
unsigned int j;
+ unsigned int clipped = 0;
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_MAX_ATTRIBS);
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_MAX_ATTRIBS);
@@ -152,19 +126,22 @@ vs_llvm_run( struct draw_vertex_shader *base,
w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
if (!draw->rasterizer->bypass_clipping) {
- vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
+ vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane,
+ draw->nr_planes);
+ clipped += vOut[j]->clipmask;
/* divide by w */
w = 1.0f / w;
x *= w;
y *= w;
- z *= w;
+ z *= w;
}
else {
vOut[j]->clipmask = 0;
}
vOut[j]->edgeflag = 1;
-
+ vOut[j]->vertex_id = UNDEFINED_VERTEX_ID;
+
if (!draw->identity_viewport) {
/* Viewport mapping */
vOut[j]->data[0][0] = x * scale[0] + trans[0];
@@ -189,6 +166,7 @@ vs_llvm_run( struct draw_vertex_shader *base,
vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
}
} /* loop over vertices */
+ return clipped != 0;
}
static void
diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c
index f40d65df08..ee0a3105b9 100644
--- a/src/gallium/auxiliary/draw/draw_vs_sse.c
+++ b/src/gallium/auxiliary/draw/draw_vs_sse.c
@@ -45,49 +45,24 @@
#include "tgsi/exec/tgsi_sse2.h"
#include "tgsi/util/tgsi_parse.h"
+#define SSE_MAX_VERTICES 4
typedef void (XSTDCALL *codegen_function) (
const struct tgsi_exec_vector *input,
struct tgsi_exec_vector *output,
float (*constant)[4],
- struct tgsi_exec_vector *temporary );
+ struct tgsi_exec_vector *temporary,
+ float (*immediates)[4] );
struct draw_sse_vertex_shader {
struct draw_vertex_shader base;
struct x86_function sse2_program;
codegen_function func;
+ float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
};
-/* Should be part of the generated shader:
- */
-static INLINE unsigned
-compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
-{
- unsigned mask = 0;
- unsigned i;
-
- /* Do the hardwired planes first:
- */
- if (-clip[0] + clip[3] < 0) mask |= CLIP_RIGHT_BIT;
- if ( clip[0] + clip[3] < 0) mask |= CLIP_LEFT_BIT;
- if (-clip[1] + clip[3] < 0) mask |= CLIP_TOP_BIT;
- if ( clip[1] + clip[3] < 0) mask |= CLIP_BOTTOM_BIT;
- if (-clip[2] + clip[3] < 0) mask |= CLIP_FAR_BIT;
- if ( clip[2] + clip[3] < 0) mask |= CLIP_NEAR_BIT;
-
- /* Followed by any remaining ones:
- */
- for (i = 6; i < nr; i++) {
- if (dot4(clip, plane[i]) < 0)
- mask |= (1<<i);
- }
-
- return mask;
-}
-
-
static void
vs_sse_prepare( struct draw_vertex_shader *base,
struct draw_context *draw )
@@ -103,23 +78,24 @@ vs_sse_prepare( struct draw_vertex_shader *base,
* \param count number of vertices to shade [1..4]
* \param vOut array of pointers to four output vertices
*/
-static void
+static boolean
vs_sse_run( struct draw_vertex_shader *base,
struct draw_context *draw,
const unsigned *elts,
unsigned count,
- struct vertex_header *vOut[] )
+ void *vOut,
+ unsigned vertex_size )
{
struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base;
struct tgsi_exec_machine *machine = &draw->machine;
- unsigned int j;
+ unsigned int i, j;
+ unsigned int clipped = 0;
ALIGN16_DECL(struct tgsi_exec_vector, inputs, PIPE_MAX_ATTRIBS);
ALIGN16_DECL(struct tgsi_exec_vector, outputs, PIPE_MAX_ATTRIBS);
const float *scale = draw->viewport.scale;
const float *trans = draw->viewport.translate;
- assert(count <= 4);
assert(draw->vertex_shader->info.output_semantic_name[0]
== TGSI_SEMANTIC_POSITION);
@@ -134,76 +110,93 @@ vs_sse_run( struct draw_vertex_shader *base,
machine->Outputs = ALIGN16_ASSIGN(outputs);
}
-
- /* Fetch vertices. This may at some point be integrated into the
- * compiled shader -- that would require a reorganization where
- * multiple versions of the compiled shader might exist,
- * specialized for each fetch state.
- */
- draw->vertex_fetch.fetch_func( draw, machine, elts, count );
-
-
- if (!draw->rasterizer->bypass_vs) {
- /* run compiled shader
- */
- shader->func(machine->Inputs,
- machine->Outputs,
- machine->Consts,
- machine->Temps );
- }
-
-
- /* XXX: Computing the clipmask and emitting results should be done
- * in the vertex program as a set of instructions appended to
- * the user-provided code.
- */
- for (j = 0; j < count; j++) {
- unsigned slot;
- float x, y, z, w;
-
- x = vOut[j]->clip[0] = machine->Outputs[0].xyzw[0].f[j];
- y = vOut[j]->clip[1] = machine->Outputs[0].xyzw[1].f[j];
- z = vOut[j]->clip[2] = machine->Outputs[0].xyzw[2].f[j];
- w = vOut[j]->clip[3] = machine->Outputs[0].xyzw[3].f[j];
-
- if (!draw->rasterizer->bypass_clipping) {
- vOut[j]->clipmask = compute_clipmask(vOut[j]->clip, draw->plane, draw->nr_planes);
-
- /* divide by w */
- w = 1.0f / w;
- x *= w;
- y *= w;
- z *= w;
- }
- else {
- vOut[j]->clipmask = 0;
- }
- vOut[j]->edgeflag = 1;
-
- if (!draw->identity_viewport) {
- /* Viewport mapping */
- vOut[j]->data[0][0] = x * scale[0] + trans[0];
- vOut[j]->data[0][1] = y * scale[1] + trans[1];
- vOut[j]->data[0][2] = z * scale[2] + trans[2];
- vOut[j]->data[0][3] = w;
- }
- else {
- vOut[j]->data[0][0] = x;
- vOut[j]->data[0][1] = y;
- vOut[j]->data[0][2] = z;
- vOut[j]->data[0][3] = w;
+ for (i = 0; i < count; i += SSE_MAX_VERTICES) {
+ unsigned int max_vertices = MIN2(SSE_MAX_VERTICES, count - i);
+ /* Fetch vertices. This may at some point be integrated into the
+ * compiled shader -- that would require a reorganization where
+ * multiple versions of the compiled shader might exist,
+ * specialized for each fetch state.
+ */
+ draw->vertex_fetch.fetch_func(draw, machine, &elts[i], max_vertices);
+
+ if (!draw->rasterizer->bypass_vs) {
+ /* run compiled shader
+ */
+ shader->func(machine->Inputs,
+ machine->Outputs,
+ machine->Consts,
+ machine->Temps,
+ shader->immediates);
}
- /* Remaining attributes are packed into sequential post-transform
- * vertex attrib slots.
+ /* XXX: Computing the clipmask and emitting results should be done
+ * in the vertex program as a set of instructions appended to
+ * the user-provided code.
*/
- for (slot = 1; slot < draw->num_vs_outputs; slot++) {
- vOut[j]->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
- vOut[j]->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
- vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
- vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ for (j = 0; j < max_vertices; j++) {
+ unsigned slot;
+ float x, y, z, w;
+ struct vertex_header *out =
+ draw_header_from_block(vOut, vertex_size, i + j);
+
+ x = out->clip[0] = machine->Outputs[0].xyzw[0].f[j];
+ y = out->clip[1] = machine->Outputs[0].xyzw[1].f[j];
+ z = out->clip[2] = machine->Outputs[0].xyzw[2].f[j];
+ w = out->clip[3] = machine->Outputs[0].xyzw[3].f[j];
+
+ if (!draw->rasterizer->bypass_clipping) {
+ out->clipmask = compute_clipmask(out->clip, draw->plane,
+ draw->nr_planes);
+ clipped += out->clipmask;
+
+ /* divide by w */
+ w = 1.0f / w;
+ x *= w;
+ y *= w;
+ z *= w;
+ }
+ else {
+ out->clipmask = 0;
+ }
+ out->edgeflag = 1;
+ out->vertex_id = UNDEFINED_VERTEX_ID;
+
+ if (!draw->identity_viewport) {
+ /* Viewport mapping */
+ out->data[0][0] = x * scale[0] + trans[0];
+ out->data[0][1] = y * scale[1] + trans[1];
+ out->data[0][2] = z * scale[2] + trans[2];
+ out->data[0][3] = w;
+ }
+ else {
+ out->data[0][0] = x;
+ out->data[0][1] = y;
+ out->data[0][2] = z;
+ out->data[0][3] = w;
+ }
+
+ /* Remaining attributes are packed into sequential post-transform
+ * vertex attrib slots.
+ */
+ for (slot = 1; slot < draw->num_vs_outputs; slot++) {
+ out->data[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
+ out->data[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
+ out->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
+ out->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
+ }
+#if 0 /*DEBUG*/
+ printf("%d) Post xform vert:\n", i + j);
+ for (slot = 0; slot < draw->num_vs_outputs; slot++) {
+ printf("\t%d: %f %f %f %f\n", slot,
+ out->data[slot][0],
+ out->data[slot][1],
+ out->data[slot][2],
+ out->data[slot][3]);
+ }
+#endif
}
- }
+ }
+ return clipped != 0;
}
@@ -243,7 +236,7 @@ draw_create_vs_sse(struct draw_context *draw,
x86_init_func( &vs->sse2_program );
if (!tgsi_emit_sse2( (struct tgsi_token *) vs->base.state.tokens,
- &vs->sse2_program ))
+ &vs->sse2_program, vs->immediates ))
goto fail;
vs->func = (codegen_function) x86_get_func( &vs->sse2_program );
diff --git a/src/gallium/auxiliary/pipebuffer/Makefile b/src/gallium/auxiliary/pipebuffer/Makefile
index a9fa518c67..d654dbcc91 100644
--- a/src/gallium/auxiliary/pipebuffer/Makefile
+++ b/src/gallium/auxiliary/pipebuffer/Makefile
@@ -6,9 +6,11 @@ LIBNAME = pipebuffer
C_SOURCES = \
pb_buffer_fenced.c \
pb_buffer_malloc.c \
+ pb_bufmgr_cache.c \
pb_bufmgr_fenced.c \
pb_bufmgr_mm.c \
pb_bufmgr_pool.c \
+ pb_bufmgr_slab.c \
pb_winsys.c
include ../../Makefile.template
diff --git a/src/gallium/auxiliary/pipebuffer/SConscript b/src/gallium/auxiliary/pipebuffer/SConscript
index 3d41fd84a6..604a217982 100644
--- a/src/gallium/auxiliary/pipebuffer/SConscript
+++ b/src/gallium/auxiliary/pipebuffer/SConscript
@@ -5,9 +5,11 @@ pipebuffer = env.ConvenienceLibrary(
source = [
'pb_buffer_fenced.c',
'pb_buffer_malloc.c',
+ 'pb_bufmgr_cache.c',
'pb_bufmgr_fenced.c',
'pb_bufmgr_mm.c',
'pb_bufmgr_pool.c',
+ 'pb_bufmgr_slab.c',
'pb_winsys.c',
])
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
index b1f7d93057..65b6584003 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
+++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_fenced.c
@@ -35,6 +35,7 @@
#include "pipe/p_compiler.h"
+#include "pipe/p_error.h"
#include "pipe/p_debug.h"
#include "pipe/p_winsys.h"
#include "pipe/p_thread.h"
@@ -54,6 +55,13 @@
*/
#define SUPER(__derived) (&(__derived)->base)
+#define PIPE_BUFFER_USAGE_CPU_READ_WRITE \
+ ( PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE )
+#define PIPE_BUFFER_USAGE_GPU_READ_WRITE \
+ ( PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE )
+#define PIPE_BUFFER_USAGE_WRITE \
+ ( PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_WRITE )
+
struct fenced_buffer_list
{
@@ -76,6 +84,15 @@ struct fenced_buffer
struct pb_buffer *buffer;
+ /* FIXME: protect access with mutex */
+
+ /**
+ * A bitmask of PIPE_BUFFER_USAGE_CPU/GPU_READ/WRITE describing the current
+ * buffer usage.
+ */
+ unsigned flags;
+
+ unsigned mapcount;
struct pipe_fence_handle *fence;
struct list_head head;
@@ -98,7 +115,9 @@ _fenced_buffer_add(struct fenced_buffer *fenced_buf)
struct fenced_buffer_list *fenced_list = fenced_buf->list;
assert(fenced_buf->base.base.refcount);
+ assert(fenced_buf->flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE);
assert(fenced_buf->fence);
+
assert(!fenced_buf->head.prev);
assert(!fenced_buf->head.next);
LIST_ADDTAIL(&fenced_buf->head, &fenced_list->delayed);
@@ -130,6 +149,7 @@ _fenced_buffer_remove(struct fenced_buffer *fenced_buf)
assert(fenced_buf->fence);
winsys->fence_reference(winsys, &fenced_buf->fence, NULL);
+ fenced_buf->flags &= ~PIPE_BUFFER_USAGE_GPU_READ_WRITE;
assert(fenced_buf->head.prev);
assert(fenced_buf->head.next);
@@ -186,6 +206,34 @@ _fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
}
+/**
+ * Serialize writes, but allow concurrent reads.
+ */
+static INLINE enum pipe_error
+fenced_buffer_serialize(struct fenced_buffer *fenced_buf, unsigned flags)
+{
+ struct fenced_buffer_list *fenced_list = fenced_buf->list;
+ struct pipe_winsys *winsys = fenced_list->winsys;
+
+ if(((fenced_buf->flags | flags) & PIPE_BUFFER_USAGE_WRITE) == 0)
+ return PIPE_OK;
+
+ if(fenced_buf->mapcount) {
+ /* FIXME */
+ debug_warning("attemp to write concurrently to buffer");
+ return PIPE_ERROR_RETRY;
+ }
+
+ if(fenced_buf->fence) {
+ if(winsys->fence_finish(winsys, fenced_buf->fence, 0) != 0)
+ return PIPE_ERROR_RETRY;
+ _fenced_buffer_remove(fenced_buf);
+ }
+
+ return PIPE_OK;
+}
+
+
static void
fenced_buffer_destroy(struct pb_buffer *buf)
{
@@ -223,16 +271,30 @@ static void *
fenced_buffer_map(struct pb_buffer *buf,
unsigned flags)
{
- struct fenced_buffer *fenced_buf = fenced_buffer(buf);
- return pb_map(fenced_buf->buffer, flags);
+ struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ void *map;
+ assert((flags & ~PIPE_BUFFER_USAGE_CPU_READ_WRITE) == 0);
+
+ if(fenced_buffer_serialize(fenced_buf, flags) != PIPE_OK)
+ return NULL;
+
+ map = pb_map(fenced_buf->buffer, flags);
+ if(map)
+ ++fenced_buf->mapcount;
+ fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ return map;
}
static void
fenced_buffer_unmap(struct pb_buffer *buf)
{
- struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ struct fenced_buffer *fenced_buf = fenced_buffer(buf);
+ assert(fenced_buf->mapcount);
pb_unmap(fenced_buf->buffer);
+ --fenced_buf->mapcount;
+ if(!fenced_buf->mapcount)
+ fenced_buf->flags &= ~PIPE_BUFFER_USAGE_CPU_READ_WRITE;
}
@@ -288,13 +350,22 @@ buffer_fence(struct pb_buffer *buf,
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
struct fenced_buffer_list *fenced_list = fenced_buf->list;
struct pipe_winsys *winsys = fenced_list->winsys;
+ /* FIXME: receive this as a parameter */
+ unsigned flags = fence ? PIPE_BUFFER_USAGE_GPU_READ_WRITE : 0;
+
+ if(fenced_buffer_serialize(fenced_buf, flags) != PIPE_OK) {
+ /* FIXME: propagate error */
+ (void)0;
+ }
_glthread_LOCK_MUTEX(fenced_list->mutex);
if (fenced_buf->fence)
_fenced_buffer_remove(fenced_buf);
- winsys->fence_reference(winsys, &fenced_buf->fence, fence);
- if (fenced_buf->fence)
+ if (fence) {
+ winsys->fence_reference(winsys, &fenced_buf->fence, fence);
+ fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE;
_fenced_buffer_add(fenced_buf);
+ }
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
index 0cf8e92e37..b2d2520b67 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
@@ -80,7 +80,7 @@ struct pb_manager
/**
- * Static buffer pool manager.
+ * Static buffer pool sub-allocator.
*
* Manages the allocation of equally sized buffers. It does so by allocating
* a single big buffer and divide it equally sized buffers.
@@ -94,7 +94,7 @@ pool_bufmgr_create(struct pb_manager *provider,
/**
- * Wraper around the old memory manager.
+ * Static sub-allocator based the old memory manager.
*
* It managers buffers of different sizes. It does so by allocating a buffer
* with the size of the heap, and then using the old mm memory manager to manage
@@ -114,6 +114,29 @@ mm_bufmgr_create_from_buffer(struct pb_buffer *buffer,
size_t size, size_t align2);
+/**
+ * Slab sub-allocator.
+ */
+struct pb_manager *
+pb_slab_manager_create(struct pb_manager *provider,
+ const struct pb_desc *desc,
+ size_t smallestSize,
+ size_t numSizes,
+ size_t desiredNumBuffers,
+ size_t maxSlabSize,
+ size_t pageAlignment);
+
+
+/**
+ * Time-based buffer cache.
+ *
+ * This manager keeps a cache of destroyed buffers during a time interval.
+ */
+struct pb_manager *
+pb_cache_manager_create(struct pb_manager *provider,
+ unsigned usecs);
+
+
/**
* Fenced buffer manager.
*
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
new file mode 100644
index 0000000000..06de0bb6c3
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
@@ -0,0 +1,299 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2008 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.
+ *
+ **************************************************************************/
+
+/**
+ * \file
+ * Buffer cache.
+ *
+ * \author José Fonseca <jrfonseca-at-tungstengraphics-dot-com>
+ * \author Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_thread.h"
+#include "pipe/p_util.h"
+#include "util/u_double_list.h"
+#include "util/u_time.h"
+
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+/**
+ * Convenience macro (type safe).
+ */
+#define SUPER(__derived) (&(__derived)->base)
+
+
+struct pb_cache_manager;
+
+
+/**
+ * Wrapper around a pipe buffer which adds delayed destruction.
+ */
+struct pb_cache_buffer
+{
+ struct pb_buffer base;
+
+ struct pb_buffer *buffer;
+ struct pb_cache_manager *mgr;
+
+ /** Caching time interval */
+ struct util_time start, end;
+
+ struct list_head head;
+};
+
+
+struct pb_cache_manager
+{
+ struct pb_manager base;
+
+ struct pb_manager *provider;
+ unsigned usecs;
+
+ _glthread_Mutex mutex;
+
+ struct list_head delayed;
+ size_t numDelayed;
+};
+
+
+static INLINE struct pb_cache_buffer *
+pb_cache_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct pb_cache_buffer *)buf;
+}
+
+
+static INLINE struct pb_cache_manager *
+pb_cache_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_cache_manager *)mgr;
+}
+
+
+/**
+ * Actually destroy the buffer.
+ */
+static INLINE void
+_pb_cache_buffer_destroy(struct pb_cache_buffer *buf)
+{
+ struct pb_cache_manager *mgr = buf->mgr;
+
+ LIST_DEL(&buf->head);
+ assert(mgr->numDelayed);
+ --mgr->numDelayed;
+ assert(!buf->base.base.refcount);
+ pb_reference(&buf->buffer, NULL);
+ FREE(buf);
+}
+
+
+/**
+ * Free as many cache buffers from the list head as possible.
+ */
+static void
+_pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr)
+{
+ struct list_head *curr, *next;
+ struct pb_cache_buffer *buf;
+ struct util_time now;
+
+ util_time_get(&now);
+
+ curr = mgr->delayed.next;
+ next = curr->next;
+ while(curr != &mgr->delayed) {
+ buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+
+ if(util_time_timeout(&buf->start, &buf->end, &now) != 0)
+ break;
+
+ _pb_cache_buffer_destroy(buf);
+
+ curr = next;
+ next = curr->next;
+ }
+}
+
+
+static void
+pb_cache_buffer_destroy(struct pb_buffer *_buf)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ struct pb_cache_manager *mgr = buf->mgr;
+
+ _glthread_LOCK_MUTEX(mgr->mutex);
+ assert(buf->base.base.refcount == 0);
+
+ _pb_cache_buffer_list_check_free(mgr);
+
+ util_time_get(&buf->start);
+ util_time_add(&buf->start, mgr->usecs, &buf->end);
+ LIST_ADDTAIL(&buf->head, &mgr->delayed);
+ ++mgr->numDelayed;
+ _glthread_UNLOCK_MUTEX(mgr->mutex);
+}
+
+
+static void *
+pb_cache_buffer_map(struct pb_buffer *_buf,
+ unsigned flags)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ return pb_map(buf->buffer, flags);
+}
+
+
+static void
+pb_cache_buffer_unmap(struct pb_buffer *_buf)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ pb_unmap(buf->buffer);
+}
+
+
+static void
+pb_cache_buffer_get_base_buffer(struct pb_buffer *_buf,
+ struct pb_buffer **base_buf,
+ unsigned *offset)
+{
+ struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
+ pb_get_base_buffer(buf->buffer, base_buf, offset);
+}
+
+
+const struct pb_vtbl
+pb_cache_buffer_vtbl = {
+ pb_cache_buffer_destroy,
+ pb_cache_buffer_map,
+ pb_cache_buffer_unmap,
+ pb_cache_buffer_get_base_buffer
+};
+
+
+static struct pb_buffer *
+pb_cache_manager_create_buffer(struct pb_manager *_mgr,
+ size_t size,
+ const struct pb_desc *desc)
+{
+ struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
+ struct pb_cache_buffer *buf;
+ struct list_head *curr, *next;
+ struct util_time now;
+
+ util_time_get(&now);
+ curr = mgr->delayed.next;
+ next = curr->next;
+ while(curr != &mgr->delayed) {
+ buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+
+ if(buf->base.base.size == size &&
+ buf->base.base.alignment >= desc->alignment &&
+ (buf->base.base.alignment % desc->alignment) == 0 &&
+ /* buf->base.base.usage == usage */ 1) {
+ ++buf->base.base.refcount;
+ return &buf->base;
+ }
+
+ if(util_time_timeout(&buf->start, &buf->end, &now) != 0)
+ _pb_cache_buffer_destroy(buf);
+
+ curr = next;
+ next = curr->next;
+ }
+
+ buf = CALLOC_STRUCT(pb_cache_buffer);
+ if(!buf)
+ return NULL;
+
+ buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc);
+ if(!buf->buffer) {
+ FREE(buf);
+ return NULL;
+ }
+
+ buf->base.base.refcount = 1;
+ buf->base.base.alignment = buf->buffer->base.alignment;
+ buf->base.base.usage = buf->buffer->base.usage;
+ buf->base.base.size = buf->buffer->base.size;
+
+ buf->base.vtbl = &pb_cache_buffer_vtbl;
+ buf->mgr = mgr;
+
+ return &buf->base;
+}
+
+
+static void
+pb_cache_manager_destroy(struct pb_manager *_mgr)
+{
+ struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
+ struct list_head *curr, *next;
+ struct pb_cache_buffer *buf;
+
+ _glthread_LOCK_MUTEX(mgr->mutex);
+ curr = mgr->delayed.next;
+ next = curr->next;
+ while(curr != &mgr->delayed) {
+ buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
+ _pb_cache_buffer_destroy(buf);
+ curr = next;
+ next = curr->next;
+ }
+ _glthread_UNLOCK_MUTEX(mgr->mutex);
+
+ FREE(mgr);
+}
+
+
+struct pb_manager *
+pb_cache_manager_create(struct pb_manager *provider,
+ unsigned usecs)
+{
+ struct pb_cache_manager *mgr;
+
+ mgr = (struct pb_cache_manager *)CALLOC(1, sizeof(*mgr));
+ if (!mgr)
+ return NULL;
+
+ mgr->base.destroy = pb_cache_manager_destroy;
+ mgr->base.create_buffer = pb_cache_manager_create_buffer;
+ mgr->provider = provider;
+ mgr->usecs = usecs;
+ LIST_INITHEAD(&mgr->delayed);
+ mgr->numDelayed = 0;
+ _glthread_INIT_MUTEX(mgr->mutex);
+
+ return &mgr->base;
+}
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c
new file mode 100644
index 0000000000..676e8e29b9
--- /dev/null
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c
@@ -0,0 +1,429 @@
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * 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 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
+ * THE COPYRIGHT HOLDERS, AUTHORS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * S-lab pool implementation.
+ *
+ * @author Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_error.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_thread.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "util/u_double_list.h"
+#include "util/u_time.h"
+
+#include "pb_buffer.h"
+#include "pb_bufmgr.h"
+
+
+#define DRI_SLABPOOL_ALLOC_RETRIES 100
+
+
+struct pb_slab;
+
+struct pb_slab_buffer
+{
+ struct pb_buffer base;
+
+ struct pb_slab *slab;
+ struct list_head head;
+ unsigned mapCount;
+ size_t start;
+ _glthread_Cond event;
+};
+
+struct pb_slab
+{
+ struct list_head head;
+ struct list_head freeBuffers;
+ size_t numBuffers;
+ size_t numFree;
+ struct pb_slab_buffer *buffers;
+ struct pb_slab_size_header *header;
+
+ struct pb_buffer *bo;
+ size_t pageAlignment;
+ void *virtual;
+};
+
+struct pb_slab_size_header
+{
+ struct list_head slabs;
+ struct list_head freeSlabs;
+ struct pb_slab_manager *pool;
+ size_t bufSize;
+ _glthread_Mutex mutex;
+};
+
+/**
+ * The data of this structure remains constant after
+ * initialization and thus needs no mutex protection.
+ */
+struct pb_slab_manager
+{
+ struct pb_manager base;
+
+ struct pb_desc desc;
+ size_t *bucketSizes;
+ size_t numBuckets;
+ size_t pageSize;
+ struct pb_manager *provider;
+ unsigned pageAlignment;
+ unsigned maxSlabSize;
+ unsigned desiredNumBuffers;
+ struct pb_slab_size_header *headers;
+};
+
+
+static INLINE struct pb_slab_buffer *
+pb_slab_buffer(struct pb_buffer *buf)
+{
+ assert(buf);
+ return (struct pb_slab_buffer *)buf;
+}
+
+
+static INLINE struct pb_slab_manager *
+pb_slab_manager(struct pb_manager *mgr)
+{
+ assert(mgr);
+ return (struct pb_slab_manager *)mgr;
+}
+
+
+/**
+ * Delete a buffer from the slab header delayed list and put
+ * it on the slab FREE list.
+ */
+static void
+pb_slab_buffer_destroy(struct pb_buffer *_buf)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+ struct pb_slab *slab = buf->slab;
+ struct pb_slab_size_header *header = slab->header;
+ struct list_head *list = &buf->head;
+
+ _glthread_LOCK_MUTEX(header->mutex);
+
+ assert(buf->base.base.refcount == 0);
+
+ buf->mapCount = 0;
+
+ LIST_DEL(list);
+ LIST_ADDTAIL(list, &slab->freeBuffers);
+ slab->numFree++;
+
+ if (slab->head.next == &slab->head)
+ LIST_ADDTAIL(&slab->head, &header->slabs);
+
+ if (slab->numFree == slab->numBuffers) {
+ list = &slab->head;
+ LIST_DEL(list);
+ LIST_ADDTAIL(list, &header->freeSlabs);
+ }
+
+ if (header->slabs.next == &header->slabs || slab->numFree
+ != slab->numBuffers) {
+
+ struct list_head *next;
+
+ for (list = header->freeSlabs.next, next = list->next; list
+ != &header->freeSlabs; list = next, next = list->next) {
+
+ slab = LIST_ENTRY(struct pb_slab, list, head);
+
+ LIST_DELINIT(list);
+ pb_reference(&slab->bo, NULL);
+ FREE(slab->buffers);
+ FREE(slab);
+ }
+ }
+
+ _glthread_UNLOCK_MUTEX(header->mutex);
+}
+
+
+static void *
+pb_slab_buffer_map(struct pb_buffer *_buf,
+ unsigned flags)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+
+ ++buf->mapCount;
+ return (void *) ((uint8_t *) buf->slab->virtual + buf->start);
+}
+
+
+static void
+pb_slab_buffer_unmap(struct pb_buffer *_buf)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+
+ --buf->mapCount;
+ if (buf->mapCount == 0)
+ _glthread_COND_BROADCAST(buf->event);
+}
+
+
+static void
+pb_slab_buffer_get_base_buffer(struct pb_buffer *_buf,
+ struct pb_buffer **base_buf,
+ unsigned *offset)
+{
+ struct pb_slab_buffer *buf = pb_slab_buffer(_buf);
+ pb_get_base_buffer(buf->slab->bo, base_buf, offset);
+ *offset += buf->start;
+}
+
+
+static const struct pb_vtbl
+pb_slab_buffer_vtbl = {
+ pb_slab_buffer_destroy,
+ pb_slab_buffer_map,
+ pb_slab_buffer_unmap,
+ pb_slab_buffer_get_base_buffer
+};
+
+
+static enum pipe_error
+pb_slab_create(struct pb_slab_size_header *header)
+{
+ struct pb_slab_manager *pool = header->pool;
+ size_t size = header->bufSize * pool->desiredNumBuffers;
+ struct pb_slab *slab;
+ struct pb_slab_buffer *buf;
+ size_t numBuffers;
+ int ret;
+ unsigned i;
+
+ slab = CALLOC_STRUCT(pb_slab);
+ if (!slab)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ /*
+ * FIXME: We should perhaps allow some variation in slabsize in order
+ * to efficiently reuse slabs.
+ */
+
+ size = (size <= pool->maxSlabSize) ? size : pool->maxSlabSize;
+ size = (size + pool->pageSize - 1) & ~(pool->pageSize - 1);
+
+ slab->bo = pool->provider->create_buffer(pool->provider, size, &pool->desc);
+ if(!slab->bo)
+ goto out_err0;
+
+ slab->virtual = pb_map(slab->bo,
+ PIPE_BUFFER_USAGE_CPU_READ |
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ if(!slab->virtual)
+ goto out_err1;
+
+ pb_unmap(slab->bo);
+
+ numBuffers = slab->bo->base.size / header->bufSize;
+
+ slab->buffers = CALLOC(numBuffers, sizeof(*slab->buffers));
+ if (!slab->buffers) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
+ goto out_err1;
+ }
+
+ LIST_INITHEAD(&slab->head);
+ LIST_INITHEAD(&slab->freeBuffers);
+ slab->numBuffers = numBuffers;
+ slab->numFree = 0;
+ slab->header = header;
+
+ buf = slab->buffers;
+ for (i=0; i < numBuffers; ++i) {
+ buf->base.base.refcount = 0;
+ buf->base.base.size = header->bufSize;
+ buf->base.base.alignment = 0;
+ buf->base.base.usage = 0;
+ buf->base.vtbl = &pb_slab_buffer_vtbl;
+ buf->slab = slab;
+ buf->start = i* header->bufSize;
+ buf->mapCount = 0;
+ _glthread_INIT_COND(buf->event);
+ LIST_ADDTAIL(&buf->head, &slab->freeBuffers);
+ slab->numFree++;
+ buf++;
+ }
+
+ LIST_ADDTAIL(&slab->head, &header->slabs);
+
+ return PIPE_OK;
+
+out_err1:
+ pb_reference(&slab->bo, NULL);
+out_err0:
+ FREE(slab);
+ return ret;
+}
+
+
+static struct pb_buffer *
+pb_slab_manager_create_buffer(struct pb_manager *_pool,
+ size_t size,
+ const struct pb_desc *desc)
+{
+ struct pb_slab_manager *pool = pb_slab_manager(_pool);
+ struct pb_slab_size_header *header;
+ unsigned i;
+ static struct pb_slab_buffer *buf;
+ struct pb_slab *slab;
+ struct list_head *list;
+ int count = DRI_SLABPOOL_ALLOC_RETRIES;
+
+ /*
+ * FIXME: Check for compatibility.
+ */
+
+ header = pool->headers;
+ for (i=0; i<pool->numBuckets; ++i) {
+ if (header->bufSize >= size)
+ break;
+ header++;
+ }
+
+ if (i >= pool->numBuckets)
+ /* Fall back to allocate a buffer object directly from the provider. */
+ return pool->provider->create_buffer(pool->provider, size, desc);
+
+
+ _glthread_LOCK_MUTEX(header->mutex);
+ while (header->slabs.next == &header->slabs && count > 0) {
+ if (header->slabs.next != &header->slabs)
+ break;
+
+ _glthread_UNLOCK_MUTEX(header->mutex);
+ if (count != DRI_SLABPOOL_ALLOC_RETRIES)
+ util_time_sleep(1);
+ _glthread_LOCK_MUTEX(header->mutex);
+ (void) pb_slab_create(header);
+ count--;
+ }
+
+ list = header->slabs.next;
+ if (list == &header->slabs) {
+ _glthread_UNLOCK_MUTEX(header->mutex);
+ return NULL;
+ }
+ slab = LIST_ENTRY(struct pb_slab, list, head);
+ if (--slab->numFree == 0)
+ LIST_DELINIT(list);
+
+ list = slab->freeBuffers.next;
+ LIST_DELINIT(list);
+
+ _glthread_UNLOCK_MUTEX(header->mutex);
+ buf = LIST_ENTRY(struct pb_slab_buffer, list, head);
+ ++buf->base.base.refcount;
+ return &buf->base;
+}
+
+
+static void
+pb_slab_manager_destroy(struct pb_manager *_pool)
+{
+ struct pb_slab_manager *pool = pb_slab_manager(_pool);
+
+ FREE(pool->headers);
+ FREE(pool->bucketSizes);
+ FREE(pool);
+}
+
+
+struct pb_manager *
+pb_slab_manager_create(struct pb_manager *provider,
+ const struct pb_desc *desc,
+ size_t smallestSize,
+ size_t numSizes,
+ size_t desiredNumBuffers,
+ size_t maxSlabSize,
+ size_t pageAlignment)
+{
+ struct pb_slab_manager *pool;
+ size_t i;
+
+ pool = CALLOC_STRUCT(pb_slab_manager);
+ if (!pool)
+ goto out_err0;
+
+ pool->bucketSizes = CALLOC(numSizes, sizeof(*pool->bucketSizes));
+ if (!pool->bucketSizes)
+ goto out_err1;
+
+ pool->headers = CALLOC(numSizes, sizeof(*pool->headers));
+ if (!pool->headers)
+ goto out_err2;
+
+ pool->desc = *desc;
+ pool->numBuckets = numSizes;
+#ifdef WIN32
+ pool->pageSize = 4096;
+#else
+ pool->pageSize = getpagesize();
+#endif
+ pool->provider = provider;
+ pool->pageAlignment = pageAlignment;
+ pool->maxSlabSize = maxSlabSize;
+ pool->desiredNumBuffers = desiredNumBuffers;
+
+ for (i=0; i<pool->numBuckets; ++i) {
+ struct pb_slab_size_header *header = &pool->headers[i];
+
+ pool->bucketSizes[i] = (smallestSize << i);
+
+ _glthread_INIT_MUTEX(header->mutex);
+
+ LIST_INITHEAD(&header->slabs);
+ LIST_INITHEAD(&header->freeSlabs);
+
+ header->pool = pool;
+ header->bufSize = (smallestSize << i);
+ }
+
+ pool->base.destroy = pb_slab_manager_destroy;
+ pool->base.create_buffer = pb_slab_manager_create_buffer;
+
+ return &pool->base;
+
+out_err2:
+ FREE(pool->bucketSizes);
+out_err1:
+ FREE(pool);
+out_err0:
+ return NULL;
+}
diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
index 4d33950e99..aea8b28e58 100644
--- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
+++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c
@@ -317,7 +317,7 @@ void x86_call( struct x86_function *p, void (*label)())
void x86_call( struct x86_function *p, struct x86_reg reg)
{
emit_1ub(p, 0xff);
- emit_modrm(p, reg, reg);
+ emit_modrm_noreg(p, 2, reg);
}
#endif
diff --git a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c
index 4e80597b3f..c37e201b2b 100755
--- a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c
+++ b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c
@@ -225,6 +225,15 @@ get_coef_base( void )
return get_output_base();
}
+static struct x86_reg
+get_immediate_base( void )
+{
+ return x86_make_reg(
+ file_REG32,
+ reg_DI );
+}
+
+
/**
* Data access helpers.
*/
@@ -239,6 +248,16 @@ get_argument(
}
static struct x86_reg
+get_immediate(
+ unsigned vec,
+ unsigned chan )
+{
+ return x86_make_disp(
+ get_immediate_base(),
+ (vec * 4 + chan) * 4 );
+}
+
+static struct x86_reg
get_const(
unsigned vec,
unsigned chan )
@@ -548,6 +567,12 @@ emit_xorps(
* Data fetch helpers.
*/
+/**
+ * Copy a shader constant to xmm register
+ * \param xmm the destination xmm register
+ * \param vec the src const buffer index
+ * \param chan src channel to fetch (X, Y, Z or W)
+ */
static void
emit_const(
struct x86_function *func,
@@ -567,6 +592,31 @@ emit_const(
}
static void
+emit_immediate(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ emit_movss(
+ func,
+ make_xmm( xmm ),
+ get_immediate( vec, chan ) );
+ emit_shufps(
+ func,
+ make_xmm( xmm ),
+ make_xmm( xmm ),
+ SHUF( 0, 0, 0, 0 ) );
+}
+
+
+/**
+ * Copy a shader input to xmm register
+ * \param xmm the destination xmm register
+ * \param vec the src input attrib
+ * \param chan src channel to fetch (X, Y, Z or W)
+ */
+static void
emit_inputf(
struct x86_function *func,
unsigned xmm,
@@ -579,6 +629,12 @@ emit_inputf(
get_input( vec, chan ) );
}
+/**
+ * Store an xmm register to a shader output
+ * \param xmm the source xmm register
+ * \param vec the dest output attrib
+ * \param chan src dest channel to store (X, Y, Z or W)
+ */
static void
emit_output(
struct x86_function *func,
@@ -592,6 +648,12 @@ emit_output(
make_xmm( xmm ) );
}
+/**
+ * Copy a shader temporary to xmm register
+ * \param xmm the destination xmm register
+ * \param vec the src temp register
+ * \param chan src channel to fetch (X, Y, Z or W)
+ */
static void
emit_tempf(
struct x86_function *func,
@@ -605,6 +667,13 @@ emit_tempf(
get_temp( vec, chan ) );
}
+/**
+ * Load an xmm register with an input attrib coefficient (a0, dadx or dady)
+ * \param xmm the destination xmm register
+ * \param vec the src input/attribute coefficient index
+ * \param chan src channel to fetch (X, Y, Z or W)
+ * \param member 0=a0, 1=dadx, 2=dady
+ */
static void
emit_coef(
struct x86_function *func,
@@ -1160,6 +1229,14 @@ emit_fetch(
swizzle );
break;
+ case TGSI_FILE_IMMEDIATE:
+ emit_immediate(
+ func,
+ xmm,
+ reg->SrcRegister.Index,
+ swizzle );
+ break;
+
case TGSI_FILE_INPUT:
emit_inputf(
func,
@@ -2020,7 +2097,7 @@ emit_instruction(
STORE( func, *inst, 0, 0, CHAN_X );
}
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
- FETCH( func, *inst, 0, 0, CHAN_Y );
+ FETCH( func, *inst, 0, 0, CHAN_X );
emit_sin( func, 0 );
STORE( func, *inst, 0, 0, CHAN_Y );
}
@@ -2236,135 +2313,116 @@ emit_declaration(
}
}
-unsigned
-tgsi_emit_sse2(
- struct tgsi_token *tokens,
- struct x86_function *func )
-{
- struct tgsi_parse_context parse;
- unsigned ok = 1;
-
- DUMP_START();
-
- func->csr = func->store;
-
- emit_mov(
- func,
- get_input_base(),
- get_argument( 0 ) );
- emit_mov(
- func,
- get_output_base(),
- get_argument( 1 ) );
- emit_mov(
- func,
- get_const_base(),
- get_argument( 2 ) );
- emit_mov(
- func,
- get_temp_base(),
- get_argument( 3 ) );
-
- tgsi_parse_init( &parse, tokens );
-
- while( !tgsi_parse_end_of_tokens( &parse ) && ok ) {
- tgsi_parse_token( &parse );
-
- switch( parse.FullToken.Token.Type ) {
- case TGSI_TOKEN_TYPE_DECLARATION:
- break;
-
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- ok = emit_instruction(
- func,
- &parse.FullToken.FullInstruction );
-
- if (!ok) {
- debug_printf("failed to translate tgsi opcode %d to SSE\n",
- parse.FullToken.FullInstruction.Instruction.Opcode );
- }
- break;
-
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- /* XXX implement this */
- ok = 0;
- debug_printf("failed to emit immediate value to SSE\n");
- break;
-
- default:
- assert( 0 );
- ok = 0;
- break;
- }
- }
-
- tgsi_parse_free( &parse );
-
- DUMP_END();
-
- return ok;
-}
/**
- * Fragment shaders are responsible for interpolating shader inputs. Because on
- * x86 we have only 4 GP registers, and here we have 5 shader arguments (input,
- * output, const, temp and coef), the code is split into two phases --
- * DECLARATION and INSTRUCTION phase.
- * GP register holding the output argument is aliased with the coeff argument,
- * as outputs are not needed in the DECLARATION phase.
+ * Translate a TGSI vertex/fragment shader to SSE2 code.
+ * Slightly different things are done for vertex vs. fragment shaders.
+ *
+ * Note that fragment shaders are responsible for interpolating shader
+ * inputs. Because on x86 we have only 4 GP registers, and here we
+ * have 5 shader arguments (input, output, const, temp and coef), the
+ * code is split into two phases -- DECLARATION and INSTRUCTION phase.
+ * GP register holding the output argument is aliased with the coeff
+ * argument, as outputs are not needed in the DECLARATION phase.
+ *
+ * \param tokens the TGSI input shader
+ * \param func the output SSE code/function
+ * \param immediates buffer to place immediates, later passed to SSE func
+ * \param return 1 for success, 0 if translation failed
*/
unsigned
-tgsi_emit_sse2_fs(
+tgsi_emit_sse2(
struct tgsi_token *tokens,
- struct x86_function *func )
+ struct x86_function *func,
+ float (*immediates)[4])
{
struct tgsi_parse_context parse;
boolean instruction_phase = FALSE;
unsigned ok = 1;
+ uint num_immediates = 0;
DUMP_START();
func->csr = func->store;
- /* DECLARATION phase, do not load output argument. */
- emit_mov(
- func,
- get_input_base(),
- get_argument( 0 ) );
- emit_mov(
- func,
- get_const_base(),
- get_argument( 2 ) );
- emit_mov(
- func,
- get_temp_base(),
- get_argument( 3 ) );
- emit_mov(
- func,
- get_coef_base(),
- get_argument( 4 ) );
-
tgsi_parse_init( &parse, tokens );
+ /*
+ * Different function args for vertex/fragment shaders:
+ */
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
+ /* DECLARATION phase, do not load output argument. */
+ emit_mov(
+ func,
+ get_input_base(),
+ get_argument( 0 ) );
+ /* skipping outputs argument here */
+ emit_mov(
+ func,
+ get_const_base(),
+ get_argument( 2 ) );
+ emit_mov(
+ func,
+ get_temp_base(),
+ get_argument( 3 ) );
+ emit_mov(
+ func,
+ get_coef_base(),
+ get_argument( 4 ) );
+ emit_mov(
+ func,
+ get_immediate_base(),
+ get_argument( 5 ) );
+ }
+ else {
+ assert(parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX);
+
+ emit_mov(
+ func,
+ get_input_base(),
+ get_argument( 0 ) );
+ emit_mov(
+ func,
+ get_output_base(),
+ get_argument( 1 ) );
+ emit_mov(
+ func,
+ get_const_base(),
+ get_argument( 2 ) );
+ emit_mov(
+ func,
+ get_temp_base(),
+ get_argument( 3 ) );
+ emit_mov(
+ func,
+ get_immediate_base(),
+ get_argument( 4 ) );
+ }
+
while( !tgsi_parse_end_of_tokens( &parse ) && ok ) {
tgsi_parse_token( &parse );
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_DECLARATION:
- emit_declaration(
- func,
- &parse.FullToken.FullDeclaration );
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
+ emit_declaration(
+ func,
+ &parse.FullToken.FullDeclaration );
+ }
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
- if( !instruction_phase ) {
- /* INSTRUCTION phase, overwrite coeff with output. */
- instruction_phase = TRUE;
- emit_mov(
- func,
- get_output_base(),
- get_argument( 1 ) );
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
+ if( !instruction_phase ) {
+ /* INSTRUCTION phase, overwrite coeff with output. */
+ instruction_phase = TRUE;
+ emit_mov(
+ func,
+ get_output_base(),
+ get_argument( 1 ) );
+ }
}
+
ok = emit_instruction(
func,
&parse.FullToken.FullInstruction );
@@ -2376,9 +2434,26 @@ tgsi_emit_sse2_fs(
break;
case TGSI_TOKEN_TYPE_IMMEDIATE:
- /* XXX implement this */
- ok = 0;
- debug_printf("failed to emit immediate value to SSE\n");
+ /* simply copy the immediate values into the next immediates[] slot */
+ {
+ const uint size = parse.FullToken.FullImmediate.Immediate.Size - 1;
+ uint i;
+ assert(size <= 4);
+ assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES);
+ for( i = 0; i < size; i++ ) {
+ immediates[num_immediates][i] =
+ parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+ }
+#if 0
+ debug_printf("SSE FS immediate[%d] = %f %f %f %f\n",
+ num_immediates,
+ immediates[num_immediates][0],
+ immediates[num_immediates][1],
+ immediates[num_immediates][2],
+ immediates[num_immediates][3]);
+#endif
+ num_immediates++;
+ }
break;
default:
diff --git a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h
index 63b8ef3911..d56bf7f98a 100755
--- a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h
+++ b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h
@@ -11,12 +11,9 @@ struct x86_function;
unsigned
tgsi_emit_sse2(
struct tgsi_token *tokens,
- struct x86_function *function );
-
-unsigned
-tgsi_emit_sse2_fs(
- struct tgsi_token *tokens,
- struct x86_function *function );
+ struct x86_function *function,
+ float (*immediates)[4]
+ );
#if defined __cplusplus
}
diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_dump.c b/src/gallium/auxiliary/tgsi/util/tgsi_dump.c
index 7d292778ad..ff6a2c4194 100644
--- a/src/gallium/auxiliary/tgsi/util/tgsi_dump.c
+++ b/src/gallium/auxiliary/tgsi/util/tgsi_dump.c
@@ -30,6 +30,7 @@
#include "pipe/p_debug.h"
#include "pipe/p_util.h"
#include "pipe/p_shader_tokens.h"
+#include "util/u_string.h"
#include "tgsi_dump.h"
#include "tgsi_parse.h"
#include "tgsi_build.h"
@@ -147,7 +148,7 @@ gen_dump_uix(
{
char str[36];
- sprintf( str, "0x%x", ui );
+ util_snprintf( str, sizeof(str), "0x%x", ui );
gen_dump_str( dump, str );
}
@@ -158,7 +159,7 @@ gen_dump_uid(
{
char str[16];
- sprintf( str, "%u", ui );
+ util_snprintf( str, sizeof(str), "%u", ui );
gen_dump_str( dump, str );
}
@@ -169,7 +170,7 @@ gen_dump_sid(
{
char str[16];
- sprintf( str, "%d", si );
+ util_snprintf( str, sizeof(str), "%d", si );
gen_dump_str( dump, str );
}
@@ -180,7 +181,7 @@ gen_dump_flt(
{
char str[48];
- sprintf( str, "%10.4f", flt );
+ util_snprintf( str, sizeof(str), "%10.4f", flt );
gen_dump_str( dump, str );
}
@@ -746,17 +747,19 @@ dump_declaration_short(
}
}
- if( decl->Declaration.Interpolate ) {
+ if (decl->Declaration.Semantic) {
TXT( ", " );
- ENM( decl->Interpolation.Interpolate, TGSI_INTERPOLATES_SHORT );
+ ENM( decl->Semantic.SemanticName, TGSI_SEMANTICS_SHORT );
+ if (decl->Semantic.SemanticIndex != 0) {
+ CHR( '[' );
+ UID( decl->Semantic.SemanticIndex );
+ CHR( ']' );
+ }
}
- if( decl->Declaration.Semantic ) {
+ if (decl->Declaration.Interpolate) {
TXT( ", " );
- ENM( decl->Semantic.SemanticName, TGSI_SEMANTICS_SHORT );
- CHR( '[' );
- UID( decl->Semantic.SemanticIndex );
- CHR( ']' );
+ ENM( decl->Interpolation.Interpolate, TGSI_INTERPOLATES_SHORT );
}
}
@@ -966,18 +969,18 @@ dump_instruction_short(
}
CHR( ' ' );
- if( src->SrcRegisterExtMod.Complement ) {
- TXT( "(1 - " );
- }
- if( src->SrcRegisterExtMod.Negate ) {
- CHR( '-' );
- }
- if( src->SrcRegisterExtMod.Absolute ) {
+ if (src->SrcRegisterExtMod.Negate)
+ TXT( "-(" );
+ if (src->SrcRegisterExtMod.Absolute)
CHR( '|' );
- }
- if( src->SrcRegister.Negate ) {
+ if (src->SrcRegisterExtMod.Scale2X)
+ TXT( "2*(" );
+ if (src->SrcRegisterExtMod.Bias)
+ CHR( '(' );
+ if (src->SrcRegisterExtMod.Complement)
+ TXT( "1-(" );
+ if (src->SrcRegister.Negate)
CHR( '-' );
- }
ENM( src->SrcRegister.File, TGSI_FILES_SHORT );
@@ -985,35 +988,37 @@ dump_instruction_short(
SID( src->SrcRegister.Index );
CHR( ']' );
- if (src->SrcRegister.Extended) {
- if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
- src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
- src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
- src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
- CHR( '.' );
- ENM( src->SrcRegisterExtSwz.ExtSwizzleX, TGSI_EXTSWIZZLES_SHORT );
- ENM( src->SrcRegisterExtSwz.ExtSwizzleY, TGSI_EXTSWIZZLES_SHORT );
- ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, TGSI_EXTSWIZZLES_SHORT );
- ENM( src->SrcRegisterExtSwz.ExtSwizzleW, TGSI_EXTSWIZZLES_SHORT );
- }
- }
- else if( src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
- src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
- src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
- src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W ) {
+ if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
+ src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
+ src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
+ src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
CHR( '.' );
ENM( src->SrcRegister.SwizzleX, TGSI_SWIZZLES_SHORT );
ENM( src->SrcRegister.SwizzleY, TGSI_SWIZZLES_SHORT );
ENM( src->SrcRegister.SwizzleZ, TGSI_SWIZZLES_SHORT );
ENM( src->SrcRegister.SwizzleW, TGSI_SWIZZLES_SHORT );
}
+ if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
+ src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
+ src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
+ src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
+ CHR( '.' );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleX, TGSI_EXTSWIZZLES_SHORT );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleY, TGSI_EXTSWIZZLES_SHORT );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, TGSI_EXTSWIZZLES_SHORT );
+ ENM( src->SrcRegisterExtSwz.ExtSwizzleW, TGSI_EXTSWIZZLES_SHORT );
+ }
- if( src->SrcRegisterExtMod.Absolute ) {
+ if (src->SrcRegisterExtMod.Complement)
+ CHR( ')' );
+ if (src->SrcRegisterExtMod.Bias)
+ TXT( ")-.5" );
+ if (src->SrcRegisterExtMod.Scale2X)
+ CHR( ')' );
+ if (src->SrcRegisterExtMod.Absolute)
CHR( '|' );
- }
- if( src->SrcRegisterExtMod.Complement ) {
+ if (src->SrcRegisterExtMod.Negate)
CHR( ')' );
- }
first_reg = FALSE;
}
@@ -1400,7 +1405,6 @@ dump_gen(
CHR( '\n' );
ENM( parse.FullHeader.Processor.Processor, TGSI_PROCESSOR_TYPES_SHORT );
- CHR( ' ' );
UID( parse.FullVersion.Version.MajorVersion );
CHR( '.' );
UID( parse.FullVersion.Version.MinorVersion );
diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile
index 9b6c2708b6..05bc43131a 100644
--- a/src/gallium/auxiliary/util/Makefile
+++ b/src/gallium/auxiliary/util/Makefile
@@ -14,7 +14,9 @@ C_SOURCES = \
u_hash_table.c \
u_mm.c \
u_simple_shaders.c \
- u_snprintf.c
+ u_snprintf.c \
+ u_time.c \
+ u_mm.c
include ../../Makefile.template
diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript
index 9b3929eb2d..d55d2c7081 100644
--- a/src/gallium/auxiliary/util/SConscript
+++ b/src/gallium/auxiliary/util/SConscript
@@ -15,6 +15,7 @@ util = env.ConvenienceLibrary(
'u_mm.c',
'u_simple_shaders.c',
'u_snprintf.c',
+ 'u_time.c',
])
auxiliaries.insert(0, util)
diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c
index 090e3b7794..f9366467cd 100644
--- a/src/gallium/auxiliary/util/p_debug.c
+++ b/src/gallium/auxiliary/util/p_debug.c
@@ -39,6 +39,7 @@
#include "pipe/p_compiler.h"
#include "pipe/p_util.h"
#include "pipe/p_debug.h"
+#include "util/u_string.h"
#ifdef WIN32
@@ -60,7 +61,7 @@ void _debug_vprintf(const char *format, va_list ap)
/* EngDebugPrint does not handle float point arguments, so we need to use
* our own vsnprintf implementation */
char buf[512 + 1];
- vsnprintf(buf, sizeof(buf), format, ap);
+ util_vsnprintf(buf, sizeof(buf), format, ap);
_EngDebugPrint("%s", buf);
#else
/* TODO: Implement debug print for WINCE */
@@ -311,7 +312,7 @@ debug_dump_enum(const struct debug_named_value *names,
++names;
}
- snprintf(rest, sizeof(rest), "0x%08lx", value);
+ util_snprintf(rest, sizeof(rest), "0x%08lx", value);
return rest;
}
@@ -344,7 +345,7 @@ debug_dump_flags(const struct debug_named_value *names,
else
first = 0;
- snprintf(rest, sizeof(rest), "0x%08lx", value);
+ util_snprintf(rest, sizeof(rest), "0x%08lx", value);
strncat(output, rest, sizeof(output));
}
diff --git a/src/gallium/auxiliary/util/p_debug_mem.c b/src/gallium/auxiliary/util/p_debug_mem.c
index 97ec9c5b39..aba69c0294 100644
--- a/src/gallium/auxiliary/util/p_debug_mem.c
+++ b/src/gallium/auxiliary/util/p_debug_mem.c
@@ -73,6 +73,25 @@ static struct list_head list = { &list, &list };
static unsigned long last_no = 0;
+static INLINE struct debug_memory_header *
+header_from_data(void *data)
+{
+ if(data)
+ return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header));
+ else
+ return NULL;
+}
+
+static INLINE void *
+data_from_header(struct debug_memory_header *hdr)
+{
+ if(hdr)
+ return (void *)((char *)hdr + sizeof(struct debug_memory_header));
+ else
+ return NULL;
+}
+
+
void *
debug_malloc(const char *file, unsigned line, const char *function,
size_t size)
@@ -92,7 +111,7 @@ debug_malloc(const char *file, unsigned line, const char *function,
LIST_ADDTAIL(&hdr->head, &list);
- return (void *)((char *)hdr + sizeof(*hdr));
+ return data_from_header(hdr);
}
void
@@ -104,7 +123,7 @@ debug_free(const char *file, unsigned line, const char *function,
if(!ptr)
return;
- hdr = (struct debug_memory_header *)((char *)ptr - sizeof(*hdr));
+ hdr = header_from_data(ptr);
if(hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
file, line, function,
@@ -133,16 +152,46 @@ void *
debug_realloc(const char *file, unsigned line, const char *function,
void *old_ptr, size_t old_size, size_t new_size )
{
- void *new_ptr = NULL;
-
- if (new_size != 0) {
- new_ptr = debug_malloc( file, line, function, new_size );
-
- if( new_ptr && old_ptr )
- memcpy( new_ptr, old_ptr, old_size );
+ struct debug_memory_header *old_hdr, *new_hdr;
+ void *new_ptr;
+
+ if(!old_ptr)
+ return debug_malloc( file, line, function, new_size );
+
+ if(!new_size) {
+ debug_free( file, line, function, old_ptr );
+ return NULL;
}
+
+ old_hdr = header_from_data(old_ptr);
+ if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
+ file, line, function,
+ old_ptr);
+ debug_assert(0);
+ return NULL;
+ }
+
+ /* alloc new */
+ new_hdr = real_malloc(sizeof(*new_hdr) + new_size);
+ if(!new_hdr)
+ return NULL;
+ new_hdr->no = old_hdr->no;
+ new_hdr->file = old_hdr->file;
+ new_hdr->line = old_hdr->line;
+ new_hdr->function = old_hdr->function;
+ new_hdr->size = new_size;
+ new_hdr->magic = DEBUG_MEMORY_MAGIC;
+ LIST_REPLACE(&old_hdr->head, &new_hdr->head);
+
+ /* copy data */
+ new_ptr = data_from_header(new_hdr);
+ memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
+
+ /* free old */
+ old_hdr->magic = 0;
+ real_free(old_hdr);
- debug_free( file, line, function, old_ptr );
return new_ptr;
}
@@ -162,7 +211,7 @@ debug_memory_end(unsigned long start_no)
struct debug_memory_header *hdr;
void *ptr;
hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
- ptr = (void *)((char *)hdr + sizeof(*hdr));
+ ptr = data_from_header(hdr);
if(start_no <= hdr->no && hdr->no < last_no ||
last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))
debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
diff --git a/src/gallium/auxiliary/util/u_double_list.h b/src/gallium/auxiliary/util/u_double_list.h
index 8cb10c9820..d108d92e52 100644
--- a/src/gallium/auxiliary/util/u_double_list.h
+++ b/src/gallium/auxiliary/util/u_double_list.h
@@ -70,6 +70,14 @@ struct list_head
(__list)->prev = (__item); \
} while(0)
+#define LIST_REPLACE(__from, __to) \
+ do { \
+ (__to)->prev = (__from)->prev; \
+ (__to)->next = (__from)->next; \
+ (__from)->next->prev = (__to); \
+ (__from)->prev->next = (__to); \
+ } while (0)
+
#define LIST_DEL(__item) \
do { \
(__item)->prev->next = (__item)->next; \
diff --git a/src/gallium/auxiliary/util/u_snprintf.c b/src/gallium/auxiliary/util/u_snprintf.c
index 48426abcb7..c4f4bbd30c 100644
--- a/src/gallium/auxiliary/util/u_snprintf.c
+++ b/src/gallium/auxiliary/util/u_snprintf.c
@@ -166,8 +166,8 @@
#include <config.h>
#else
#ifdef WIN32
-#define vsnprintf rpl_vsnprintf
-#define snprintf rpl_snprintf
+#define vsnprintf util_vsnprintf
+#define snprintf util_snprintf
#define HAVE_VSNPRINTF 0
#define HAVE_SNPRINTF 0
#define HAVE_VASPRINTF 1 /* not needed */
@@ -445,7 +445,7 @@ static UINTMAX_T myround(LDOUBLE);
static LDOUBLE mypow10(int);
int
-rpl_vsnprintf(char *str, size_t size, const char *format, va_list args)
+util_vsnprintf(char *str, size_t size, const char *format, va_list args)
{
LDOUBLE fvalue;
INTMAX_T value;
@@ -1404,7 +1404,7 @@ mymemcpy(void *dst, void *src, size_t len)
#endif /* NEED_MYMEMCPY */
int
-rpl_vasprintf(char **ret, const char *format, va_list ap)
+util_vasprintf(char **ret, const char *format, va_list ap)
{
size_t size;
int len;
@@ -1422,10 +1422,10 @@ rpl_vasprintf(char **ret, const char *format, va_list ap)
#if !HAVE_SNPRINTF
#if HAVE_STDARG_H
int
-rpl_snprintf(char *str, size_t size, const char *format, ...)
+util_snprintf(char *str, size_t size, const char *format, ...)
#else
int
-rpl_snprintf(va_alist) va_dcl
+util_snprintf(va_alist) va_dcl
#endif /* HAVE_STDARG_H */
{
#if !HAVE_STDARG_H
@@ -1449,10 +1449,10 @@ rpl_snprintf(va_alist) va_dcl
#if !HAVE_ASPRINTF
#if HAVE_STDARG_H
int
-rpl_asprintf(char **ret, const char *format, ...)
+util_asprintf(char **ret, const char *format, ...)
#else
int
-rpl_asprintf(va_alist) va_dcl
+util_asprintf(va_alist) va_dcl
#endif /* HAVE_STDARG_H */
{
#if !HAVE_STDARG_H
diff --git a/src/gallium/auxiliary/util/u_string.h b/src/gallium/auxiliary/util/u_string.h
new file mode 100644
index 0000000000..b99d4e8021
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_string.h
@@ -0,0 +1,63 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Platform independent functions for string manipulation.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_STRING_H_
+#define U_STRING_H_
+
+#ifndef WIN32
+#include <stdio.h>
+#endif
+#include <stddef.h>
+#include <stdarg.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef WIN32
+int util_vsnprintf(char *, size_t, const char *, va_list);
+int util_snprintf(char *str, size_t size, const char *format, ...);
+#else
+#define util_vsnprintf vsnprintf
+#define util_snprintf snprintf
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_STRING_H_ */
diff --git a/src/gallium/auxiliary/util/u_time.c b/src/gallium/auxiliary/util/u_time.c
new file mode 100644
index 0000000000..e6c0b19ff6
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_time.c
@@ -0,0 +1,152 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * OS independent time-manipulation functions.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+#ifndef WIN32
+#include <sys/time.h>
+#else
+#include <windows.h>
+#include <winddi.h>
+#endif
+
+#include "util/u_time.h"
+
+
+#ifdef WIN32
+static LONGLONG frequency = 0;
+#endif
+
+
+void
+util_time_get(struct util_time *t)
+{
+#ifndef WIN32
+ gettimeofday(&t->tv, NULL);
+#else
+ EngQueryPerformanceCounter(&t->counter);
+#endif
+}
+
+
+void
+util_time_add(const struct util_time *t1,
+ int64_t usecs,
+ struct util_time *t2)
+{
+#ifndef WIN32
+ t2->tv.tv_sec = t1->tv.tv_sec + usecs / 1000000;
+ t2->tv.tv_usec = t1->tv.tv_usec + usecs % 1000000;
+#else
+ if(!frequency)
+ EngQueryPerformanceFrequency(&frequency);
+ t2->counter = t1->counter + (usecs * frequency + 999999LL)/1000000LL;
+#endif
+}
+
+
+int64_t
+util_time_diff(const struct util_time *t1,
+ const struct util_time *t2)
+{
+#ifndef WIN32
+ return (t2->tv.tv_usec - t1->tv.tv_usec) +
+ (t2->tv.tv_sec - t1->tv.tv_sec)*1000000;
+#else
+ return (t2->counter - t1->counter)*1000000LL/frequency;
+#endif
+}
+
+
+/**
+ * Compare two time values.
+ *
+ * Not publicly available because it does not take in account wrap-arounds.
+ * Use util_time_timeout instead.
+ */
+static INLINE int
+util_time_compare(const struct util_time *t1,
+ const struct util_time *t2)
+{
+#ifndef WIN32
+ if (t1->tv.tv_sec < t2->tv.tv_sec)
+ return -1;
+ else if(t1->tv.tv_sec > t2->tv.tv_sec)
+ return 1;
+ else if (t1->tv.tv_usec < t2->tv.tv_usec)
+ return -1;
+ else if(t1->tv.tv_usec > t2->tv.tv_usec)
+ return 1;
+ else
+ return 0;
+#else
+ if (t1->counter < t2->counter)
+ return -1;
+ else if(t1->counter > t2->counter)
+ return 1;
+ else
+ return 0;
+#endif
+}
+
+
+int
+util_time_timeout(const struct util_time *start,
+ const struct util_time *end,
+ const struct util_time *curr)
+{
+ if(util_time_compare(start, end) <= 0)
+ return util_time_compare(start, curr) <= 0 && util_time_compare(curr, end) < 0;
+ else
+ return util_time_compare(start, curr) <= 0 || util_time_compare(curr, end) < 0;
+}
+
+
+#ifdef WIN32
+void util_time_usleep(unsigned usecs)
+{
+ LONGLONG start, curr, end;
+
+ EngQueryPerformanceCounter(&start);
+
+ if(!frequency)
+ EngQueryPerformanceFrequency(&frequency);
+
+ end = start + (usecs * frequency + 999999LL)/1000000LL;
+
+ do {
+ EngQueryPerformanceCounter(&curr);
+ } while(start <= curr && curr < end ||
+ end < start && (curr < end || start <= curr));
+}
+#endif
diff --git a/src/gallium/auxiliary/util/u_time.h b/src/gallium/auxiliary/util/u_time.h
new file mode 100644
index 0000000000..32035cceb5
--- /dev/null
+++ b/src/gallium/auxiliary/util/u_time.h
@@ -0,0 +1,99 @@
+/**************************************************************************
+ *
+ * Copyright 2008 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * OS independent time-manipulation functions.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+#ifndef U_TIME_H_
+#define U_TIME_H_
+
+
+#ifndef WIN32
+#include <time.h> /* timeval */
+#include <unistd.h> /* usleep */
+#endif
+
+#include "pipe/p_compiler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Time abstraction.
+ *
+ * Do not access this structure directly. Use the provided function instead.
+ */
+struct util_time
+{
+#ifndef WIN32
+ struct timeval tv;
+#else
+ long long counter;
+#endif
+};
+
+
+void
+util_time_get(struct util_time *t);
+
+void
+util_time_add(const struct util_time *t1,
+ int64_t usecs,
+ struct util_time *t2);
+
+int64_t
+util_time_diff(const struct util_time *t1,
+ const struct util_time *t2);
+
+/**
+ * Returns zero when the timeout expires, non zero otherwise.
+ */
+int
+util_time_timeout(const struct util_time *start,
+ const struct util_time *end,
+ const struct util_time *curr);
+
+#ifndef WIN32
+#define util_time_sleep usleep
+#else
+int
+util_time_sleep(unsigned usecs);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_TIME_H_ */