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
11struct 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
26static INLINE void
27util_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
44static INLINE boolean
45util_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