summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/cso_cache/cso_cache.c41
-rw-r--r--src/gallium/auxiliary/draw/Makefile4
-rw-r--r--src/gallium/auxiliary/draw/SConscript6
-rw-r--r--src/gallium/auxiliary/draw/draw_aaline.c9
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c65
-rw-r--r--src/gallium/auxiliary/draw/draw_passthrough.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_prim.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h33
-rw-r--r--src/gallium/auxiliary/draw/draw_pstipple.c31
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c206
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h118
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_elts.c88
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c364
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_vcache.c337
-rw-r--r--src/gallium/auxiliary/draw/draw_validate.c26
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_exec.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_sse.c6
-rw-r--r--src/gallium/auxiliary/tgsi/util/tgsi_parse.c13
-rw-r--r--src/gallium/auxiliary/tgsi/util/tgsi_parse.h4
-rw-r--r--src/gallium/auxiliary/util/SConscript1
-rw-r--r--src/gallium/auxiliary/util/p_debug.c213
-rw-r--r--src/gallium/auxiliary/util/p_debug_mem.c172
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c26
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.h3
-rw-r--r--src/gallium/drivers/softpipe/sp_winsys.h10
-rw-r--r--src/gallium/include/pipe/p_debug.h218
-rw-r--r--src/gallium/include/pipe/p_util.h29
28 files changed, 1842 insertions, 201 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.c b/src/gallium/auxiliary/cso_cache/cso_cache.c
index a2764b4265c..18acab09674 100644
--- a/src/gallium/auxiliary/cso_cache/cso_cache.c
+++ b/src/gallium/auxiliary/cso_cache/cso_cache.c
@@ -29,6 +29,7 @@
*/
#include "pipe/p_util.h"
+#include "pipe/p_debug.h"
#include "cso_cache.h"
#include "cso_hash.h"
@@ -131,75 +132,77 @@ static int _cso_size_for_type(enum cso_cache_type type)
static void delete_blend_state(void *state, void *data)
{
struct cso_blend *cso = (struct cso_blend *)state;
- if (cso->delete_state && cso->data != &cso->state)
+ if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
+ FREE(state);
}
static void delete_depth_stencil_state(void *state, void *data)
{
struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
- if (cso->delete_state && cso->data != &cso->state)
+ if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
+ FREE(state);
}
static void delete_sampler_state(void *state, void *data)
{
struct cso_sampler *cso = (struct cso_sampler *)state;
- if (cso->delete_state && cso->data != &cso->state)
+ if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
+ FREE(state);
}
static void delete_rasterizer_state(void *state, void *data)
{
struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
- if (cso->delete_state && cso->data != &cso->state)
+ if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
+ FREE(state);
}
static void delete_fs_state(void *state, void *data)
{
struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
- if (cso->delete_state && cso->data != &cso->state)
+ if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
+ FREE(state);
}
static void delete_vs_state(void *state, void *data)
{
struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
- if (cso->delete_state && cso->data != &cso->state)
+ if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
+ FREE(state);
}
static INLINE void delete_cso(void *state, enum cso_cache_type type)
{
switch (type) {
- case CSO_BLEND: {
+ case CSO_BLEND:
delete_blend_state(state, 0);
- }
break;
- case CSO_SAMPLER: {
+ case CSO_SAMPLER:
delete_sampler_state(state, 0);
- }
break;
- case CSO_DEPTH_STENCIL_ALPHA: {
+ case CSO_DEPTH_STENCIL_ALPHA:
delete_depth_stencil_state(state, 0);
- }
break;
- case CSO_RASTERIZER: {
+ case CSO_RASTERIZER:
delete_rasterizer_state(state, 0);
- }
break;
- case CSO_FRAGMENT_SHADER: {
+ case CSO_FRAGMENT_SHADER:
delete_fs_state(state, 0);
- }
break;
- case CSO_VERTEX_SHADER: {
+ case CSO_VERTEX_SHADER:
delete_vs_state(state, 0);
- }
break;
+ default:
+ assert(0);
+ FREE(state);
}
- FREE(state);
}
static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile
index 21e9f737b77..0c7ce5da5ba 100644
--- a/src/gallium/auxiliary/draw/Makefile
+++ b/src/gallium/auxiliary/draw/Makefile
@@ -16,6 +16,10 @@ C_SOURCES = \
draw_flatshade.c \
draw_offset.c \
draw_passthrough.c \
+ draw_pt.c \
+ draw_pt_vcache.c \
+ draw_pt_fetch_emit.c \
+ draw_pt_elts.c \
draw_prim.c \
draw_pstipple.c \
draw_stipple.c \
diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript
index d7fb86d992c..9b3e7247c54 100644
--- a/src/gallium/auxiliary/draw/SConscript
+++ b/src/gallium/auxiliary/draw/SConscript
@@ -14,7 +14,11 @@ draw = env.ConvenienceLibrary(
'draw_debug.c',
'draw_flatshade.c',
'draw_offset.c',
- 'draw_passthrough.c',
+ 'draw_passthrough.c', # going away soon
+ 'draw_pt.c',
+ 'draw_pt_vcache.c',
+ 'draw_pt_fetch_emit.c',
+ 'draw_pt_elts.c',
'draw_prim.c',
'draw_pstipple.c',
'draw_stipple.c',
diff --git a/src/gallium/auxiliary/draw/draw_aaline.c b/src/gallium/auxiliary/draw/draw_aaline.c
index 6742f7f4b96..cc1873abada 100644
--- a/src/gallium/auxiliary/draw/draw_aaline.c
+++ b/src/gallium/auxiliary/draw/draw_aaline.c
@@ -621,7 +621,7 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header)
bind_aaline_fragment_shader(aaline);
aaline->state.sampler[num] = aaline->sampler_cso;
- aaline->state.texture[num] = aaline->texture;
+ pipe_texture_reference(&aaline->state.texture[num], aaline->texture);
aaline->driver_bind_sampler_states(pipe, num + 1, aaline->state.sampler);
aaline->driver_set_sampler_textures(pipe, num + 1, aaline->state.texture);
@@ -769,9 +769,14 @@ aaline_set_sampler_textures(struct pipe_context *pipe,
unsigned num, struct pipe_texture **texture)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+ uint i;
+
/* save current */
- memcpy(aaline->state.texture, texture, num * sizeof(struct pipe_texture *));
+ for (i = 0; i < num; i++) {
+ pipe_texture_reference(&aaline->state.texture[i], texture[i]);
+ }
aaline->num_textures = num;
+
/* pass-through */
aaline->driver_set_sampler_textures(aaline->pipe, num, texture);
}
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 41da93cdf83..903cc267662 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -37,10 +37,11 @@
#include "draw_vbuf.h"
-
struct draw_context *draw_create( void )
{
struct draw_context *draw = CALLOC_STRUCT( draw_context );
+ if (draw == NULL)
+ goto fail;
#if defined(__i386__) || defined(__386__)
draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL;
@@ -61,6 +62,19 @@ struct draw_context *draw_create( void )
draw->pipeline.validate = draw_validate_stage( draw );
draw->pipeline.first = draw->pipeline.validate;
+ if (!draw->pipeline.wide_line ||
+ !draw->pipeline.wide_point ||
+ !draw->pipeline.stipple ||
+ !draw->pipeline.unfilled ||
+ !draw->pipeline.twoside ||
+ !draw->pipeline.offset ||
+ !draw->pipeline.clip ||
+ !draw->pipeline.flatshade ||
+ !draw->pipeline.cull ||
+ !draw->pipeline.validate)
+ goto fail;
+
+
ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 );
ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 );
ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 );
@@ -75,6 +89,8 @@ struct draw_context *draw_create( void )
uint i;
const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
char *tmp = align_malloc(Elements(draw->vs.queue) * size, 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);
@@ -93,22 +109,42 @@ struct draw_context *draw_create( void )
draw_vertex_cache_invalidate( draw );
draw_set_mapped_element_buffer( draw, 0, NULL );
+ if (!draw_pt_init( draw ))
+ goto fail;
+
return draw;
+
+fail:
+ draw_destroy( draw );
+ return NULL;
}
void draw_destroy( struct draw_context *draw )
{
- draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
- draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
- draw->pipeline.stipple->destroy( draw->pipeline.stipple );
- draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
- draw->pipeline.twoside->destroy( draw->pipeline.twoside );
- draw->pipeline.offset->destroy( draw->pipeline.offset );
- draw->pipeline.clip->destroy( draw->pipeline.clip );
- draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
- draw->pipeline.cull->destroy( draw->pipeline.cull );
- draw->pipeline.validate->destroy( draw->pipeline.validate );
+ if (!draw)
+ return;
+
+ if (draw->pipeline.wide_line)
+ draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
+ if (draw->pipeline.wide_point)
+ draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
+ if (draw->pipeline.stipple)
+ draw->pipeline.stipple->destroy( draw->pipeline.stipple );
+ if (draw->pipeline.unfilled)
+ draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
+ if (draw->pipeline.twoside)
+ draw->pipeline.twoside->destroy( draw->pipeline.twoside );
+ if (draw->pipeline.offset)
+ draw->pipeline.offset->destroy( draw->pipeline.offset );
+ if (draw->pipeline.clip)
+ draw->pipeline.clip->destroy( draw->pipeline.clip );
+ if (draw->pipeline.flatshade)
+ draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
+ if (draw->pipeline.cull)
+ draw->pipeline.cull->destroy( draw->pipeline.cull );
+ if (draw->pipeline.validate)
+ draw->pipeline.validate->destroy( draw->pipeline.validate );
if (draw->pipeline.aaline)
draw->pipeline.aaline->destroy( draw->pipeline.aaline );
if (draw->pipeline.aapoint)
@@ -117,8 +153,11 @@ void draw_destroy( struct draw_context *draw )
draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
if (draw->pipeline.rasterize)
draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
+
tgsi_exec_machine_free_data(&draw->machine);
- align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
+
+ if (draw->vs.queue[0].vertex)
+ align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
/* Not so fast -- we're just borrowing this at the moment.
*
@@ -126,6 +165,8 @@ void draw_destroy( struct draw_context *draw )
draw->render->destroy( draw->render );
*/
+ draw_pt_destroy( draw );
+
FREE( draw );
}
diff --git a/src/gallium/auxiliary/draw/draw_passthrough.c b/src/gallium/auxiliary/draw/draw_passthrough.c
index fdec6a591b8..dd00894c5bd 100644
--- a/src/gallium/auxiliary/draw/draw_passthrough.c
+++ b/src/gallium/auxiliary/draw/draw_passthrough.c
@@ -125,9 +125,9 @@ fetch_store_general( struct draw_context *draw,
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
ubyte *ub = (ubyte *) from;
- attrib[0] = UBYTE_TO_FLOAT(ub[0]);
+ attrib[2] = UBYTE_TO_FLOAT(ub[0]);
attrib[1] = UBYTE_TO_FLOAT(ub[1]);
- attrib[2] = UBYTE_TO_FLOAT(ub[2]);
+ attrib[0] = UBYTE_TO_FLOAT(ub[2]);
attrib[3] = UBYTE_TO_FLOAT(ub[3]);
}
break;
diff --git a/src/gallium/auxiliary/draw/draw_prim.c b/src/gallium/auxiliary/draw/draw_prim.c
index cb0277fb6c9..4fe0ddc02a7 100644
--- a/src/gallium/auxiliary/draw/draw_prim.c
+++ b/src/gallium/auxiliary/draw/draw_prim.c
@@ -526,7 +526,7 @@ draw_arrays(struct draw_context *draw, unsigned prim,
/* drawing done here: */
if (!draw->rasterizer->bypass_vs ||
- !draw_passthrough_arrays(draw, prim, start, count)) {
+ !draw_pt_arrays(draw, prim, start, count)) {
/* we have to run the whole pipeline */
draw_prim(draw, prim, start, count);
}
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 1c65c3d1b2a..0c5afcacfae 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -53,6 +53,9 @@ struct pipe_context;
struct gallivm_prog;
struct gallivm_cpu_engine;
+struct draw_pt_middle_end;
+struct draw_pt_front_end;
+
/**
* Basic vertex info.
* Carry some useful information around with the vertices in the prim pipe.
@@ -203,8 +206,21 @@ struct draw_context
/* Support prototype passthrough path:
*/
struct {
- unsigned prim;
- unsigned hw_vertex_size;
+ unsigned prim; /* XXX: to be removed */
+ unsigned hw_vertex_size; /* XXX: to be removed */
+
+ struct {
+ struct draw_pt_middle_end *fetch_emit;
+ struct draw_pt_middle_end *fetch_shade_emit;
+ struct draw_pt_middle_end *fetch_shade_cliptest_pipeline_or_emit;
+ } middle;
+
+ struct {
+ struct draw_pt_front_end *noop;
+ struct draw_pt_front_end *split_arrays;
+ struct draw_pt_front_end *vcache;
+ } front;
+
} pt;
@@ -351,7 +367,18 @@ extern void draw_update_vertex_fetch( struct draw_context *draw );
extern boolean draw_need_pipeline(const struct draw_context *draw);
-/* Prototype/hack
+/* Passthrough mode (second attempt):
+ */
+boolean draw_pt_init( struct draw_context *draw );
+void draw_pt_destroy( struct draw_context *draw );
+boolean draw_pt_arrays( struct draw_context *draw,
+ unsigned prim,
+ unsigned start,
+ unsigned count );
+
+
+
+/* Prototype/hack (DEPRECATED)
*/
boolean
draw_passthrough_arrays(struct draw_context *draw,
diff --git a/src/gallium/auxiliary/draw/draw_pstipple.c b/src/gallium/auxiliary/draw/draw_pstipple.c
index bd8d3a76ae5..9cec9866408 100644
--- a/src/gallium/auxiliary/draw/draw_pstipple.c
+++ b/src/gallium/auxiliary/draw/draw_pstipple.c
@@ -56,6 +56,7 @@ struct pstip_fragment_shader
struct pipe_shader_state state;
void *driver_fs;
void *pstip_fs;
+ uint sampler_unit;
};
@@ -67,7 +68,6 @@ struct pstip_stage
struct draw_stage stage;
void *sampler_cso;
- uint sampler_unit;
struct pipe_texture *texture;
uint num_samplers;
uint num_textures;
@@ -329,7 +329,7 @@ generate_pstip_fs(struct pstip_stage *pstip)
tgsi_dump(pstip_fs.tokens, 0);
#endif
- pstip->sampler_unit = transform.maxSampler + 1;
+ pstip->fs->sampler_unit = transform.maxSampler + 1;
pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
}
@@ -398,6 +398,7 @@ pstip_create_texture(struct pstip_stage *pstip)
texTemp.cpp = 1;
pstip->texture = screen->texture_create(screen, &texTemp);
+ assert(pstip->texture->refcount == 1);
//pstip_update_texture(pstip);
}
@@ -488,11 +489,14 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
/* how many samplers? */
/* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
num_samplers = MAX2(pstip->num_textures, pstip->num_samplers);
- num_samplers = MAX2(num_samplers, pstip->sampler_unit + 1);
+ num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1);
/* plug in our sampler, texture */
- pstip->state.samplers[pstip->sampler_unit] = pstip->sampler_cso;
- pstip->state.textures[pstip->sampler_unit] = pstip->texture;
+ pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
+ pipe_texture_reference(&pstip->state.textures[pstip->fs->sampler_unit],
+ pstip->texture);
+
+ assert(num_samplers <= PIPE_MAX_SAMPLERS);
pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers);
pstip->driver_set_sampler_textures(pipe, num_samplers, pstip->state.textures);
@@ -624,8 +628,14 @@ pstip_bind_sampler_states(struct pipe_context *pipe,
unsigned num, void **sampler)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
+ uint i;
+
/* save current */
memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
+ for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
+ pstip->state.samplers[i] = NULL;
+ }
+
pstip->num_samplers = num;
/* pass-through */
pstip->driver_bind_sampler_states(pstip->pipe, num, sampler);
@@ -637,9 +647,18 @@ pstip_set_sampler_textures(struct pipe_context *pipe,
unsigned num, struct pipe_texture **texture)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
+ uint i;
+
/* save current */
- memcpy(pstip->state.textures, texture, num * sizeof(struct pipe_texture *));
+ for (i = 0; i < num; i++) {
+ pipe_texture_reference(&pstip->state.textures[i], texture[i]);
+ }
+ for (; i < PIPE_MAX_SAMPLERS; i++) {
+ pipe_texture_reference(&pstip->state.textures[i], NULL);
+ }
+
pstip->num_textures = num;
+
/* pass-through */
pstip->driver_set_sampler_textures(pstip->pipe, num, texture);
}
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
new file mode 100644
index 00000000000..d7169f78f44
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -0,0 +1,206 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_pt.h"
+
+
+static boolean too_many_verts( struct draw_context *draw,
+ unsigned verts )
+{
+ return verts < 1024;
+}
+
+static boolean too_many_elts( struct draw_context *draw,
+ unsigned elts )
+{
+ return elts < (16 * 1024);
+}
+
+
+boolean
+draw_pt_arrays(struct draw_context *draw,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ const boolean pipeline = draw_need_pipeline(draw);
+ const boolean cliptest = !draw->rasterizer->bypass_clipping;
+ const boolean shading = !draw->rasterizer->bypass_vs;
+ struct draw_pt_front_end *frontend = NULL;
+ struct draw_pt_middle_end *middle = NULL;
+
+
+ /* Overall we do:
+ * - frontend -- prepare fetch_elts, draw_elts - eg vcache
+ * - middle -- fetch, shade, cliptest, viewport
+ * - pipeline -- the prim pipeline: clipping, wide lines, etc
+ * - backend -- the vbuf_render provided by the driver.
+ */
+
+
+#if 0
+ if (!cliptest && !pipeline && !shading) {
+ /* This is the 'passthrough' path:
+ */
+ /* Fetch user verts, emit hw verts:
+ */
+ middle = draw->pt.middle.fetch_emit;
+ }
+ else if (!cliptest && !pipeline) {
+ /* Fetch user verts, run vertex shader, emit hw verts:
+ */
+ middle = draw->pt.middle.fetch_shade_emit;
+ }
+ else if (!pipeline) {
+ /* Even though !pipeline, we have to run it to get clipping. We
+ * do know that the pipeline is just the clipping operation, but
+ * that probably doesn't help much.
+ *
+ * This is going to be the most important path for a lot of
+ * swtnl cards.
+ */
+ /* Fetch user verts,
+ * run vertex shader,
+ * cliptest and viewport trasform
+ * if no clipped vertices,
+ * emit hw verts
+ * else
+ * run pipline
+ */
+ 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:
+ */
+ middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
+ }
+#else
+ if (cliptest || pipeline || shading)
+ return FALSE;
+
+ middle = draw->pt.middle.fetch_emit;
+#endif
+
+
+ /* If !pipeline, need to make sure we respect the driver's limited
+ * capabilites to receive blocks of vertex data and elements.
+ */
+#if 0
+ if (!pipeline) {
+ unsigned vertex_mode = passthrough;
+ unsigned nr_verts = count_vertices( draw, start, count );
+ unsigned hw_prim = prim;
+
+ if (is_elts(draw)) {
+ frontend = draw->pt.front.vcache;
+ hw_prim = reduced_prim(prim);
+ }
+
+ if (too_many_verts(nr_verts)) {
+ /* if (is_verts(draw) && can_split(prim)) {
+ draw = draw_arrays_split;
+ }
+ else */ {
+ frontend = draw->pt.front.vcache;
+ hw_prim = reduced_prim(prim);
+ }
+ }
+
+ if (too_many_elts(count)) {
+
+ /* if (is_elts(draw) && can_split(prim)) {
+ draw = draw_elts_split;
+ }
+ else */ {
+ frontend = draw->pt.front.vcache;
+ hw_prim = reduced_prim(prim);
+ }
+ }
+
+ if (!good_prim(hw_prim)) {
+ draw = draw->pt.front.vcache;
+ }
+ }
+#else
+ frontend = draw->pt.front.vcache;
+#endif
+
+ frontend->prepare( frontend, middle );
+
+ frontend->run( frontend,
+ prim,
+ draw_pt_elt_func( draw ),
+ draw_pt_elt_ptr( draw, start ),
+ count );
+
+ frontend->finish( frontend );
+
+ return TRUE;
+}
+
+
+boolean draw_pt_init( struct draw_context *draw )
+{
+ draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
+ if (!draw->pt.middle.fetch_emit)
+ return FALSE;
+
+ draw->pt.front.vcache = draw_pt_vcache();
+ if (!draw->pt.front.vcache)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+void draw_pt_destroy( struct draw_context *draw )
+{
+ if (draw->pt.middle.fetch_emit) {
+ draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
+ draw->pt.middle.fetch_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
new file mode 100644
index 00000000000..439fa4c8813
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -0,0 +1,118 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#ifndef DRAW_PT_H
+#define DRAW_PT_H
+
+#include "pipe/p_compiler.h"
+
+typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx );
+
+struct draw_pt_middle_end;
+struct draw_context;
+
+/* The "front end" - prepare sets of fetch, draw elements for the
+ * middle end.
+ *
+ * Currenly one version of this:
+ * - vcache - catchall implementation, decomposes to TRI/LINE/POINT prims
+ * Later:
+ * - varray, varray_split
+ * - velement, velement_split
+ *
+ * Currenly only using the vcache version.
+ */
+struct draw_pt_front_end {
+ void (*prepare)( struct draw_pt_front_end *,
+ struct draw_pt_middle_end * );
+
+ void (*run)( struct draw_pt_front_end *,
+ unsigned prim,
+ pt_elt_func elt_func,
+ const void *elt_ptr,
+ unsigned count );
+
+ void (*finish)( struct draw_pt_front_end * );
+ void (*destroy)( struct draw_pt_front_end * );
+};
+
+
+/* The "middle end" - prepares actual hardware vertices for the
+ * hardware backend.
+ *
+ * Currently two versions of this:
+ * - fetch, vertex shade, cliptest, prim-pipeline
+ * - fetch, emit (ie passthrough)
+ * Later:
+ * - fetch, vertex shade, cliptest, maybe-pipeline, maybe-emit
+ * - fetch, vertex shade, emit
+ *
+ * Currenly only using the passthrough version.
+ */
+struct draw_pt_middle_end {
+ void (*prepare)( struct draw_pt_middle_end * );
+
+ void (*run)( struct draw_pt_middle_end *,
+ unsigned prim,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count );
+
+ void (*finish)( struct draw_pt_middle_end * );
+ void (*destroy)( struct draw_pt_middle_end * );
+};
+
+
+/* The "back end" - supplied by the driver, defined in draw_vbuf.h.
+ *
+ * Not sure whether to wrap the prim pipeline up as an alternate
+ * backend. Would be a win for everything except pure passthrough
+ * mode...
+ */
+struct vbuf_render;
+
+
+/* Helper functions.
+ */
+pt_elt_func draw_pt_elt_func( struct draw_context *draw );
+const void *draw_pt_elt_ptr( struct draw_context *draw,
+ unsigned start );
+
+/* Implementations:
+ */
+struct draw_pt_front_end *draw_pt_vcache( void );
+struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
+
+
+
+#endif
diff --git a/src/gallium/auxiliary/draw/draw_pt_elts.c b/src/gallium/auxiliary/draw/draw_pt_elts.c
new file mode 100644
index 00000000000..d49770e7b2d
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_elts.c
@@ -0,0 +1,88 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "draw/draw_pt.h"
+#include "draw/draw_private.h"
+
+/* Neat get_elt func that also works for varrays drawing by encoding
+ * the start value into a pointer.
+ */
+
+static unsigned elt_uint( const void *elts, unsigned idx )
+{
+ return *(((const uint *)elts) + idx);
+}
+
+static unsigned elt_ushort( const void *elts, unsigned idx )
+{
+ return *(((const ushort *)elts) + idx);
+}
+
+static unsigned elt_ubyte( const void *elts, unsigned idx )
+{
+ return *(((const ubyte *)elts) + idx);
+}
+
+static unsigned elt_vert( const void *elts, unsigned idx )
+{
+ return (const ubyte *)elts - (const ubyte *)NULL + idx;
+}
+
+pt_elt_func draw_pt_elt_func( struct draw_context *draw )
+{
+ switch (draw->user.eltSize) {
+ case 0: return elt_vert;
+ case 1: return elt_ubyte;
+ case 2: return elt_ushort;
+ case 4: return elt_uint;
+ default: return NULL;
+ }
+}
+
+const void *draw_pt_elt_ptr( struct draw_context *draw,
+ unsigned start )
+{
+ const char *elts = draw->user.elts;
+
+ switch (draw->user.eltSize) {
+ case 0:
+ return (const void *)(((const ubyte *)NULL) + start);
+ case 1:
+ return (const void *)(((const ubyte *)elts) + start);
+ case 2:
+ return (const void *)(((const ushort *)elts) + start);
+ case 4:
+ return (const void *)(((const uint *)elts) + start);
+ default:
+ return NULL;
+ }
+}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
new file mode 100644
index 00000000000..64ef83d8001
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -0,0 +1,364 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+
+/* The simplest 'middle end' in the new vertex code.
+ *
+ * The responsibilities of a middle end are to:
+ * - perform vertex fetch using
+ * - draw vertex element/buffer state
+ * - a list of fetch indices we received as an input
+ * - run the vertex shader
+ * - cliptest,
+ * - clip coord calculation
+ * - viewport transformation
+ * - if necessary, run the primitive pipeline, passing it:
+ * - a linear array of vertex_header vertices constructed here
+ * - a set of draw indices we received as an input
+ * - otherwise, drive the hw backend,
+ * - allocate space for hardware format vertices
+ * - translate the vertex-shader output vertices to hw format
+ * - calling the backend draw functions.
+ *
+ * For convenience, we provide a helper function to drive the hardware
+ * backend given similar inputs to those required to run the pipeline.
+ *
+ * In the case of passthrough mode, many of these actions are disabled
+ * or noops, so we end up doing:
+ *
+ * - perform vertex fetch
+ * - drive the hw backend
+ *
+ * IE, basically just vertex fetch to post-vs-format vertices,
+ * followed by a call to the backend helper function.
+ */
+
+
+struct fetch_emit_middle_end {
+ struct draw_pt_middle_end base;
+ struct draw_context *draw;
+
+ struct {
+ const ubyte *ptr;
+ unsigned pitch;
+ void (*fetch)( const void *from, float *attrib);
+ void (*emit)( const float *attrib, float **out );
+ } fetch[PIPE_ATTRIB_MAX];
+
+ unsigned nr_fetch;
+ unsigned hw_vertex_size;
+};
+
+
+static void fetch_B8G8R8A8_UNORM( const void *from,
+ float *attrib )
+{
+ ubyte *ub = (ubyte *) from;
+ attrib[2] = UBYTE_TO_FLOAT(ub[0]);
+ attrib[1] = UBYTE_TO_FLOAT(ub[1]);
+ attrib[0] = UBYTE_TO_FLOAT(ub[2]);
+ attrib[3] = UBYTE_TO_FLOAT(ub[3]);
+}
+
+static void fetch_R32G32B32A32_FLOAT( const void *from,
+ float *attrib )
+{
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = f[1];
+ attrib[2] = f[2];
+ attrib[3] = f[3];
+}
+
+static void fetch_R32G32B32_FLOAT( const void *from,
+ float *attrib )
+{
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = f[1];
+ attrib[2] = f[2];
+ attrib[3] = 1.0;
+}
+
+static void fetch_R32G32_FLOAT( const void *from,
+ float *attrib )
+{
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = f[1];
+ attrib[2] = 0.0;
+ attrib[3] = 1.0;
+}
+
+static void fetch_R32_FLOAT( const void *from,
+ float *attrib )
+{
+ float *f = (float *) from;
+ attrib[0] = f[0];
+ attrib[1] = 0.0;
+ attrib[2] = 0.0;
+ attrib[3] = 1.0;
+}
+
+
+static void emit_R32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out) += 1;
+}
+
+static void emit_R32G32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out) += 2;
+}
+
+static void emit_R32G32B32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out)[2] = attrib[2];
+ (*out) += 3;
+}
+
+static void emit_R32G32B32A32_FLOAT( const float *attrib,
+ float **out )
+{
+ (*out)[0] = attrib[0];
+ (*out)[1] = attrib[1];
+ (*out)[2] = attrib[2];
+ (*out)[3] = attrib[3];
+ (*out) += 4;
+}
+
+
+/**
+ * General-purpose fetch from user's vertex arrays, emit to driver's
+ * vertex buffer.
+ *
+ * XXX this is totally temporary.
+ */
+static void
+fetch_store_general( struct fetch_emit_middle_end *feme,
+ void *out_ptr,
+ const unsigned *fetch_elts,
+ unsigned count )
+{
+ float *out = (float *)out_ptr;
+ struct vbuf_render *render = feme->draw->render;
+ uint i, j;
+
+ for (i = 0; i < count; i++) {
+ unsigned elt = fetch_elts[i];
+
+ for (j = 0; j < feme->nr_fetch; j++) {
+ float attrib[4];
+ const ubyte *from = (feme->fetch[j].ptr +
+ feme->fetch[j].pitch * elt);
+
+ feme->fetch[j].fetch( from, attrib );
+ feme->fetch[j].emit( attrib, &out );
+ }
+ }
+}
+
+
+
+static void fetch_emit_prepare( struct draw_pt_middle_end *middle )
+{
+ static const float zero = 0;
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
+ unsigned nr_attrs = vinfo->num_attribs;
+ unsigned i;
+
+ for (i = 0; i < nr_attrs; i++) {
+ unsigned src_element = vinfo->src_index[i];
+ unsigned src_buffer = draw->vertex_element[src_element].vertex_buffer_index;
+
+ feme->fetch[i].ptr = ((const ubyte *)draw->user.vbuffer[src_buffer] +
+ draw->vertex_buffer[src_buffer].buffer_offset +
+ draw->vertex_element[src_element].src_offset);
+
+ feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch;
+
+ switch (draw->vertex_element[src_element].src_format) {
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ feme->fetch[i].fetch = fetch_B8G8R8A8_UNORM;
+ break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ feme->fetch[i].fetch = fetch_R32G32B32A32_FLOAT;
+ break;
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ feme->fetch[i].fetch = fetch_R32G32B32_FLOAT;
+ break;
+ case PIPE_FORMAT_R32G32_FLOAT:
+ feme->fetch[i].fetch = fetch_R32G32_FLOAT;
+ break;
+ case PIPE_FORMAT_R32_FLOAT:
+ feme->fetch[i].fetch = fetch_R32_FLOAT;
+ break;
+ default:
+ assert(0);
+ feme->fetch[i].fetch = NULL;
+ break;
+ }
+
+ switch (vinfo->emit[i]) {
+ case EMIT_4F:
+ feme->fetch[i].emit = emit_R32G32B32A32_FLOAT;
+ break;
+ case EMIT_3F:
+ feme->fetch[i].emit = emit_R32G32B32_FLOAT;
+ break;
+ case EMIT_2F:
+ feme->fetch[i].emit = emit_R32G32_FLOAT;
+ break;
+ case EMIT_1F:
+ feme->fetch[i].emit = emit_R32_FLOAT;
+ break;
+ case EMIT_HEADER:
+ feme->fetch[i].ptr = (const ubyte *)&zero;
+ feme->fetch[i].pitch = 0;
+ feme->fetch[i].fetch = fetch_R32_FLOAT;
+ feme->fetch[i].emit = emit_R32_FLOAT;
+ break;
+ case EMIT_1F_PSIZE:
+ feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size;
+ feme->fetch[i].pitch = 0;
+ feme->fetch[i].fetch = fetch_R32_FLOAT;
+ feme->fetch[i].emit = emit_R32_FLOAT;
+ default:
+ assert(0);
+ feme->fetch[i].emit = NULL;
+ break;
+ }
+ }
+
+ feme->nr_fetch = nr_attrs;
+ feme->hw_vertex_size = vinfo->size * 4;
+}
+
+
+
+
+
+static void fetch_emit_run( struct draw_pt_middle_end *middle,
+ unsigned prim,
+ const unsigned *fetch_elts,
+ unsigned fetch_count,
+ const ushort *draw_elts,
+ unsigned draw_count )
+{
+ struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
+ struct draw_context *draw = feme->draw;
+ void *hw_verts;
+ boolean ok;
+
+ ok = draw->render->set_primitive( draw->render,
+ prim );
+ if (!ok) {
+ assert(0);
+ return;
+ }
+
+
+ hw_verts = draw->render->allocate_vertices( draw->render,
+ (ushort)feme->hw_vertex_size,
+ (ushort)fetch_count );
+ if (!hw_verts) {
+ assert(0);
+ return;
+ }
+
+
+ /* Single routine to fetch vertices and emit HW verts.
+ */
+ fetch_store_general( feme,
+ hw_verts,
+ fetch_elts,
+ fetch_count );
+
+ /* XXX: Draw arrays path to avoid re-emitting index list again and
+ * again.
+ */
+ draw->render->draw( draw->render,
+ draw_elts,
+ draw_count );
+
+ /* Done -- that was easy, wasn't it:
+ */
+ draw->render->release_vertices( draw->render,
+ hw_verts,
+ feme->hw_vertex_size,
+ fetch_count );
+
+}
+
+
+
+static void fetch_emit_finish( struct draw_pt_middle_end *middle )
+{
+ /* nothing to do */
+}
+
+static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
+{
+ FREE(middle);
+}
+
+
+struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
+{
+ struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end );
+
+ fetch_emit->base.prepare = fetch_emit_prepare;
+ fetch_emit->base.run = fetch_emit_run;
+ fetch_emit->base.finish = fetch_emit_finish;
+ fetch_emit->base.destroy = fetch_emit_destroy;
+
+ fetch_emit->draw = draw;
+
+ return &fetch_emit->base;
+}
+
diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c
new file mode 100644
index 00000000000..98c22eb4d4a
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c
@@ -0,0 +1,337 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+ /*
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+#include "pipe/p_util.h"
+#include "draw/draw_context.h"
+#include "draw/draw_private.h"
+//#include "draw/draw_vbuf.h"
+//#include "draw/draw_vertex.h"
+#include "draw/draw_pt.h"
+
+
+#define CACHE_MAX 32
+#define FETCH_MAX 128
+#define DRAW_MAX (16*1024)
+
+struct vcache_frontend {
+ struct draw_pt_front_end base;
+
+ unsigned in[CACHE_MAX];
+ ushort out[CACHE_MAX];
+
+ ushort draw_elts[DRAW_MAX];
+ unsigned fetch_elts[FETCH_MAX];
+
+ unsigned draw_count;
+ unsigned fetch_count;
+
+ pt_elt_func elt_func;
+ const void *elt_ptr;
+
+ struct draw_pt_middle_end *middle;
+ unsigned output_prim;
+};
+
+static void vcache_flush( struct vcache_frontend *vcache )
+{
+#if 0
+ /* Should always be true if output_prim == input_prim, otherwise
+ * not so much...
+ */
+ unsigned i;
+ for (i = 0; i < vcache->draw_count; i++) {
+ assert( vcache->fetch_elts[vcache->draw_elts[i]] ==
+ vcache->elt_func(vcache->elt_ptr, i) );
+ }
+#endif
+
+ if (vcache->draw_count) {
+ vcache->middle->run( vcache->middle,
+ vcache->output_prim,
+ vcache->fetch_elts,
+ vcache->fetch_count,
+ vcache->draw_elts,
+ vcache->draw_count );
+ }
+
+ memset(vcache->in, ~0, sizeof(vcache->in));
+ vcache->fetch_count = 0;
+ vcache->draw_count = 0;
+}
+
+static void vcache_check_flush( struct vcache_frontend *vcache )
+{
+ if ( vcache->draw_count + 6 >= DRAW_MAX ||
+ vcache->fetch_count + 4 >= FETCH_MAX )
+ {
+ vcache_flush( vcache );
+ }
+}
+
+
+static void vcache_elt( struct vcache_frontend *vcache,
+ unsigned felt )
+{
+ unsigned idx = felt % CACHE_MAX;
+
+ if (vcache->in[idx] != felt) {
+ assert(vcache->fetch_count < FETCH_MAX);
+
+ vcache->in[idx] = felt;
+ vcache->out[idx] = vcache->fetch_count;
+ vcache->fetch_elts[vcache->fetch_count++] = felt;
+ }
+
+ vcache->draw_elts[vcache->draw_count++] = vcache->out[idx];
+}
+
+static void vcache_triangle( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2 )
+{
+ /* TODO: encode edgeflags in draw_elts */
+ vcache_elt(vcache, i0);
+ vcache_elt(vcache, i1);
+ vcache_elt(vcache, i2);
+ vcache_check_flush(vcache);
+}
+
+static void vcache_line( struct vcache_frontend *vcache,
+ boolean reset,
+ unsigned i0,
+ unsigned i1 )
+{
+ /* TODO: encode reset-line-stipple in draw_elts */
+ (void) reset;
+ vcache_elt(vcache, i0);
+ vcache_elt(vcache, i1);
+ vcache_check_flush(vcache);
+}
+
+
+static void vcache_point( struct vcache_frontend *vcache,
+ unsigned i0 )
+{
+ vcache_elt(vcache, i0);
+ vcache_check_flush(vcache);
+}
+
+static void vcache_quad( struct vcache_frontend *vcache,
+ unsigned i0,
+ unsigned i1,
+ unsigned i2,
+ unsigned i3 )
+{
+ vcache_triangle( vcache, i0, i1, i3 );
+ vcache_triangle( vcache, i1, i2, i3 );
+}
+
+
+static void vcache_prepare( struct draw_pt_front_end *frontend,
+ struct draw_pt_middle_end *middle )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ vcache->middle = middle;
+ middle->prepare( middle );
+}
+
+static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
+ PIPE_PRIM_POINTS,
+ PIPE_PRIM_LINES,
+ PIPE_PRIM_LINES,
+ PIPE_PRIM_LINES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLES,
+ PIPE_PRIM_TRIANGLES
+};
+
+
+static void vcache_run( struct draw_pt_front_end *frontend,
+ unsigned prim,
+ pt_elt_func get_elt,
+ const void *elts,
+ unsigned count )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ unsigned i;
+
+ /* These are for validation only:
+ */
+ vcache->elt_func = get_elt;
+ vcache->elt_ptr = elts;
+ vcache->output_prim = reduced_prim[prim];
+
+ switch (prim) {
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < count; i ++) {
+ vcache_point( vcache,
+ get_elt(elts, i) );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i+1 < count; i += 2) {
+ vcache_line( vcache,
+ TRUE,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1));
+ }
+ break;
+
+ case PIPE_PRIM_LINE_LOOP:
+ if (count >= 2) {
+ for (i = 1; i < count; i++) {
+ vcache_line( vcache,
+ i == 1, /* XXX: only if vb not split */
+ get_elt(elts, i - 1),
+ get_elt(elts, i) );
+ }
+
+ vcache_line( vcache,
+ 0,
+ get_elt(elts, count - 1),
+ get_elt(elts, 0) );
+ }
+ break;
+
+ case PIPE_PRIM_LINE_STRIP:
+ for (i = 1; i < count; i++) {
+ vcache_line( vcache,
+ i == 1,
+ get_elt(elts, i - 1),
+ get_elt(elts, i) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i+2 < count; i += 3) {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2) );
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ for (i = 0; i+2 < count; i++) {
+ if (i & 1) {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 2) );
+ }
+ else {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2) );
+ }
+ }
+ break;
+
+ case PIPE_PRIM_TRIANGLE_FAN:
+ for (i = 0; i+2 < count; i++) {
+ vcache_triangle( vcache,
+ get_elt(elts, 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2) );
+ }
+ break;
+
+
+ case PIPE_PRIM_QUADS:
+ for (i = 0; i+3 < count; i += 4) {
+ vcache_quad( vcache,
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, i + 3));
+ }
+ break;
+
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 0; i+3 < count; i += 2) {
+ vcache_quad( vcache,
+ get_elt(elts, i + 2),
+ get_elt(elts, i + 0),
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 3));
+ }
+ break;
+
+ case PIPE_PRIM_POLYGON:
+ for (i = 0; i+2 < count; i++) {
+ vcache_triangle( vcache,
+ get_elt(elts, i + 1),
+ get_elt(elts, i + 2),
+ get_elt(elts, 0));
+ }
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ vcache_flush( vcache );
+}
+
+static void vcache_finish( struct draw_pt_front_end *frontend )
+{
+ struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
+ vcache->middle->finish( vcache->middle );
+ vcache->middle = NULL;
+}
+
+static void vcache_destroy( struct draw_pt_front_end *frontend )
+{
+ FREE(frontend);
+}
+
+
+struct draw_pt_front_end *draw_pt_vcache( void )
+{
+ struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
+
+ vcache->base.prepare = vcache_prepare;
+ vcache->base.run = vcache_run;
+ vcache->base.finish = vcache_finish;
+ vcache->base.destroy = vcache_destroy;
+
+ memset(vcache->in, ~0, sizeof(vcache->in));
+
+ return &vcache->base;
+}
diff --git a/src/gallium/auxiliary/draw/draw_validate.c b/src/gallium/auxiliary/draw/draw_validate.c
index 33e55595081..70b477ba5cc 100644
--- a/src/gallium/auxiliary/draw/draw_validate.c
+++ b/src/gallium/auxiliary/draw/draw_validate.c
@@ -34,20 +34,14 @@
/**
- * Check if we need any special pipeline stages, or whether prims/verts
- * can go through untouched.
+ * Check if we need any special pipeline stages, or whether
+ * prims/verts can go through untouched. Don't test for bypass
+ * clipping or vs modes, this function is just about the primitive
+ * pipeline stages.
*/
boolean
draw_need_pipeline(const struct draw_context *draw)
{
- /* clipping */
- if (!draw->rasterizer->bypass_clipping)
- return TRUE;
-
- /* vertex shader */
- if (!draw->rasterizer->bypass_vs)
- return TRUE;
-
/* line stipple */
if (draw->rasterizer->line_stipple_enable && draw->line_stipple)
return TRUE;
@@ -72,6 +66,11 @@ draw_need_pipeline(const struct draw_context *draw)
if (draw->rasterizer->poly_stipple_enable && draw->pipeline.pstipple)
return TRUE;
+ /* unfilled polygons */
+ if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
+ draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL)
+ return TRUE;
+
/* polygon offset */
if (draw->rasterizer->offset_cw || draw->rasterizer->offset_ccw)
return TRUE;
@@ -84,9 +83,14 @@ draw_need_pipeline(const struct draw_context *draw)
if (draw->rasterizer->light_twoside)
return TRUE;
- /* polygon cull */
+ /* polygon cull - this is difficult - hardware can cull just fine
+ * most of the time (though sometimes CULL_NEITHER is unsupported.
+ *
+ * Generally this isn't a reason to require the pipeline, though.
+ *
if (draw->rasterizer->cull_mode)
return TRUE;
+ */
return FALSE;
}
diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
index 364693e0b49..4e2fa727070 100644
--- a/src/gallium/auxiliary/draw/draw_vs_exec.c
+++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
@@ -38,6 +38,8 @@
#include "draw_context.h"
#include "draw_vs.h"
+#include "tgsi/util/tgsi_parse.h"
+
static INLINE unsigned
compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
@@ -187,6 +189,7 @@ vs_exec_run( struct draw_vertex_shader *shader,
static void
vs_exec_delete( struct draw_vertex_shader *dvs )
{
+ FREE((void*) dvs->state.tokens);
FREE( dvs );
}
@@ -196,11 +199,13 @@ draw_create_vs_exec(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct draw_vertex_shader *vs = CALLOC_STRUCT( draw_vertex_shader );
+ uint nt = tgsi_num_tokens(state->tokens);
if (vs == NULL)
return NULL;
- vs->state = *state;
+ /* we make a private copy of the tokens */
+ vs->state.tokens = mem_dup(state->tokens, nt * sizeof(state->tokens[0]));
vs->prepare = vs_exec_prepare;
vs->run = vs_exec_run;
vs->delete = vs_exec_delete;
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
index 53c260be53a..bd983f2ddfa 100644
--- a/src/gallium/auxiliary/draw/draw_vs_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -38,6 +38,8 @@
#include "draw_context.h"
#include "draw_vs.h"
+#include "tgsi/util/tgsi_parse.h"
+
#ifdef MESA_LLVM
#include "gallivm/gallivm.h"
@@ -186,6 +188,7 @@ vs_llvm_delete( struct draw_vertex_shader *base )
/* Do something to free compiled shader:
*/
+ FREE( (void*) shader->base.state.tokens );
FREE( shader );
}
@@ -197,12 +200,14 @@ draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *templ)
{
struct draw_llvm_vertex_shader *vs;
+ uint nt = tgsi_num_tokens(templ->tokens);
vs = CALLOC_STRUCT( draw_llvm_vertex_shader );
if (vs == NULL)
return NULL;
- vs->base.state = templ;
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0]));
vs->base.prepare = vs_llvm_prepare;
vs->base.run = vs_llvm_run;
vs->base.delete = vs_llvm_delete;
diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c
index 5ee2adb3447..a4503c143ed 100644
--- a/src/gallium/auxiliary/draw/draw_vs_sse.c
+++ b/src/gallium/auxiliary/draw/draw_vs_sse.c
@@ -43,6 +43,7 @@
#include "rtasm/rtasm_x86sse.h"
#include "tgsi/exec/tgsi_sse2.h"
+#include "tgsi/util/tgsi_parse.h"
typedef void (XSTDCALL *codegen_function) (
@@ -204,6 +205,7 @@ vs_sse_delete( struct draw_vertex_shader *base )
x86_release_func( &shader->sse2_program );
+ FREE( (void*) shader->base.state.tokens );
FREE( shader );
}
@@ -213,6 +215,7 @@ draw_create_vs_sse(struct draw_context *draw,
const struct pipe_shader_state *templ)
{
struct draw_sse_vertex_shader *vs;
+ uint nt = tgsi_num_tokens(templ->tokens);
if (!draw->use_sse)
return NULL;
@@ -221,7 +224,8 @@ draw_create_vs_sse(struct draw_context *draw,
if (vs == NULL)
return NULL;
- vs->base.state = *templ;
+ /* we make a private copy of the tokens */
+ vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0]));
vs->base.prepare = vs_sse_prepare;
vs->base.run = vs_sse_run;
vs->base.delete = vs_sse_delete;
diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_parse.c b/src/gallium/auxiliary/tgsi/util/tgsi_parse.c
index bf6b89ce564..c3526cb71ff 100644
--- a/src/gallium/auxiliary/tgsi/util/tgsi_parse.c
+++ b/src/gallium/auxiliary/tgsi/util/tgsi_parse.c
@@ -317,3 +317,16 @@ tgsi_parse_token(
}
}
+
+unsigned
+tgsi_num_tokens(const struct tgsi_token *tokens)
+{
+ struct tgsi_parse_context ctx;
+ if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) {
+ unsigned len = (ctx.FullHeader.Header.HeaderSize +
+ ctx.FullHeader.Header.BodySize +
+ 1);
+ return len;
+ }
+ return 0;
+}
diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_parse.h b/src/gallium/auxiliary/tgsi/util/tgsi_parse.h
index 40083728d64..a98e88e3437 100644
--- a/src/gallium/auxiliary/tgsi/util/tgsi_parse.h
+++ b/src/gallium/auxiliary/tgsi/util/tgsi_parse.h
@@ -113,6 +113,10 @@ void
tgsi_parse_token(
struct tgsi_parse_context *ctx );
+unsigned
+tgsi_num_tokens(const struct tgsi_token *tokens);
+
+
#if defined __cplusplus
}
#endif
diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript
index b44f2d5e398..9b3929eb2d3 100644
--- a/src/gallium/auxiliary/util/SConscript
+++ b/src/gallium/auxiliary/util/SConscript
@@ -4,6 +4,7 @@ util = env.ConvenienceLibrary(
target = 'util',
source = [
'p_debug.c',
+ 'p_debug_mem.c',
'p_tile.c',
'p_util.c',
'u_blit.c',
diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c
index c51e9e6a692..cc036dabf82 100644
--- a/src/gallium/auxiliary/util/p_debug.c
+++ b/src/gallium/auxiliary/util/p_debug.c
@@ -58,7 +58,7 @@ int rpl_snprintf(char *str, size_t size, const char *format, ...);
#endif
-void debug_vprintf(const char *format, va_list ap)
+void _debug_vprintf(const char *format, va_list ap)
{
#ifdef WIN32
#ifndef WINCE
@@ -76,15 +76,7 @@ void debug_vprintf(const char *format, va_list ap)
}
-void debug_printf(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- debug_vprintf(format, ap);
- va_end(ap);
-}
-
-
+#ifdef DEBUG
void debug_print_blob( const char *name,
const void *blob,
unsigned size )
@@ -99,12 +91,10 @@ void debug_print_blob( const char *name,
debug_printf("%d:\t%08x\n", i, ublob[i]);
}
}
+#endif
-/* TODO: implement a debug_abort that calls EngBugCheckEx on WIN32 */
-
-
-static INLINE void debug_break(void)
+void _debug_break(void)
{
#if (defined(__i386__) || defined(__386__)) && defined(__GNUC__)
__asm("int3");
@@ -117,6 +107,150 @@ static INLINE void debug_break(void)
#endif
}
+
+#ifdef WIN32
+static const char *
+find(const char *start, const char *end, char c)
+{
+ const char *p;
+ for(p = start; !end || p != end; ++p) {
+ if(*p == c)
+ return p;
+ if(*p < 32)
+ break;
+ }
+ return NULL;
+}
+
+static int
+compare(const char *start, const char *end, const char *s)
+{
+ const char *p, *q;
+ for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
+ if(*p != *q)
+ return 0;
+ }
+ return p == end && *q == '\0';
+}
+
+static void
+copy(char *dst, const char *start, const char *end, size_t n)
+{
+ const char *p;
+ char *q;
+ for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
+ *q = *p;
+ *q = '\0';
+}
+#endif
+
+
+const char *
+debug_get_option(const char *name, const char *dfault)
+{
+ const char *result;
+#ifdef WIN32
+ ULONG_PTR iFile = 0;
+ const void *pMap = NULL;
+ const char *sol, *eol, *sep;
+ static char output[1024];
+
+ pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
+ if(!pMap)
+ result = dfault;
+ else {
+ sol = (const char *)pMap;
+ while(1) {
+ /* TODO: handle LF line endings */
+ eol = find(sol, NULL, '\r');
+ if(!eol || eol == sol)
+ break;
+ sep = find(sol, eol, '=');
+ if(!sep)
+ break;
+ if(compare(sol, sep, name)) {
+ copy(output, sep + 1, eol, sizeof(output));
+ result = output;
+ break;
+ }
+ sol = eol + 2;
+ }
+ EngUnmapFile(iFile);
+ }
+#else
+
+ result = getenv(name);
+ if(!result)
+ result = dfault;
+#endif
+
+ if(result)
+ debug_printf("%s: %s = %s\n", __FUNCTION__, name, result);
+ else
+ debug_printf("%s: %s = (null)\n", __FUNCTION__, name);
+
+ return result;
+}
+
+boolean
+debug_get_bool_option(const char *name, boolean dfault)
+{
+ const char *str = debug_get_option(name, NULL);
+ boolean result;
+
+ if(str == NULL)
+ result = dfault;
+ else if(!strcmp(str, "no"))
+ result = FALSE;
+ else if(!strcmp(str, "0"))
+ result = FALSE;
+ else if(!strcmp(str, "f"))
+ result = FALSE;
+ else if(!strcmp(str, "false"))
+ result = FALSE;
+ else
+ result = TRUE;
+
+ debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
+
+ return result;
+}
+
+
+long
+debug_get_num_option(const char *name, long dfault)
+{
+ /* FIXME */
+ return dfault;
+}
+
+
+unsigned long
+debug_get_flags_option(const char *name,
+ const struct debug_named_value *flags,
+ unsigned long dfault)
+{
+ unsigned long result;
+ const char *str;
+
+ str = debug_get_option(name, NULL);
+ if(!str)
+ result = dfault;
+ else {
+ result = 0;
+ while( flags->name ) {
+ if (!strcmp(str, "all") || strstr(str, flags->name ))
+ result |= flags->value;
+ ++flags;
+ }
+ }
+
+ debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
+
+ return result;
+}
+
+
#if defined(WIN32)
ULONG_PTR debug_config_file = 0;
void *mapped_config_file = 0;
@@ -126,7 +260,7 @@ enum {
};
/* Check for aborts enabled. */
-static unsigned abort_en()
+static unsigned abort_en(void)
{
if (!mapped_config_file)
{
@@ -149,59 +283,28 @@ static unsigned abort_en()
return ((((char *)mapped_config_file)[0]) - 0x30) & eAssertAbortEn;
}
#else /* WIN32 */
-static unsigned abort_en()
+static unsigned abort_en(void)
{
return !GETENV("GALLIUM_ABORT_ON_ASSERT");
}
#endif
-void debug_assert_fail(const char *expr, const char *file, unsigned line)
+void _debug_assert_fail(const char *expr,
+ const char *file,
+ unsigned line,
+ const char *function)
{
- debug_printf("%s:%i: Assertion `%s' failed.\n", file, line, expr);
+ _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
if (abort_en())
{
debug_break();
} else
{
- debug_printf("continuing...\n");
+ _debug_printf("continuing...\n");
}
}
-#define DEBUG_MASK_TABLE_SIZE 256
-
-
-/**
- * Mask hash table.
- *
- * For now we just take the lower bits of the key, and do no attempt to solve
- * collisions. Use a proper hash table when we have dozens of drivers.
- */
-static uint32_t debug_mask_table[DEBUG_MASK_TABLE_SIZE];
-
-
-void debug_mask_set(uint32_t uuid, uint32_t mask)
-{
- unsigned hash = uuid & (DEBUG_MASK_TABLE_SIZE - 1);
- debug_mask_table[hash] = mask;
-}
-
-
-uint32_t debug_mask_get(uint32_t uuid)
-{
- unsigned hash = uuid & (DEBUG_MASK_TABLE_SIZE - 1);
- return debug_mask_table[hash];
-}
-
-
-void debug_mask_vprintf(uint32_t uuid, uint32_t what, const char *format, va_list ap)
-{
- uint32_t mask = debug_mask_get(uuid);
- if(mask & what)
- debug_vprintf(format, ap);
-}
-
-
const char *
debug_dump_enum(const struct debug_named_value *names,
unsigned long value)
@@ -214,7 +317,7 @@ debug_dump_enum(const struct debug_named_value *names,
++names;
}
- snprintf(rest, sizeof(rest), "0x%08x", value);
+ snprintf(rest, sizeof(rest), "0x%08lx", value);
return rest;
}
@@ -247,7 +350,7 @@ debug_dump_flags(const struct debug_named_value *names,
else
first = 0;
- snprintf(rest, sizeof(rest), "0x%08x", value);
+ 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
new file mode 100644
index 00000000000..c160afe5b7f
--- /dev/null
+++ b/src/gallium/auxiliary/util/p_debug_mem.c
@@ -0,0 +1,172 @@
+/**************************************************************************
+ *
+ * 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
+ * Memory debugging.
+ *
+ * @author José Fonseca <[email protected]>
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <winddi.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include "pipe/p_debug.h"
+#include "util/u_double_list.h"
+
+
+#define DEBUG_MEMORY_MAGIC 0x6e34090aU
+
+
+#if defined(WIN32) && !defined(WINCE)
+#define real_malloc(_size) EngAllocMem(0, _size, 'D3AG')
+#define real_free(_ptr) EngFreeMem(_ptr)
+#else
+#define real_malloc(_size) malloc(_size)
+#define real_free(_ptr) free(_ptr)
+#endif
+
+
+struct debug_memory_header
+{
+ struct list_head head;
+
+ unsigned long no;
+ const char *file;
+ unsigned line;
+ const char *function;
+ size_t size;
+ unsigned magic;
+};
+
+static struct list_head list = { &list, &list };
+
+static unsigned long start_no = 0;
+static unsigned long end_no = 0;
+
+
+void *
+debug_malloc(const char *file, unsigned line, const char *function,
+ size_t size)
+{
+ struct debug_memory_header *hdr;
+
+ hdr = real_malloc(sizeof(*hdr) + size);
+ if(!hdr)
+ return NULL;
+
+ hdr->no = end_no++;
+ hdr->file = file;
+ hdr->line = line;
+ hdr->function = function;
+ hdr->size = size;
+ hdr->magic = DEBUG_MEMORY_MAGIC;
+
+ LIST_ADDTAIL(&hdr->head, &list);
+
+ return (void *)((char *)hdr + sizeof(*hdr));
+}
+
+void
+debug_free(const char *file, unsigned line, const char *function,
+ void *ptr)
+{
+ struct debug_memory_header *hdr;
+
+ if(!ptr)
+ return;
+
+ hdr = (struct debug_memory_header *)((char *)ptr - sizeof(*hdr));
+ if(hdr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
+ file, line, function,
+ ptr);
+ debug_assert(0);
+ return;
+ }
+
+ LIST_DEL(&hdr->head);
+ hdr->magic = 0;
+
+ real_free(hdr);
+}
+
+void *
+debug_calloc(const char *file, unsigned line, const char *function,
+ size_t count, size_t size )
+{
+ void *ptr = debug_malloc( file, line, function, count * size );
+ if( ptr )
+ memset( ptr, 0, count * size );
+ return ptr;
+}
+
+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 );
+ }
+
+ debug_free( file, line, function, old_ptr );
+ return new_ptr;
+}
+
+void
+debug_memory_reset(void)
+{
+ start_no = end_no;
+}
+
+void
+debug_memory_report(void)
+{
+ struct list_head *entry;
+
+ entry = list.prev;
+ for (; entry != &list; entry = entry->prev) {
+ struct debug_memory_header *hdr;
+ void *ptr;
+ hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
+ ptr = (void *)((char *)hdr + sizeof(*hdr));
+ if(hdr->no >= start_no)
+ debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
+ hdr->file, hdr->line, hdr->function,
+ hdr->size, ptr);
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index cf02f00b1b7..e129c062be6 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -719,8 +719,6 @@ util_create_gen_mipmap(struct pipe_context *pipe,
ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
- ctx->sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
- ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
ctx->sampler.normalized_coords = 1;
@@ -774,23 +772,23 @@ set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
{
void *buf;
- ctx->vertices[0][0][0] = 0.0f; /*x*/
- ctx->vertices[0][0][1] = 0.0f; /*y*/
+ ctx->vertices[0][0][0] = -0.5f; /*x*/
+ ctx->vertices[0][0][1] = -0.5f; /*y*/
ctx->vertices[0][1][0] = 0.0f; /*s*/
ctx->vertices[0][1][1] = 0.0f; /*t*/
- ctx->vertices[1][0][0] = width; /*x*/
- ctx->vertices[1][0][1] = 0.0f; /*y*/
+ ctx->vertices[1][0][0] = width - 0.5f; /*x*/
+ ctx->vertices[1][0][1] = -0.5f; /*y*/
ctx->vertices[1][1][0] = 1.0f; /*s*/
ctx->vertices[1][1][1] = 0.0f; /*t*/
- ctx->vertices[2][0][0] = width;
- ctx->vertices[2][0][1] = height;
+ ctx->vertices[2][0][0] = width - 0.5f;
+ ctx->vertices[2][0][1] = height - 0.5f;
ctx->vertices[2][1][0] = 1.0f;
ctx->vertices[2][1][1] = 1.0f;
- ctx->vertices[3][0][0] = 0.0f;
- ctx->vertices[3][0][1] = height;
+ ctx->vertices[3][0][0] = -0.5f;
+ ctx->vertices[3][0][1] = height - 0.5f;
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
@@ -849,11 +847,13 @@ simple_viewport(struct pipe_context *pipe, uint width, uint height)
* \param face which cube face to generate mipmaps for (0 for non-cube maps)
* \param baseLevel the first mipmap level to use as a src
* \param lastLevel the last mipmap level to generate
+ * \param filter the minification filter used to generate mipmap levels with
+ * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
*/
void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
- uint face, uint baseLevel, uint lastLevel)
+ uint face, uint baseLevel, uint lastLevel, uint filter)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
@@ -890,6 +890,10 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
memset(&fb, 0, sizeof(fb));
fb.num_cbufs = 1;
+ /* set min/mag to same filter for faster sw speed */
+ ctx->sampler.mag_img_filter = filter;
+ ctx->sampler.min_img_filter = filter;
+
/*
* XXX for small mipmap levels, it may be faster to use the software
* fallback path...
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h
index eeabf3bf075..bd9af54fb74 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.h
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -50,7 +50,6 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
extern void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
- uint face, uint baseLevel, uint lastLevel);
-
+ uint face, uint baseLevel, uint lastLevel, uint filter);
#endif
diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/drivers/softpipe/sp_winsys.h
index fc372dba27b..291825dfe22 100644
--- a/src/gallium/drivers/softpipe/sp_winsys.h
+++ b/src/gallium/drivers/softpipe/sp_winsys.h
@@ -37,6 +37,12 @@
#include "pipe/p_compiler.h" /* for boolean */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
enum pipe_format;
struct softpipe_winsys {
@@ -60,4 +66,8 @@ struct pipe_screen *
softpipe_create_screen(struct pipe_winsys *);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* SP_WINSYS_H */
diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h
index 14f8056924d..577cdaebcdf 100644
--- a/src/gallium/include/pipe/p_debug.h
+++ b/src/gallium/include/pipe/p_debug.h
@@ -60,43 +60,102 @@ extern "C" {
#endif
+void _debug_vprintf(const char *format, va_list ap);
+
+
+static INLINE void
+_debug_printf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _debug_vprintf(format, ap);
+ va_end(ap);
+}
+
+
/**
* Print debug messages.
*
- * A debug message will be printed regardless of the DEBUG/NDEBUG macros.
- *
* The actual channel used to output debug message is platform specific. To
* avoid misformating or truncation, follow these rules of thumb:
* - output whole lines
* - avoid outputing large strings (512 bytes is the current maximum length
* that is guaranteed to be printed in all platforms)
*/
-void debug_printf(const char *format, ...);
+static INLINE void
+debug_printf(const char *format, ...)
+{
+#ifdef DEBUG
+ va_list ap;
+ va_start(ap, format);
+ _debug_vprintf(format, ap);
+ va_end(ap);
+#endif
+}
-/* Dump a blob in hex to the same place that debug_printf sends its
- * messages:
+#ifdef DEBUG
+#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
+#else
+#define debug_vprintf(_format, _ap) ((void)0)
+#endif
+
+
+/**
+ * Dump a blob in hex to the same place that debug_printf sends its
+ * messages.
*/
+#ifdef DEBUG
void debug_print_blob( const char *name,
const void *blob,
unsigned size );
+#else
+#define debug_print_blob(_name, _blob, _size) ((void)0)
+#endif
+
+
+void _debug_break(void);
+
/**
- * @sa debug_printf
+ * Hard-coded breakpoint.
*/
-void debug_vprintf(const char *format, va_list ap);
+#ifdef DEBUG
+#if (defined(__i386__) || defined(__386__)) && defined(__GNUC__)
+#define debug_break() __asm("int3")
+#elif (defined(__i386__) || defined(__386__)) && defined(__MSC__)
+#define debug_break() _asm {int 3}
+#else
+#define debug_break() _debug_break()
+#endif
+#else /* !DEBUG */
+#define debug_break() ((void)0)
+#endif /* !DEBUG */
-void debug_assert_fail(const char *expr, const char *file, unsigned line);
+long
+debug_get_num_option(const char *name, long dfault);
-/** Assert macro */
+void _debug_assert_fail(const char *expr,
+ const char *file,
+ unsigned line,
+ const char *function);
+
+
+/**
+ * Assert macro
+ *
+ * Do not expect that the assert call terminates -- errors must be handled
+ * regardless of assert behavior.
+ */
#ifdef DEBUG
-#define debug_assert(expr) ((expr) ? (void)0 : debug_assert_fail(#expr, __FILE__, __LINE__))
+#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
#else
#define debug_assert(expr) ((void)0)
#endif
+/** Override standard assert macro */
#ifdef assert
#undef assert
#endif
@@ -104,72 +163,35 @@ void debug_assert_fail(const char *expr, const char *file, unsigned line);
/**
- * Set a channel's debug mask.
- *
- * uuid is just a random 32 bit integer that uniquely identifies the debugging
- * channel.
- *
- * @note Due to current implementation issues, make sure the lower 8 bits of
- * UUID are unique.
+ * Output the current function name.
*/
-void debug_mask_set(uint32_t uuid, uint32_t mask);
-
-
-uint32_t debug_mask_get(uint32_t uuid);
+#ifdef DEBUG
+#define debug_checkpoint() \
+ _debug_printf("%s\n", __FUNCTION__)
+#else
+#define debug_checkpoint() \
+ ((void)0)
+#endif
/**
- * Conditional debug output.
- *
- * This is just a generalization of the debug filtering mechanism used
- * throughout Gallium.
- *
- * You use this function as:
- *
- * @code
- * #define MYDRIVER_UUID 0x12345678 // random 32 bit identifier
- *
- * static void inline
- * mydriver_debug(uint32_t what, const char *format, ...)
- * {
- * #ifdef DEBUG
- * va_list ap;
- * va_start(ap, format);
- * debug_mask_vprintf(MYDRIVER_UUID, what, format, ap);
- * va_end(ap);
- * #endif
- * }
- *
- * ...
- *
- * debug_mask_set(MYDRIVER_UUID,
- * MYDRIVER_DEBUG_THIS |
- * MYDRIVER_DEBUG_THAT |
- * ... );
- *
- * ...
- *
- * mydriver_debug(MYDRIVER_DEBUG_THIS,
- * "this and this happened\n");
- *
- * mydriver_debug(MYDRIVER_DEBUG_THAT,
- * "that = %f\n", that);
- * ...
- * @endcode
- *
- * You can also define several variants of mydriver_debug, with hardcoded what.
- * Note that although macros with variable number of arguments would accomplish
- * more in less code, they are not portable.
+ * Output the full source code position.
*/
-void debug_mask_vprintf(uint32_t uuid,
- uint32_t what,
- const char *format,
- va_list ap);
+#ifdef DEBUG
+#define debug_checkpoint_full() \
+ _debug_printf("%s:%u:%s", __FILE__, __LINE__, __FUNCTION__)
+#else
+#define debug_checkpoint_full() \
+ ((void)0)
+#endif
+/**
+ * Output a warning message. Muted on release version.
+ */
#ifdef DEBUG
#define debug_warning(__msg) \
- debug_printf("%s:%i:warning: %s\n", __FILE__, __LINE__, (__msg))
+ _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, (__msg))
#else
#define debug_warning(__msg) \
((void)0)
@@ -177,6 +199,18 @@ void debug_mask_vprintf(uint32_t uuid,
/**
+ * Output an error message. Not muted on release version.
+ */
+#ifdef DEBUG
+#define debug_error(__msg) \
+ _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, (__msg))
+#else
+#define debug_error(__msg) \
+ _debug_printf("error: %s\n", __msg))
+#endif
+
+
+/**
* Used by debug_dump_enum and debug_dump_flags to describe symbols.
*/
struct debug_named_value
@@ -225,6 +259,56 @@ debug_dump_flags(const struct debug_named_value *names,
unsigned long value);
+/**
+ * Get option.
+ *
+ * It is an alias for getenv on Linux.
+ *
+ * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
+ * endings with one option per line as
+ *
+ * NAME=value
+ *
+ * This file must be terminated with an extra empty line.
+ */
+const char *
+debug_get_option(const char *name, const char *dfault);
+
+boolean
+debug_get_bool_option(const char *name, boolean dfault);
+
+long
+debug_get_unsigned_option(const char *name, long dfault);
+
+unsigned long
+debug_get_flags_option(const char *name,
+ const struct debug_named_value *flags,
+ unsigned long dfault);
+
+
+void *
+debug_malloc(const char *file, unsigned line, const char *function,
+ size_t size);
+
+void
+debug_free(const char *file, unsigned line, const char *function,
+ void *ptr);
+
+void *
+debug_calloc(const char *file, unsigned line, const char *function,
+ size_t count, size_t size );
+
+void *
+debug_realloc(const char *file, unsigned line, const char *function,
+ void *old_ptr, size_t old_size, size_t new_size );
+
+void
+debug_memory_reset(void);
+
+void
+debug_memory_report(void);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gallium/include/pipe/p_util.h b/src/gallium/include/pipe/p_util.h
index c2e0f8c6a5d..505626c60b5 100644
--- a/src/gallium/include/pipe/p_util.h
+++ b/src/gallium/include/pipe/p_util.h
@@ -39,6 +39,22 @@ extern "C" {
#endif
+#if defined(WIN32) && defined(DEBUG) /* memory debugging */
+
+#include "p_debug.h"
+
+#define MALLOC( _size ) \
+ debug_malloc( __FILE__, __LINE__, __FUNCTION__, _size )
+#define CALLOC( _count, _size ) \
+ debug_calloc(__FILE__, __LINE__, __FUNCTION__, _count, _size )
+#define FREE( _ptr ) \
+ debug_free( __FILE__, __LINE__, __FUNCTION__, _ptr )
+#define REALLOC( _ptr, _old_size, _size ) \
+ debug_realloc( __FILE__, __LINE__, __FUNCTION__, _ptr, _old_size, _size )
+#define GETENV( X ) NULL
+
+#else
+
#ifdef WIN32
void * __stdcall
@@ -91,10 +107,10 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
void *new_ptr = NULL;
if (new_size != 0) {
+ unsigned copy_size = old_size < new_size ? old_size : new_size;
new_ptr = MALLOC( new_size );
-
- if( new_ptr && old_ptr ) {
- memcpy( new_ptr, old_ptr, old_size );
+ if (new_ptr && old_ptr && copy_size) {
+ memcpy( new_ptr, old_ptr, copy_size );
}
}
@@ -104,7 +120,7 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
#define GETENV( X ) NULL
-#else /* WIN32 */
+#else /* !WIN32 */
#define MALLOC( SIZE ) malloc( SIZE )
@@ -116,7 +132,8 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
#define GETENV( X ) getenv( X )
-#endif /* WIN32 */
+#endif /* !WIN32 */
+#endif /* !DEBUG */
#define MALLOC_STRUCT(T) (struct T *) MALLOC(sizeof(struct T))
@@ -184,7 +201,7 @@ mem_dup(const void *src, uint size)
#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
-#define Elements(x) sizeof(x)/sizeof(*(x))
+#define Elements(x) (sizeof(x)/sizeof((x)[0]))
#define Offset(TYPE, MEMBER) ((unsigned)&(((TYPE *)NULL)->MEMBER))
/**