draw: associate rhw divide with clipping not viewport flag
[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 static void fetch_B8G8R8A8_UNORM( const void *from,
89 float *attrib )
90 {
91 ubyte *ub = (ubyte *) from;
92 attrib[2] = UBYTE_TO_FLOAT(ub[0]);
93 attrib[1] = UBYTE_TO_FLOAT(ub[1]);
94 attrib[0] = UBYTE_TO_FLOAT(ub[2]);
95 attrib[3] = UBYTE_TO_FLOAT(ub[3]);
96 }
97
98 static void fetch_R32G32B32A32_FLOAT( const void *from,
99 float *attrib )
100 {
101 float *f = (float *) from;
102 attrib[0] = f[0];
103 attrib[1] = f[1];
104 attrib[2] = f[2];
105 attrib[3] = f[3];
106 }
107
108 static void fetch_R32G32B32_FLOAT( const void *from,
109 float *attrib )
110 {
111 float *f = (float *) from;
112 attrib[0] = f[0];
113 attrib[1] = f[1];
114 attrib[2] = f[2];
115 attrib[3] = 1.0;
116 }
117
118 static void fetch_R32G32_FLOAT( const void *from,
119 float *attrib )
120 {
121 float *f = (float *) from;
122 attrib[0] = f[0];
123 attrib[1] = f[1];
124 attrib[2] = 0.0;
125 attrib[3] = 1.0;
126 }
127
128 static void fetch_R32_FLOAT( const void *from,
129 float *attrib )
130 {
131 float *f = (float *) from;
132 attrib[0] = f[0];
133 attrib[1] = 0.0;
134 attrib[2] = 0.0;
135 attrib[3] = 1.0;
136 }
137
138
139 static void emit_R32_FLOAT( const float *attrib,
140 float **out )
141 {
142 (*out)[0] = attrib[0];
143 (*out) += 1;
144 }
145
146 static void emit_R32G32_FLOAT( const float *attrib,
147 float **out )
148 {
149 (*out)[0] = attrib[0];
150 (*out)[1] = attrib[1];
151 (*out) += 2;
152 }
153
154 static void emit_R32G32B32_FLOAT( const float *attrib,
155 float **out )
156 {
157 (*out)[0] = attrib[0];
158 (*out)[1] = attrib[1];
159 (*out)[2] = attrib[2];
160 (*out) += 3;
161 }
162
163 static void emit_R32G32B32A32_FLOAT( const float *attrib,
164 float **out )
165 {
166 (*out)[0] = attrib[0];
167 (*out)[1] = attrib[1];
168 (*out)[2] = attrib[2];
169 (*out)[3] = attrib[3];
170 (*out) += 4;
171 }
172
173
174 /**
175 * General-purpose fetch from user's vertex arrays, emit to driver's
176 * vertex buffer.
177 *
178 * XXX this is totally temporary.
179 */
180 static void
181 fetch_store_general( struct fetch_emit_middle_end *feme,
182 void *out_ptr,
183 const unsigned *fetch_elts,
184 unsigned count )
185 {
186 float *out = (float *)out_ptr;
187 struct vbuf_render *render = feme->draw->render;
188 uint i, j;
189
190 for (i = 0; i < count; i++) {
191 unsigned elt = fetch_elts[i];
192
193 for (j = 0; j < feme->nr_fetch; j++) {
194 float attrib[4];
195 const ubyte *from = (feme->fetch[j].ptr +
196 feme->fetch[j].pitch * elt);
197
198 feme->fetch[j].fetch( from, attrib );
199 feme->fetch[j].emit( attrib, &out );
200 }
201 }
202 }
203
204
205
206 static void fetch_emit_prepare( struct draw_pt_middle_end *middle )
207 {
208 static const float zero = 0;
209 struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
210 struct draw_context *draw = feme->draw;
211 const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
212 unsigned nr_attrs = vinfo->num_attribs;
213 unsigned i;
214
215 for (i = 0; i < nr_attrs; i++) {
216 unsigned src_element = vinfo->src_index[i];
217 unsigned src_buffer = draw->vertex_element[src_element].vertex_buffer_index;
218
219 feme->fetch[i].ptr = ((const ubyte *)draw->user.vbuffer[src_buffer] +
220 draw->vertex_buffer[src_buffer].buffer_offset +
221 draw->vertex_element[src_element].src_offset);
222
223 feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch;
224
225 switch (draw->vertex_element[src_element].src_format) {
226 case PIPE_FORMAT_B8G8R8A8_UNORM:
227 feme->fetch[i].fetch = fetch_B8G8R8A8_UNORM;
228 break;
229 case PIPE_FORMAT_R32G32B32A32_FLOAT:
230 feme->fetch[i].fetch = fetch_R32G32B32A32_FLOAT;
231 break;
232 case PIPE_FORMAT_R32G32B32_FLOAT:
233 feme->fetch[i].fetch = fetch_R32G32B32_FLOAT;
234 break;
235 case PIPE_FORMAT_R32G32_FLOAT:
236 feme->fetch[i].fetch = fetch_R32G32_FLOAT;
237 break;
238 case PIPE_FORMAT_R32_FLOAT:
239 feme->fetch[i].fetch = fetch_R32_FLOAT;
240 break;
241 default:
242 assert(0);
243 feme->fetch[i].fetch = NULL;
244 break;
245 }
246
247 switch (vinfo->emit[i]) {
248 case EMIT_4F:
249 feme->fetch[i].emit = emit_R32G32B32A32_FLOAT;
250 break;
251 case EMIT_3F:
252 feme->fetch[i].emit = emit_R32G32B32_FLOAT;
253 break;
254 case EMIT_2F:
255 feme->fetch[i].emit = emit_R32G32_FLOAT;
256 break;
257 case EMIT_1F:
258 feme->fetch[i].emit = emit_R32_FLOAT;
259 break;
260 case EMIT_HEADER:
261 feme->fetch[i].ptr = (const ubyte *)&zero;
262 feme->fetch[i].pitch = 0;
263 feme->fetch[i].fetch = fetch_R32_FLOAT;
264 feme->fetch[i].emit = emit_R32_FLOAT;
265 break;
266 case EMIT_1F_PSIZE:
267 feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size;
268 feme->fetch[i].pitch = 0;
269 feme->fetch[i].fetch = fetch_R32_FLOAT;
270 feme->fetch[i].emit = emit_R32_FLOAT;
271 default:
272 assert(0);
273 feme->fetch[i].emit = NULL;
274 break;
275 }
276 }
277
278 feme->nr_fetch = nr_attrs;
279 feme->hw_vertex_size = vinfo->size * 4;
280 }
281
282
283
284
285
286 static void fetch_emit_run( struct draw_pt_middle_end *middle,
287 unsigned prim,
288 const unsigned *fetch_elts,
289 unsigned fetch_count,
290 const ushort *draw_elts,
291 unsigned draw_count )
292 {
293 struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
294 struct draw_context *draw = feme->draw;
295 void *hw_verts;
296 boolean ok;
297
298 ok = draw->render->set_primitive( draw->render,
299 prim );
300 if (!ok) {
301 assert(0);
302 return;
303 }
304
305
306 hw_verts = draw->render->allocate_vertices( draw->render,
307 (ushort)feme->hw_vertex_size,
308 (ushort)fetch_count );
309 if (!hw_verts) {
310 assert(0);
311 return;
312 }
313
314
315 /* Single routine to fetch vertices and emit HW verts.
316 */
317 fetch_store_general( feme,
318 hw_verts,
319 fetch_elts,
320 fetch_count );
321
322 /* XXX: Draw arrays path to avoid re-emitting index list again and
323 * again.
324 */
325 draw->render->draw( draw->render,
326 draw_elts,
327 draw_count );
328
329 /* Done -- that was easy, wasn't it:
330 */
331 draw->render->release_vertices( draw->render,
332 hw_verts,
333 feme->hw_vertex_size,
334 fetch_count );
335
336 }
337
338
339
340 static void fetch_emit_finish( struct draw_pt_middle_end *middle )
341 {
342 /* nothing to do */
343 }
344
345 static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
346 {
347 FREE(middle);
348 }
349
350
351 struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
352 {
353 struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end );
354
355 fetch_emit->base.prepare = fetch_emit_prepare;
356 fetch_emit->base.run = fetch_emit_run;
357 fetch_emit->base.finish = fetch_emit_finish;
358 fetch_emit->base.destroy = fetch_emit_destroy;
359
360 fetch_emit->draw = draw;
361
362 return &fetch_emit->base;
363 }
364