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