diff options
author | Brian <[email protected]> | 2007-07-09 16:04:08 -0600 |
---|---|---|
committer | Brian <[email protected]> | 2007-07-09 16:04:08 -0600 |
commit | 10f4b37bd70c12c8caaa85ff5b94aec532788abd (patch) | |
tree | 61ff3cf40104ed0f96584b9c564f20b30243edbf /src/mesa/pipe/draw | |
parent | 9b32c33e9d87e4571e85efdbb14c6a98a090cae6 (diff) |
Rename/move some files to modularize the primitive/draw code.
Diffstat (limited to 'src/mesa/pipe/draw')
-rw-r--r-- | src/mesa/pipe/draw/draw_clip.c | 429 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_context.h | 56 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_cull.c | 120 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_flatshade.c | 151 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_offset.c | 157 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_private.h | 90 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_twoside.c | 152 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_unfilled.c | 165 | ||||
-rw-r--r-- | src/mesa/pipe/draw/draw_vb.c | 697 |
9 files changed, 2017 insertions, 0 deletions
diff --git a/src/mesa/pipe/draw/draw_clip.c b/src/mesa/pipe/draw/draw_clip.c new file mode 100644 index 00000000000..304c43c3f48 --- /dev/null +++ b/src/mesa/pipe/draw/draw_clip.c @@ -0,0 +1,429 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#include "imports.h" +#include "macros.h" + +#include "sp_context.h" +#include "sp_prim.h" + +struct clipper { + struct prim_stage stage; + + GLuint active_user_planes; +}; + +/* This is a bit confusing: + */ +static INLINE struct clipper *clipper_stage( struct prim_stage *stage ) +{ + return (struct clipper *)stage; +} + + +#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT))) + + +/* All attributes are float[4], so this is easy: + */ +static void interp_attr( GLfloat *fdst, + GLfloat t, + const GLfloat *fin, + const GLfloat *fout ) +{ + 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] ); +} + + + + +/* Interpolate between two vertices to produce a third. + */ +static void interp( struct clipper *clip, + struct vertex_header *dst, + GLfloat t, + const struct vertex_header *out, + const struct vertex_header *in ) +{ + const GLuint nr_attrs = clip->stage.softpipe->nr_attrs; + GLuint j; + + /* Vertex header. + */ + { + dst->clipmask = 0; + dst->edgeflag = 0; + dst->pad = 0; + } + + /* Clip coordinates: interpolate normally + */ + { + interp_attr(dst->clip, t, in->clip, out->clip); + } + + /* Do the projective divide and insert window coordinates: + */ + { + const GLfloat *pos = dst->clip; + const GLfloat *scale = clip->stage.softpipe->viewport.scale; + const GLfloat *trans = clip->stage.softpipe->viewport.translate; + GLfloat oow; + + oow = 1.0 / pos[3]; + + dst->data[0][0] = pos[0] * oow * scale[0] + trans[0]; + dst->data[0][1] = pos[1] * oow * scale[1] + trans[1]; + dst->data[0][2] = pos[2] * oow * scale[2] + trans[2]; + dst->data[0][3] = oow; + } + + + /* Other attributes + */ + for (j = 1; j < nr_attrs-1; j++) { + interp_attr(dst->data[j], t, in->data[j], out->data[j]); + } +} + + +#define CLIP_USER_BIT 0x40 +#define CLIP_CULL_BIT 0x80 + + +static INLINE GLfloat dot4( const GLfloat *a, + const GLfloat *b ) +{ + GLfloat result = (a[0]*b[0] + + a[1]*b[1] + + a[2]*b[2] + + a[3]*b[3]); + + return result; +} + + +#if 0 +static INLINE void do_tri( struct prim_stage *next, + struct prim_header *header ) +{ + GLuint i; + for (i = 0; i < 3; i++) { + GLfloat *ndc = header->v[i]->data[0]; + _mesa_printf("ndc %f %f %f\n", ndc[0], ndc[1], ndc[2]); + assert(ndc[0] >= -1 && ndc[0] <= 641); + assert(ndc[1] >= 30 && ndc[1] <= 481); + } + _mesa_printf("\n"); + next->tri(next, header); +} +#endif + + +static void emit_poly( struct prim_stage *stage, + struct vertex_header **inlist, + GLuint n ) +{ + struct prim_header header; + GLuint i; + + for (i = 2; i < n; i++) { + header.v[0] = inlist[0]; + header.v[1] = inlist[i-1]; + header.v[2] = inlist[i]; + + { + GLuint tmp0 = header.v[0]->edgeflag; + GLuint tmp2 = header.v[2]->edgeflag; + + if (i != 2) header.v[0]->edgeflag = 0; + if (i != n-1) header.v[2]->edgeflag = 0; + + stage->next->tri( stage->next, &header ); + + header.v[0]->edgeflag = tmp0; + header.v[2]->edgeflag = tmp2; + } + } +} + + +#if 0 +static void emit_poly( struct prim_stage *stage ) +{ + GLuint i; + + for (i = 2; i < n; i++) { + header->v[0] = inlist[0]; + header->v[1] = inlist[i-1]; + header->v[2] = inlist[i]; + + stage->next->tri( stage->next, header ); + } +} +#endif + + +/* Clip a triangle against the viewport and user clip planes. + */ +static void +do_clip_tri( struct prim_stage *stage, + struct prim_header *header, + GLuint clipmask ) +{ + struct clipper *clipper = clipper_stage( stage ); + struct vertex_header *a[MAX_CLIPPED_VERTICES]; + struct vertex_header *b[MAX_CLIPPED_VERTICES]; + struct vertex_header **inlist = a; + struct vertex_header **outlist = b; + GLuint tmpnr = 0; + GLuint n = 3; + GLuint i; + + inlist[0] = header->v[0]; + inlist[1] = header->v[1]; + inlist[2] = header->v[2]; + + /* XXX: Note stupid hack to deal with tnl's 8-bit clipmask. Remove + * this once we correctly use 16bit masks for userclip planes. + */ + clipmask &= ~CLIP_CULL_BIT; + if (clipmask & CLIP_USER_BIT) { + clipmask &= ~CLIP_USER_BIT; + clipmask |= clipper->active_user_planes; + } + + while (clipmask && n >= 3) { + GLuint plane_idx = ffs(clipmask)-1; + const GLfloat *plane = clipper->stage.softpipe->plane[plane_idx]; + struct vertex_header *vert_prev = inlist[0]; + GLfloat dp_prev = dot4( vert_prev->clip, plane ); + GLuint outcount = 0; + + clipmask &= ~(1<<plane_idx); + + inlist[n] = inlist[0]; /* prevent rotation of vertices */ + + for (i = 1; i <= n; i++) { + struct vertex_header *vert = inlist[i]; + + GLfloat dp = dot4( vert->clip, plane ); + + if (!IS_NEGATIVE(dp_prev)) { + outlist[outcount++] = vert_prev; + } + + if (DIFFERENT_SIGNS(dp, dp_prev)) { + struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++]; + outlist[outcount++] = new_vert; + + if (IS_NEGATIVE(dp)) { + /* Going out of bounds. Avoid division by zero as we + * know dp != dp_prev from DIFFERENT_SIGNS, above. + */ + GLfloat t = dp / (dp - dp_prev); + interp( clipper, new_vert, t, vert, vert_prev ); + + /* Force edgeflag true in this case: + */ + new_vert->edgeflag = 1; + } else { + /* Coming back in. + */ + GLfloat t = dp_prev / (dp_prev - dp); + interp( clipper, new_vert, t, vert_prev, vert ); + + /* Copy starting vert's edgeflag: + */ + new_vert->edgeflag = vert_prev->edgeflag; + } + } + + vert_prev = vert; + dp_prev = dp; + } + + { + struct vertex_header **tmp = inlist; + inlist = outlist; + outlist = tmp; + n = outcount; + } + } + + /* Emit the polygon as triangles to the setup stage: + */ + if (n >= 3) + emit_poly( stage, inlist, n ); +} + + +/* Clip a line against the viewport and user clip planes. + */ +static void +do_clip_line( struct prim_stage *stage, + struct prim_header *header, + GLuint clipmask ) +{ + struct clipper *clipper = clipper_stage( stage ); + struct vertex_header *v0 = header->v[0]; + struct vertex_header *v1 = header->v[1]; + const GLfloat *pos0 = v0->clip; + const GLfloat *pos1 = v1->clip; + GLfloat t0 = 0; + GLfloat t1 = 0; + + /* XXX: Note stupid hack to deal with tnl's 8-bit clipmask. Remove + * this once we correctly use 16bit masks for userclip planes. + */ + clipmask &= ~CLIP_CULL_BIT; + if (clipmask & CLIP_USER_BIT) { + clipmask &= ~CLIP_USER_BIT; + clipmask |= clipper->active_user_planes; + } + + while (clipmask) { + GLuint plane_idx = ffs(clipmask)-1; + const GLfloat *plane = clipper->stage.softpipe->plane[plane_idx]; + + clipmask &= ~(1<<plane_idx); + + const GLfloat dp0 = dot4( pos0, plane ); + const GLfloat dp1 = dot4( pos1, plane ); + + if (dp1 < 0) { + GLfloat t = dp1 / (dp1 - dp0); + if (t > t1) t1 = t; + } + + if (dp0 < 0) { + GLfloat t = dp0 / (dp0 - dp1); + if (t > t0) t0 = t; + } + + if (t0 + t1 >= 1.0) + return; /* discard */ + } + + if (v0->clipmask) { + interp( clipper, stage->tmp[0], t0, v0, v1 ); + header->v[0] = stage->tmp[0]; + } + + if (v1->clipmask) { + interp( clipper, stage->tmp[1], t1, v1, v0 ); + header->v[1] = stage->tmp[1]; + } + + stage->next->line( stage->next, header ); +} + + + +static void clip_begin( struct prim_stage *stage ) +{ + struct clipper *clipper = clipper_stage(stage); + GLuint nr = stage->softpipe->nr_planes; + + /* Hacky bitmask to use when we hit CLIP_USER_BIT: + */ + clipper->active_user_planes = ((1<<nr)-1) & ~((1<<6)-1); + + stage->next->begin( stage->next ); +} + +static void +clip_point( struct prim_stage *stage, + struct prim_header *header ) +{ + if (header->v[0]->clipmask == 0) + stage->next->point( stage->next, header ); +} + + +static void +clip_line( struct prim_stage *stage, + struct prim_header *header ) +{ + GLuint clipmask = (header->v[0]->clipmask | + header->v[1]->clipmask); + + if (clipmask == 0) { + stage->next->line( stage->next, header ); + } + else if ((header->v[0]->clipmask & + header->v[1]->clipmask) == 0) { + do_clip_line(stage, header, clipmask); + } +} + + +static void +clip_tri( struct prim_stage *stage, + struct prim_header *header ) +{ + GLuint clipmask = (header->v[0]->clipmask | + header->v[1]->clipmask | + header->v[2]->clipmask); + + if (clipmask == 0) { + stage->next->tri( stage->next, header ); + } + else if ((header->v[0]->clipmask & + header->v[1]->clipmask & + header->v[2]->clipmask) == 0) { + do_clip_tri(stage, header, clipmask); + } +} + +static void clip_end( struct prim_stage *stage ) +{ + stage->next->end( stage->next ); +} + + +struct prim_stage *prim_clip( struct softpipe_context *softpipe ) +{ + struct clipper *clipper = CALLOC_STRUCT(clipper); + + prim_alloc_tmps( &clipper->stage, MAX_CLIPPED_VERTICES ); + + clipper->stage.softpipe = softpipe; + 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; + + return &clipper->stage; +} diff --git a/src/mesa/pipe/draw/draw_context.h b/src/mesa/pipe/draw/draw_context.h new file mode 100644 index 00000000000..a138f812fa4 --- /dev/null +++ b/src/mesa/pipe/draw/draw_context.h @@ -0,0 +1,56 @@ + +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#ifndef G_DRAW_H +#define G_DRAW_H + +#include "glheader.h" +#include "pipe/p_state.h" + + +struct draw_context; + +struct draw_context *draw_create( struct softpipe_context *softpipe ); + +void draw_destroy( struct draw_context *draw ); + +void draw_set_viewport( struct draw_context *draw, + const GLfloat *scale, + const GLfloat *translate ); + +void draw_set_vertex_attributes( struct draw_context *draw, + const GLuint *attrs, + GLuint nr_attrs ); + +void draw_vb(struct draw_context *draw, + struct vertex_buffer *VB ); + +#endif diff --git a/src/mesa/pipe/draw/draw_cull.c b/src/mesa/pipe/draw/draw_cull.c new file mode 100644 index 00000000000..63099fbee0a --- /dev/null +++ b/src/mesa/pipe/draw/draw_cull.c @@ -0,0 +1,120 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" + +#include "pipe/p_defines.h" +#include "sp_context.h" +#include "sp_prim.h" + + + +struct cull_stage { + struct prim_stage stage; + GLuint mode; +}; + + + +static INLINE struct cull_stage *cull_stage( struct prim_stage *stage ) +{ + return (struct cull_stage *)stage; +} + + +static void cull_begin( struct prim_stage *stage ) +{ + struct cull_stage *cull = cull_stage(stage); + + cull->mode = stage->softpipe->setup.cull_mode; + + stage->next->begin( stage->next ); +} + + +static void cull_tri( struct prim_stage *stage, + struct prim_header *header ) +{ + /* Window coords: */ + GLfloat *v0 = (GLfloat *)&(header->v[0]->data[0]); + GLfloat *v1 = (GLfloat *)&(header->v[1]->data[0]); + GLfloat *v2 = (GLfloat *)&(header->v[2]->data[0]); + + GLfloat ex = v0[0] - v2[0]; + GLfloat ey = v0[1] - v2[1]; + GLfloat fx = v1[0] - v2[0]; + GLfloat fy = v1[1] - v2[1]; + + header->det = ex * fy - ey * fx; + + _mesa_printf("%s %f\n", __FUNCTION__, header->det ); + + if (header->det != 0) { + GLuint mode = (header->det < 0) ? PIPE_WINDING_CW : PIPE_WINDING_CCW; + + if ((mode & cull_stage(stage)->mode) == 0) + stage->next->tri( stage->next, header ); + } +} + + +static void cull_line( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->line( stage->next, header ); +} + + +static void cull_point( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + +static void cull_end( struct prim_stage *stage ) +{ + stage->next->end( stage->next ); +} + +struct prim_stage *prim_cull( struct softpipe_context *softpipe ) +{ + struct cull_stage *cull = CALLOC_STRUCT(cull_stage); + + prim_alloc_tmps( &cull->stage, 0 ); + + cull->stage.softpipe = softpipe; + 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; + + return &cull->stage; +} diff --git a/src/mesa/pipe/draw/draw_flatshade.c b/src/mesa/pipe/draw/draw_flatshade.c new file mode 100644 index 00000000000..3a7d9de4667 --- /dev/null +++ b/src/mesa/pipe/draw/draw_flatshade.c @@ -0,0 +1,151 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" + +#include "vf/vf.h" + +#include "sp_context.h" +#include "sp_prim.h" + + +struct flatshade_stage { + struct prim_stage stage; + + const GLuint *lookup; +}; + + + +static INLINE struct flatshade_stage *flatshade_stage( struct prim_stage *stage ) +{ + return (struct flatshade_stage *)stage; +} + + +static void flatshade_begin( struct prim_stage *stage ) +{ + stage->next->begin( stage->next ); +} + + + +static INLINE void copy_attr( GLuint attr, + struct vertex_header *dst, + const struct vertex_header *src ) +{ + if (attr) { + memcpy( dst->data[attr], + src->data[attr], + sizeof(src->data[0]) ); + } +} + +static void copy_colors( struct prim_stage *stage, + struct vertex_header *dst, + const struct vertex_header *src ) +{ + struct flatshade_stage *flatshade = flatshade_stage(stage); + const GLuint *lookup = flatshade->lookup; + + copy_attr( lookup[VF_ATTRIB_COLOR0], dst, src ); + copy_attr( lookup[VF_ATTRIB_COLOR1], dst, src ); + copy_attr( lookup[VF_ATTRIB_BFC0], dst, src ); + copy_attr( lookup[VF_ATTRIB_BFC1], dst, src ); +} + + + +/* Flatshade tri. Required for clipping and when unfilled tris are + * active, otherwise handled by hardware. + */ +static void flatshade_tri( struct prim_stage *stage, + struct prim_header *header ) +{ + struct prim_header tmp; + + tmp.det = header->det; + tmp.v[0] = dup_vert(stage, header->v[0], 0); + 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]); + + stage->next->tri( stage->next, &tmp ); +} + + +/* Flatshade line. Required for clipping. + */ +static void flatshade_line( struct prim_stage *stage, + struct prim_header *header ) +{ + struct prim_header tmp; + + tmp.v[0] = dup_vert(stage, header->v[0], 0); + tmp.v[1] = header->v[1]; + + copy_colors(stage, tmp.v[0], tmp.v[1]); + + stage->next->line( stage->next, &tmp ); +} + + +static void flatshade_point( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + +static void flatshade_end( struct prim_stage *stage ) +{ + stage->next->end( stage->next ); +} + +struct prim_stage *prim_flatshade( struct softpipe_context *softpipe ) +{ + struct flatshade_stage *flatshade = CALLOC_STRUCT(flatshade_stage); + + prim_alloc_tmps( &flatshade->stage, 2 ); + + flatshade->stage.softpipe = softpipe; + flatshade->stage.next = NULL; + flatshade->stage.begin = flatshade_begin; + flatshade->stage.point = flatshade_point; + flatshade->stage.line = flatshade_line; + flatshade->stage.tri = flatshade_tri; + flatshade->stage.end = flatshade_end; + + flatshade->lookup = softpipe->vf_attr_to_slot; + + return &flatshade->stage; +} + + diff --git a/src/mesa/pipe/draw/draw_offset.c b/src/mesa/pipe/draw/draw_offset.c new file mode 100644 index 00000000000..5fd6ac911a5 --- /dev/null +++ b/src/mesa/pipe/draw/draw_offset.c @@ -0,0 +1,157 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" +#include "macros.h" + +#include "sp_context.h" +#include "sp_prim.h" + + + +struct offset_stage { + struct prim_stage stage; + + GLuint hw_data_offset; + + GLfloat scale; + GLfloat units; +}; + + + +static INLINE struct offset_stage *offset_stage( struct prim_stage *stage ) +{ + return (struct offset_stage *)stage; +} + + +static void offset_begin( struct prim_stage *stage ) +{ + struct offset_stage *offset = offset_stage(stage); + + offset->units = stage->softpipe->setup.offset_units; + offset->scale = stage->softpipe->setup.offset_scale; + + stage->next->begin( stage->next ); +} + + +/* Offset tri. Some hardware can handle this, but not usually when + * doing unfilled rendering. + */ +static void do_offset_tri( struct prim_stage *stage, + struct prim_header *header ) +{ + struct offset_stage *offset = offset_stage(stage); + GLfloat inv_det = 1.0 / header->det; + + /* Window coords: + */ + GLfloat *v0 = (GLfloat *)&(header->v[0]->data[0]); + GLfloat *v1 = (GLfloat *)&(header->v[1]->data[0]); + GLfloat *v2 = (GLfloat *)&(header->v[2]->data[0]); + + GLfloat ex = v0[0] - v2[2]; + GLfloat fx = v1[0] - v2[2]; + GLfloat ey = v0[1] - v2[2]; + GLfloat fy = v1[1] - v2[2]; + GLfloat ez = v0[2] - v2[2]; + GLfloat fz = v1[2] - v2[2]; + + GLfloat a = ey*fz - ez*fy; + GLfloat b = ez*fx - ex*fz; + + GLfloat ac = a * inv_det; + GLfloat bc = b * inv_det; + GLfloat zoffset; + + if ( ac < 0.0f ) ac = -ac; + if ( bc < 0.0f ) bc = -bc; + + zoffset = offset->units + MAX2( ac, bc ) * offset->scale; + + v0[2] += zoffset; + v1[2] += zoffset; + v2[2] += zoffset; + + stage->next->tri( stage->next, header ); +} + + +static void offset_tri( struct prim_stage *stage, + struct prim_header *header ) +{ + struct prim_header tmp; + + tmp.det = header->det; + tmp.v[0] = dup_vert(stage, header->v[0], 0); + tmp.v[1] = dup_vert(stage, header->v[1], 1); + tmp.v[2] = dup_vert(stage, header->v[2], 2); + + do_offset_tri( stage->next, &tmp ); +} + + + +static void offset_line( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->line( stage->next, header ); +} + + +static void offset_point( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + + +static void offset_end( struct prim_stage *stage ) +{ + stage->next->end( stage->next ); +} + +struct prim_stage *prim_offset( struct softpipe_context *softpipe ) +{ + struct offset_stage *offset = CALLOC_STRUCT(offset_stage); + + prim_alloc_tmps( &offset->stage, 3 ); + + offset->stage.softpipe = softpipe; + 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; + + return &offset->stage; +} diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h new file mode 100644 index 00000000000..b6cbaae085d --- /dev/null +++ b/src/mesa/pipe/draw/draw_private.h @@ -0,0 +1,90 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#ifndef G_PRIM_H +#define G_PRIM_H + +#include "glheader.h" +#include "sp_headers.h" + +struct softpipe_context; + +struct prim_stage *prim_setup( struct softpipe_context *context ); +struct prim_stage *prim_unfilled( struct softpipe_context *context ); +struct prim_stage *prim_twoside( struct softpipe_context *context ); +struct prim_stage *prim_offset( struct softpipe_context *context ); +struct prim_stage *prim_clip( struct softpipe_context *context ); +struct prim_stage *prim_flatshade( struct softpipe_context *context ); +struct prim_stage *prim_cull( struct softpipe_context *context ); + + +/* Internal structs and helpers for the primitive clip/setup pipeline: + */ +struct prim_stage { + struct softpipe_context *softpipe; + + struct prim_stage *next; + + struct vertex_header **tmp; + GLuint nr_tmps; + + void (*begin)( struct prim_stage * ); + + void (*point)( struct prim_stage *, + struct prim_header * ); + + void (*line)( struct prim_stage *, + struct prim_header * ); + + void (*tri)( struct prim_stage *, + struct prim_header * ); + + void (*end)( struct prim_stage * ); +}; + + + +/* Get a writeable copy of a vertex: + */ +static INLINE struct vertex_header * +dup_vert( struct prim_stage *stage, + const struct vertex_header *vert, + GLuint idx ) +{ + struct vertex_header *tmp = stage->tmp[idx]; + memcpy(tmp, vert, stage->softpipe->prim.vertex_size ); + return tmp; +} + +void prim_free_tmps( struct prim_stage *stage ); +void prim_alloc_tmps( struct prim_stage *stage, GLuint nr ); + + +#endif diff --git a/src/mesa/pipe/draw/draw_twoside.c b/src/mesa/pipe/draw/draw_twoside.c new file mode 100644 index 00000000000..5e9f218d1e9 --- /dev/null +++ b/src/mesa/pipe/draw/draw_twoside.c @@ -0,0 +1,152 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" +#include "vf/vf.h" + +#include "pipe/p_defines.h" +#include "sp_context.h" +#include "sp_prim.h" + + +struct twoside_stage { + struct prim_stage stage; + + GLfloat facing; + const GLuint *lookup; +}; + + +static INLINE struct twoside_stage *twoside_stage( struct prim_stage *stage ) +{ + return (struct twoside_stage *)stage; +} + + +static void twoside_begin( struct prim_stage *stage ) +{ + struct twoside_stage *twoside = twoside_stage(stage); + + twoside->facing = (stage->softpipe->setup.front_winding == PIPE_WINDING_CW) ? -1 : 1; + + stage->next->begin( stage->next ); +} + + +static INLINE void copy_color( GLuint attr_dst, + GLuint attr_src, + struct vertex_header *v ) +{ + if (attr_dst && attr_src) { + memcpy( v->data[attr_dst], + v->data[attr_src], + sizeof(v->data[0]) ); + } +} + + +static struct vertex_header *copy_bfc( struct twoside_stage *twoside, + const struct vertex_header *v, + GLuint idx ) +{ + struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx ); + + copy_color( twoside->lookup[VF_ATTRIB_COLOR0], + twoside->lookup[VF_ATTRIB_BFC0], + tmp ); + + copy_color( twoside->lookup[VF_ATTRIB_COLOR1], + twoside->lookup[VF_ATTRIB_BFC1], + tmp ); + + return tmp; +} + + +/* Twoside tri: + */ +static void twoside_tri( struct prim_stage *stage, + struct prim_header *header ) +{ + struct twoside_stage *twoside = twoside_stage(stage); + + if (header->det * twoside->facing < 0) { + struct prim_header tmp; + + tmp.det = header->det; + tmp.v[0] = copy_bfc(twoside, header->v[0], 0); + tmp.v[1] = copy_bfc(twoside, header->v[1], 1); + tmp.v[2] = copy_bfc(twoside, header->v[2], 2); + + stage->next->tri( stage->next, &tmp ); + } + else { + stage->next->tri( stage->next, header ); + } +} + + +static void twoside_line( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->line( stage->next, header ); +} + + +static void twoside_point( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + +static void twoside_end( struct prim_stage *stage ) +{ + stage->next->end( stage->next ); +} + + + +struct prim_stage *prim_twoside( struct softpipe_context *softpipe ) +{ + struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage); + + prim_alloc_tmps( &twoside->stage, 3 ); + + twoside->stage.softpipe = softpipe; + 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->lookup = softpipe->vf_attr_to_slot; + + return &twoside->stage; +} diff --git a/src/mesa/pipe/draw/draw_unfilled.c b/src/mesa/pipe/draw/draw_unfilled.c new file mode 100644 index 00000000000..ab0dab09d4b --- /dev/null +++ b/src/mesa/pipe/draw/draw_unfilled.c @@ -0,0 +1,165 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" + +#include "sp_context.h" +#include "sp_prim.h" +#include "pipe/p_defines.h" + + +struct unfilled_stage { + struct prim_stage stage; + + GLuint mode[2]; +}; + + +static INLINE struct unfilled_stage *unfilled_stage( struct prim_stage *stage ) +{ + return (struct unfilled_stage *)stage; +} + + +static void unfilled_begin( struct prim_stage *stage ) +{ + struct unfilled_stage *unfilled = unfilled_stage(stage); + + unfilled->mode[0] = stage->softpipe->setup.fill_ccw; + unfilled->mode[1] = stage->softpipe->setup.fill_cw; + + stage->next->begin( stage->next ); +} + +static void point( struct prim_stage *stage, + struct vertex_header *v0 ) +{ + struct prim_header tmp; + tmp.v[0] = v0; + stage->next->point( stage->next, &tmp ); +} + +static void line( struct prim_stage *stage, + struct vertex_header *v0, + struct vertex_header *v1 ) +{ + struct prim_header tmp; + tmp.v[0] = v0; + tmp.v[1] = v1; + stage->next->line( stage->next, &tmp ); +} + + +static void points( struct prim_stage *stage, + struct prim_header *header ) +{ + struct vertex_header *v0 = header->v[0]; + struct vertex_header *v1 = header->v[1]; + struct vertex_header *v2 = header->v[2]; + + if (v0->edgeflag) point( stage, v0 ); + if (v1->edgeflag) point( stage, v1 ); + if (v2->edgeflag) point( stage, v2 ); +} + +static void lines( struct prim_stage *stage, + struct prim_header *header ) +{ + struct vertex_header *v0 = header->v[0]; + struct vertex_header *v1 = header->v[1]; + struct vertex_header *v2 = header->v[2]; + + if (v0->edgeflag) line( stage, v0, v1 ); + if (v1->edgeflag) line( stage, v1, v2 ); + if (v2->edgeflag) line( stage, v2, v0 ); +} + + +/* Unfilled tri: + * + * Note edgeflags in the vertex struct is not sufficient as we will + * need to manipulate them when decomposing primitives??? + */ +static void unfilled_tri( struct prim_stage *stage, + struct prim_header *header ) +{ + struct unfilled_stage *unfilled = unfilled_stage(stage); + GLuint mode = unfilled->mode[header->det < 0]; + + switch (mode) { + case PIPE_POLYGON_MODE_FILL: + stage->next->tri( stage->next, header ); + break; + case PIPE_POLYGON_MODE_LINE: + lines( stage, header ); + break; + case PIPE_POLYGON_MODE_POINT: + points( stage, header ); + break; + default: + abort(); + } +} + +static void unfilled_line( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->line( stage->next, header ); +} + + +static void unfilled_point( struct prim_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + + +static void unfilled_end( struct prim_stage *stage ) +{ + stage->next->end( stage->next ); +} + +struct prim_stage *prim_unfilled( struct softpipe_context *softpipe ) +{ + struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage); + + prim_alloc_tmps( &unfilled->stage, 0 ); + + unfilled->stage.softpipe = softpipe; + 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; + + return &unfilled->stage; +} diff --git a/src/mesa/pipe/draw/draw_vb.c b/src/mesa/pipe/draw/draw_vb.c new file mode 100644 index 00000000000..3fc30dd2034 --- /dev/null +++ b/src/mesa/pipe/draw/draw_vb.c @@ -0,0 +1,697 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "imports.h" + +#include "tnl/t_context.h" +#include "vf/vf.h" + +#include "sp_context.h" +#include "sp_prim.h" +#include "sp_headers.h" +#include "sp_draw.h" + +/* This file is a temporary set of hooks to allow us to use the tnl/ + * and vf/ modules until we have replacements in pipe. + */ + + +struct draw_context +{ + struct softpipe_context *softpipe; + + struct vf_attr_map attrs[VF_ATTRIB_MAX]; + GLuint nr_attrs; + GLuint vertex_size; + struct vertex_fetch *vf; + + GLubyte *verts; + GLuint nr_vertices; + GLboolean in_vb; + + GLenum prim; + + /* Helper for tnl: + */ + GLvector4f header; +}; + + +static struct vertex_header *get_vertex( struct draw_context *pipe, + GLuint i ) +{ + return (struct vertex_header *)(pipe->verts + i * pipe->vertex_size); +} + + + +static void draw_allocate_vertices( struct draw_context *draw, + GLuint nr_vertices ) +{ + draw->nr_vertices = nr_vertices; + draw->verts = MALLOC( nr_vertices * draw->vertex_size ); + + draw->softpipe->prim.first->begin( draw->softpipe->prim.first ); +} + +static void draw_set_prim( struct draw_context *draw, + GLenum prim ) +{ + draw->prim = prim; + + /* Not done yet - need to force edgeflags to 1 in strip/fan + * primitives. + */ +#if 0 + switch (prim) { + case GL_TRIANGLES: + case GL_POLYGON: + case GL_QUADS: + case GL_QUAD_STRIP: /* yes, we need this */ + respect_edgeflags( pipe, GL_TRUE ); + break; + + default: + respect_edgeflags( pipe, GL_FALSE ); + break; + } +#endif +} + + + +static void do_quad( struct prim_stage *first, + struct vertex_header *v0, + struct vertex_header *v1, + struct vertex_header *v2, + struct vertex_header *v3 ) +{ + struct prim_header prim; + + { + GLuint tmp = v1->edgeflag; + v1->edgeflag = 0; + + prim.v[0] = v0; + prim.v[1] = v1; + prim.v[2] = v3; + first->tri( first, &prim ); + + v1->edgeflag = tmp; + } + + { + GLuint tmp = v3->edgeflag; + v3->edgeflag = 0; + + prim.v[0] = v1; + prim.v[1] = v2; + prim.v[2] = v3; + first->tri( first, &prim ); + + v3->edgeflag = tmp; + } +} + + + + +static void draw_indexed_prim( struct draw_context *draw, + const GLuint *elts, + GLuint count ) +{ + struct prim_stage * const first = draw->softpipe->prim.first; + struct prim_header prim; + GLuint i; + + prim.det = 0; /* valid from cull stage onwards */ + prim.v[0] = 0; + prim.v[1] = 0; + prim.v[2] = 0; + + switch (draw->prim) { + case GL_POINTS: + for (i = 0; i < count; i ++) { + prim.v[0] = get_vertex( draw, elts[i] ); + + first->point( first, &prim ); + } + break; + + case GL_LINES: + for (i = 0; i+1 < count; i += 2) { + prim.v[0] = get_vertex( draw, elts[i + 0] ); + prim.v[1] = get_vertex( draw, elts[i + 1] ); + + first->line( first, &prim ); + } + break; + + case GL_LINE_LOOP: + if (count >= 2) { + for (i = 1; i < count; i++) { + prim.v[0] = get_vertex( draw, elts[i-1] ); + prim.v[1] = get_vertex( draw, elts[i] ); + first->line( first, &prim ); + } + + prim.v[0] = get_vertex( draw, elts[count-1] ); + prim.v[1] = get_vertex( draw, elts[0] ); + first->line( first, &prim ); + } + break; + + case GL_LINE_STRIP: + /* I'm guessing it will be necessary to have something like a + * render->reset_line_stipple() method to properly support + * splitting strips into primitives like this. Alternately we + * could just scan ahead to find individual clipped lines and + * otherwise leave the strip intact - that might be better, but + * require more complex code here. + */ + if (count >= 2) { + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, elts[0] ); + + for (i = 1; i < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, elts[i] ); + + first->line( first, &prim ); + } + } + break; + + case GL_TRIANGLES: + for (i = 0; i+2 < count; i += 3) { + prim.v[0] = get_vertex( draw, elts[i + 0] ); + prim.v[1] = get_vertex( draw, elts[i + 1] ); + prim.v[2] = get_vertex( draw, elts[i + 2] ); + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_STRIP: + for (i = 0; i+2 < count; i++) { + if (i & 1) { + prim.v[0] = get_vertex( draw, elts[i + 1] ); + prim.v[1] = get_vertex( draw, elts[i + 0] ); + prim.v[2] = get_vertex( draw, elts[i + 2] ); + } + else { + prim.v[0] = get_vertex( draw, elts[i + 0] ); + prim.v[1] = get_vertex( draw, elts[i + 1] ); + prim.v[2] = get_vertex( draw, elts[i + 2] ); + } + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_FAN: + if (count >= 3) { + prim.v[0] = get_vertex( draw, elts[0] ); + prim.v[1] = 0; + prim.v[2] = get_vertex( draw, elts[1] ); + + for (i = 0; i+2 < count; i++) { + prim.v[1] = prim.v[2]; + prim.v[2] = get_vertex( draw, elts[i+2] ); + + first->tri( first, &prim ); + } + } + break; + + case GL_QUADS: + for (i = 0; i+3 < count; i += 4) { + do_quad( first, + get_vertex( draw, elts[i + 0] ), + get_vertex( draw, elts[i + 1] ), + get_vertex( draw, elts[i + 2] ), + get_vertex( draw, elts[i + 3] )); + } + break; + + case GL_QUAD_STRIP: + for (i = 0; i+3 < count; i += 2) { + do_quad( first, + get_vertex( draw, elts[i + 2] ), + get_vertex( draw, elts[i + 0] ), + get_vertex( draw, elts[i + 1] ), + get_vertex( draw, elts[i + 3] )); + } + break; + + + case GL_POLYGON: + if (count >= 3) { + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, elts[1] ); + prim.v[2] = get_vertex( draw, elts[0] ); + + for (i = 0; i+2 < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, elts[i+2] ); + + first->tri( first, &prim ); + } + } + break; + + default: + assert(0); + break; + } +} + +static void draw_prim( struct draw_context *draw, + GLuint start, + GLuint count ) +{ + struct prim_stage * const first = draw->softpipe->prim.first; + struct prim_header prim; + GLuint i; + +// _mesa_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count ); + + prim.det = 0; /* valid from cull stage onwards */ + prim.v[0] = 0; + prim.v[1] = 0; + prim.v[2] = 0; + + switch (draw->prim) { + case GL_POINTS: + for (i = 0; i < count; i ++) { + prim.v[0] = get_vertex( draw, start + i ); + first->point( first, &prim ); + } + break; + + case GL_LINES: + for (i = 0; i+1 < count; i += 2) { + prim.v[0] = get_vertex( draw, start + i + 0 ); + prim.v[1] = get_vertex( draw, start + i + 1 ); + + first->line( first, &prim ); + } + break; + + case GL_LINE_LOOP: + if (count >= 2) { + for (i = 1; i < count; i++) { + prim.v[0] = get_vertex( draw, start + i - 1 ); + prim.v[1] = get_vertex( draw, start + i ); + first->line( first, &prim ); + } + + prim.v[0] = get_vertex( draw, start + count - 1 ); + prim.v[1] = get_vertex( draw, start + 0 ); + first->line( first, &prim ); + } + break; + + case GL_LINE_STRIP: + if (count >= 2) { + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, start + 0 ); + + for (i = 1; i < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, start + i ); + + first->line( first, &prim ); + } + } + break; + + case GL_TRIANGLES: + for (i = 0; i+2 < count; i += 3) { + prim.v[0] = get_vertex( draw, start + i + 0 ); + prim.v[1] = get_vertex( draw, start + i + 1 ); + prim.v[2] = get_vertex( draw, start + i + 2 ); + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_STRIP: + for (i = 0; i+2 < count; i++) { + if (i & 1) { + prim.v[0] = get_vertex( draw, start + i + 1 ); + prim.v[1] = get_vertex( draw, start + i + 0 ); + prim.v[2] = get_vertex( draw, start + i + 2 ); + } + else { + prim.v[0] = get_vertex( draw, start + i + 0 ); + prim.v[1] = get_vertex( draw, start + i + 1 ); + prim.v[2] = get_vertex( draw, start + i + 2 ); + } + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_FAN: + if (count >= 3) { + prim.v[0] = get_vertex( draw, start + 0 ); + prim.v[1] = 0; + prim.v[2] = get_vertex( draw, start + 1 ); + + for (i = 0; i+2 < count; i++) { + prim.v[1] = prim.v[2]; + prim.v[2] = get_vertex( draw, start + i + 2 ); + + first->tri( first, &prim ); + } + } + break; + + + case GL_QUADS: + for (i = 0; i+3 < count; i += 4) { + do_quad( first, + get_vertex( draw, start + i + 0 ), + get_vertex( draw, start + i + 1 ), + get_vertex( draw, start + i + 2 ), + get_vertex( draw, start + i + 3 )); + } + break; + + case GL_QUAD_STRIP: + for (i = 0; i+3 < count; i += 2) { + do_quad( first, + get_vertex( draw, start + i + 2 ), + get_vertex( draw, start + i + 0 ), + get_vertex( draw, start + i + 1 ), + get_vertex( draw, start + i + 3 )); + } + break; + + case GL_POLYGON: + if (count >= 3) { + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, start + 1 ); + prim.v[2] = get_vertex( draw, start + 0 ); + + for (i = 0; i+2 < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, start + i + 2 ); + + first->tri( first, &prim ); + } + } + break; + + default: + assert(0); + break; + } +} + + +static void draw_release_vertices( struct draw_context *draw ) +{ + draw->softpipe->prim.first->end( draw->softpipe->prim.first ); + + FREE(draw->verts); + draw->verts = NULL; +} + + +struct header_dword { + GLuint clipmask:12; + GLuint edgeflag:1; + GLuint pad:19; +}; + + +static void +build_vertex_headers( struct draw_context *draw, + struct vertex_buffer *VB ) +{ + if (draw->header.storage == NULL) { + draw->header.stride = sizeof(GLfloat); + draw->header.size = 1; + draw->header.storage = ALIGN_MALLOC( VB->Size * sizeof(GLfloat), 32 ); + draw->header.data = draw->header.storage; + draw->header.count = 0; + draw->header.flags = VEC_SIZE_1 | VEC_MALLOC; + } + + /* Build vertex header attribute. + * + */ + + { + GLuint i; + struct header_dword *header = (struct header_dword *)draw->header.storage; + + /* yes its a hack + */ + assert(sizeof(*header) == sizeof(GLfloat)); + + draw->header.count = VB->Count; + + if (VB->EdgeFlag) { + for (i = 0; i < VB->Count; i++) { + header[i].clipmask = VB->ClipMask[i]; + header[i].edgeflag = VB->EdgeFlag[i]; + header[i].pad = 0; + } + } + else if (VB->ClipOrMask) { + for (i = 0; i < VB->Count; i++) { + header[i].clipmask = VB->ClipMask[i]; + header[i].edgeflag = 0; + header[i].pad = 0; + } + } + else { + for (i = 0; i < VB->Count; i++) { + header[i].clipmask = 0; + header[i].edgeflag = 0; + header[i].pad = 0; + } + } + } + + VB->AttribPtr[VF_ATTRIB_VERTEX_HEADER] = &draw->header; +} + + + + + +static GLuint draw_prim_info(GLenum mode, GLuint *first, GLuint *incr) +{ + switch (mode) { + case GL_POINTS: + *first = 1; + *incr = 1; + return 0; + case GL_LINES: + *first = 2; + *incr = 2; + return 0; + case GL_LINE_STRIP: + *first = 2; + *incr = 1; + return 0; + case GL_LINE_LOOP: + *first = 2; + *incr = 1; + return 1; + case GL_TRIANGLES: + *first = 3; + *incr = 3; + return 0; + case GL_TRIANGLE_STRIP: + *first = 3; + *incr = 1; + return 0; + case GL_TRIANGLE_FAN: + case GL_POLYGON: + *first = 3; + *incr = 1; + return 1; + case GL_QUADS: + *first = 4; + *incr = 4; + return 0; + case GL_QUAD_STRIP: + *first = 4; + *incr = 2; + return 0; + default: + assert(0); + *first = 1; + *incr = 1; + return 0; + } +} + + +static GLuint trim( GLuint count, GLuint first, GLuint incr ) +{ + if (count < first) + return 0; + else + return count - (count - first) % incr; +} + + +/* This is a hack & will all go away. + */ +void draw_vb(struct draw_context *draw, + struct vertex_buffer *VB ) +{ + GLuint i; + + VB->AttribPtr[VF_ATTRIB_POS] = VB->NdcPtr; + VB->AttribPtr[VF_ATTRIB_BFC0] = VB->ColorPtr[1]; + VB->AttribPtr[VF_ATTRIB_BFC1] = VB->SecondaryColorPtr[1]; + VB->AttribPtr[VF_ATTRIB_CLIP_POS] = VB->ClipPtr; + + /* Build vertex headers: + */ + build_vertex_headers( draw, VB ); + + draw->in_vb = 1; + + /* Allocate the vertices: + */ + draw_allocate_vertices( draw, VB->Count ); + + /* Bind the vb outputs: + */ + vf_set_sources( draw->vf, VB->AttribPtr, 0 ); + + /* Build the hardware or prim-pipe vertices: + */ + vf_emit_vertices( draw->vf, VB->Count, draw->verts ); + + + for (i = 0; i < VB->PrimitiveCount; i++) { + + GLenum mode = VB->Primitive[i].mode; + GLuint start = VB->Primitive[i].start; + GLuint length, first, incr; + + /* Trim the primitive down to a legal size. + */ + draw_prim_info( mode, &first, &incr ); + length = trim( VB->Primitive[i].count, first, incr ); + + if (!length) + continue; + + if (draw->prim != mode) + draw_set_prim( draw, mode ); + + if (VB->Elts) { + draw_indexed_prim( draw, + VB->Elts + start, + length ); + } + else { + draw_prim( draw, + start, + length ); + } + } + + draw_release_vertices( draw ); + draw->verts = NULL; + draw->in_vb = 0; +} + +void draw_set_viewport( struct draw_context *draw, + const GLfloat *scale, + const GLfloat *translate ) +{ + assert(!draw->in_vb); + vf_set_vp_scale_translate( draw->vf, scale, translate ); +} + + + +struct draw_context *draw_create( struct softpipe_context *softpipe ) +{ + struct draw_context *draw = CALLOC_STRUCT( draw_context ); + draw->softpipe = softpipe; + draw->vf = vf_create( GL_TRUE ); + + return draw; +} + + +void draw_destroy( struct draw_context *draw ) +{ + if (draw->header.storage) + ALIGN_FREE( draw->header.storage ); + + vf_destroy( draw->vf ); + + FREE( draw ); +} + +#define EMIT_ATTR( ATTR, STYLE ) \ +do { \ + draw->attrs[draw->nr_attrs].attrib = ATTR; \ + draw->attrs[draw->nr_attrs].format = STYLE; \ + draw->nr_attrs++; \ +} while (0) + + +void draw_set_vertex_attributes( struct draw_context *draw, + const GLuint *attrs, + GLuint nr_attrs ) +{ + GLuint i; + + draw->nr_attrs = 0; + + EMIT_ATTR(VF_ATTRIB_VERTEX_HEADER, EMIT_1F); + EMIT_ATTR(VF_ATTRIB_CLIP_POS, EMIT_4F); + + assert(attrs[0] == VF_ATTRIB_POS); + EMIT_ATTR(attrs[0], EMIT_4F_VIEWPORT); + + for (i = 1; i < nr_attrs; i++) + EMIT_ATTR(attrs[i], EMIT_4F); + + draw->vertex_size = vf_set_vertex_attributes( draw->vf, draw->attrs, draw->nr_attrs, 0 ); +} + + |