forked from KolibriOS/kolibrios
115 lines
2.6 KiB
C
115 lines
2.6 KiB
C
|
/* Originally written by Ben Skeggs for the nv50 driver*/
|
||
|
|
||
|
#ifndef U_SPLIT_PRIM_H
|
||
|
#define U_SPLIT_PRIM_H
|
||
|
|
||
|
#include "pipe/p_defines.h"
|
||
|
#include "pipe/p_compiler.h"
|
||
|
|
||
|
#include "util/u_debug.h"
|
||
|
|
||
|
struct util_split_prim {
|
||
|
void *priv;
|
||
|
void (*emit)(void *priv, unsigned start, unsigned count);
|
||
|
void (*edge)(void *priv, boolean enabled);
|
||
|
|
||
|
unsigned mode;
|
||
|
unsigned start;
|
||
|
unsigned p_start;
|
||
|
unsigned p_end;
|
||
|
|
||
|
uint repeat_first:1;
|
||
|
uint close_first:1;
|
||
|
uint edgeflag_off:1;
|
||
|
};
|
||
|
|
||
|
static INLINE void
|
||
|
util_split_prim_init(struct util_split_prim *s,
|
||
|
unsigned mode, unsigned start, unsigned count)
|
||
|
{
|
||
|
if (mode == PIPE_PRIM_LINE_LOOP) {
|
||
|
s->mode = PIPE_PRIM_LINE_STRIP;
|
||
|
s->close_first = 1;
|
||
|
} else {
|
||
|
s->mode = mode;
|
||
|
s->close_first = 0;
|
||
|
}
|
||
|
s->start = start;
|
||
|
s->p_start = start;
|
||
|
s->p_end = start + count;
|
||
|
s->edgeflag_off = 0;
|
||
|
s->repeat_first = 0;
|
||
|
}
|
||
|
|
||
|
static INLINE boolean
|
||
|
util_split_prim_next(struct util_split_prim *s, unsigned max_verts)
|
||
|
{
|
||
|
int repeat = 0;
|
||
|
|
||
|
if (s->repeat_first) {
|
||
|
s->emit(s->priv, s->start, 1);
|
||
|
max_verts--;
|
||
|
if (s->edgeflag_off) {
|
||
|
s->edge(s->priv, TRUE);
|
||
|
s->edgeflag_off = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((s->p_end - s->p_start) + s->close_first <= max_verts) {
|
||
|
s->emit(s->priv, s->p_start, s->p_end - s->p_start);
|
||
|
if (s->close_first)
|
||
|
s->emit(s->priv, s->start, 1);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
switch (s->mode) {
|
||
|
case PIPE_PRIM_LINES:
|
||
|
max_verts &= ~1;
|
||
|
break;
|
||
|
case PIPE_PRIM_LINE_STRIP:
|
||
|
repeat = 1;
|
||
|
break;
|
||
|
case PIPE_PRIM_POLYGON:
|
||
|
max_verts--;
|
||
|
s->emit(s->priv, s->p_start, max_verts);
|
||
|
s->edge(s->priv, FALSE);
|
||
|
s->emit(s->priv, s->p_start + max_verts, 1);
|
||
|
s->p_start += max_verts;
|
||
|
s->repeat_first = TRUE;
|
||
|
s->edgeflag_off = TRUE;
|
||
|
return FALSE;
|
||
|
case PIPE_PRIM_TRIANGLES:
|
||
|
max_verts = max_verts - (max_verts % 3);
|
||
|
break;
|
||
|
case PIPE_PRIM_TRIANGLE_STRIP:
|
||
|
/* to ensure winding stays correct, always split
|
||
|
* on an even number of generated triangles
|
||
|
*/
|
||
|
max_verts = max_verts & ~1;
|
||
|
repeat = 2;
|
||
|
break;
|
||
|
case PIPE_PRIM_TRIANGLE_FAN:
|
||
|
s->repeat_first = TRUE;
|
||
|
repeat = 1;
|
||
|
break;
|
||
|
case PIPE_PRIM_QUADS:
|
||
|
max_verts &= ~3;
|
||
|
break;
|
||
|
case PIPE_PRIM_QUAD_STRIP:
|
||
|
max_verts &= ~1;
|
||
|
repeat = 2;
|
||
|
break;
|
||
|
case PIPE_PRIM_POINTS:
|
||
|
break;
|
||
|
default:
|
||
|
/* TODO: implement adjacency primitives */
|
||
|
assert(0);
|
||
|
}
|
||
|
|
||
|
s->emit (s->priv, s->p_start, max_verts);
|
||
|
s->p_start += (max_verts - repeat);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
#endif /* U_SPLIT_PRIM_H */
|