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