summaryrefslogtreecommitdiff
path: root/src/mesa/pipe/draw
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/pipe/draw')
-rw-r--r--src/mesa/pipe/draw/draw_clip.c19
-rw-r--r--src/mesa/pipe/draw/draw_context.c35
-rw-r--r--src/mesa/pipe/draw/draw_context.h1
-rw-r--r--src/mesa/pipe/draw/draw_cull.c31
-rw-r--r--src/mesa/pipe/draw/draw_flatshade.c120
-rw-r--r--src/mesa/pipe/draw/draw_offset.c37
-rw-r--r--src/mesa/pipe/draw/draw_prim.c104
-rw-r--r--src/mesa/pipe/draw/draw_private.h50
-rw-r--r--src/mesa/pipe/draw/draw_stipple.c46
-rw-r--r--src/mesa/pipe/draw/draw_twoside.c99
-rw-r--r--src/mesa/pipe/draw/draw_unfilled.c33
-rw-r--r--src/mesa/pipe/draw/draw_validate.c80
-rw-r--r--src/mesa/pipe/draw/draw_vbuf.c44
-rw-r--r--src/mesa/pipe/draw/draw_vertex.c88
-rw-r--r--src/mesa/pipe/draw/draw_vertex.h43
-rw-r--r--src/mesa/pipe/draw/draw_vertex_cache.c10
-rw-r--r--src/mesa/pipe/draw/draw_vertex_fetch.c200
-rw-r--r--src/mesa/pipe/draw/draw_vertex_shader.c11
-rw-r--r--src/mesa/pipe/draw/draw_vertex_shader_llvm.c5
-rw-r--r--src/mesa/pipe/draw/draw_wide_prims.c53
20 files changed, 607 insertions, 502 deletions
diff --git a/src/mesa/pipe/draw/draw_clip.c b/src/mesa/pipe/draw/draw_clip.c
index c50376f11f..2d410e3244 100644
--- a/src/mesa/pipe/draw/draw_clip.c
+++ b/src/mesa/pipe/draw/draw_clip.c
@@ -93,7 +93,7 @@ static void interp( const struct clipper *clip,
const struct vertex_header *out,
const struct vertex_header *in )
{
- const unsigned nr_attrs = clip->stage.draw->vertex_info.num_attribs;
+ const unsigned nr_attrs = clip->stage.draw->num_vs_outputs;
unsigned j;
/* Vertex header.
@@ -346,15 +346,6 @@ do_clip_line( struct draw_stage *stage,
}
-static void clip_begin( struct draw_stage *stage )
-{
- /* should always have position, at least */
- assert(stage->draw->vertex_info.num_attribs >= 1);
-
- stage->next->begin( stage->next );
-}
-
-
static void
clip_point( struct draw_stage *stage,
struct prim_header *header )
@@ -402,10 +393,9 @@ clip_tri( struct draw_stage *stage,
}
}
-
-static void clip_end( struct draw_stage *stage )
+static void clip_flush( struct draw_stage *stage, unsigned flags )
{
- stage->next->end( stage->next );
+ stage->next->flush( stage->next, flags );
}
@@ -433,11 +423,10 @@ struct draw_stage *draw_clip_stage( struct draw_context *draw )
draw_alloc_tmps( &clipper->stage, MAX_CLIPPED_VERTICES );
clipper->stage.draw = draw;
- clipper->stage.begin = clip_begin;
clipper->stage.point = clip_point;
clipper->stage.line = clip_line;
clipper->stage.tri = clip_tri;
- clipper->stage.end = clip_end;
+ clipper->stage.flush = clip_flush;
clipper->stage.reset_stipple_counter = clip_reset_stipple_counter;
clipper->stage.destroy = clip_destroy;
diff --git a/src/mesa/pipe/draw/draw_context.c b/src/mesa/pipe/draw/draw_context.c
index 5b9ea55630..e8ca1f035b 100644
--- a/src/mesa/pipe/draw/draw_context.c
+++ b/src/mesa/pipe/draw/draw_context.c
@@ -77,15 +77,10 @@ struct draw_context *draw_create( void )
draw->vcache.vertex[i] = (struct vertex_header *)(tmp + i * MAX_VERTEX_SIZE);
}
- draw->attrib_front0 = 0;
- draw->attrib_back0 = 0;
- draw->attrib_front1 = 0;
- draw->attrib_back1 = 0;
-
draw->convert_wide_points = TRUE;
draw->convert_wide_lines = TRUE;
- draw->prim = ~0; /* != any of PIPE_PRIM_x */
+ draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
draw_vertex_cache_invalidate( draw );
draw_set_mapped_element_buffer( draw, 0, NULL );
@@ -116,8 +111,7 @@ void draw_destroy( struct draw_context *draw )
void draw_flush( struct draw_context *draw )
{
- if (draw->drawing)
- draw_do_flush( draw, DRAW_FLUSH_DRAW );
+ draw_do_flush( draw, DRAW_FLUSH_BACKEND );
}
@@ -129,7 +123,8 @@ void draw_flush( struct draw_context *draw )
void draw_set_rasterizer_state( struct draw_context *draw,
const struct pipe_rasterizer_state *raster )
{
- draw_flush( draw );
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
draw->rasterizer = raster;
}
@@ -142,7 +137,8 @@ void draw_set_rasterizer_state( struct draw_context *draw,
void draw_set_rasterize_stage( struct draw_context *draw,
struct draw_stage *stage )
{
- draw_flush( draw );
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
draw->pipeline.rasterize = stage;
}
@@ -153,7 +149,7 @@ void draw_set_rasterize_stage( struct draw_context *draw,
void draw_set_clip_state( struct draw_context *draw,
const struct pipe_clip_state *clip )
{
- draw_flush( draw );
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
assert(clip->nr <= PIPE_MAX_CLIP_PLANES);
memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
@@ -167,7 +163,7 @@ void draw_set_clip_state( struct draw_context *draw,
void draw_set_viewport_state( struct draw_context *draw,
const struct pipe_viewport_state *viewport )
{
- draw_flush( draw );
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->viewport = *viewport; /* struct copy */
}
@@ -178,8 +174,7 @@ draw_set_vertex_buffer(struct draw_context *draw,
unsigned attr,
const struct pipe_vertex_buffer *buffer)
{
- draw_flush( draw );
-
+ draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
assert(attr < PIPE_ATTRIB_MAX);
draw->vertex_buffer[attr] = *buffer;
}
@@ -190,8 +185,7 @@ draw_set_vertex_element(struct draw_context *draw,
unsigned attr,
const struct pipe_vertex_element *element)
{
- draw_flush( draw );
-
+ draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
assert(attr < PIPE_ATTRIB_MAX);
draw->vertex_element[attr] = *element;
}
@@ -204,8 +198,7 @@ void
draw_set_mapped_vertex_buffer(struct draw_context *draw,
unsigned attr, const void *buffer)
{
- draw_flush( draw );
-
+ draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
draw->user.vbuffer[attr] = buffer;
}
@@ -214,8 +207,7 @@ void
draw_set_mapped_constant_buffer(struct draw_context *draw,
const void *buffer)
{
- draw_flush( draw );
-
+ draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE/*STATE_CHANGE*/ );
draw->user.constants = buffer;
}
@@ -227,6 +219,7 @@ draw_set_mapped_constant_buffer(struct draw_context *draw,
void
draw_convert_wide_points(struct draw_context *draw, boolean enable)
{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->convert_wide_points = enable;
}
@@ -238,11 +231,11 @@ draw_convert_wide_points(struct draw_context *draw, boolean enable)
void
draw_convert_wide_lines(struct draw_context *draw, boolean enable)
{
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->convert_wide_lines = enable;
}
-
/**
* Allocate space for temporary post-transform vertices, such as for clipping.
*/
diff --git a/src/mesa/pipe/draw/draw_context.h b/src/mesa/pipe/draw/draw_context.h
index cfde26ceb7..ddeb184497 100644
--- a/src/mesa/pipe/draw/draw_context.h
+++ b/src/mesa/pipe/draw/draw_context.h
@@ -122,7 +122,6 @@ void draw_set_mapped_constant_buffer(struct draw_context *draw,
const void *buffer);
-
/***********************************************************************
* draw_prim.c
*/
diff --git a/src/mesa/pipe/draw/draw_cull.c b/src/mesa/pipe/draw/draw_cull.c
index 9bd53f45f2..05c274e4dc 100644
--- a/src/mesa/pipe/draw/draw_cull.c
+++ b/src/mesa/pipe/draw/draw_cull.c
@@ -50,14 +50,6 @@ static INLINE struct cull_stage *cull_stage( struct draw_stage *stage )
}
-static void cull_begin( struct draw_stage *stage )
-{
- struct cull_stage *cull = cull_stage(stage);
-
- cull->winding = stage->draw->rasterizer->cull_mode;
-
- stage->next->begin( stage->next );
-}
static void cull_tri( struct draw_stage *stage,
@@ -90,6 +82,18 @@ static void cull_tri( struct draw_stage *stage,
}
}
+static void cull_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct cull_stage *cull = cull_stage(stage);
+
+ cull->winding = stage->draw->rasterizer->cull_mode;
+
+ stage->tri = cull_tri;
+ stage->tri( stage, header );
+}
+
+
static void cull_line( struct draw_stage *stage,
struct prim_header *header )
@@ -105,12 +109,12 @@ static void cull_point( struct draw_stage *stage,
}
-static void cull_end( struct draw_stage *stage )
+static void cull_flush( struct draw_stage *stage, unsigned flags )
{
- stage->next->end( stage->next );
+ stage->tri = cull_first_tri;
+ stage->next->flush( stage->next, flags );
}
-
static void cull_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
@@ -135,11 +139,10 @@ struct draw_stage *draw_cull_stage( struct draw_context *draw )
cull->stage.draw = draw;
cull->stage.next = NULL;
- cull->stage.begin = cull_begin;
cull->stage.point = cull_point;
cull->stage.line = cull_line;
- cull->stage.tri = cull_tri;
- cull->stage.end = cull_end;
+ cull->stage.tri = cull_first_tri;
+ cull->stage.flush = cull_flush;
cull->stage.reset_stipple_counter = cull_reset_stipple_counter;
cull->stage.destroy = cull_destroy;
diff --git a/src/mesa/pipe/draw/draw_flatshade.c b/src/mesa/pipe/draw/draw_flatshade.c
index d7551e7948..1419f287d2 100644
--- a/src/mesa/pipe/draw/draw_flatshade.c
+++ b/src/mesa/pipe/draw/draw_flatshade.c
@@ -29,42 +29,53 @@
*/
#include "pipe/p_util.h"
+#include "pipe/p_shader_tokens.h"
#include "draw_private.h"
-static void flatshade_begin( struct draw_stage *stage )
+/** subclass of draw_stage */
+struct flat_stage
{
- stage->next->begin( stage->next );
-}
+ struct draw_stage stage;
+ uint num_color_attribs;
+ uint color_attribs[4]; /* front/back primary/secondary colors */
+};
-static INLINE void copy_attr( unsigned attr,
- struct vertex_header *dst,
- const struct vertex_header *src )
+static INLINE struct flat_stage *
+flat_stage(struct draw_stage *stage)
{
- if (attr) {
- memcpy( dst->data[attr],
- src->data[attr],
- sizeof(src->data[0]) );
- }
+ return (struct flat_stage *) stage;
}
-static INLINE void copy_colors( struct draw_stage *stage,
- struct vertex_header *dst,
+/** Copy all the color attributes from 'src' vertex to 'dst' vertex */
+static INLINE void copy_colors( struct draw_stage *stage,
+ struct vertex_header *dst,
const struct vertex_header *src )
{
- const uint num_attribs = stage->draw->vertex_info.num_attribs;
- const enum interp_mode *interp = stage->draw->vertex_info.interp_mode;
+ const struct flat_stage *flat = flat_stage(stage);
uint i;
+ for (i = 0; i < flat->num_color_attribs; i++) {
+ const uint attr = flat->color_attribs[i];
+ COPY_4FV(dst->data[attr], src->data[attr]);
+ }
+}
- /* Look for constant/flat attribs and duplicate from src to dst vertex */
- /* skip attrib[0] which is vert pos */
- for (i = 1; i < num_attribs; i++) {
- if (interp[i] == INTERP_CONSTANT) {
- copy_attr( i, dst, src );
- }
+
+/** Copy all the color attributes from src vertex to dst0 & dst1 vertices */
+static INLINE void copy_colors2( struct draw_stage *stage,
+ struct vertex_header *dst0,
+ struct vertex_header *dst1,
+ const struct vertex_header *src )
+{
+ const struct flat_stage *flat = flat_stage(stage);
+ uint i;
+ for (i = 0; i < flat->num_color_attribs; i++) {
+ const uint attr = flat->color_attribs[i];
+ COPY_4FV(dst0->data[attr], src->data[attr]);
+ COPY_4FV(dst1->data[attr], src->data[attr]);
}
}
@@ -84,8 +95,7 @@ static void flatshade_tri( struct draw_stage *stage,
tmp.v[1] = dup_vert(stage, header->v[1], 1);
tmp.v[2] = header->v[2];
- copy_colors(stage, tmp.v[0], tmp.v[2]);
- copy_colors(stage, tmp.v[1], tmp.v[2]);
+ copy_colors2(stage, tmp.v[0], tmp.v[1], tmp.v[2]);
stage->next->tri( stage->next, &tmp );
}
@@ -115,9 +125,46 @@ static void flatshade_point( struct draw_stage *stage,
}
-static void flatshade_end( struct draw_stage *stage )
+static void flatshade_init_state( struct draw_stage *stage )
+{
+ struct flat_stage *flat = flat_stage(stage);
+ const struct pipe_shader_state *vs = stage->draw->vertex_shader->state;
+ uint i;
+
+ /* Find which vertex shader outputs are colors, make a list */
+ flat->num_color_attribs = 0;
+ for (i = 0; i < vs->num_outputs; i++) {
+ if (vs->output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
+ vs->output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
+ flat->color_attribs[flat->num_color_attribs++] = i;
+ }
+ }
+
+ stage->line = flatshade_line;
+ stage->tri = flatshade_tri;
+}
+
+static void flatshade_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ flatshade_init_state( stage );
+ stage->tri( stage, header );
+}
+
+static void flatshade_first_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ flatshade_init_state( stage );
+ stage->line( stage, header );
+}
+
+
+static void flatshade_flush( struct draw_stage *stage,
+ unsigned flags )
{
- stage->next->end( stage->next );
+ stage->tri = flatshade_first_tri;
+ stage->line = flatshade_first_line;
+ stage->next->flush( stage->next, flags );
}
@@ -139,21 +186,20 @@ static void flatshade_destroy( struct draw_stage *stage )
*/
struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
{
- struct draw_stage *flatshade = CALLOC_STRUCT(draw_stage);
+ struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage);
- draw_alloc_tmps( flatshade, 2 );
+ draw_alloc_tmps( &flatshade->stage, 2 );
- flatshade->draw = draw;
- flatshade->next = NULL;
- flatshade->begin = flatshade_begin;
- flatshade->point = flatshade_point;
- flatshade->line = flatshade_line;
- flatshade->tri = flatshade_tri;
- flatshade->end = flatshade_end;
- flatshade->reset_stipple_counter = flatshade_reset_stipple_counter;
- flatshade->destroy = flatshade_destroy;
+ flatshade->stage.draw = draw;
+ flatshade->stage.next = NULL;
+ flatshade->stage.point = flatshade_point;
+ flatshade->stage.line = flatshade_first_line;
+ flatshade->stage.tri = flatshade_first_tri;
+ flatshade->stage.flush = flatshade_flush;
+ flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
+ flatshade->stage.destroy = flatshade_destroy;
- return flatshade;
+ return &flatshade->stage;
}
diff --git a/src/mesa/pipe/draw/draw_offset.c b/src/mesa/pipe/draw/draw_offset.c
index f8a01db3dd..a2990ee8a8 100644
--- a/src/mesa/pipe/draw/draw_offset.c
+++ b/src/mesa/pipe/draw/draw_offset.c
@@ -52,16 +52,7 @@ static INLINE struct offset_stage *offset_stage( struct draw_stage *stage )
}
-static void offset_begin( struct draw_stage *stage )
-{
- struct offset_stage *offset = offset_stage(stage);
- float mrd = 1.0f / 65535.0f; /* XXX this depends on depthbuffer bits! */
- offset->units = stage->draw->rasterizer->offset_units * mrd;
- offset->scale = stage->draw->rasterizer->offset_scale;
-
- stage->next->begin( stage->next );
-}
/**
@@ -124,24 +115,39 @@ static void offset_tri( struct draw_stage *stage,
}
+static void offset_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct offset_stage *offset = offset_stage(stage);
+ float mrd = 1.0f / 65535.0f; /* XXX this depends on depthbuffer bits! */
+
+ offset->units = stage->draw->rasterizer->offset_units * mrd;
+ offset->scale = stage->draw->rasterizer->offset_scale;
+
+ stage->tri = offset_tri;
+ stage->tri( stage, header );
+}
+
static void offset_line( struct draw_stage *stage,
- struct prim_header *header )
+ struct prim_header *header )
{
stage->next->line( stage->next, header );
}
static void offset_point( struct draw_stage *stage,
- struct prim_header *header )
+ struct prim_header *header )
{
stage->next->point( stage->next, header );
}
-static void offset_end( struct draw_stage *stage )
+static void offset_flush( struct draw_stage *stage,
+ unsigned flags )
{
- stage->next->end( stage->next );
+ stage->tri = offset_first_tri;
+ stage->next->flush( stage->next, flags );
}
@@ -169,11 +175,10 @@ struct draw_stage *draw_offset_stage( struct draw_context *draw )
offset->stage.draw = draw;
offset->stage.next = NULL;
- offset->stage.begin = offset_begin;
offset->stage.point = offset_point;
offset->stage.line = offset_line;
- offset->stage.tri = offset_tri;
- offset->stage.end = offset_end;
+ offset->stage.tri = offset_first_tri;
+ offset->stage.flush = offset_flush;
offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
offset->stage.destroy = offset_destroy;
diff --git a/src/mesa/pipe/draw/draw_prim.c b/src/mesa/pipe/draw/draw_prim.c
index f8fc23b510..243381aec0 100644
--- a/src/mesa/pipe/draw/draw_prim.c
+++ b/src/mesa/pipe/draw/draw_prim.c
@@ -57,39 +57,40 @@ static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
static void draw_prim_queue_flush( struct draw_context *draw )
{
- struct draw_stage *first = draw->pipeline.first;
unsigned i;
if (0)
fprintf(stdout,"Flushing with %d prims, %d verts\n",
draw->pq.queue_nr, draw->vs.queue_nr);
- /* Make sure all vertices are available/shaded:
- */
- if (draw->vs.queue_nr)
- draw_vertex_shader_queue_flush(draw);
+ if (draw->pq.queue_nr == 0)
+ return;
+ /* NOTE: we cannot save draw->pipeline->first in a local var because
+ * draw->pipeline->first is often changed by the first call to tri(),
+ * line(), etc.
+ */
switch (draw->reduced_prim) {
case RP_TRI:
for (i = 0; i < draw->pq.queue_nr; i++) {
if (draw->pq.queue[i].reset_line_stipple)
- first->reset_stipple_counter( first );
+ draw->pipeline.first->reset_stipple_counter( draw->pipeline.first );
- first->tri( first, &draw->pq.queue[i] );
+ draw->pipeline.first->tri( draw->pipeline.first, &draw->pq.queue[i] );
}
break;
case RP_LINE:
for (i = 0; i < draw->pq.queue_nr; i++) {
if (draw->pq.queue[i].reset_line_stipple)
- first->reset_stipple_counter( first );
+ draw->pipeline.first->reset_stipple_counter( draw->pipeline.first );
- first->line( first, &draw->pq.queue[i] );
+ draw->pipeline.first->line( draw->pipeline.first, &draw->pq.queue[i] );
}
break;
case RP_POINT:
- first->reset_stipple_counter( first );
+ draw->pipeline.first->reset_stipple_counter( draw->pipeline.first );
for (i = 0; i < draw->pq.queue_nr; i++)
- first->point( first, &draw->pq.queue[i] );
+ draw->pipeline.first->point( draw->pipeline.first, &draw->pq.queue[i] );
break;
}
@@ -98,33 +99,32 @@ static void draw_prim_queue_flush( struct draw_context *draw )
}
-void draw_do_flush( struct draw_context *draw,
- unsigned flush )
+
+void draw_do_flush( struct draw_context *draw, unsigned flags )
{
- if ((flush & (DRAW_FLUSH_PRIM_QUEUE |
- DRAW_FLUSH_VERTEX_CACHE_INVALIDATE |
- DRAW_FLUSH_DRAW)) &&
- draw->pq.queue_nr)
- {
- draw_prim_queue_flush(draw);
- }
+ if (0)
+ fprintf(stdout,"Flushing with %d verts, %d prims\n",
+ draw->vs.queue_nr,
+ draw->pq.queue_nr );
- if ((flush & (DRAW_FLUSH_VERTEX_CACHE_INVALIDATE |
- DRAW_FLUSH_DRAW)) &&
- draw->drawing)
- {
- draw_vertex_cache_invalidate(draw);
- }
- if ((flush & DRAW_FLUSH_DRAW) &&
- draw->drawing)
- {
- draw->pipeline.first->end( draw->pipeline.first );
- draw->drawing = FALSE;
- draw->prim = ~0;
- draw->pipeline.first = draw->pipeline.validate;
- }
+ if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
+ draw_vertex_shader_queue_flush(draw);
+
+ if (flags >= DRAW_FLUSH_PRIM_QUEUE) {
+ draw_prim_queue_flush(draw);
+ if (flags >= DRAW_FLUSH_VERTEX_CACHE) {
+ draw_vertex_cache_invalidate(draw);
+
+ if (flags >= DRAW_FLUSH_STATE_CHANGE) {
+ draw->pipeline.first->flush( draw->pipeline.first, flags );
+ draw->pipeline.first = draw->pipeline.validate;
+ draw->reduced_prim = ~0;
+ }
+ }
+ }
+ }
}
@@ -139,7 +139,7 @@ static struct prim_header *get_queued_prim( struct draw_context *draw,
{
if (!draw_vertex_cache_check_space( draw, nr_verts )) {
// fprintf(stderr, "v");
- draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE_INVALIDATE );
+ draw_do_flush( draw, DRAW_FLUSH_VERTEX_CACHE );
}
else if (draw->pq.queue_nr == PRIM_QUEUE_LENGTH) {
// fprintf(stderr, "p");
@@ -247,13 +247,14 @@ static void do_quad( struct draw_context *draw,
* Main entrypoint to draw some number of points/lines/triangles
*/
static void
-draw_prim( struct draw_context *draw, unsigned start, unsigned count )
+draw_prim( struct draw_context *draw,
+ unsigned prim, unsigned start, unsigned count )
{
unsigned i;
// _mesa_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count );
- switch (draw->prim) {
+ switch (prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < count; i ++) {
do_point( draw,
@@ -385,21 +386,6 @@ draw_prim( struct draw_context *draw, unsigned start, unsigned count )
}
-static void
-draw_set_prim( struct draw_context *draw, unsigned prim )
-{
- assert(prim >= PIPE_PRIM_POINTS);
- assert(prim <= PIPE_PRIM_POLYGON);
-
- if (reduced_prim[prim] != draw->reduced_prim) {
- draw_do_flush( draw, DRAW_FLUSH_PRIM_QUEUE );
- draw->reduced_prim = reduced_prim[prim];
- }
-
- draw->prim = prim;
-}
-
-
/**
@@ -413,19 +399,13 @@ void
draw_arrays(struct draw_context *draw, unsigned prim,
unsigned start, unsigned count)
{
- if (!draw->drawing) {
- draw->drawing = TRUE;
-
- /* tell drawing pipeline we're beginning drawing */
- draw->pipeline.first->begin( draw->pipeline.first );
- }
-
- if (draw->prim != prim) {
- draw_set_prim( draw, prim );
+ if (reduced_prim[prim] != draw->reduced_prim) {
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+ draw->reduced_prim = reduced_prim[prim];
}
/* drawing done here: */
- draw_prim(draw, start, count);
+ draw_prim(draw, prim, start, count);
}
diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h
index a264fabfb4..1e59f5bd8d 100644
--- a/src/mesa/pipe/draw/draw_private.h
+++ b/src/mesa/pipe/draw/draw_private.h
@@ -44,8 +44,6 @@
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
-#include "draw_vertex.h"
-
#include "x86/rtasm/x86sse.h"
#include "pipe/tgsi/exec/tgsi_exec.h"
@@ -103,8 +101,6 @@ struct draw_stage
struct vertex_header **tmp; /**< temp vert storage, such as for clipping */
unsigned nr_tmps;
- void (*begin)( struct draw_stage * );
-
void (*point)( struct draw_stage *,
struct prim_header * );
@@ -114,7 +110,8 @@ struct draw_stage
void (*tri)( struct draw_stage *,
struct prim_header * );
- void (*end)( struct draw_stage * );
+ void (*flush)( struct draw_stage *,
+ unsigned flags );
void (*reset_stipple_counter)( struct draw_stage * );
@@ -140,6 +137,13 @@ struct draw_vertex_shader {
#endif
};
+
+/* Internal function for vertex fetch.
+ */
+typedef void (*fetch_func)(const void *ptr, float *attrib);
+
+
+
/**
* Private context for the drawing module.
*/
@@ -170,6 +174,8 @@ struct draw_context
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
const struct draw_vertex_shader *vertex_shader;
+ uint num_vs_outputs; /**< convenience, from vertex_shader */
+
/* user-space vertex data, buffers */
struct {
/** vertex element/index buffer (ex: glDrawElements) */
@@ -189,22 +195,23 @@ struct draw_context
float plane[12][4];
unsigned nr_planes;
- /** Describes the layout of post-transformation vertices */
- struct vertex_info vertex_info;
- /** Two-sided attributes: */
- uint attrib_front0, attrib_back0;
- uint attrib_front1, attrib_back1;
-
boolean convert_wide_points; /**< convert wide points to tris? */
boolean convert_wide_lines; /**< convert side lines to tris? */
- boolean drawing; /**< do we presently have something queued for drawing? */
- unsigned prim; /**< current prim type: PIPE_PRIM_x */
unsigned reduced_prim;
/** TGSI program interpreter runtime state */
struct tgsi_exec_machine machine;
+ /* Vertex fetch internal state
+ */
+ struct {
+ const ubyte *src_ptr[PIPE_ATTRIB_MAX];
+ unsigned pitch[PIPE_ATTRIB_MAX];
+ fetch_func fetch[PIPE_ATTRIB_MAX];
+ unsigned nr_attrs;
+ } vertex_fetch;
+
/* Post-tnl vertex cache:
*/
struct {
@@ -279,20 +286,21 @@ extern void draw_vertex_shader_queue_flush_llvm( struct draw_context *draw );
struct tgsi_exec_machine;
+extern void draw_update_vertex_fetch( struct draw_context *draw );
extern void draw_vertex_fetch( struct draw_context *draw,
struct tgsi_exec_machine *machine,
const unsigned *elts,
unsigned count );
-#define DRAW_FLUSH_PRIM_QUEUE 0x1
-#define DRAW_FLUSH_VERTEX_CACHE_INVALIDATE 0x2
-#define DRAW_FLUSH_DRAW 0x4
-
+#define DRAW_FLUSH_SHADER_QUEUE 0x1 /* sized not to overflow, never raised */
+#define DRAW_FLUSH_PRIM_QUEUE 0x2
+#define DRAW_FLUSH_VERTEX_CACHE 0x4
+#define DRAW_FLUSH_STATE_CHANGE 0x8
+#define DRAW_FLUSH_BACKEND 0x10
-void draw_do_flush( struct draw_context *draw,
- unsigned flags );
+void draw_do_flush( struct draw_context *draw, unsigned flags );
@@ -309,7 +317,9 @@ dup_vert( struct draw_stage *stage,
unsigned idx )
{
struct vertex_header *tmp = stage->tmp[idx];
- memcpy(tmp, vert, stage->draw->vertex_info.size * sizeof(float) );
+ const uint vsize = sizeof(struct vertex_header)
+ + stage->draw->num_vs_outputs * 4 * sizeof(float);
+ memcpy(tmp, vert, vsize);
tmp->vertex_id = UNDEFINED_VERTEX_ID;
return tmp;
}
diff --git a/src/mesa/pipe/draw/draw_stipple.c b/src/mesa/pipe/draw/draw_stipple.c
index 3e0d5689e1..9029101916 100644
--- a/src/mesa/pipe/draw/draw_stipple.c
+++ b/src/mesa/pipe/draw/draw_stipple.c
@@ -61,6 +61,7 @@ stipple_stage(struct draw_stage *stage)
/**
* Compute interpolated vertex attributes for 'dst' at position 't'
* between 'v0' and 'v1'.
+ * XXX using linear interpolation for all attribs at this time.
*/
static void
screen_interp( struct draw_context *draw,
@@ -70,28 +71,13 @@ screen_interp( struct draw_context *draw,
const struct vertex_header *v1 )
{
uint attr;
- for (attr = 0; attr < draw->vertex_info.num_attribs; attr++) {
- switch (draw->vertex_info.interp_mode[attr]) {
- case INTERP_NONE:
- case INTERP_CONSTANT:
- COPY_4FV(dst->data[attr], v0->data[attr]);
- break;
- case INTERP_PERSPECTIVE:
- /* Fall-through */
- /* XXX special-case perspective? */
- case INTERP_LINEAR:
- {
- const float *val0 = v0->data[attr];
- const float *val1 = v1->data[attr];
- float *newv = dst->data[attr];
- uint i;
- for (i = 0; i < 4; i++) {
- newv[i] = val0[i] + t * (val1[i] - val0[i]);
- }
- }
- break;
- default:
- abort();
+ for (attr = 0; attr < draw->num_vs_outputs; attr++) {
+ const float *val0 = v0->data[attr];
+ const float *val1 = v1->data[attr];
+ float *newv = dst->data[attr];
+ uint i;
+ for (i = 0; i < 4; i++) {
+ newv[i] = val0[i] + t * (val1[i] - val0[i]);
}
}
}
@@ -187,7 +173,8 @@ reset_stipple_counter(struct draw_stage *stage)
static void
-stipple_begin(struct draw_stage *stage)
+stipple_first_line(struct draw_stage *stage,
+ struct prim_header *header)
{
struct stipple_stage *stipple = stipple_stage(stage);
struct draw_context *draw = stage->draw;
@@ -195,14 +182,16 @@ stipple_begin(struct draw_stage *stage)
stipple->pattern = draw->rasterizer->line_stipple_pattern;
stipple->factor = draw->rasterizer->line_stipple_factor + 1;
- stage->next->begin( stage->next );
+ stage->line = stipple_line;
+ stage->line( stage, header );
}
static void
-stipple_end(struct draw_stage *stage)
+stipple_flush(struct draw_stage *stage, unsigned flags)
{
- stage->next->end( stage->next );
+ stage->line = stipple_first_line;
+ stage->next->flush( stage->next, flags );
}
@@ -238,12 +227,11 @@ struct draw_stage *draw_stipple_stage( struct draw_context *draw )
stipple->stage.draw = draw;
stipple->stage.next = NULL;
- stipple->stage.begin = stipple_begin;
stipple->stage.point = passthrough_point;
- stipple->stage.line = stipple_line;
+ stipple->stage.line = stipple_first_line;
stipple->stage.tri = passthrough_tri;
stipple->stage.reset_stipple_counter = reset_stipple_counter;
- stipple->stage.end = stipple_end;
+ stipple->stage.flush = stipple_flush;
stipple->stage.destroy = stipple_destroy;
return &stipple->stage;
diff --git a/src/mesa/pipe/draw/draw_twoside.c b/src/mesa/pipe/draw/draw_twoside.c
index c7e268f11e..ad2aaf10bb 100644
--- a/src/mesa/pipe/draw/draw_twoside.c
+++ b/src/mesa/pipe/draw/draw_twoside.c
@@ -30,12 +30,15 @@
#include "pipe/p_util.h"
#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
#include "draw_private.h"
struct twoside_stage {
struct draw_stage stage;
float sign; /**< +1 or -1 */
+ uint attrib_front0, attrib_back0;
+ uint attrib_front1, attrib_back1;
};
@@ -45,44 +48,25 @@ static INLINE struct twoside_stage *twoside_stage( struct draw_stage *stage )
}
-static void twoside_begin( struct draw_stage *stage )
-{
- struct twoside_stage *twoside = twoside_stage(stage);
-
- /*
- * We'll multiply the primitive's determinant by this sign to determine
- * if the triangle is back-facing (negative).
- * sign = -1 for CCW, +1 for CW
- */
- twoside->sign = (stage->draw->rasterizer->front_winding == PIPE_WINDING_CCW) ? -1.0f : 1.0f;
-
- stage->next->begin( stage->next );
-}
-
-
-static INLINE void copy_attrib( unsigned attr_dst,
- unsigned attr_src,
- struct vertex_header *v )
-{
- COPY_4FV(v->data[attr_dst], v->data[attr_src]);
-}
/**
* Copy back color(s) to front color(s).
*/
-static struct vertex_header *copy_bfc( struct twoside_stage *twoside,
- const struct vertex_header *v,
- unsigned idx )
+static INLINE struct vertex_header *
+copy_bfc( struct twoside_stage *twoside,
+ const struct vertex_header *v,
+ unsigned idx )
{
struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx );
- const struct draw_context *draw = twoside->stage.draw;
- if (draw->attrib_front0 && draw->attrib_back0) {
- copy_attrib(draw->attrib_front0, draw->attrib_back0, tmp);
+ if (twoside->attrib_back0) {
+ COPY_4FV(tmp->data[twoside->attrib_front0],
+ tmp->data[twoside->attrib_back0]);
}
- if (draw->attrib_front1 && draw->attrib_back1) {
- copy_attrib(draw->attrib_front1, draw->attrib_back1, tmp);
+ if (twoside->attrib_back1) {
+ COPY_4FV(tmp->data[twoside->attrib_front1],
+ tmp->data[twoside->attrib_back1]);
}
return tmp;
@@ -131,10 +115,56 @@ static void twoside_point( struct draw_stage *stage,
}
-static void twoside_end( struct draw_stage *stage )
+static void twoside_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
{
- /* pass-through */
- stage->next->end( stage->next );
+ struct twoside_stage *twoside = twoside_stage(stage);
+ const struct pipe_shader_state *vs = stage->draw->vertex_shader->state;
+ uint i;
+
+ twoside->attrib_front0 = 0;
+ twoside->attrib_front1 = 0;
+ twoside->attrib_back0 = 0;
+ twoside->attrib_back1 = 0;
+
+ /* Find which vertex shader outputs are front/back colors */
+ for (i = 0; i < vs->num_outputs; i++) {
+ if (vs->output_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
+ if (vs->output_semantic_index[i] == 0)
+ twoside->attrib_front0 = i;
+ else
+ twoside->attrib_front1 = i;
+ }
+ if (vs->output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
+ if (vs->output_semantic_index[i] == 0)
+ twoside->attrib_back0 = i;
+ else
+ twoside->attrib_back1 = i;
+ }
+ }
+
+ if (!twoside->attrib_back0)
+ twoside->attrib_front0 = 0;
+
+ if (!twoside->attrib_back1)
+ twoside->attrib_front1 = 0;
+
+ /*
+ * We'll multiply the primitive's determinant by this sign to determine
+ * if the triangle is back-facing (negative).
+ * sign = -1 for CCW, +1 for CW
+ */
+ twoside->sign = (stage->draw->rasterizer->front_winding == PIPE_WINDING_CCW) ? -1.0f : 1.0f;
+
+ stage->tri = twoside_tri;
+ stage->tri( stage, header );
+}
+
+
+static void twoside_flush( struct draw_stage *stage, unsigned flags )
+{
+ stage->tri = twoside_first_tri;
+ stage->next->flush( stage->next, flags );
}
@@ -162,11 +192,10 @@ struct draw_stage *draw_twoside_stage( struct draw_context *draw )
twoside->stage.draw = draw;
twoside->stage.next = NULL;
- twoside->stage.begin = twoside_begin;
twoside->stage.point = twoside_point;
twoside->stage.line = twoside_line;
- twoside->stage.tri = twoside_tri;
- twoside->stage.end = twoside_end;
+ twoside->stage.tri = twoside_first_tri;
+ twoside->stage.flush = twoside_flush;
twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
twoside->stage.destroy = twoside_destroy;
diff --git a/src/mesa/pipe/draw/draw_unfilled.c b/src/mesa/pipe/draw/draw_unfilled.c
index 786826b33c..364bda8b79 100644
--- a/src/mesa/pipe/draw/draw_unfilled.c
+++ b/src/mesa/pipe/draw/draw_unfilled.c
@@ -55,15 +55,6 @@ static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage )
}
-static void unfilled_begin( struct draw_stage *stage )
-{
- struct unfilled_stage *unfilled = unfilled_stage(stage);
-
- unfilled->mode[0] = stage->draw->rasterizer->fill_ccw; /* front */
- unfilled->mode[1] = stage->draw->rasterizer->fill_cw; /* back */
-
- stage->next->begin( stage->next );
-}
static void point( struct draw_stage *stage,
struct vertex_header *v0 )
@@ -142,6 +133,20 @@ static void unfilled_tri( struct draw_stage *stage,
}
}
+
+static void unfilled_first_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct unfilled_stage *unfilled = unfilled_stage(stage);
+
+ unfilled->mode[0] = stage->draw->rasterizer->fill_ccw; /* front */
+ unfilled->mode[1] = stage->draw->rasterizer->fill_cw; /* back */
+
+ stage->tri = unfilled_tri;
+ stage->tri( stage, header );
+}
+
+
static void unfilled_line( struct draw_stage *stage,
struct prim_header *header )
{
@@ -156,9 +161,10 @@ static void unfilled_point( struct draw_stage *stage,
}
-static void unfilled_end( struct draw_stage *stage )
+static void unfilled_flush( struct draw_stage *stage,
+ unsigned flags )
{
- stage->next->end( stage->next );
+ stage->next->flush( stage->next, flags );
}
@@ -187,11 +193,10 @@ struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
unfilled->stage.draw = draw;
unfilled->stage.next = NULL;
unfilled->stage.tmp = NULL;
- unfilled->stage.begin = unfilled_begin;
unfilled->stage.point = unfilled_point;
unfilled->stage.line = unfilled_line;
- unfilled->stage.tri = unfilled_tri;
- unfilled->stage.end = unfilled_end;
+ unfilled->stage.tri = unfilled_first_tri;
+ unfilled->stage.flush = unfilled_flush;
unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
unfilled->stage.destroy = unfilled_destroy;
diff --git a/src/mesa/pipe/draw/draw_validate.c b/src/mesa/pipe/draw/draw_validate.c
index 3b1f5179a9..86d5a5f814 100644
--- a/src/mesa/pipe/draw/draw_validate.c
+++ b/src/mesa/pipe/draw/draw_validate.c
@@ -39,10 +39,17 @@
/**
* Rebuild the rendering pipeline.
*/
-static void validate_begin( struct draw_stage *stage )
+static struct draw_stage *validate_pipeline( struct draw_stage *stage )
{
struct draw_context *draw = stage->draw;
struct draw_stage *next = draw->pipeline.rasterize;
+ int need_det = 0;
+ int precalc_flat = 0;
+
+ /* Set the validate's next stage to the rasterize stage, so that it
+ * can be found later if needed for flushing.
+ */
+ stage->next = next;
/*
* NOTE: we build up the pipeline in end-to-start order.
@@ -61,29 +68,38 @@ static void validate_begin( struct draw_stage *stage )
if (draw->rasterizer->line_stipple_enable) {
draw->pipeline.stipple->next = next;
next = draw->pipeline.stipple;
+ precalc_flat = 1; /* only needed for lines really */
}
if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) {
draw->pipeline.unfilled->next = next;
next = draw->pipeline.unfilled;
+ precalc_flat = 1; /* only needed for triangles really */
+ need_det = 1;
}
if (draw->rasterizer->offset_cw ||
draw->rasterizer->offset_ccw) {
draw->pipeline.offset->next = next;
next = draw->pipeline.offset;
+ need_det = 1;
}
if (draw->rasterizer->light_twoside) {
draw->pipeline.twoside->next = next;
next = draw->pipeline.twoside;
+ need_det = 1;
}
/* Always run the cull stage as we calculate determinant there
- * also. Fix this..
+ * also.
+ *
+ * This can actually be a win as culling out the triangles can lead
+ * to less work emitting vertices, smaller vertex buffers, etc.
+ * It's difficult to say whether this will be true in general.
*/
- {
+ if (need_det || draw->rasterizer->cull_mode) {
draw->pipeline.cull->next = next;
next = draw->pipeline.cull;
}
@@ -94,19 +110,52 @@ static void validate_begin( struct draw_stage *stage )
{
draw->pipeline.clip->next = next;
next = draw->pipeline.clip;
+ precalc_flat = 1; /* XXX: FIX ME! Only needed for clipped prims */
}
- /* Do software flatshading prior to clipping. XXX: should only do
- * this for clipped primitives, ie it is a part of the clip
- * routine.
- */
- if (draw->rasterizer->flatshade) {
+ if (draw->rasterizer->flatshade && precalc_flat) {
draw->pipeline.flatshade->next = next;
next = draw->pipeline.flatshade;
}
-
+
draw->pipeline.first = next;
- draw->pipeline.first->begin( draw->pipeline.first );
+ return next;
+}
+
+static void validate_tri( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->tri( pipeline, header );
+}
+
+static void validate_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->line( pipeline, header );
+}
+
+static void validate_point( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->point( pipeline, header );
+}
+
+static void validate_reset_stipple_counter( struct draw_stage *stage )
+{
+ struct draw_stage *pipeline = validate_pipeline( stage );
+ pipeline->reset_stipple_counter( pipeline );
+}
+
+static void validate_flush( struct draw_stage *stage,
+ unsigned flags )
+{
+ /* May need to pass a backend flush on to the rasterize stage.
+ */
+ if (stage->next)
+ stage->next->flush( stage->next, flags );
}
@@ -125,12 +174,11 @@ struct draw_stage *draw_validate_stage( struct draw_context *draw )
stage->draw = draw;
stage->next = NULL;
- stage->begin = validate_begin;
- stage->point = NULL;
- stage->line = NULL;
- stage->tri = NULL;
- stage->end = NULL;
- stage->reset_stipple_counter = NULL;
+ stage->point = validate_point;
+ stage->line = validate_line;
+ stage->tri = validate_tri;
+ stage->flush = validate_flush;
+ stage->reset_stipple_counter = validate_reset_stipple_counter;
stage->destroy = validate_destroy;
return stage;
diff --git a/src/mesa/pipe/draw/draw_vbuf.c b/src/mesa/pipe/draw/draw_vbuf.c
index a4b6247e18..cd0b4fbbb9 100644
--- a/src/mesa/pipe/draw/draw_vbuf.c
+++ b/src/mesa/pipe/draw/draw_vbuf.c
@@ -141,37 +141,43 @@ emit_vertex( struct vbuf_stage *vbuf,
for (i = 0; i < vinfo->num_attribs; i++) {
uint j = vinfo->src_index[i];
- switch (vinfo->format[i]) {
- case FORMAT_OMIT:
+ switch (vinfo->emit[i]) {
+ case EMIT_OMIT:
/* no-op */
break;
- case FORMAT_1F:
+ case EMIT_ALL:
+ /* just copy the whole vertex as-is to the vbuf */
+ assert(i == 0);
+ memcpy(vbuf->vertex_ptr, vertex, vinfo->size * 4);
+ vbuf->vertex_ptr += vinfo->size;
+ return;
+ case EMIT_1F:
*vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
count++;
break;
- case FORMAT_1F_PSIZE:
+ case EMIT_1F_PSIZE:
*vbuf->vertex_ptr++ = fui(vbuf->stage.draw->rasterizer->point_size);
count++;
break;
- case FORMAT_2F:
+ case EMIT_2F:
*vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
*vbuf->vertex_ptr++ = fui(vertex->data[j][1]);
count += 2;
break;
- case FORMAT_3F:
+ case EMIT_3F:
*vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
*vbuf->vertex_ptr++ = fui(vertex->data[j][1]);
*vbuf->vertex_ptr++ = fui(vertex->data[j][2]);
count += 3;
break;
- case FORMAT_4F:
+ case EMIT_4F:
*vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
*vbuf->vertex_ptr++ = fui(vertex->data[j][1]);
*vbuf->vertex_ptr++ = fui(vertex->data[j][2]);
*vbuf->vertex_ptr++ = fui(vertex->data[j][3]);
count += 4;
break;
- case FORMAT_4UB:
+ case EMIT_4UB:
*vbuf->vertex_ptr++ = pack_ub4(float_to_ubyte( vertex->data[j][2] ),
float_to_ubyte( vertex->data[j][1] ),
float_to_ubyte( vertex->data[j][0] ),
@@ -381,29 +387,26 @@ vbuf_alloc_vertices( struct draw_stage *stage,
}
-static void
-vbuf_begin( struct draw_stage *stage )
-{
- /* no-op, vbuffer allocated by first point/line/tri */
-}
-
static void
-vbuf_end( struct draw_stage *stage )
+vbuf_flush( struct draw_stage *stage, unsigned flags )
{
-// vbuf_flush_indices( stage );
- /* XXX: Overkill */
- vbuf_flush_vertices( stage );
-
+ vbuf_flush_indices( stage );
+
stage->point = vbuf_first_point;
stage->line = vbuf_first_line;
stage->tri = vbuf_first_tri;
+
+ if (flags & DRAW_FLUSH_BACKEND)
+ vbuf_flush_vertices( stage );
}
static void
vbuf_reset_stipple_counter( struct draw_stage *stage )
{
+ /* XXX: Need to do something here for hardware with linestipple.
+ */
(void) stage;
}
@@ -426,11 +429,10 @@ struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
struct vbuf_stage *vbuf = CALLOC_STRUCT(vbuf_stage);
vbuf->stage.draw = draw;
- vbuf->stage.begin = vbuf_begin;
vbuf->stage.point = vbuf_first_point;
vbuf->stage.line = vbuf_first_line;
vbuf->stage.tri = vbuf_first_tri;
- vbuf->stage.end = vbuf_end;
+ vbuf->stage.flush = vbuf_flush;
vbuf->stage.reset_stipple_counter = vbuf_reset_stipple_counter;
vbuf->stage.destroy = vbuf_destroy;
diff --git a/src/mesa/pipe/draw/draw_vertex.c b/src/mesa/pipe/draw/draw_vertex.c
index 6191fcedbf..2d6592150f 100644
--- a/src/mesa/pipe/draw/draw_vertex.c
+++ b/src/mesa/pipe/draw/draw_vertex.c
@@ -38,17 +38,6 @@
#include "pipe/draw/draw_vertex.h"
-static INLINE void
-emit_vertex_attr(struct vertex_info *vinfo,
- enum attrib_format format, enum interp_mode interp)
-{
- const uint n = vinfo->num_attribs;
- vinfo->interp_mode[n] = interp;
- vinfo->format[n] = format;
- vinfo->num_attribs++;
-}
-
-
/**
* Compute the size of a vertex, in dwords/floats, to update the
* vinfo->size field.
@@ -60,25 +49,27 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
vinfo->size = 0;
for (i = 0; i < vinfo->num_attribs; i++) {
- switch (vinfo->format[i]) {
- case FORMAT_OMIT:
+ switch (vinfo->emit[i]) {
+ case EMIT_OMIT:
break;
- case FORMAT_4UB:
+ case EMIT_4UB:
/* fall-through */
- case FORMAT_1F_PSIZE:
+ case EMIT_1F_PSIZE:
/* fall-through */
- case FORMAT_1F:
+ case EMIT_1F:
vinfo->size += 1;
break;
- case FORMAT_2F:
+ case EMIT_2F:
vinfo->size += 2;
break;
- case FORMAT_3F:
+ case EMIT_3F:
vinfo->size += 3;
break;
- case FORMAT_4F:
+ case EMIT_4F:
vinfo->size += 4;
break;
+ case EMIT_ALL:
+ /* fall-through */
default:
assert(0);
}
@@ -86,62 +77,3 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
assert(vinfo->size * 4 <= MAX_VERTEX_SIZE);
}
-
-
-/**
- * Tell the drawing module about the contents of post-transformation vertices.
- * Note that the vertex attribute format info isn't used by 'draw'; all
- * attributes are handled as float[4]. But when the driver emits vertices
- * it'll use that info.
- * We _do_ care about the number of attributes and their interpolation modes.
- */
-void
-draw_set_vertex_info( struct draw_context *draw,
- const struct vertex_info *info)
-{
- assert(info->interp_mode[0] == INTERP_LINEAR); /* should be vert pos */
- assert(info->num_attribs <= PIPE_MAX_SHADER_OUTPUTS);
-
- memcpy(&draw->vertex_info, info, sizeof(*info));
-
- /* Need to know vertex size (in words) for vertex copying elsewhere.
- * Four words per attribute, plus vertex header (uint) and clip
- * position (float[4]).
- */
- draw->vertex_info.size = draw->vertex_info.num_attribs * 4 + 5;
-}
-
-
-/**
- * This function is used to tell the draw module about attributes
- * (like colors) that need to be selected based on front/back face
- * orientation.
- *
- * The logic is:
- * if (polygon is back-facing) {
- * vertex->attrib[front0] = vertex->attrib[back0];
- * vertex->attrib[front1] = vertex->attrib[back1];
- * }
- *
- * \param front0 first attrib to replace if the polygon is back-facing
- * \param back0 first attrib to copy if the polygon is back-facing
- * \param front1 second attrib to replace if the polygon is back-facing
- * \param back1 second attrib to copy if the polygon is back-facing
- *
- * Pass -1 to disable two-sided attributes.
- */
-void
-draw_set_twoside_attributes(struct draw_context *draw,
- uint front0, uint back0,
- uint front1, uint back1)
-{
- /* XXX we could alternately pass an array of front/back attribs if there's
- * ever need for more than two. One could imagine a shader extension
- * that allows arbitrary attributes to be selected based on polygon
- * orientation...
- */
- draw->attrib_front0 = front0;
- draw->attrib_back0 = back0;
- draw->attrib_front1 = front1;
- draw->attrib_back1 = back1;
-}
diff --git a/src/mesa/pipe/draw/draw_vertex.h b/src/mesa/pipe/draw/draw_vertex.h
index e4f85bc49f..dfc637b19b 100644
--- a/src/mesa/pipe/draw/draw_vertex.h
+++ b/src/mesa/pipe/draw/draw_vertex.h
@@ -34,20 +34,21 @@
#define DRAW_VERTEX_H
-struct draw_context;
+#include "pipe/p_state.h"
/**
- * Vertex attribute format
+ * Vertex attribute emit modes
*/
-enum attrib_format {
- FORMAT_OMIT, /**< don't emit the attribute */
- FORMAT_1F,
- FORMAT_1F_PSIZE, /**< insert constant point size */
- FORMAT_2F,
- FORMAT_3F,
- FORMAT_4F,
- FORMAT_4UB /**< XXX may need variations for RGBA vs BGRA, etc */
+enum attrib_emit {
+ EMIT_OMIT, /**< don't emit the attribute */
+ EMIT_ALL, /**< emit whole post-xform vertex, w/ header */
+ EMIT_1F,
+ EMIT_1F_PSIZE, /**< insert constant point size */
+ EMIT_2F,
+ EMIT_3F,
+ EMIT_4F,
+ EMIT_4UB /**< XXX may need variations for RGBA vs BGRA, etc */
};
@@ -56,6 +57,7 @@ enum attrib_format {
*/
enum interp_mode {
INTERP_NONE, /**< never interpolate vertex header info */
+ INTERP_POS, /**< special case for frag position */
INTERP_CONSTANT,
INTERP_LINEAR,
INTERP_PERSPECTIVE
@@ -63,15 +65,15 @@ enum interp_mode {
/**
- * Information about post-transformed vertex layout.
+ * Information about hardware/rasterization vertex layout.
*/
struct vertex_info
{
uint num_attribs;
uint hwfmt[4]; /**< hardware format info for this format */
- enum interp_mode interp_mode[PIPE_MAX_SHADER_OUTPUTS];
- enum attrib_format format[PIPE_MAX_SHADER_OUTPUTS]; /**< FORMAT_x */
- uint src_index[PIPE_MAX_SHADER_OUTPUTS];
+ enum interp_mode interp_mode[PIPE_MAX_SHADER_INPUTS];
+ enum attrib_emit emit[PIPE_MAX_SHADER_INPUTS]; /**< EMIT_x */
+ uint src_index[PIPE_MAX_SHADER_INPUTS]; /**< map to post-xform attribs */
uint size; /**< total vertex size in dwords */
};
@@ -85,12 +87,12 @@ struct vertex_info
*/
static INLINE uint
draw_emit_vertex_attr(struct vertex_info *vinfo,
- enum attrib_format format, enum interp_mode interp,
+ enum attrib_emit emit, enum interp_mode interp,
uint src_index)
{
const uint n = vinfo->num_attribs;
- assert(n < PIPE_MAX_SHADER_OUTPUTS);
- vinfo->format[n] = format;
+ assert(n < PIPE_MAX_SHADER_INPUTS);
+ vinfo->emit[n] = emit;
vinfo->interp_mode[n] = interp;
vinfo->src_index[n] = src_index;
vinfo->num_attribs++;
@@ -98,13 +100,6 @@ draw_emit_vertex_attr(struct vertex_info *vinfo,
}
-extern void draw_set_vertex_info( struct draw_context *draw,
- const struct vertex_info *info);
-
-extern void draw_set_twoside_attributes(struct draw_context *draw,
- uint front0, uint back0,
- uint front1, uint back1);
-
extern void draw_compute_vertex_size(struct vertex_info *vinfo);
diff --git a/src/mesa/pipe/draw/draw_vertex_cache.c b/src/mesa/pipe/draw/draw_vertex_cache.c
index 29993f14d2..44427999cc 100644
--- a/src/mesa/pipe/draw/draw_vertex_cache.c
+++ b/src/mesa/pipe/draw/draw_vertex_cache.c
@@ -33,21 +33,15 @@
#include "pipe/p_util.h"
#include "draw_private.h"
#include "draw_context.h"
-#include "draw_vertex.h"
void draw_vertex_cache_invalidate( struct draw_context *draw )
{
- unsigned i;
-
assert(draw->pq.queue_nr == 0);
assert(draw->vs.queue_nr == 0);
assert(draw->vcache.referenced == 0);
-
- for (i = 0; i < Elements( draw->vcache.idx ); i++)
- draw->vcache.idx[i] = ~0;
-// fprintf(stderr, "x\n");
+ memset(draw->vcache.idx, ~0, sizeof(draw->vcache.idx));
}
@@ -149,7 +143,7 @@ void draw_vertex_cache_unreference( struct draw_context *draw )
int draw_vertex_cache_check_space( struct draw_context *draw,
- unsigned nr_verts )
+ unsigned nr_verts )
{
if (draw->vcache.overflow + nr_verts < VCACHE_OVERFLOW) {
/* The vs queue is sized so that this can never happen:
diff --git a/src/mesa/pipe/draw/draw_vertex_fetch.c b/src/mesa/pipe/draw/draw_vertex_fetch.c
index 3ca17f8829..fb64723a19 100644
--- a/src/mesa/pipe/draw/draw_vertex_fetch.c
+++ b/src/mesa/pipe/draw/draw_vertex_fetch.c
@@ -34,7 +34,6 @@
#include "pipe/p_shader_tokens.h"
#include "draw_private.h"
#include "draw_context.h"
-#include "draw_vertex.h"
#define DRAW_DBG 0
@@ -43,53 +42,114 @@
/**
* Fetch a float[4] vertex attribute from memory, doing format/type
* conversion as needed.
- * XXX this might be a temporary thing.
+ *
+ * This is probably needed/dupliocated elsewhere, eg format
+ * conversion, texture sampling etc.
*/
-static void
-fetch_attrib4(const void *ptr, enum pipe_format format, float attrib[4])
+#define FETCH_ATTRIB( NAME, SZ, CVT ) \
+static void \
+fetch_##NAME(const void *ptr, float *attrib) \
+{ \
+ static const float defaults[4] = { 0,0,0,1 }; \
+ int i; \
+ \
+ for (i = 0; i < SZ; i++) { \
+ attrib[i] = CVT; \
+ } \
+ \
+ for (; i < 4; i++) { \
+ attrib[i] = defaults[i]; \
+ } \
+}
+
+#define CVT_32_FLOAT ((float *) ptr)[i]
+#define CVT_32_SSCALED (float) ((int *) ptr)[i]
+#define CVT_8_UNORM (float) ((unsigned char *) ptr)[i] / 255.0f
+
+FETCH_ATTRIB( R32G32B32A32_FLOAT, 4, CVT_32_FLOAT )
+FETCH_ATTRIB( R32G32B32_FLOAT, 3, CVT_32_FLOAT )
+FETCH_ATTRIB( R32G32_FLOAT, 2, CVT_32_FLOAT )
+FETCH_ATTRIB( R32_FLOAT, 1, CVT_32_FLOAT )
+FETCH_ATTRIB( R32G32B32A32_SSCALED, 4, CVT_32_SSCALED )
+FETCH_ATTRIB( R32G32B32_SSCALED, 3, CVT_32_SSCALED )
+FETCH_ATTRIB( R32G32_SSCALED, 2, CVT_32_SSCALED )
+FETCH_ATTRIB( R32_SSCALED, 1, CVT_32_SSCALED )
+FETCH_ATTRIB( A8R8G8B8_UNORM, 4, CVT_8_UNORM )
+FETCH_ATTRIB( R8G8B8A8_UNORM, 4, CVT_8_UNORM )
+
+
+
+static fetch_func get_fetch_func( enum pipe_format format )
{
- /* defaults */
- attrib[1] = 0.0;
- attrib[2] = 0.0;
- attrib[3] = 1.0;
switch (format) {
case PIPE_FORMAT_R32G32B32A32_FLOAT:
- attrib[3] = ((float *) ptr)[3];
- /* fall-through */
+ return fetch_R32G32B32A32_FLOAT;
case PIPE_FORMAT_R32G32B32_FLOAT:
- attrib[2] = ((float *) ptr)[2];
- /* fall-through */
+ return fetch_R32G32B32_FLOAT;
case PIPE_FORMAT_R32G32_FLOAT:
- attrib[1] = ((float *) ptr)[1];
- /* fall-through */
+ return fetch_R32G32_FLOAT;
case PIPE_FORMAT_R32_FLOAT:
- attrib[0] = ((float *) ptr)[0];
- break;
-
+ return fetch_R32_FLOAT;
case PIPE_FORMAT_R32G32B32A32_SSCALED:
- attrib[3] = (float) ((int *) ptr)[3];
- /* fall-through */
+ return fetch_R32G32B32A32_SSCALED;
case PIPE_FORMAT_R32G32B32_SSCALED:
- attrib[2] = (float) ((int *) ptr)[2];
- /* fall-through */
+ return fetch_R32G32B32_SSCALED;
case PIPE_FORMAT_R32G32_SSCALED:
- attrib[1] = (float) ((int *) ptr)[1];
- /* fall-through */
+ return fetch_R32G32_SSCALED;
case PIPE_FORMAT_R32_SSCALED:
- attrib[0] = (float) ((int *) ptr)[0];
- break;
-
+ return fetch_R32_SSCALED;
case PIPE_FORMAT_A8R8G8B8_UNORM:
+ return fetch_A8R8G8B8_UNORM;
case PIPE_FORMAT_R8G8B8A8_UNORM:
- attrib[0] = (float) ((unsigned char *) ptr)[2] / 255.0f;
- attrib[1] = (float) ((unsigned char *) ptr)[1] / 255.0f;
- attrib[2] = (float) ((unsigned char *) ptr)[0] / 255.0f;
- attrib[3] = (float) ((unsigned char *) ptr)[3] / 255.0f;
- break;
-
+ return fetch_R8G8B8A8_UNORM;
+ case 0:
+ return NULL;
default:
+ /* Lots of missing cases! */
assert(0);
+ return NULL;
+ }
+}
+
+
+static void
+transpose_4x4( float *out, const float *in )
+{
+ /* This can be achieved in 12 sse instructions, plus the final
+ * stores I guess. This is probably a bit more than that - maybe
+ * 32 or so?
+ */
+ out[0] = in[0]; out[1] = in[4]; out[2] = in[8]; out[3] = in[12];
+ out[4] = in[1]; out[5] = in[5]; out[6] = in[9]; out[7] = in[13];
+ out[8] = in[2]; out[9] = in[6]; out[10] = in[10]; out[11] = in[14];
+ out[12] = in[3]; out[13] = in[7]; out[14] = in[11]; out[15] = in[15];
+}
+
+
+
+void draw_update_vertex_fetch( struct draw_context *draw )
+{
+ unsigned nr_attrs, i;
+
+ /* this may happend during context init */
+ if (!draw->vertex_shader)
+ return;
+
+ nr_attrs = draw->vertex_shader->state->num_inputs;
+
+ for (i = 0; i < nr_attrs; i++) {
+ unsigned buf = draw->vertex_element[i].vertex_buffer_index;
+ enum pipe_format format = draw->vertex_element[i].src_format;
+
+ draw->vertex_fetch.src_ptr[i] = (const ubyte *) draw->user.vbuffer[buf] +
+ draw->vertex_buffer[buf].buffer_offset +
+ draw->vertex_element[i].src_offset;
+
+ draw->vertex_fetch.pitch[i] = draw->vertex_buffer[buf].pitch;
+ draw->vertex_fetch.fetch[i] = get_fetch_func( format );
}
+
+ draw->vertex_fetch.nr_attrs = nr_attrs;
}
@@ -101,40 +161,48 @@ void draw_vertex_fetch( struct draw_context *draw,
const unsigned *elts,
unsigned count )
{
- unsigned j;
-
- /* loop over vertices */
- for (j = 0; j < count; j++) {
- uint attr;
-
-#if DRAW_DBG
- printf("fetch vertex %u: \n", j);
-#endif
-
- /* loop over vertex attributes (vertex shader inputs) */
- for (attr = 0; attr < draw->vertex_shader->state->num_inputs; attr++) {
-
- unsigned buf = draw->vertex_element[attr].vertex_buffer_index;
- const void *src
- = (const void *) ((const ubyte *) draw->user.vbuffer[buf]
- + draw->vertex_buffer[buf].buffer_offset
- + draw->vertex_element[attr].src_offset
- + elts[j] * draw->vertex_buffer[buf].pitch);
- float p[4];
-
- fetch_attrib4(src, draw->vertex_element[attr].src_format, p);
-
-#if DRAW_DBG
- printf(" %u: %f %f %f %f\n", attr, p[0], p[1], p[2], p[3]);
-#endif
-
- /* Transform to AoS xxxx/yyyy/zzzz/wwww representation:
- */
- machine->Inputs[attr].xyzw[0].f[j] = p[0]; /*X*/
- machine->Inputs[attr].xyzw[1].f[j] = p[1]; /*Y*/
- machine->Inputs[attr].xyzw[2].f[j] = p[2]; /*Z*/
- machine->Inputs[attr].xyzw[3].f[j] = p[3]; /*W*/
- }
+ unsigned nr_attrs = draw->vertex_fetch.nr_attrs;
+ unsigned attr;
+
+ assert(count <= 4);
+
+// _mesa_printf("%s %d\n", __FUNCTION__, count);
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (attr = 0; attr < nr_attrs; attr++) {
+
+ const unsigned pitch = draw->vertex_fetch.pitch[attr];
+ const ubyte *src = draw->vertex_fetch.src_ptr[attr];
+ const fetch_func fetch = draw->vertex_fetch.fetch[attr];
+ unsigned i;
+ float p[4][4];
+
+
+ /* Fetch four attributes for four vertices.
+ *
+ * Could fetch directly into AOS format, but this is meant to be
+ * a prototype for an sse implementation, which would have
+ * difficulties doing that.
+ */
+ for (i = 0; i < count; i++)
+ fetch( src + elts[i] * pitch, p[i] );
+
+ /* Be nice and zero out any missing vertices:
+ */
+ for ( ; i < 4; i++)
+ p[i][0] = p[i][1] = p[i][2] = p[i][3] = 0;
+
+ /* Transpose/swizzle into sse-friendly format. Currently
+ * assuming that all vertex shader inputs are float[4], but this
+ * isn't true -- if the vertex shader only wants tex0.xy, we
+ * could optimize for that.
+ *
+ * To do so fully without codegen would probably require an
+ * excessive number of fetch functions, but we could at least
+ * minimize the transpose step:
+ */
+ transpose_4x4( (float *)&machine->Inputs[attr].xyzw[0].f[0], (float *)p );
}
}
diff --git a/src/mesa/pipe/draw/draw_vertex_shader.c b/src/mesa/pipe/draw/draw_vertex_shader.c
index c2e038453e..3041974b9a 100644
--- a/src/mesa/pipe/draw/draw_vertex_shader.c
+++ b/src/mesa/pipe/draw/draw_vertex_shader.c
@@ -38,7 +38,6 @@
#endif
#include "draw_private.h"
#include "draw_context.h"
-#include "draw_vertex.h"
#include "x86/rtasm/x86sse.h"
#include "pipe/llvm/gallivm.h"
@@ -176,7 +175,7 @@ run_vertex_program(struct draw_context *draw,
/* Remaining attributes are packed into sequential post-transform
* vertex attrib slots.
*/
- for (slot = 1; slot < draw->vertex_info.num_attribs; slot++) {
+ 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];
@@ -202,6 +201,10 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)
{
unsigned i, j;
+ /* XXX: do this on statechange:
+ */
+ draw_update_vertex_fetch( draw );
+
// fprintf(stderr, " q(%d) ", draw->vs.queue_nr );
#ifdef MESA_LLVM
if (draw->vertex_shader->llvm_prog) {
@@ -272,8 +275,10 @@ void
draw_bind_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs)
{
- draw_flush(draw);
+ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
+
draw->vertex_shader = dvs;
+ draw->num_vs_outputs = dvs->state->num_outputs;
/* specify the fragment program to interpret/execute */
tgsi_exec_machine_init(&draw->machine,
diff --git a/src/mesa/pipe/draw/draw_vertex_shader_llvm.c b/src/mesa/pipe/draw/draw_vertex_shader_llvm.c
index acd61163fa..4228c4f388 100644
--- a/src/mesa/pipe/draw/draw_vertex_shader_llvm.c
+++ b/src/mesa/pipe/draw/draw_vertex_shader_llvm.c
@@ -33,7 +33,6 @@
#include "pipe/p_util.h"
#include "draw_private.h"
#include "draw_context.h"
-#include "draw_vertex.h"
#ifdef MESA_LLVM
@@ -132,7 +131,7 @@ void draw_vertex_shader_queue_flush_llvm(struct draw_context *draw)
gallivm_prog_exec(prog, inputs, outputs, consts,
draw->vs.queue_nr,
draw->vertex_shader->state->num_inputs,
- draw->vertex_info.num_attribs - 2);
+ draw->vertex_shader->state->num_outputs);
/* store machine results */
@@ -173,7 +172,7 @@ void draw_vertex_shader_queue_flush_llvm(struct draw_context *draw)
/* Remaining attributes are packed into sequential post-transform
* vertex attrib slots.
*/
- for (slot = 1; slot < draw->vertex_info.num_attribs; slot++) {
+ for (slot = 1; slot < draw->num_vs_outputs; slot++) {
vOut->data[slot][0] = dests[slot][0];
vOut->data[slot][1] = dests[slot][1];
vOut->data[slot][2] = dests[slot][2];
diff --git a/src/mesa/pipe/draw/draw_wide_prims.c b/src/mesa/pipe/draw/draw_wide_prims.c
index a56c9b8893..9759e7e2e8 100644
--- a/src/mesa/pipe/draw/draw_wide_prims.c
+++ b/src/mesa/pipe/draw/draw_wide_prims.c
@@ -217,7 +217,7 @@ static void wide_point( struct draw_stage *stage,
/* point size is either per-vertex or fixed size */
if (wide->psize_slot >= 0) {
- half_size = header->v[0]->data[wide->psize_slot][0];
+ half_size = 0.5f * header->v[0]->data[wide->psize_slot][0];
}
else {
half_size = wide->half_point_size;
@@ -262,26 +262,19 @@ static void wide_point( struct draw_stage *stage,
}
-static void wide_begin( struct draw_stage *stage )
+static void wide_first_point( struct draw_stage *stage,
+ struct prim_header *header )
{
struct wide_stage *wide = wide_stage(stage);
struct draw_context *draw = stage->draw;
wide->half_point_size = 0.5f * draw->rasterizer->point_size;
- wide->half_line_width = 0.5f * draw->rasterizer->line_width;
-
- if (draw->rasterizer->line_width != 1.0) {
- wide->stage.line = wide_line;
- }
- else {
- wide->stage.line = passthrough_line;
- }
if (draw->rasterizer->point_size != 1.0) {
- wide->stage.point = wide_point;
+ stage->point = wide_point;
}
else {
- wide->stage.point = passthrough_point;
+ stage->point = passthrough_point;
}
if (draw->rasterizer->point_sprite) {
@@ -299,6 +292,7 @@ static void wide_begin( struct draw_stage *stage )
}
wide->psize_slot = -1;
+
if (draw->rasterizer->point_size_per_vertex) {
/* find PSIZ vertex output */
const struct draw_vertex_shader *vs = draw->vertex_shader;
@@ -311,13 +305,35 @@ static void wide_begin( struct draw_stage *stage )
}
}
- stage->next->begin( stage->next );
+ stage->point( stage, header );
+}
+
+
+
+static void wide_first_line( struct draw_stage *stage,
+ struct prim_header *header )
+{
+ struct wide_stage *wide = wide_stage(stage);
+ struct draw_context *draw = stage->draw;
+
+ wide->half_line_width = 0.5f * draw->rasterizer->line_width;
+
+ if (draw->rasterizer->line_width != 1.0) {
+ wide->stage.line = wide_line;
+ }
+ else {
+ wide->stage.line = passthrough_line;
+ }
+
+ stage->line( stage, header );
}
-static void wide_end( struct draw_stage *stage )
+static void wide_flush( struct draw_stage *stage, unsigned flags )
{
- stage->next->end( stage->next );
+ stage->line = wide_first_line;
+ stage->point = wide_first_point;
+ stage->next->flush( stage->next, flags );
}
@@ -342,11 +358,10 @@ struct draw_stage *draw_wide_stage( struct draw_context *draw )
wide->stage.draw = draw;
wide->stage.next = NULL;
- wide->stage.begin = wide_begin;
- wide->stage.point = wide_point;
- wide->stage.line = wide_line;
+ wide->stage.point = wide_first_point;
+ wide->stage.line = wide_first_line;
wide->stage.tri = passthrough_tri;
- wide->stage.end = wide_end;
+ wide->stage.flush = wide_flush;
wide->stage.reset_stipple_counter = draw_reset_stipple_counter;
wide->stage.destroy = wide_destroy;