1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "pipe/p_util.h"
34 #include "draw/draw_context.h"
35 #include "draw/draw_private.h"
36 #include "draw/draw_vertex.h"
37 #include "draw/draw_pt.h"
39 /* The simplest 'middle end' in the new vertex code.
41 * The responsibilities of a middle end are to:
42 * - perform vertex fetch using
43 * - draw vertex element/buffer state
44 * - a list of fetch indices we received as an input
45 * - run the vertex shader
47 * - clip coord calculation
48 * - viewport transformation
49 * - if necessary, run the primitive pipeline, passing it:
50 * - a linear array of vertex_header vertices constructed here
51 * - a set of draw indices we received as an input
52 * - otherwise, drive the hw backend,
53 * - allocate space for hardware format vertices
54 * - translate the vertex-shader output vertices to hw format
55 * - calling the backend draw functions.
57 * For convenience, we provide a helper function to drive the hardware
58 * backend given similar inputs to those required to run the pipeline.
60 * In the case of passthrough mode, many of these actions are disabled
61 * or noops, so we end up doing:
63 * - perform vertex fetch
64 * - drive the hw backend
66 * IE, basically just vertex fetch to post-vs-format vertices,
67 * followed by a call to the backend helper function.
71 struct fetch_pipeline_middle_end
{
72 struct draw_pt_middle_end base
;
73 struct draw_context
*draw
;
78 void (*fetch
)( const void *from
, float *attrib
);
79 void (*emit
)( const float *attrib
, float **out
);
80 } fetch
[PIPE_MAX_ATTRIBS
];
83 unsigned pipeline_vertex_size
;
88 static void fetch_NULL( const void *from
,
95 static void emit_R32_FLOAT( const float *attrib
,
98 (*out
)[0] = attrib
[0];
102 static void emit_R32G32_FLOAT( const float *attrib
,
105 (*out
)[0] = attrib
[0];
106 (*out
)[1] = attrib
[1];
110 static void emit_R32G32B32_FLOAT( const float *attrib
,
113 (*out
)[0] = attrib
[0];
114 (*out
)[1] = attrib
[1];
115 (*out
)[2] = attrib
[2];
119 static void emit_R32G32B32A32_FLOAT( const float *attrib
,
122 (*out
)[0] = attrib
[0];
123 (*out
)[1] = attrib
[1];
124 (*out
)[2] = attrib
[2];
125 (*out
)[3] = attrib
[3];
129 static void emit_header( const float *attrib
,
141 * General-purpose fetch from user's vertex arrays, emit to driver's
144 * XXX this is totally temporary.
147 fetch_store_general( struct fetch_pipeline_middle_end
*fpme
,
149 const unsigned *fetch_elts
,
152 float *out
= (float *)out_ptr
;
155 for (i
= 0; i
< count
; i
++) {
156 unsigned elt
= fetch_elts
[i
];
158 for (j
= 0; j
< fpme
->nr_fetch
; j
++) {
160 const ubyte
*from
= (fpme
->fetch
[j
].ptr
+
161 fpme
->fetch
[j
].pitch
* elt
);
163 fpme
->fetch
[j
].fetch( from
, attrib
);
164 fpme
->fetch
[j
].emit( attrib
, &out
);
170 /* We aren't running a vertex shader, but are running the pipeline.
171 * That means the vertices we need to build look like:
173 * dw0: vertex header (zero?)
178 * dw5: screen coord 0
179 * dw6: screen coord 0
180 * dw7: screen coord 0
181 * dw8: screen coord 0
182 * dw9: other attribs...
185 static void fetch_pipeline_prepare( struct draw_pt_middle_end
*middle
,
188 static const float zero
= 0;
189 struct fetch_pipeline_middle_end
*fpme
= (struct fetch_pipeline_middle_end
*)middle
;
190 struct draw_context
*draw
= fpme
->draw
;
195 /* Emit the vertex header and empty clipspace coord field:
198 fpme
->fetch
[nr
].ptr
= NULL
;
199 fpme
->fetch
[nr
].pitch
= 0;
200 fpme
->fetch
[nr
].fetch
= fetch_NULL
;
201 fpme
->fetch
[nr
].emit
= emit_header
;
206 /* Need to look at vertex shader inputs (we know it is a
207 * passthrough shader, so these define the outputs too). If we
208 * were running a shader, we'd still be looking at the inputs at
211 for (i
= 0; i
< draw
->vertex_shader
->info
.num_inputs
; i
++) {
212 unsigned buf
= draw
->vertex_element
[i
].vertex_buffer_index
;
213 enum pipe_format format
= draw
->vertex_element
[i
].src_format
;
215 fpme
->fetch
[nr
].ptr
= ((const ubyte
*) draw
->user
.vbuffer
[buf
] +
216 draw
->vertex_buffer
[buf
].buffer_offset
+
217 draw
->vertex_element
[i
].src_offset
);
219 fpme
->fetch
[nr
].pitch
= draw
->vertex_buffer
[buf
].pitch
;
220 fpme
->fetch
[nr
].fetch
= draw_get_fetch_func( format
);
222 /* Always do this -- somewhat redundant...
224 fpme
->fetch
[nr
].emit
= emit_R32G32B32A32_FLOAT
;
229 fpme
->pipeline_vertex_size
= (5 + (nr
-1) * 4) * sizeof(float);
235 * Add a point to the primitive queue.
236 * \param i0 index into user's vertex arrays
238 static void do_point( struct draw_context
*draw
,
241 struct prim_header prim
;
243 prim
.reset_line_stipple
= 0;
246 prim
.v
[0] = (struct vertex_header
*)v0
;
248 draw
->pipeline
.first
->point( draw
->pipeline
.first
, &prim
);
253 * Add a line to the primitive queue.
254 * \param i0 index into user's vertex arrays
255 * \param i1 index into user's vertex arrays
257 static void do_line( struct draw_context
*draw
,
261 struct prim_header prim
;
263 prim
.reset_line_stipple
= 1; /* fixme */
266 prim
.v
[0] = (struct vertex_header
*)v0
;
267 prim
.v
[1] = (struct vertex_header
*)v1
;
269 draw
->pipeline
.first
->line( draw
->pipeline
.first
, &prim
);
273 * Add a triangle to the primitive queue.
275 static void do_triangle( struct draw_context
*draw
,
280 struct prim_header prim
;
282 // _mesa_printf("tri %d %d %d\n", i0, i1, i2);
283 prim
.reset_line_stipple
= 1;
286 prim
.v
[0] = (struct vertex_header
*)v0
;
287 prim
.v
[1] = (struct vertex_header
*)v1
;
288 prim
.v
[2] = (struct vertex_header
*)v2
;
290 draw
->pipeline
.first
->tri( draw
->pipeline
.first
, &prim
);
294 static void run_pipeline( struct fetch_pipeline_middle_end
*fpme
,
299 struct draw_context
*draw
= fpme
->draw
;
300 unsigned stride
= fpme
->pipeline_vertex_size
;
303 switch (fpme
->prim
) {
304 case PIPE_PRIM_POINTS
:
305 for (i
= 0; i
< count
; i
++)
307 verts
+ stride
* elts
[i
] );
309 case PIPE_PRIM_LINES
:
310 for (i
= 0; i
+1 < count
; i
+= 2)
312 verts
+ stride
* elts
[i
+0],
313 verts
+ stride
* elts
[i
+1]);
315 case PIPE_PRIM_TRIANGLES
:
316 for (i
= 0; i
+2 < count
; i
+= 3)
318 verts
+ stride
* elts
[i
+0],
319 verts
+ stride
* elts
[i
+1],
320 verts
+ stride
* elts
[i
+2]);
328 static void fetch_pipeline_run( struct draw_pt_middle_end
*middle
,
329 const unsigned *fetch_elts
,
330 unsigned fetch_count
,
331 const ushort
*draw_elts
,
332 unsigned draw_count
)
334 struct fetch_pipeline_middle_end
*fpme
= (struct fetch_pipeline_middle_end
*)middle
;
335 struct draw_context
*draw
= fpme
->draw
;
336 char *pipeline_verts
;
338 pipeline_verts
= MALLOC( fpme
->pipeline_vertex_size
*
340 if (!pipeline_verts
) {
346 /* Single routine to fetch vertices and emit pipeline verts.
348 fetch_store_general( fpme
,
360 /* Done -- that was easy, wasn't it:
362 FREE( pipeline_verts
);
367 static void fetch_pipeline_finish( struct draw_pt_middle_end
*middle
)
372 static void fetch_pipeline_destroy( struct draw_pt_middle_end
*middle
)
378 struct draw_pt_middle_end
*draw_pt_fetch_pipeline( struct draw_context
*draw
)
380 struct fetch_pipeline_middle_end
*fetch_pipeline
= CALLOC_STRUCT( fetch_pipeline_middle_end
);
382 fetch_pipeline
->base
.prepare
= fetch_pipeline_prepare
;
383 fetch_pipeline
->base
.run
= fetch_pipeline_run
;
384 fetch_pipeline
->base
.finish
= fetch_pipeline_finish
;
385 fetch_pipeline
->base
.destroy
= fetch_pipeline_destroy
;
387 fetch_pipeline
->draw
= draw
;
389 return &fetch_pipeline
->base
;