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_vbuf.h"
37 #include "draw/draw_vertex.h"
38 #include "draw/draw_pt.h"
40 /* The simplest 'middle end' in the new vertex code.
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
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.
58 * For convenience, we provide a helper function to drive the hardware
59 * backend given similar inputs to those required to run the pipeline.
61 * In the case of passthrough mode, many of these actions are disabled
62 * or noops, so we end up doing:
64 * - perform vertex fetch
65 * - drive the hw backend
67 * IE, basically just vertex fetch to post-vs-format vertices,
68 * followed by a call to the backend helper function.
72 struct fetch_emit_middle_end
{
73 struct draw_pt_middle_end base
;
74 struct draw_context
*draw
;
79 void (*fetch
)( const void *from
, float *attrib
);
80 void (*emit
)( const float *attrib
, float **out
);
81 } fetch
[PIPE_MAX_ATTRIBS
];
84 unsigned hw_vertex_size
;
89 static void fetch_R32_FLOAT( const void *from
,
92 float *f
= (float *) from
;
100 static void emit_R32_FLOAT( const float *attrib
,
103 (*out
)[0] = attrib
[0];
107 static void emit_R32G32_FLOAT( const float *attrib
,
110 (*out
)[0] = attrib
[0];
111 (*out
)[1] = attrib
[1];
115 static void emit_R32G32B32_FLOAT( const float *attrib
,
118 (*out
)[0] = attrib
[0];
119 (*out
)[1] = attrib
[1];
120 (*out
)[2] = attrib
[2];
124 static void emit_R32G32B32A32_FLOAT( const float *attrib
,
127 (*out
)[0] = attrib
[0];
128 (*out
)[1] = attrib
[1];
129 (*out
)[2] = attrib
[2];
130 (*out
)[3] = attrib
[3];
136 * General-purpose fetch from user's vertex arrays, emit to driver's
139 * XXX this is totally temporary.
142 fetch_store_general( struct fetch_emit_middle_end
*feme
,
144 const unsigned *fetch_elts
,
147 float *out
= (float *)out_ptr
;
150 for (i
= 0; i
< count
; i
++) {
151 unsigned elt
= fetch_elts
[i
] & ~DRAW_PT_FLAG_MASK
;
153 for (j
= 0; j
< feme
->nr_fetch
; j
++) {
155 const ubyte
*from
= (feme
->fetch
[j
].ptr
+
156 feme
->fetch
[j
].pitch
* elt
);
158 feme
->fetch
[j
].fetch( from
, attrib
);
159 feme
->fetch
[j
].emit( attrib
, &out
);
166 static void fetch_emit_prepare( struct draw_pt_middle_end
*middle
,
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
;
177 ok
= draw
->render
->set_primitive( draw
->render
,
184 /* Must do this after set_primitive() above:
186 vinfo
= draw
->render
->get_vertex_info(draw
->render
);
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
;
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
);
196 feme
->fetch
[i
].pitch
= draw
->vertex_buffer
[src_buffer
].pitch
;
198 feme
->fetch
[i
].fetch
= draw_get_fetch_func(draw
->vertex_element
[src_element
].src_format
);
201 switch (vinfo
->emit
[i
]) {
203 feme
->fetch
[i
].emit
= emit_R32G32B32A32_FLOAT
;
206 feme
->fetch
[i
].emit
= emit_R32G32B32_FLOAT
;
209 feme
->fetch
[i
].emit
= emit_R32G32_FLOAT
;
212 feme
->fetch
[i
].emit
= emit_R32_FLOAT
;
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
;
222 feme
->fetch
[i
].emit
= NULL
;
227 feme
->nr_fetch
= vinfo
->num_attribs
;
228 feme
->hw_vertex_size
= vinfo
->size
* 4;
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
)
241 struct fetch_emit_middle_end
*feme
= (struct fetch_emit_middle_end
*)middle
;
242 struct draw_context
*draw
= feme
->draw
;
245 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
247 draw_do_flush( draw
, DRAW_FLUSH_BACKEND
);
249 hw_verts
= draw
->render
->allocate_vertices( draw
->render
,
250 (ushort
)feme
->hw_vertex_size
,
251 (ushort
)fetch_count
);
258 /* Single routine to fetch vertices and emit HW verts.
260 fetch_store_general( feme
,
265 /* XXX: Draw arrays path to avoid re-emitting index list again and
268 draw
->render
->draw( draw
->render
,
272 /* Done -- that was easy, wasn't it:
274 draw
->render
->release_vertices( draw
->render
,
276 feme
->hw_vertex_size
,
283 static void fetch_emit_finish( struct draw_pt_middle_end
*middle
)
288 static void fetch_emit_destroy( struct draw_pt_middle_end
*middle
)
294 struct draw_pt_middle_end
*draw_pt_fetch_emit( struct draw_context
*draw
)
296 struct fetch_emit_middle_end
*fetch_emit
= CALLOC_STRUCT( fetch_emit_middle_end
);
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
;
303 fetch_emit
->draw
= draw
;
305 return &fetch_emit
->base
;