implement linear emition and fetching and plug it in the varray paths
[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 void varray_flush_linear(struct varray_frontend *varray)
79 {
80 if (varray->draw_count) {
81 debug_printf("FLUSH LINEAR fc = %d, dc = %d\n",
82 varray->fetch_count,
83 varray->draw_count);
84 debug_printf("\telt0 = %d, eltx = %d, draw0 = %d, drawx = %d\n",
85 varray->fetch_elts[0],
86 varray->fetch_elts[varray->fetch_count-1],
87 varray->draw_elts[0],
88 varray->draw_elts[varray->draw_count-1]);
89 varray->middle->run_linear(varray->middle,
90 varray->fetch_elts[0],
91 varray->fetch_count,
92 varray->draw_elts,
93 varray->draw_count);
94 }
95
96 varray->fetch_count = 0;
97 varray->draw_count = 0;
98 }
99
100 static INLINE void fetch_init(struct varray_frontend *varray,
101 unsigned count)
102 {
103 unsigned idx;
104 #if 0
105 debug_printf("FETCH INIT c = %d, fs = %d\n",
106 count,
107 varray->fetch_start);
108 #endif
109 for (idx = 0; idx < count; ++idx) {
110 varray->fetch_elts[idx] = varray->fetch_start + idx;
111 }
112 varray->fetch_start += idx;
113 varray->fetch_count = idx;
114 }
115
116
117 static boolean split_prim_inplace(unsigned prim, unsigned *first, unsigned *incr)
118 {
119 switch (prim) {
120 case PIPE_PRIM_POINTS:
121 *first = 1;
122 *incr = 1;
123 return TRUE;
124 case PIPE_PRIM_LINES:
125 *first = 2;
126 *incr = 2;
127 return TRUE;
128 case PIPE_PRIM_LINE_STRIP:
129 *first = 2;
130 *incr = 1;
131 return TRUE;
132 case PIPE_PRIM_TRIANGLES:
133 *first = 3;
134 *incr = 3;
135 return TRUE;
136 case PIPE_PRIM_TRIANGLE_STRIP:
137 *first = 3;
138 *incr = 1;
139 return TRUE;
140 case PIPE_PRIM_TRIANGLE_FAN:
141 *first = 3;
142 *incr = 1;
143 return TRUE;
144 case PIPE_PRIM_QUADS:
145 *first = 4;
146 *incr = 4;
147 return TRUE;
148 case PIPE_PRIM_QUAD_STRIP:
149 *first = 4;
150 *incr = 2;
151 return TRUE;
152 case PIPE_PRIM_POLYGON:
153 *first = 3;
154 *incr = 1;
155 return TRUE;
156 default:
157 *first = 0;
158 *incr = 1; /* set to one so that count % incr works */
159 return FALSE;
160 }
161 }
162
163
164 static INLINE void add_draw_el(struct varray_frontend *varray,
165 int idx, ushort flags)
166 {
167 varray->draw_elts[varray->draw_count++] = idx | flags;
168 }
169
170
171 static INLINE void varray_triangle( struct varray_frontend *varray,
172 unsigned i0,
173 unsigned i1,
174 unsigned i2 )
175 {
176 add_draw_el(varray, i0, 0);
177 add_draw_el(varray, i1, 0);
178 add_draw_el(varray, i2, 0);
179 }
180
181 static INLINE void varray_triangle_flags( struct varray_frontend *varray,
182 ushort flags,
183 unsigned i0,
184 unsigned i1,
185 unsigned i2 )
186 {
187 add_draw_el(varray, i0, flags);
188 add_draw_el(varray, i1, 0);
189 add_draw_el(varray, i2, 0);
190 }
191
192 static INLINE void varray_line( struct varray_frontend *varray,
193 unsigned i0,
194 unsigned i1 )
195 {
196 add_draw_el(varray, i0, 0);
197 add_draw_el(varray, i1, 0);
198 }
199
200
201 static INLINE void varray_line_flags( struct varray_frontend *varray,
202 ushort flags,
203 unsigned i0,
204 unsigned i1 )
205 {
206 add_draw_el(varray, i0, flags);
207 add_draw_el(varray, i1, 0);
208 }
209
210
211 static INLINE void varray_point( struct varray_frontend *varray,
212 unsigned i0 )
213 {
214 add_draw_el(varray, i0, 0);
215 }
216
217 static INLINE void varray_quad( struct varray_frontend *varray,
218 unsigned i0,
219 unsigned i1,
220 unsigned i2,
221 unsigned i3 )
222 {
223 varray_triangle( varray, i0, i1, i3 );
224 varray_triangle( varray, i1, i2, i3 );
225 }
226
227 static INLINE void varray_ef_quad( struct varray_frontend *varray,
228 unsigned i0,
229 unsigned i1,
230 unsigned i2,
231 unsigned i3 )
232 {
233 const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2;
234 const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1;
235
236 varray_triangle_flags( varray,
237 DRAW_PIPE_RESET_STIPPLE | omitEdge1,
238 i0, i1, i3 );
239
240 varray_triangle_flags( varray,
241 omitEdge2,
242 i1, i2, i3 );
243 }
244
245 /* At least for now, we're back to using a template include file for
246 * this. The two paths aren't too different though - it may be
247 * possible to reunify them.
248 */
249 #define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle_flags(vc,flags,i0,i1,i2)
250 #define QUAD(vc,i0,i1,i2,i3) varray_ef_quad(vc,i0,i1,i2,i3)
251 #define LINE(vc,flags,i0,i1) varray_line_flags(vc,flags,i0,i1)
252 #define POINT(vc,i0) varray_point(vc,i0)
253 #define FUNC varray_run_extras
254 #include "draw_pt_varray_tmp.h"
255
256 #define TRIANGLE(vc,flags,i0,i1,i2) varray_triangle(vc,i0,i1,i2)
257 #define QUAD(vc,i0,i1,i2,i3) varray_quad(vc,i0,i1,i2,i3)
258 #define LINE(vc,flags,i0,i1) varray_line(vc,i0,i1)
259 #define POINT(vc,i0) varray_point(vc,i0)
260 #define FUNC varray_run
261 #include "draw_pt_varray_tmp.h"
262
263
264
265 static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
266 PIPE_PRIM_POINTS,
267 PIPE_PRIM_LINES,
268 PIPE_PRIM_LINES,
269 PIPE_PRIM_LINES,
270 PIPE_PRIM_TRIANGLES,
271 PIPE_PRIM_TRIANGLES,
272 PIPE_PRIM_TRIANGLES,
273 PIPE_PRIM_TRIANGLES,
274 PIPE_PRIM_TRIANGLES,
275 PIPE_PRIM_TRIANGLES
276 };
277
278
279
280 static void varray_prepare(struct draw_pt_front_end *frontend,
281 unsigned prim,
282 struct draw_pt_middle_end *middle,
283 unsigned opt)
284 {
285 struct varray_frontend *varray = (struct varray_frontend *)frontend;
286
287 if (opt & PT_PIPELINE)
288 {
289 varray->base.run = varray_run_extras;
290 }
291 else
292 {
293 varray->base.run = varray_run;
294 }
295
296 varray->input_prim = prim;
297 varray->output_prim = reduced_prim[prim];
298
299 varray->middle = middle;
300 middle->prepare(middle, varray->output_prim, opt);
301 }
302
303
304
305
306 static void varray_finish(struct draw_pt_front_end *frontend)
307 {
308 struct varray_frontend *varray = (struct varray_frontend *)frontend;
309 varray->middle->finish(varray->middle);
310 varray->middle = NULL;
311 }
312
313 static void varray_destroy(struct draw_pt_front_end *frontend)
314 {
315 FREE(frontend);
316 }
317
318
319 struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw)
320 {
321 struct varray_frontend *varray = CALLOC_STRUCT(varray_frontend);
322 if (varray == NULL)
323 return NULL;
324
325 varray->base.prepare = varray_prepare;
326 varray->base.run = NULL;
327 varray->base.finish = varray_finish;
328 varray->base.destroy = varray_destroy;
329 varray->draw = draw;
330
331 return &varray->base;
332 }