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_context.c27
-rw-r--r--src/mesa/pipe/draw/draw_context.h4
-rw-r--r--src/mesa/pipe/draw/draw_linestipple.c272
-rw-r--r--src/mesa/pipe/draw/draw_private.h5
-rw-r--r--src/mesa/pipe/draw/draw_stipple.c250
-rw-r--r--src/mesa/pipe/draw/draw_validate.c9
-rw-r--r--src/mesa/pipe/draw/draw_vbuf.c104
-rw-r--r--src/mesa/pipe/draw/draw_vertex.c2
-rw-r--r--src/mesa/pipe/draw/draw_vertex.h12
9 files changed, 365 insertions, 320 deletions
diff --git a/src/mesa/pipe/draw/draw_context.c b/src/mesa/pipe/draw/draw_context.c
index fd43d690f6..5b9ea55630 100644
--- a/src/mesa/pipe/draw/draw_context.c
+++ b/src/mesa/pipe/draw/draw_context.c
@@ -49,6 +49,7 @@ struct draw_context *draw_create( void )
/* create pipeline stages */
draw->pipeline.wide = draw_wide_stage( draw );
+ draw->pipeline.stipple = draw_stipple_stage( draw );
draw->pipeline.unfilled = draw_unfilled_stage( draw );
draw->pipeline.twoside = draw_twoside_stage( draw );
draw->pipeline.offset = draw_offset_stage( draw );
@@ -70,7 +71,7 @@ struct draw_context *draw_create( void )
*/
{
uint i;
- char *tmp = MALLOC( Elements(draw->vcache.vertex) * MAX_VERTEX_SIZE );
+ char *tmp = (char*) MALLOC( Elements(draw->vcache.vertex) * MAX_VERTEX_SIZE );
for (i = 0; i < Elements(draw->vcache.vertex); i++)
draw->vcache.vertex[i] = (struct vertex_header *)(tmp + i * MAX_VERTEX_SIZE);
@@ -81,6 +82,9 @@ struct draw_context *draw_create( void )
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_vertex_cache_invalidate( draw );
@@ -93,6 +97,7 @@ struct draw_context *draw_create( void )
void draw_destroy( struct draw_context *draw )
{
draw->pipeline.wide->destroy( draw->pipeline.wide );
+ 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 );
@@ -215,6 +220,26 @@ draw_set_mapped_constant_buffer(struct draw_context *draw,
}
+/**
+ * Tells the draw module whether to convert wide points (size != 1)
+ * into triangles.
+ */
+void
+draw_convert_wide_points(struct draw_context *draw, boolean enable)
+{
+ draw->convert_wide_points = enable;
+}
+
+
+/**
+ * Tells the draw module whether to convert wide lines (width != 1)
+ * into triangles.
+ */
+void
+draw_convert_wide_lines(struct draw_context *draw, boolean enable)
+{
+ draw->convert_wide_lines = enable;
+}
diff --git a/src/mesa/pipe/draw/draw_context.h b/src/mesa/pipe/draw/draw_context.h
index 91e11e6930..cfde26ceb7 100644
--- a/src/mesa/pipe/draw/draw_context.h
+++ b/src/mesa/pipe/draw/draw_context.h
@@ -89,6 +89,10 @@ void draw_set_rasterizer_state( struct draw_context *draw,
void draw_set_rasterize_stage( struct draw_context *draw,
struct draw_stage *stage );
+void draw_convert_wide_points(struct draw_context *draw, boolean enable);
+
+void draw_convert_wide_lines(struct draw_context *draw, boolean enable);
+
struct draw_vertex_shader *
draw_create_vertex_shader(struct draw_context *draw,
diff --git a/src/mesa/pipe/draw/draw_linestipple.c b/src/mesa/pipe/draw/draw_linestipple.c
deleted file mode 100644
index d7fe1071f0..0000000000
--- a/src/mesa/pipe/draw/draw_linestipple.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/**************************************************************************
- *
- * 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 <keith@tungstengraphics.com>
- */
-
-/* Implement line stipple by cutting lines up into smaller lines.
- * There are hundreds of ways to implement line stipple, this is one
- * choice that should work in all situations, requires no state
- * manipulations, but with a penalty in terms of large amounts of
- * generated geometry.
- */
-
-#include "imports.h"
-#include "macros.h"
-
-#define CLIP_PRIVATE
-#include "clip/clip_context.h"
-
-#define CLIP_PIPE_PRIVATE
-#include "clip/clip_pipe.h"
-
-
-
-struct stipple_stage {
- struct clip_pipe_stage stage;
-
- GLuint hw_data_offset;
-
- GLfloat counter;
- GLuint pattern;
- GLuint factor;
-};
-
-
-
-
-static INLINE struct stipple_stage *stipple_stage( struct clip_pipe_stage *stage )
-{
- return (struct stipple_stage *)stage;
-}
-
-
-
-
-static void interp_attr( const struct vf_attr *a,
- GLubyte *vdst,
- GLfloat t,
- const GLubyte *vin,
- const GLubyte *vout )
-{
- GLuint offset = a->vertoffset;
- GLfloat fin[4], fout[4], fdst[4];
-
- a->extract( a, fin, vin + offset );
- a->extract( a, fout, vout + offset );
-
- fdst[0] = LINTERP( t, fout[0], fin[0] );
- fdst[1] = LINTERP( t, fout[1], fin[1] );
- fdst[2] = LINTERP( t, fout[2], fin[2] );
- fdst[3] = LINTERP( t, fout[3], fin[3] );
-
- a->insert[4-1]( a, vdst + offset, fdst );
-}
-
-
-
-
-/* Weird screen-space interpolation?? Otherwise do something special
- * with pos.w or fix vertices to always have clip coords available.
- */
-static void screen_interp( struct vertex_fetch *vf,
- struct vertex_header *dst,
- GLfloat t,
- const struct vertex_header *out,
- const struct vertex_header *in )
-{
- GLubyte *vdst = (GLubyte *)dst;
- const GLubyte *vin = (const GLubyte *)in;
- const GLubyte *vout = (const GLubyte *)out;
-
- const struct vf_attr *a = vf->attr;
- const GLuint attr_count = vf->attr_count;
- GLuint j;
-
- /* Vertex header.
- */
- {
- assert(a[0].attrib == VF_ATTRIB_VERTEX_HEADER);
- dst->clipmask = 0;
- dst->edgeflag = 0;
- dst->pad = 0;
- dst->index = 0xffff;
- }
-
-
- /* Other attributes
- */
- for (j = 1; j < attr_count; j++) {
- interp_attr(&a[j], vdst, t, vin, vout);
- }
-}
-
-
-
-/* Clip a line against the viewport and user clip planes.
- */
-static void draw_line_segment( struct clip_pipe_stage *stage,
- struct prim_header *header,
- GLfloat t0,
- GLfloat t1 )
-{
- struct vertex_fetch *vf = stage->pipe->draw->vb.vf;
- struct vertex_header *v0 = header->v[0];
- struct vertex_header *v1 = header->v[1];
-
- struct prim_header newprim = *header;
- header = &newprim;
-
- _mesa_printf("%s %f %f\n", __FUNCTION__, t0, t1);
-
- if (t0 > 0.0) {
- screen_interp( vf, stage->tmp[0], t0, v0, v1 );
- header->v[0] = stage->tmp[0];
- }
-
- if (t1 < 1.0) {
- screen_interp( vf, stage->tmp[1], t1, v0, v1 );
- header->v[1] = stage->tmp[1];
- }
-
- stage->next->line( stage->next, header );
-}
-
-
-
-/* XXX: don't really want to iterate like this.
- */
-static INLINE unsigned
-stipple_test(int counter, ushort pattern, int factor)
-{
- int b = (counter / factor) & 0xf;
- return (1 << b) & pattern;
-}
-
-
-
-/* XXX: Need to have precalculated flatshading already.
- */
-static void stipple_line( struct clip_pipe_stage *stage,
- struct prim_header *header )
-{
- struct stipple_stage *stipple = stipple_stage(stage);
- GLuint hw_data_offset = stipple->hw_data_offset;
- const GLfloat *pos0 = (GLfloat *)&(header->v[0]->data[hw_data_offset]);
- const GLfloat *pos1 = (GLfloat *)&(header->v[1]->data[hw_data_offset]);
- GLfloat start = 0;
- int state = 0;
-
- GLfloat x0 = (GLfloat)pos0[0];
- GLfloat x1 = (GLfloat)pos1[0];
- GLfloat y0 = (GLfloat)pos0[1];
- GLfloat y1 = (GLfloat)pos1[1];
-
- GLfloat dx = x0 > x1 ? x0 - x1 : x1 - x0;
- GLfloat dy = y0 > y1 ? y0 - y1 : y1 - y0;
-
- GLfloat length = MAX2(dx, dy);
- GLint i;
-
- if (header->reset_line_stipple)
- stipple->counter = 0;
-
- /* XXX: iterating like this is lame
- */
- for (i = 0; i < length; i++) {
- int result = !!stipple_test( stipple->counter+i, stipple->pattern, stipple->factor );
-// _mesa_printf("%d %f %d\n", i, length, result);
- if (result != state) {
- if (state) {
- if (start != i)
- draw_line_segment( stage, header, start / length, i / length );
- }
- else {
- start = i;
- }
- state = result;
- }
- }
-
- if (state && start < length)
- draw_line_segment( stage, header, start / length, 1.0 );
-
- stipple->counter += length;
-}
-
-
-
-static void stipple_begin( struct clip_pipe_stage *stage )
-{
- struct stipple_stage *stipple = stipple_stage(stage);
- struct clip_context *draw = stage->pipe->draw;
-
- if (stage->pipe->draw->vb_state.clipped_prims)
- stipple->hw_data_offset = 16;
- else
- stipple->hw_data_offset = 0;
-
- stipple->stage.tri = clip_passthrough_tri;
- stipple->stage.point = clip_passthrough_point;
-
- stipple->stage.line = stipple_line;
- stipple->factor = draw->state.line_stipple_factor + 1;
- stipple->pattern = draw->state.line_stipple_pattern;
-
- stage->next->begin( stage->next );
-}
-
-
-static void stipple_end( struct clip_pipe_stage *stage )
-{
- stage->next->end( stage->next );
-}
-
-
-static void stipple_destroy( struct clip_pipe_stage *stage )
-{
- FREE( stage );
-}
-
-
-struct clip_pipe_stage *clip_pipe_stipple( struct clip_pipeline *pipe )
-{
- struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage);
-
- clip_pipe_alloc_tmps( &stipple->stage, 4 );
-
- stipple->stage.pipe = pipe;
- stipple->stage.next = NULL;
- stipple->stage.begin = stipple_begin;
- stipple->stage.point = clip_passthrough_point;
- stipple->stage.line = stipple_line;
- stipple->stage.tri = clip_passthrough_tri;
- stipple->stage.end = stipple_end;
- stipple->stage.destroy = stipple_destroy;
-
- return &stipple->stage;
-}
diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h
index d8832449ea..a264fabfb4 100644
--- a/src/mesa/pipe/draw/draw_private.h
+++ b/src/mesa/pipe/draw/draw_private.h
@@ -158,6 +158,7 @@ struct draw_context
struct draw_stage *twoside;
struct draw_stage *offset;
struct draw_stage *unfilled;
+ struct draw_stage *stipple;
struct draw_stage *wide;
struct draw_stage *rasterize;
} pipeline;
@@ -194,6 +195,9 @@ struct draw_context
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;
@@ -248,6 +252,7 @@ extern struct draw_stage *draw_offset_stage( struct draw_context *context );
extern struct draw_stage *draw_clip_stage( struct draw_context *context );
extern struct draw_stage *draw_flatshade_stage( struct draw_context *context );
extern struct draw_stage *draw_cull_stage( struct draw_context *context );
+extern struct draw_stage *draw_stipple_stage( struct draw_context *context );
extern struct draw_stage *draw_wide_stage( struct draw_context *context );
extern struct draw_stage *draw_validate_stage( struct draw_context *context );
diff --git a/src/mesa/pipe/draw/draw_stipple.c b/src/mesa/pipe/draw/draw_stipple.c
new file mode 100644
index 0000000000..3e0d5689e1
--- /dev/null
+++ b/src/mesa/pipe/draw/draw_stipple.c
@@ -0,0 +1,250 @@
+/**************************************************************************
+ *
+ * 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 <keith@tungstengraphics.com>
+ */
+
+/* Implement line stipple by cutting lines up into smaller lines.
+ * There are hundreds of ways to implement line stipple, this is one
+ * choice that should work in all situations, requires no state
+ * manipulations, but with a penalty in terms of large amounts of
+ * generated geometry.
+ */
+
+
+#include "pipe/p_util.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+#include "draw_private.h"
+
+
+/** Subclass of draw_stage */
+struct stipple_stage {
+ struct draw_stage stage;
+ float counter;
+ uint pattern;
+ uint factor;
+};
+
+
+static INLINE struct stipple_stage *
+stipple_stage(struct draw_stage *stage)
+{
+ return (struct stipple_stage *) stage;
+}
+
+
+/**
+ * Compute interpolated vertex attributes for 'dst' at position 't'
+ * between 'v0' and 'v1'.
+ */
+static void
+screen_interp( struct draw_context *draw,
+ struct vertex_header *dst,
+ float t,
+ const struct vertex_header *v0,
+ 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();
+ }
+ }
+}
+
+
+static void
+emit_segment(struct draw_stage *stage, struct prim_header *header,
+ float t0, float t1)
+{
+ struct vertex_header *v0new = dup_vert(stage, header->v[0], 0);
+ struct vertex_header *v1new = dup_vert(stage, header->v[1], 1);
+ struct prim_header newprim = *header;
+
+ if (t0 > 0.0) {
+ screen_interp( stage->draw, v0new, t0, header->v[0], header->v[1] );
+ newprim.v[0] = v0new;
+ }
+
+ if (t1 < 1.0) {
+ screen_interp( stage->draw, v1new, t1, header->v[0], header->v[1] );
+ newprim.v[1] = v1new;
+ }
+
+ stage->next->line( stage->next, &newprim );
+}
+
+
+static INLINE unsigned
+stipple_test(int counter, ushort pattern, int factor)
+{
+ int b = (counter / factor) & 0xf;
+ return (1 << b) & pattern;
+}
+
+
+static void
+stipple_line(struct draw_stage *stage, struct prim_header *header)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ struct vertex_header *v0 = header->v[0];
+ struct vertex_header *v1 = header->v[1];
+ const float *pos0 = v0->data[0];
+ const float *pos1 = v1->data[0];
+ float start = 0;
+ int state = 0;
+
+ float x0 = pos0[0];
+ float x1 = pos1[0];
+ float y0 = pos0[1];
+ float y1 = pos1[1];
+
+ float dx = x0 > x1 ? x0 - x1 : x1 - x0;
+ float dy = y0 > y1 ? y0 - y1 : y1 - y0;
+
+ float length = MAX2(dx, dy);
+ int i;
+
+ /* XXX ToDo: intead of iterating pixel-by-pixel, use a look-up table.
+ */
+ for (i = 0; i < length; i++) {
+ int result = stipple_test( (int) stipple->counter+i,
+ (ushort) stipple->pattern, stipple->factor );
+ if (result != state) {
+ /* changing from "off" to "on" or vice versa */
+ if (state) {
+ if (start != i) {
+ /* finishing an "on" segment */
+ emit_segment( stage, header, start / length, i / length );
+ }
+ }
+ else {
+ /* starting an "on" segment */
+ start = (float) i;
+ }
+ state = result;
+ }
+ }
+
+ if (state && start < length)
+ emit_segment( stage, header, start / length, 1.0 );
+
+ stipple->counter += length;
+}
+
+
+static void
+reset_stipple_counter(struct draw_stage *stage)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ stipple->counter = 0;
+ stage->next->reset_stipple_counter( stage->next );
+}
+
+
+static void
+stipple_begin(struct draw_stage *stage)
+{
+ struct stipple_stage *stipple = stipple_stage(stage);
+ struct draw_context *draw = stage->draw;
+
+ stipple->pattern = draw->rasterizer->line_stipple_pattern;
+ stipple->factor = draw->rasterizer->line_stipple_factor + 1;
+
+ stage->next->begin( stage->next );
+}
+
+
+static void
+stipple_end(struct draw_stage *stage)
+{
+ stage->next->end( stage->next );
+}
+
+
+static void
+passthrough_point(struct draw_stage *stage, struct prim_header *header)
+{
+ stage->next->point( stage->next, header );
+}
+
+
+static void
+passthrough_tri(struct draw_stage *stage, struct prim_header *header)
+{
+ stage->next->tri(stage->next, header);
+}
+
+
+static void
+stipple_destroy( struct draw_stage *stage )
+{
+ FREE( stage );
+}
+
+
+/**
+ * Create line stippler stage
+ */
+struct draw_stage *draw_stipple_stage( struct draw_context *draw )
+{
+ struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage);
+
+ draw_alloc_tmps( &stipple->stage, 2 );
+
+ 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.tri = passthrough_tri;
+ stipple->stage.reset_stipple_counter = reset_stipple_counter;
+ stipple->stage.end = stipple_end;
+ stipple->stage.destroy = stipple_destroy;
+
+ return &stipple->stage;
+}
diff --git a/src/mesa/pipe/draw/draw_validate.c b/src/mesa/pipe/draw/draw_validate.c
index 58cf340281..3b1f5179a9 100644
--- a/src/mesa/pipe/draw/draw_validate.c
+++ b/src/mesa/pipe/draw/draw_validate.c
@@ -51,13 +51,18 @@ static void validate_begin( struct draw_stage *stage )
* shorter pipelines for lines & points.
*/
- if (draw->rasterizer->line_width != 1.0 ||
- draw->rasterizer->point_size != 1.0 ||
+ if ((draw->rasterizer->line_width != 1.0 && draw->convert_wide_lines) ||
+ (draw->rasterizer->point_size != 1.0 && draw->convert_wide_points) ||
draw->rasterizer->point_sprite) {
draw->pipeline.wide->next = next;
next = draw->pipeline.wide;
}
+ if (draw->rasterizer->line_stipple_enable) {
+ draw->pipeline.stipple->next = next;
+ next = draw->pipeline.stipple;
+ }
+
if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) {
draw->pipeline.unfilled->next = next;
diff --git a/src/mesa/pipe/draw/draw_vbuf.c b/src/mesa/pipe/draw/draw_vbuf.c
index 6cda122c3a..a4b6247e18 100644
--- a/src/mesa/pipe/draw/draw_vbuf.c
+++ b/src/mesa/pipe/draw/draw_vbuf.c
@@ -110,10 +110,11 @@ check_space( struct vbuf_stage *vbuf, unsigned nr )
/**
- * Extract the needed fields from vertex_header and emit i915 dwords.
+ * Extract the needed fields from post-transformed vertex and emit
+ * a hardware(driver) vertex.
* Recall that the vertices are constructed by the 'draw' module and
* have a couple of slots at the beginning (1-dword header, 4-dword
- * clip pos) that we ignore here.
+ * clip pos) that we ignore here. We only use the vertex->data[] fields.
*/
static INLINE void
emit_vertex( struct vbuf_stage *vbuf,
@@ -139,37 +140,42 @@ emit_vertex( struct vbuf_stage *vbuf,
vertex->vertex_id = vbuf->nr_vertices++;
for (i = 0; i < vinfo->num_attribs; i++) {
+ uint j = vinfo->src_index[i];
switch (vinfo->format[i]) {
case FORMAT_OMIT:
/* no-op */
break;
case FORMAT_1F:
- *vbuf->vertex_ptr++ = fui(vertex->data[i][0]);
+ *vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
+ count++;
+ break;
+ case FORMAT_1F_PSIZE:
+ *vbuf->vertex_ptr++ = fui(vbuf->stage.draw->rasterizer->point_size);
count++;
break;
case FORMAT_2F:
- *vbuf->vertex_ptr++ = fui(vertex->data[i][0]);
- *vbuf->vertex_ptr++ = fui(vertex->data[i][1]);
+ *vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
+ *vbuf->vertex_ptr++ = fui(vertex->data[j][1]);
count += 2;
break;
case FORMAT_3F:
- *vbuf->vertex_ptr++ = fui(vertex->data[i][0]);
- *vbuf->vertex_ptr++ = fui(vertex->data[i][1]);
- *vbuf->vertex_ptr++ = fui(vertex->data[i][2]);
+ *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:
- *vbuf->vertex_ptr++ = fui(vertex->data[i][0]);
- *vbuf->vertex_ptr++ = fui(vertex->data[i][1]);
- *vbuf->vertex_ptr++ = fui(vertex->data[i][2]);
- *vbuf->vertex_ptr++ = fui(vertex->data[i][3]);
+ *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:
- *vbuf->vertex_ptr++ = pack_ub4(float_to_ubyte( vertex->data[i][2] ),
- float_to_ubyte( vertex->data[i][1] ),
- float_to_ubyte( vertex->data[i][0] ),
- float_to_ubyte( vertex->data[i][3] ));
+ *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] ),
+ float_to_ubyte( vertex->data[j][3] ));
count += 1;
break;
default:
@@ -228,18 +234,43 @@ vbuf_point( struct draw_stage *stage,
}
+/**
+ * Set the prim type for subsequent vertices.
+ * This may result in a new vertex size. The existing vbuffer (if any)
+ * will be flushed if needed and a new one allocated.
+ */
+static void
+vbuf_set_prim( struct draw_stage *stage, uint newprim )
+{
+ struct vbuf_stage *vbuf = vbuf_stage(stage);
+ const struct vertex_info *vinfo;
+ unsigned vertex_size;
+
+ assert(newprim == PIPE_PRIM_POINTS ||
+ newprim == PIPE_PRIM_LINES ||
+ newprim == PIPE_PRIM_TRIANGLES);
+
+ vbuf->prim = newprim;
+ vbuf->render->set_primitive(vbuf->render, newprim);
+
+ vinfo = vbuf->render->get_vertex_info(vbuf->render);
+ vertex_size = vinfo->size * sizeof(float);
+
+ if (vertex_size != vbuf->vertex_size)
+ vbuf_flush_vertices(stage);
+
+ if (!vbuf->vertices)
+ vbuf_alloc_vertices(stage, vertex_size);
+}
+
+
static void
vbuf_first_tri( struct draw_stage *stage,
struct prim_header *prim )
{
- struct vbuf_stage *vbuf = vbuf_stage( stage );
-
vbuf_flush_indices( stage );
-
stage->tri = vbuf_tri;
- vbuf->prim = PIPE_PRIM_TRIANGLES;
- vbuf->render->set_primitive(vbuf->render, PIPE_PRIM_TRIANGLES);
-
+ vbuf_set_prim(stage, PIPE_PRIM_TRIANGLES);
stage->tri( stage, prim );
}
@@ -248,13 +279,9 @@ static void
vbuf_first_line( struct draw_stage *stage,
struct prim_header *prim )
{
- struct vbuf_stage *vbuf = vbuf_stage( stage );
-
vbuf_flush_indices( stage );
stage->line = vbuf_line;
- vbuf->prim = PIPE_PRIM_LINES;
- vbuf->render->set_primitive(vbuf->render, PIPE_PRIM_LINES);
-
+ vbuf_set_prim(stage, PIPE_PRIM_LINES);
stage->line( stage, prim );
}
@@ -263,14 +290,9 @@ static void
vbuf_first_point( struct draw_stage *stage,
struct prim_header *prim )
{
- struct vbuf_stage *vbuf = vbuf_stage( stage );
-
vbuf_flush_indices( stage );
-
stage->point = vbuf_point;
- vbuf->prim = PIPE_PRIM_POINTS;
- vbuf->render->set_primitive(vbuf->render, PIPE_PRIM_POINTS);
-
+ vbuf_set_prim(stage, PIPE_PRIM_POINTS);
stage->point( stage, prim );
}
@@ -352,7 +374,7 @@ vbuf_alloc_vertices( struct draw_stage *stage,
/* Allocate a new vertex buffer */
vbuf->vertex_size = new_vertex_size;
vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
- vbuf->vertices = vbuf->render->allocate_vertices(vbuf->render,
+ vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render,
(ushort) vbuf->vertex_size,
(ushort) vbuf->max_vertices);
vbuf->vertex_ptr = vbuf->vertices;
@@ -362,12 +384,7 @@ vbuf_alloc_vertices( struct draw_stage *stage,
static void
vbuf_begin( struct draw_stage *stage )
{
- struct vbuf_stage *vbuf = vbuf_stage(stage);
- const struct vertex_info *vinfo = vbuf->render->get_vertex_info(vbuf->render);
- unsigned vertex_size = vinfo->size * sizeof(float);
-
- /* XXX: Overkill */
- vbuf_alloc_vertices(&vbuf->stage, vertex_size);
+ /* no-op, vbuffer allocated by first point/line/tri */
}
@@ -387,6 +404,7 @@ vbuf_end( struct draw_stage *stage )
static void
vbuf_reset_stipple_counter( struct draw_stage *stage )
{
+ (void) stage;
}
@@ -420,11 +438,13 @@ struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
assert(render->max_indices < UNDEFINED_VERTEX_ID);
vbuf->max_indices = render->max_indices;
- vbuf->indices
- = align_malloc( vbuf->max_indices * sizeof(vbuf->indices[0]), 16 );
+ vbuf->indices = (ushort *)
+ align_malloc( vbuf->max_indices * sizeof(vbuf->indices[0]), 16 );
vbuf->vertices = NULL;
vbuf->vertex_ptr = vbuf->vertices;
+
+ vbuf->prim = ~0;
return &vbuf->stage;
}
diff --git a/src/mesa/pipe/draw/draw_vertex.c b/src/mesa/pipe/draw/draw_vertex.c
index a1926d951a..6191fcedbf 100644
--- a/src/mesa/pipe/draw/draw_vertex.c
+++ b/src/mesa/pipe/draw/draw_vertex.c
@@ -65,6 +65,8 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
break;
case FORMAT_4UB:
/* fall-through */
+ case FORMAT_1F_PSIZE:
+ /* fall-through */
case FORMAT_1F:
vinfo->size += 1;
break;
diff --git a/src/mesa/pipe/draw/draw_vertex.h b/src/mesa/pipe/draw/draw_vertex.h
index 8bb328affa..e4f85bc49f 100644
--- a/src/mesa/pipe/draw/draw_vertex.h
+++ b/src/mesa/pipe/draw/draw_vertex.h
@@ -41,12 +41,13 @@ struct draw_context;
* Vertex attribute format
*/
enum attrib_format {
- FORMAT_OMIT,
+ FORMAT_OMIT, /**< don't emit the attribute */
FORMAT_1F,
+ FORMAT_1F_PSIZE, /**< insert constant point size */
FORMAT_2F,
FORMAT_3F,
FORMAT_4F,
- FORMAT_4UB
+ FORMAT_4UB /**< XXX may need variations for RGBA vs BGRA, etc */
};
@@ -70,6 +71,7 @@ struct vertex_info
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];
uint size; /**< total vertex size in dwords */
};
@@ -77,16 +79,20 @@ struct vertex_info
/**
* Add another attribute to the given vertex_info object.
+ * \param src_index indicates which post-transformed vertex attrib slot
+ * corresponds to this attribute.
* \return slot in which the attribute was added
*/
static INLINE uint
draw_emit_vertex_attr(struct vertex_info *vinfo,
- enum attrib_format format, enum interp_mode interp)
+ enum attrib_format format, enum interp_mode interp,
+ uint src_index)
{
const uint n = vinfo->num_attribs;
assert(n < PIPE_MAX_SHADER_OUTPUTS);
vinfo->format[n] = format;
vinfo->interp_mode[n] = interp;
+ vinfo->src_index[n] = src_index;
vinfo->num_attribs++;
return n;
}