draw: handle edgeflags and reset-line-stipple again
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_vcache.c
1 /**************************************************************************
2 *
3 * Copyright 2007 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 /*
29 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 */
32
33 #include "pipe/p_util.h"
34 #include "draw/draw_context.h"
35 #include "draw/draw_private.h"
36 #include "draw/draw_pt.h"
37
38
39 #define CACHE_MAX 32
40 #define FETCH_MAX 128
41 #define DRAW_MAX (16*1024)
42
43 struct vcache_frontend {
44 struct draw_pt_front_end base;
45 struct draw_context *draw;
46
47 unsigned in[CACHE_MAX];
48 ushort out[CACHE_MAX];
49
50 ushort draw_elts[DRAW_MAX];
51 unsigned fetch_elts[FETCH_MAX];
52
53 unsigned draw_count;
54 unsigned fetch_count;
55
56 struct draw_pt_middle_end *middle;
57
58 unsigned input_prim;
59 unsigned output_prim;
60 };
61
62 static void vcache_flush( struct vcache_frontend *vcache )
63 {
64 if (vcache->draw_count) {
65 vcache->middle->run( vcache->middle,
66 vcache->fetch_elts,
67 vcache->fetch_count,
68 vcache->draw_elts,
69 vcache->draw_count );
70 }
71
72 memset(vcache->in, ~0, sizeof(vcache->in));
73 vcache->fetch_count = 0;
74 vcache->draw_count = 0;
75 }
76
77 static void vcache_check_flush( struct vcache_frontend *vcache )
78 {
79 if ( vcache->draw_count + 6 >= DRAW_MAX ||
80 vcache->fetch_count + 4 >= FETCH_MAX )
81 {
82 vcache_flush( vcache );
83 }
84 }
85
86
87 static INLINE void vcache_elt( struct vcache_frontend *vcache,
88 unsigned felt,
89 ushort flags )
90 {
91 unsigned idx = felt % CACHE_MAX;
92
93 if (vcache->in[idx] != felt) {
94 assert(vcache->fetch_count < FETCH_MAX);
95
96 vcache->in[idx] = felt;
97 vcache->out[idx] = (ushort)vcache->fetch_count;
98 vcache->fetch_elts[vcache->fetch_count++] = felt;
99 }
100
101 vcache->draw_elts[vcache->draw_count++] = vcache->out[idx] | flags;
102 }
103
104
105
106 static void vcache_triangle( struct vcache_frontend *vcache,
107 unsigned i0,
108 unsigned i1,
109 unsigned i2 )
110 {
111 vcache_elt(vcache, i0, 0);
112 vcache_elt(vcache, i1, 0);
113 vcache_elt(vcache, i2, 0);
114 vcache_check_flush(vcache);
115 }
116
117
118 static void vcache_triangle_flags( struct vcache_frontend *vcache,
119 ushort flags,
120 unsigned i0,
121 unsigned i1,
122 unsigned i2 )
123 {
124 vcache_elt(vcache, i0, flags);
125 vcache_elt(vcache, i1, 0);
126 vcache_elt(vcache, i2, 0);
127 vcache_check_flush(vcache);
128 }
129
130 static void vcache_line( struct vcache_frontend *vcache,
131 unsigned i0,
132 unsigned i1 )
133 {
134 vcache_elt(vcache, i0, 0);
135 vcache_elt(vcache, i1, 0);
136 vcache_check_flush(vcache);
137 }
138
139
140 static void vcache_line_flags( struct vcache_frontend *vcache,
141 ushort flags,
142 unsigned i0,
143 unsigned i1 )
144 {
145 vcache_elt(vcache, i0, flags);
146 vcache_elt(vcache, i1, 0);
147 vcache_check_flush(vcache);
148 }
149
150
151 static void vcache_point( struct vcache_frontend *vcache,
152 unsigned i0 )
153 {
154 vcache_elt(vcache, i0, 0);
155 vcache_check_flush(vcache);
156 }
157
158 static void vcache_quad( struct vcache_frontend *vcache,
159 unsigned i0,
160 unsigned i1,
161 unsigned i2,
162 unsigned i3 )
163 {
164 vcache_triangle( vcache, i0, i1, i3 );
165 vcache_triangle( vcache, i1, i2, i3 );
166 }
167
168 static void vcache_ef_quad( struct vcache_frontend *vcache,
169 unsigned i0,
170 unsigned i1,
171 unsigned i2,
172 unsigned i3 )
173 {
174 const unsigned omitEdge1 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_2;
175 const unsigned omitEdge2 = DRAW_PIPE_EDGE_FLAG_0 | DRAW_PIPE_EDGE_FLAG_1;
176
177 vcache_triangle_flags( vcache,
178 DRAW_PIPE_RESET_STIPPLE | omitEdge1,
179 i0, i1, i3 );
180
181 vcache_triangle_flags( vcache,
182 omitEdge2,
183 i1, i2, i3 );
184 }
185
186 /* At least for now, we're back to using a template include file for
187 * this. The two paths aren't too different though - it may be
188 * possible to reunify them.
189 */
190 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
191 #define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
192 #define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
193 #define POINT(vc,i0) vcache_point(vc,i0)
194 #define FUNC vcache_run_extras
195 #include "draw_pt_vcache_tmp.h"
196
197 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
198 #define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
199 #define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
200 #define POINT(vc,i0) vcache_point(vc,i0)
201 #define FUNC vcache_run
202 #include "draw_pt_vcache_tmp.h"
203
204
205
206
207 static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
208 PIPE_PRIM_POINTS,
209 PIPE_PRIM_LINES,
210 PIPE_PRIM_LINES,
211 PIPE_PRIM_LINES,
212 PIPE_PRIM_TRIANGLES,
213 PIPE_PRIM_TRIANGLES,
214 PIPE_PRIM_TRIANGLES,
215 PIPE_PRIM_TRIANGLES,
216 PIPE_PRIM_TRIANGLES,
217 PIPE_PRIM_TRIANGLES
218 };
219
220
221
222 static void vcache_prepare( struct draw_pt_front_end *frontend,
223 unsigned prim,
224 struct draw_pt_middle_end *middle,
225 unsigned opt )
226 {
227 struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
228 const struct pipe_rasterizer_state *rasterizer = vcache->draw->rasterizer;
229
230
231 if (rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
232 rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL ||
233 rasterizer->line_stipple_enable)
234 {
235 assert(opt & PT_PIPELINE);
236 vcache->base.run = vcache_run_extras;
237 }
238 else
239 {
240 vcache->base.run = vcache_run;
241 }
242
243 vcache->input_prim = prim;
244 vcache->output_prim = reduced_prim[prim];
245
246 vcache->middle = middle;
247 middle->prepare( middle, vcache->output_prim, opt );
248 }
249
250
251
252
253 static void vcache_finish( struct draw_pt_front_end *frontend )
254 {
255 struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
256 vcache->middle->finish( vcache->middle );
257 vcache->middle = NULL;
258 }
259
260 static void vcache_destroy( struct draw_pt_front_end *frontend )
261 {
262 FREE(frontend);
263 }
264
265
266 struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw )
267 {
268 struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
269 if (vcache == NULL)
270 return NULL;
271
272 vcache->base.prepare = vcache_prepare;
273 vcache->base.run = NULL;
274 vcache->base.finish = vcache_finish;
275 vcache->base.destroy = vcache_destroy;
276 vcache->draw = draw;
277
278 memset(vcache->in, ~0, sizeof(vcache->in));
279
280 return &vcache->base;
281 }