split larger primitives in the simple varray pt
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_varray.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "pipe/p_util.h"
29 #include "draw/draw_context.h"
30 #include "draw/draw_private.h"
31 #include "draw/draw_pt.h"
32
33 #define FETCH_MAX 256
34 #define DRAW_MAX (16*FETCH_MAX)
35
36 struct varray_frontend {
37 struct draw_pt_front_end base;
38 struct draw_context *draw;
39
40 ushort draw_elts[DRAW_MAX];
41 unsigned fetch_elts[FETCH_MAX];
42
43 unsigned draw_count;
44 unsigned fetch_count;
45
46 unsigned fetch_start;
47
48 struct draw_pt_middle_end *middle;
49
50 unsigned input_prim;
51 unsigned output_prim;
52 };
53
54 static void varray_flush(struct varray_frontend *varray)
55 {
56 if (varray->draw_count) {
57 #if 0
58 debug_printf("FLUSH fc = %d, dc = %d\n",
59 varray->fetch_count,
60 varray->draw_count);
61 debug_printf("\telt0 = %d, eltx = %d, draw0 = %d, drawx = %d\n",
62 varray->fetch_elts[0],
63 varray->fetch_elts[varray->fetch_count-1],
64 varray->draw_elts[0],
65 varray->draw_elts[varray->draw_count-1]);
66 #endif
67 varray->middle->run(varray->middle,
68 varray->fetch_elts,
69 varray->fetch_count,
70 varray->draw_elts,
71 varray->draw_count);
72 }
73
74 varray->fetch_count = 0;
75 varray->draw_count = 0;
76 }
77
78 static INLINE void fetch_init(struct varray_frontend *varray,
79 unsigned count)
80 {
81 unsigned idx;
82 #if 0
83 debug_printf("FETCH INIT c = %d, fs = %d\n",
84 count,
85 varray->fetch_start);
86 #endif
87 for (idx = 0; idx < count; ++idx) {
88 varray->fetch_elts[idx] = varray->fetch_start + idx;
89 }
90 varray->fetch_start += idx;
91 varray->fetch_count = idx;
92 }
93
94
95 static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr)
96 {
97 switch (prim) {
98 case PIPE_PRIM_POINTS:
99 *first = 1;
100 *incr = 1;
101 return TRUE;
102 case PIPE_PRIM_LINES:
103 *first = 2;
104 *incr = 2;
105 return TRUE;
106 case PIPE_PRIM_LINE_STRIP:
107 *first = 2;
108 *incr = 1;
109 return TRUE;
110 case PIPE_PRIM_TRIANGLES:
111 *first = 3;
112 *incr = 3;
113 return TRUE;
114 case PIPE_PRIM_TRIANGLE_STRIP:
115 *first = 3;
116 *incr = 1;
117 return TRUE;
118 case PIPE_PRIM_TRIANGLE_FAN:
119 *first = 3;
120 *incr = 1;
121 return TRUE;
122 case PIPE_PRIM_QUADS:
123 *first = 4;
124 *incr = 4;
125 return TRUE;
126 case PIPE_PRIM_QUAD_STRIP:
127 *first = 4;
128 *incr = 2;
129 return TRUE;
130 case PIPE_PRIM_POLYGON:
131 *first = 3;
132 *incr = 1;
133 return TRUE;
134 default:
135 *first = 0;
136 *incr = 1; /* set to one so that count % incr works */
137 return FALSE;
138 }
139 }
140
141
142 static INLINE void add_draw_el(struct varray_frontend *varray,
143 int idx, ushort flags)
144 {
145 varray->draw_elts[varray->draw_count++] = idx | flags;
146 }
147
148
149 static INLINE void varray_triangle( struct varray_frontend *varray,
150 unsigned i0,
151 unsigned i1,
152 unsigned i2 )
153 {
154 add_draw_el(varray, i0, 0);
155 add_draw_el(varray, i1, 0);
156 add_draw_el(varray, i2, 0);
157 }
158
159 static INLINE void varray_triangle_flags( struct varray_frontend *varray,
160 ushort flags,
161 unsigned i0,
162 unsigned i1,
163 unsigned i2 )
164 {
165 add_draw_el(varray, i0, flags);
166 add_draw_el(varray, i1, 0);
167 add_draw_el(varray, i2, 0);
168 }
169
170 static INLINE void varray_line( struct varray_frontend *varray,
171 unsigned i0,
172 unsigned i1 )
173 {
174 add_draw_el(varray, i0, 0);
175 add_draw_el(varray, i1, 0);
176 }
177
178
179 static INLINE void varray_line_flags( struct varray_frontend *varray,
180 ushort flags,
181 unsigned i0,
182 unsigned i1 )
183 {
184 add_draw_el(varray, i0, flags);
185 add_draw_el(varray, i1, 0);
186 }
187
188
189 static INLINE void varray_point( struct varray_frontend *varray,
190 unsigned i0 )
191 {
192 add_draw_el(varray, i0, 0);
193 }
194
195 static INLINE void varray_quad( struct varray_frontend *varray,
196 unsigned i0,
197 unsigned i1,
198 unsigned i2,
199 unsigned i3 )
200 {
201 varray_triangle( varray, i0, i1, i3 );
202 varray_triangle( varray, i1, i2, i3 );
203 }
204
205 static INLINE void varray_ef_quad( struct varray_frontend *varray,
206 unsigned i0,
207 unsigned i1,
208 unsigned i2,
209 unsigned i3 )
210 {
211 const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2;
212 const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1;
213
214 varray_triangle_flags( varray,
215 DRAW_PIPE_RESET_STIPPLE | omitEdge1,
216 i0, i1, i3 );
217
218 varray_triangle_flags( varray,
219 omitEdge2,
220 i1, i2, i3 );
221 }
222
223 /* At least for now, we're back to using a template include file for
224 * this. The two paths aren't too different though - it may be
225 * possible to reunify them.
226 */
227 #define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle_flags(vc,flags,i0,i1,i2)
228 #define QUAD(vc,i0,i1,i2,i3) varray_ef_quad(vc,i0,i1,i2,i3)
229 #define LINE(vc,flags,i0,i1) varray_line_flags(vc,flags,i0,i1)
230 #define POINT(vc,i0) varray_point(vc,i0)
231 #define FUNC varray_run_extras
232 #include "draw_pt_varray_tmp.h"
233
234 #define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle(vc,i0,i1,i2)
235 #define QUAD(vc,i0,i1,i2,i3) varray_quad(vc,i0,i1,i2,i3)
236 #define LINE(vc,flags,i0,i1) varray_line(vc,i0,i1)
237 #define POINT(vc,i0) varray_point(vc,i0)
238 #define FUNC varray_run
239 #include "draw_pt_varray_tmp.h"
240
241
242
243 static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
244 PIPE_PRIM_POINTS,
245 PIPE_PRIM_LINES,
246 PIPE_PRIM_LINES,
247 PIPE_PRIM_LINES,
248 PIPE_PRIM_TRIANGLES,
249 PIPE_PRIM_TRIANGLES,
250 PIPE_PRIM_TRIANGLES,
251 PIPE_PRIM_TRIANGLES,
252 PIPE_PRIM_TRIANGLES,
253 PIPE_PRIM_TRIANGLES
254 };
255
256
257
258 static void varray_prepare(struct draw_pt_front_end *frontend,
259 unsigned prim,
260 struct draw_pt_middle_end *middle,
261 unsigned opt)
262 {
263 struct varray_frontend *varray = (struct varray_frontend *)frontend;
264
265 if (opt & PT_PIPELINE)
266 {
267 varray->base.run = varray_run_extras;
268 }
269 else
270 {
271 varray->base.run = varray_run;
272 }
273
274 varray->input_prim = prim;
275 varray->output_prim = reduced_prim[prim];
276
277 varray->middle = middle;
278 middle->prepare(middle, varray->output_prim, opt);
279 }
280
281
282
283
284 static void varray_finish(struct draw_pt_front_end *frontend)
285 {
286 struct varray_frontend *varray = (struct varray_frontend *)frontend;
287 varray->middle->finish(varray->middle);
288 varray->middle = NULL;
289 }
290
291 static void varray_destroy(struct draw_pt_front_end *frontend)
292 {
293 FREE(frontend);
294 }
295
296
297 struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw)
298 {
299 struct varray_frontend *varray = CALLOC_STRUCT(varray_frontend);
300 if (varray == NULL)
301 return NULL;
302
303 varray->base.prepare = varray_prepare;
304 varray->base.run = NULL;
305 varray->base.finish = varray_finish;
306 varray->base.destroy = varray_destroy;
307 varray->draw = draw;
308
309 return &varray->base;
310 }