draw: make pt run pipeline when need_pipeline is true, not just when clipped
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch_emit.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_vbuf.h"
37 #include "draw/draw_vertex.h"
38 #include "draw/draw_pt.h"
39
40 /* The simplest 'middle end' in the new vertex code.
41 *
42 * The responsibilities of a middle end are to:
43 * - perform vertex fetch using
44 * - draw vertex element/buffer state
45 * - a list of fetch indices we received as an input
46 * - run the vertex shader
47 * - cliptest,
48 * - clip coord calculation
49 * - viewport transformation
50 * - if necessary, run the primitive pipeline, passing it:
51 * - a linear array of vertex_header vertices constructed here
52 * - a set of draw indices we received as an input
53 * - otherwise, drive the hw backend,
54 * - allocate space for hardware format vertices
55 * - translate the vertex-shader output vertices to hw format
56 * - calling the backend draw functions.
57 *
58 * For convenience, we provide a helper function to drive the hardware
59 * backend given similar inputs to those required to run the pipeline.
60 *
61 * In the case of passthrough mode, many of these actions are disabled
62 * or noops, so we end up doing:
63 *
64 * - perform vertex fetch
65 * - drive the hw backend
66 *
67 * IE, basically just vertex fetch to post-vs-format vertices,
68 * followed by a call to the backend helper function.
69 */
70
71
72 struct fetch_emit_middle_end {
73 struct draw_pt_middle_end base;
74 struct draw_context *draw;
75
76 struct {
77 const ubyte *ptr;
78 unsigned pitch;
79 void (*fetch)( const void *from, float *attrib);
80 void (*emit)( const float *attrib, float **out );
81 } fetch[PIPE_MAX_ATTRIBS];
82
83 unsigned nr_fetch;
84 unsigned hw_vertex_size;
85 };
86
87
88
89 static void fetch_R32_FLOAT( const void *from,
90 float *attrib )
91 {
92 float *f = (float *) from;
93 attrib[0] = f[0];
94 attrib[1] = 0.0;
95 attrib[2] = 0.0;
96 attrib[3] = 1.0;
97 }
98
99
100 static void emit_R32_FLOAT( const float *attrib,
101 float **out )
102 {
103 (*out)[0] = attrib[0];
104 (*out) += 1;
105 }
106
107 static void emit_R32G32_FLOAT( const float *attrib,
108 float **out )
109 {
110 (*out)[0] = attrib[0];
111 (*out)[1] = attrib[1];
112 (*out) += 2;
113 }
114
115 static void emit_R32G32B32_FLOAT( const float *attrib,
116 float **out )
117 {
118 (*out)[0] = attrib[0];
119 (*out)[1] = attrib[1];
120 (*out)[2] = attrib[2];
121 (*out) += 3;
122 }
123
124 static void emit_R32G32B32A32_FLOAT( const float *attrib,
125 float **out )
126 {
127 (*out)[0] = attrib[0];
128 (*out)[1] = attrib[1];
129 (*out)[2] = attrib[2];
130 (*out)[3] = attrib[3];
131 (*out) += 4;
132 }
133
134
135 /**
136 * General-purpose fetch from user's vertex arrays, emit to driver's
137 * vertex buffer.
138 *
139 * XXX this is totally temporary.
140 */
141 static void
142 fetch_store_general( struct fetch_emit_middle_end *feme,
143 void *out_ptr,
144 const unsigned *fetch_elts,
145 unsigned count )
146 {
147 float *out = (float *)out_ptr;
148 uint i, j;
149
150 for (i = 0; i < count; i++) {
151 unsigned elt = fetch_elts[i] & ~DRAW_PT_FLAG_MASK;
152
153 for (j = 0; j < feme->nr_fetch; j++) {
154 float attrib[4];
155 const ubyte *from = (feme->fetch[j].ptr +
156 feme->fetch[j].pitch * elt);
157
158 feme->fetch[j].fetch( from, attrib );
159 feme->fetch[j].emit( attrib, &out );
160 }
161 }
162 }
163
164
165
166 static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
167 unsigned prim,
168 unsigned opt )
169 {
170 struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
171 struct draw_context *draw = feme->draw;
172 const struct vertex_info *vinfo;
173 unsigned i;
174 boolean ok;
175
176
177 ok = draw->render->set_primitive( draw->render,
178 prim );
179 if (!ok) {
180 assert(0);
181 return;
182 }
183
184 /* Must do this after set_primitive() above:
185 */
186 vinfo = draw->render->get_vertex_info(draw->render);
187
188 for (i = 0; i < vinfo->num_attribs; i++) {
189 unsigned src_element = vinfo->src_index[i];
190 unsigned src_buffer = draw->vertex_element[src_element].vertex_buffer_index;
191
192 feme->fetch[i].ptr = ((const ubyte *)draw->user.vbuffer[src_buffer] +
193 draw->vertex_buffer[src_buffer].buffer_offset +
194 draw->vertex_element[src_element].src_offset);
195
196 feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch;
197
198 feme->fetch[i].fetch = draw_get_fetch_func(draw->vertex_element[src_element].src_format);
199
200
201 switch (vinfo->emit[i]) {
202 case EMIT_4F:
203 feme->fetch[i].emit = emit_R32G32B32A32_FLOAT;
204 break;
205 case EMIT_3F:
206 feme->fetch[i].emit = emit_R32G32B32_FLOAT;
207 break;
208 case EMIT_2F:
209 feme->fetch[i].emit = emit_R32G32_FLOAT;
210 break;
211 case EMIT_1F:
212 feme->fetch[i].emit = emit_R32_FLOAT;
213 break;
214 case EMIT_1F_PSIZE:
215 feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size;
216 feme->fetch[i].pitch = 0;
217 feme->fetch[i].fetch = fetch_R32_FLOAT;
218 feme->fetch[i].emit = emit_R32_FLOAT;
219 break;
220 default:
221 assert(0);
222 feme->fetch[i].emit = NULL;
223 break;
224 }
225 }
226
227 feme->nr_fetch = vinfo->num_attribs;
228 feme->hw_vertex_size = vinfo->size * 4;
229 }
230
231
232
233
234
235 static void fetch_emit_run( struct draw_pt_middle_end *middle,
236 const unsigned *fetch_elts,
237 unsigned fetch_count,
238 const ushort *draw_elts,
239 unsigned draw_count )
240 {
241 struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
242 struct draw_context *draw = feme->draw;
243 void *hw_verts;
244
245 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
246 */
247 draw_do_flush( draw, DRAW_FLUSH_BACKEND );
248
249 hw_verts = draw->render->allocate_vertices( draw->render,
250 (ushort)feme->hw_vertex_size,
251 (ushort)fetch_count );
252 if (!hw_verts) {
253 assert(0);
254 return;
255 }
256
257
258 /* Single routine to fetch vertices and emit HW verts.
259 */
260 fetch_store_general( feme,
261 hw_verts,
262 fetch_elts,
263 fetch_count );
264
265 /* XXX: Draw arrays path to avoid re-emitting index list again and
266 * again.
267 */
268 draw->render->draw( draw->render,
269 draw_elts,
270 draw_count );
271
272 /* Done -- that was easy, wasn't it:
273 */
274 draw->render->release_vertices( draw->render,
275 hw_verts,
276 feme->hw_vertex_size,
277 fetch_count );
278
279 }
280
281
282
283 static void fetch_emit_finish( struct draw_pt_middle_end *middle )
284 {
285 /* nothing to do */
286 }
287
288 static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
289 {
290 FREE(middle);
291 }
292
293
294 struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
295 {
296 struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end );
297
298 fetch_emit->base.prepare = fetch_emit_prepare;
299 fetch_emit->base.run = fetch_emit_run;
300 fetch_emit->base.finish = fetch_emit_finish;
301 fetch_emit->base.destroy = fetch_emit_destroy;
302
303 fetch_emit->draw = draw;
304
305 return &fetch_emit->base;
306 }
307