206e1ec3118c233da2ffbdd878d2f272304bfb13
[mesa.git] / src / gallium / auxiliary / util / u_split_prim.h
1 /* Originally written by Ben Skeggs for the nv50 driver*/
2 #include <pipe/p_defines.h>
3
4 struct util_split_prim {
5 void *priv;
6 void (*emit)(void *priv, unsigned start, unsigned count);
7 void (*edge)(void *priv, boolean enabled);
8
9 unsigned mode;
10 unsigned start;
11 unsigned p_start;
12 unsigned p_end;
13
14 uint repeat_first:1;
15 uint close_first:1;
16 uint edgeflag_off:1;
17 };
18
19 static INLINE void
20 util_split_prim_init(struct util_split_prim *s,
21 unsigned mode, unsigned start, unsigned count)
22 {
23 if (mode == PIPE_PRIM_LINE_LOOP) {
24 s->mode = PIPE_PRIM_LINE_STRIP;
25 s->close_first = 1;
26 } else {
27 s->mode = mode;
28 s->close_first = 0;
29 }
30 s->start = start;
31 s->p_start = start;
32 s->p_end = start + count;
33 s->edgeflag_off = 0;
34 s->repeat_first = 0;
35 }
36
37 static INLINE boolean
38 util_split_prim_next(struct util_split_prim *s, unsigned max_verts)
39 {
40 int repeat = 0;
41
42 if (s->repeat_first) {
43 s->emit(s->priv, s->start, 1);
44 max_verts--;
45 if (s->edgeflag_off) {
46 s->edge(s->priv, TRUE);
47 s->edgeflag_off = FALSE;
48 }
49 }
50
51 if (s->p_start + s->close_first + max_verts >= s->p_end) {
52 s->emit(s->priv, s->p_start, s->p_end - s->p_start);
53 if (s->close_first)
54 s->emit(s->priv, s->start, 1);
55 return TRUE;
56 }
57
58 switch (s->mode) {
59 case PIPE_PRIM_LINES:
60 max_verts &= ~1;
61 break;
62 case PIPE_PRIM_LINE_STRIP:
63 repeat = 1;
64 break;
65 case PIPE_PRIM_POLYGON:
66 max_verts--;
67 s->emit(s->priv, s->p_start, max_verts);
68 s->edge(s->priv, FALSE);
69 s->emit(s->priv, s->p_start + max_verts, 1);
70 s->p_start += max_verts;
71 s->repeat_first = TRUE;
72 s->edgeflag_off = TRUE;
73 return FALSE;
74 case PIPE_PRIM_TRIANGLES:
75 max_verts = max_verts - (max_verts % 3);
76 break;
77 case PIPE_PRIM_TRIANGLE_STRIP:
78 /* to ensure winding stays correct, always split
79 * on an even number of generated triangles
80 */
81 max_verts = max_verts & ~1;
82 repeat = 2;
83 break;
84 case PIPE_PRIM_TRIANGLE_FAN:
85 s->repeat_first = TRUE;
86 repeat = 1;
87 break;
88 case PIPE_PRIM_QUADS:
89 max_verts &= ~3;
90 break;
91 case PIPE_PRIM_QUAD_STRIP:
92 max_verts &= ~1;
93 repeat = 2;
94 break;
95 case PIPE_PRIM_POINTS:
96 break;
97 default:
98 /* TODO: implement adjacency primitives */
99 assert(0);
100 }
101
102 s->emit (s->priv, s->p_start, max_verts);
103 s->p_start += (max_verts - repeat);
104 return FALSE;
105 }