/* Originally written by Ben Skeggs for the nv50 driver*/ #ifndef U_SPLIT_PRIM_H #define U_SPLIT_PRIM_H #include "pipe/p_defines.h" #include "pipe/p_compiler.h" #include "util/u_debug.h" struct util_split_prim { void *priv; void (*emit)(void *priv, unsigned start, unsigned count); void (*edge)(void *priv, boolean enabled); unsigned mode; unsigned start; unsigned p_start; unsigned p_end; uint repeat_first:1; uint close_first:1; uint edgeflag_off:1; }; static INLINE void util_split_prim_init(struct util_split_prim *s, unsigned mode, unsigned start, unsigned count) { if (mode == PIPE_PRIM_LINE_LOOP) { s->mode = PIPE_PRIM_LINE_STRIP; s->close_first = 1; } else { s->mode = mode; s->close_first = 0; } s->start = start; s->p_start = start; s->p_end = start + count; s->edgeflag_off = 0; s->repeat_first = 0; } static INLINE boolean util_split_prim_next(struct util_split_prim *s, unsigned max_verts) { int repeat = 0; if (s->repeat_first) { s->emit(s->priv, s->start, 1); max_verts--; if (s->edgeflag_off) { s->edge(s->priv, TRUE); s->edgeflag_off = FALSE; } } if ((s->p_end - s->p_start) + s->close_first <= max_verts) { s->emit(s->priv, s->p_start, s->p_end - s->p_start); if (s->close_first) s->emit(s->priv, s->start, 1); return TRUE; } switch (s->mode) { case PIPE_PRIM_LINES: max_verts &= ~1; break; case PIPE_PRIM_LINE_STRIP: repeat = 1; break; case PIPE_PRIM_POLYGON: max_verts--; s->emit(s->priv, s->p_start, max_verts); s->edge(s->priv, FALSE); s->emit(s->priv, s->p_start + max_verts, 1); s->p_start += max_verts; s->repeat_first = TRUE; s->edgeflag_off = TRUE; return FALSE; case PIPE_PRIM_TRIANGLES: max_verts = max_verts - (max_verts % 3); break; case PIPE_PRIM_TRIANGLE_STRIP: /* to ensure winding stays correct, always split * on an even number of generated triangles */ max_verts = max_verts & ~1; repeat = 2; break; case PIPE_PRIM_TRIANGLE_FAN: s->repeat_first = TRUE; repeat = 1; break; case PIPE_PRIM_QUADS: max_verts &= ~3; break; case PIPE_PRIM_QUAD_STRIP: max_verts &= ~1; repeat = 2; break; case PIPE_PRIM_POINTS: break; default: /* TODO: implement adjacency primitives */ assert(0); } s->emit (s->priv, s->p_start, max_verts); s->p_start += (max_verts - repeat); return FALSE; } #endif /* U_SPLIT_PRIM_H */