Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.