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