Home | History | Annotate | Download | only in util
      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