| /* 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 */ |