1 #ifndef __NOUVEAU_UTIL_H__
2 #define __NOUVEAU_UTIL_H__
4 /* Determine how many vertices can be pushed into the command stream.
5 * Where the remaining space isn't large enough to represent all verices,
6 * split the buffer at primitive boundaries.
8 * Returns a count of vertices that can be rendered, and an index to
9 * restart drawing at after a flush.
11 static INLINE
unsigned
12 nouveau_vbuf_split(unsigned remaining
, unsigned overhead
, unsigned vpp
,
13 unsigned mode
, unsigned start
, unsigned count
,
18 max
= remaining
- overhead
;
27 case PIPE_PRIM_POINTS
:
32 case PIPE_PRIM_TRIANGLES
:
33 max
= max
- (max
% 3);
38 case PIPE_PRIM_LINE_LOOP
:
39 case PIPE_PRIM_LINE_STRIP
:
44 case PIPE_PRIM_POLYGON
:
45 case PIPE_PRIM_TRIANGLE_STRIP
:
46 case PIPE_PRIM_TRIANGLE_FAN
:
51 case PIPE_PRIM_QUAD_STRIP
:
60 *restart
= start
+ max
- adj
;
64 /* Integer base-2 logarithm, rounded towards zero. */
65 static INLINE
unsigned log2i(unsigned i
)
93 void (*emit
)(void *priv
, unsigned start
, unsigned count
);
94 void (*edge
)(void *priv
, boolean enabled
);
107 u_split_prim_init(struct u_split_prim
*s
,
108 unsigned mode
, unsigned start
, unsigned count
)
110 if (mode
== PIPE_PRIM_LINE_LOOP
) {
111 s
->mode
= PIPE_PRIM_LINE_STRIP
;
119 s
->p_end
= start
+ count
;
124 static INLINE boolean
125 u_split_prim_next(struct u_split_prim
*s
, unsigned max_verts
)
129 if (s
->repeat_first
) {
130 s
->emit(s
->priv
, s
->start
, 1);
132 if (s
->edgeflag_off
) {
133 s
->edge(s
->priv
, TRUE
);
134 s
->edgeflag_off
= FALSE
;
138 if (s
->p_start
+ s
->close_first
+ max_verts
>= s
->p_end
) {
139 s
->emit(s
->priv
, s
->p_start
, s
->p_end
- s
->p_start
);
141 s
->emit(s
->priv
, s
->start
, 1);
146 case PIPE_PRIM_LINES
:
149 case PIPE_PRIM_LINE_STRIP
:
152 case PIPE_PRIM_POLYGON
:
154 s
->emit(s
->priv
, s
->p_start
, max_verts
);
155 s
->edge(s
->priv
, FALSE
);
156 s
->emit(s
->priv
, s
->p_start
+ max_verts
, 1);
157 s
->p_start
+= max_verts
;
158 s
->repeat_first
= TRUE
;
159 s
->edgeflag_off
= TRUE
;
161 case PIPE_PRIM_TRIANGLES
:
162 max_verts
= max_verts
- (max_verts
% 3);
164 case PIPE_PRIM_TRIANGLE_STRIP
:
165 /* to ensure winding stays correct, always split
166 * on an even number of generated triangles
168 max_verts
= max_verts
& ~1;
171 case PIPE_PRIM_TRIANGLE_FAN
:
172 s
->repeat_first
= TRUE
;
175 case PIPE_PRIM_QUADS
:
178 case PIPE_PRIM_QUAD_STRIP
:
186 s
->emit (s
->priv
, s
->p_start
, max_verts
);
187 s
->p_start
+= (max_verts
- repeat
);