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
;
88 static void fetch_B8G8R8A8_UNORM( const void *from
,
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]);
98 static void fetch_R32G32B32A32_FLOAT( const void *from
,
101 float *f
= (float *) from
;
108 static void fetch_R32G32B32_FLOAT( const void *from
,
111 float *f
= (float *) from
;
118 static void fetch_R32G32_FLOAT( const void *from
,
121 float *f
= (float *) from
;
128 static void fetch_R32_FLOAT( const void *from
,
131 float *f
= (float *) from
;
139 static void emit_R32_FLOAT( const float *attrib
,
142 (*out
)[0] = attrib
[0];
146 static void emit_R32G32_FLOAT( const float *attrib
,
149 (*out
)[0] = attrib
[0];
150 (*out
)[1] = attrib
[1];
154 static void emit_R32G32B32_FLOAT( const float *attrib
,
157 (*out
)[0] = attrib
[0];
158 (*out
)[1] = attrib
[1];
159 (*out
)[2] = attrib
[2];
163 static void emit_R32G32B32A32_FLOAT( const float *attrib
,
166 (*out
)[0] = attrib
[0];
167 (*out
)[1] = attrib
[1];
168 (*out
)[2] = attrib
[2];
169 (*out
)[3] = attrib
[3];
175 * General-purpose fetch from user's vertex arrays, emit to driver's
178 * XXX this is totally temporary.
181 fetch_store_general( struct fetch_emit_middle_end
*feme
,
183 const unsigned *fetch_elts
,
186 float *out
= (float *)out_ptr
;
187 struct vbuf_render
*render
= feme
->draw
->render
;
190 for (i
= 0; i
< count
; i
++) {
191 unsigned elt
= fetch_elts
[i
];
193 for (j
= 0; j
< feme
->nr_fetch
; j
++) {
195 const ubyte
*from
= (feme
->fetch
[j
].ptr
+
196 feme
->fetch
[j
].pitch
* elt
);
198 feme
->fetch
[j
].fetch( from
, attrib
);
199 feme
->fetch
[j
].emit( attrib
, &out
);
206 static void fetch_emit_prepare( struct draw_pt_middle_end
*middle
)
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
;
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
;
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
);
223 feme
->fetch
[i
].pitch
= draw
->vertex_buffer
[src_buffer
].pitch
;
225 switch (draw
->vertex_element
[src_element
].src_format
) {
226 case PIPE_FORMAT_B8G8R8A8_UNORM
:
227 feme
->fetch
[i
].fetch
= fetch_B8G8R8A8_UNORM
;
229 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
230 feme
->fetch
[i
].fetch
= fetch_R32G32B32A32_FLOAT
;
232 case PIPE_FORMAT_R32G32B32_FLOAT
:
233 feme
->fetch
[i
].fetch
= fetch_R32G32B32_FLOAT
;
235 case PIPE_FORMAT_R32G32_FLOAT
:
236 feme
->fetch
[i
].fetch
= fetch_R32G32_FLOAT
;
238 case PIPE_FORMAT_R32_FLOAT
:
239 feme
->fetch
[i
].fetch
= fetch_R32_FLOAT
;
243 feme
->fetch
[i
].fetch
= NULL
;
247 switch (vinfo
->emit
[i
]) {
249 feme
->fetch
[i
].emit
= emit_R32G32B32A32_FLOAT
;
252 feme
->fetch
[i
].emit
= emit_R32G32B32_FLOAT
;
255 feme
->fetch
[i
].emit
= emit_R32G32_FLOAT
;
258 feme
->fetch
[i
].emit
= emit_R32_FLOAT
;
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
;
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
;
273 feme
->fetch
[i
].emit
= NULL
;
278 feme
->nr_fetch
= nr_attrs
;
279 feme
->hw_vertex_size
= vinfo
->size
* 4;
286 static void fetch_emit_run( struct draw_pt_middle_end
*middle
,
288 const unsigned *fetch_elts
,
289 unsigned fetch_count
,
290 const ushort
*draw_elts
,
291 unsigned draw_count
)
293 struct fetch_emit_middle_end
*feme
= (struct fetch_emit_middle_end
*)middle
;
294 struct draw_context
*draw
= feme
->draw
;
298 ok
= draw
->render
->set_primitive( draw
->render
,
306 hw_verts
= draw
->render
->allocate_vertices( draw
->render
,
307 (ushort
)feme
->hw_vertex_size
,
308 (ushort
)fetch_count
);
315 /* Single routine to fetch vertices and emit HW verts.
317 fetch_store_general( feme
,
322 /* XXX: Draw arrays path to avoid re-emitting index list again and
325 draw
->render
->draw( draw
->render
,
329 /* Done -- that was easy, wasn't it:
331 draw
->render
->release_vertices( draw
->render
,
333 feme
->hw_vertex_size
,
340 static void fetch_emit_finish( struct draw_pt_middle_end
*middle
)
345 static void fetch_emit_destroy( struct draw_pt_middle_end
*middle
)
351 struct draw_pt_middle_end
*draw_pt_fetch_emit( struct draw_context
*draw
)
353 struct fetch_emit_middle_end
*fetch_emit
= CALLOC_STRUCT( fetch_emit_middle_end
);
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
;
360 fetch_emit
->draw
= draw
;
362 return &fetch_emit
->base
;