diff options
Diffstat (limited to 'src/mesa/pipe/draw')
-rw-r--r-- | src/mesa/pipe/draw/draw_context.c | 27 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_context.h | 4 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_linestipple.c | 272 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_private.h | 5 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_stipple.c | 250 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_validate.c | 9 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_vbuf.c | 104 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_vertex.c | 2 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_vertex.h | 12 |
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; } |