Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /************************************************************************** |
2 | * |
||
3 | * Copyright 2010 VMware, Inc. |
||
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 VMWARE 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 | #include "draw/draw_private.h" |
||
29 | #include "draw/draw_vs.h" |
||
30 | #include "draw/draw_gs.h" |
||
31 | #include "draw/draw_context.h" |
||
32 | #include "draw/draw_vbuf.h" |
||
33 | #include "draw/draw_vertex.h" |
||
34 | #include "draw/draw_pt.h" |
||
35 | |||
36 | #include "pipe/p_state.h" |
||
37 | |||
38 | #include "util/u_math.h" |
||
39 | #include "util/u_memory.h" |
||
40 | |||
41 | struct pt_so_emit { |
||
42 | struct draw_context *draw; |
||
43 | |||
44 | unsigned input_vertex_stride; |
||
45 | const float (*inputs)[4]; |
||
46 | const float *pre_clip_pos; |
||
47 | boolean has_so; |
||
48 | boolean use_pre_clip_pos; |
||
49 | int pos_idx; |
||
50 | unsigned emitted_primitives; |
||
51 | unsigned emitted_vertices; |
||
52 | unsigned generated_primitives; |
||
53 | }; |
||
54 | |||
55 | static const struct pipe_stream_output_info * |
||
56 | draw_so_info(const struct draw_context *draw) |
||
57 | { |
||
58 | const struct pipe_stream_output_info *state = NULL; |
||
59 | |||
60 | if (draw->gs.geometry_shader) { |
||
61 | state = &draw->gs.geometry_shader->state.stream_output; |
||
62 | } else { |
||
63 | state = &draw->vs.vertex_shader->state.stream_output; |
||
64 | } |
||
65 | |||
66 | return state; |
||
67 | } |
||
68 | |||
69 | static INLINE boolean |
||
70 | draw_has_so(const struct draw_context *draw) |
||
71 | { |
||
72 | const struct pipe_stream_output_info *state = draw_so_info(draw); |
||
73 | |||
74 | if (state && state->num_outputs > 0) |
||
75 | return TRUE; |
||
76 | |||
77 | return FALSE; |
||
78 | } |
||
79 | |||
80 | void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos) |
||
81 | { |
||
82 | struct draw_context *draw = emit->draw; |
||
83 | |||
84 | emit->use_pre_clip_pos = use_pre_clip_pos; |
||
85 | emit->has_so = draw_has_so(draw); |
||
86 | if (use_pre_clip_pos) |
||
87 | emit->pos_idx = draw_current_shader_position_output(draw); |
||
88 | |||
89 | /* if we have a state with outputs make sure we have |
||
90 | * buffers to output to */ |
||
91 | if (emit->has_so) { |
||
92 | boolean has_valid_buffer = FALSE; |
||
93 | unsigned i; |
||
94 | for (i = 0; i < draw->so.num_targets; ++i) { |
||
95 | if (draw->so.targets[i]) { |
||
96 | has_valid_buffer = TRUE; |
||
97 | break; |
||
98 | } |
||
99 | } |
||
100 | emit->has_so = has_valid_buffer; |
||
101 | } |
||
102 | |||
103 | if (!emit->has_so) |
||
104 | return; |
||
105 | |||
106 | /* XXX: need to flush to get prim_vbuf.c to release its allocation?? |
||
107 | */ |
||
108 | draw_do_flush( draw, DRAW_FLUSH_BACKEND ); |
||
109 | } |
||
110 | |||
111 | static void so_emit_prim(struct pt_so_emit *so, |
||
112 | unsigned *indices, |
||
113 | unsigned num_vertices) |
||
114 | { |
||
115 | unsigned slot, i; |
||
116 | unsigned input_vertex_stride = so->input_vertex_stride; |
||
117 | struct draw_context *draw = so->draw; |
||
118 | const float (*input_ptr)[4]; |
||
119 | const float *pcp_ptr = NULL; |
||
120 | const struct pipe_stream_output_info *state = draw_so_info(draw); |
||
121 | float *buffer; |
||
122 | int buffer_total_bytes[PIPE_MAX_SO_BUFFERS]; |
||
123 | boolean buffer_written[PIPE_MAX_SO_BUFFERS] = {0}; |
||
124 | |||
125 | input_ptr = so->inputs; |
||
126 | if (so->use_pre_clip_pos) |
||
127 | pcp_ptr = so->pre_clip_pos; |
||
128 | |||
129 | ++so->generated_primitives; |
||
130 | |||
131 | for (i = 0; i < draw->so.num_targets; i++) { |
||
132 | struct draw_so_target *target = draw->so.targets[i]; |
||
133 | if (target) { |
||
134 | buffer_total_bytes[i] = target->internal_offset; |
||
135 | } else { |
||
136 | buffer_total_bytes[i] = 0; |
||
137 | } |
||
138 | } |
||
139 | |||
140 | /* check have we space to emit prim first - if not don't do anything */ |
||
141 | for (i = 0; i < num_vertices; ++i) { |
||
142 | unsigned ob; |
||
143 | for (slot = 0; slot < state->num_outputs; ++slot) { |
||
144 | unsigned num_comps = state->output[slot].num_components; |
||
145 | int ob = state->output[slot].output_buffer; |
||
146 | unsigned dst_offset = state->output[slot].dst_offset * sizeof(float); |
||
147 | unsigned write_size = num_comps * sizeof(float); |
||
148 | /* If a buffer is missing then that's equivalent to |
||
149 | * an overflow */ |
||
150 | if (!draw->so.targets[ob]) { |
||
151 | return; |
||
152 | } |
||
153 | if ((buffer_total_bytes[ob] + write_size + dst_offset) > |
||
154 | draw->so.targets[ob]->target.buffer_size) { |
||
155 | return; |
||
156 | } |
||
157 | } |
||
158 | for (ob = 0; ob < draw->so.num_targets; ++ob) { |
||
159 | buffer_total_bytes[ob] += state->stride[ob] * sizeof(float); |
||
160 | } |
||
161 | } |
||
162 | |||
163 | for (i = 0; i < num_vertices; ++i) { |
||
164 | const float (*input)[4]; |
||
165 | const float *pre_clip_pos = NULL; |
||
166 | int ob; |
||
167 | |||
168 | input = (const float (*)[4])( |
||
169 | (const char *)input_ptr + (indices[i] * input_vertex_stride)); |
||
170 | |||
171 | if (pcp_ptr) |
||
172 | pre_clip_pos = (const float *)( |
||
173 | (const char *)pcp_ptr + (indices[i] * input_vertex_stride)); |
||
174 | |||
175 | for (slot = 0; slot < state->num_outputs; ++slot) { |
||
176 | unsigned idx = state->output[slot].register_index; |
||
177 | unsigned start_comp = state->output[slot].start_component; |
||
178 | unsigned num_comps = state->output[slot].num_components; |
||
179 | |||
180 | ob = state->output[slot].output_buffer; |
||
181 | buffer_written[ob] = TRUE; |
||
182 | |||
183 | buffer = (float *)((char *)draw->so.targets[ob]->mapping + |
||
184 | draw->so.targets[ob]->target.buffer_offset + |
||
185 | draw->so.targets[ob]->internal_offset) + |
||
186 | state->output[slot].dst_offset; |
||
187 | |||
188 | if (idx == so->pos_idx && pcp_ptr) |
||
189 | memcpy(buffer, &pre_clip_pos[start_comp], |
||
190 | num_comps * sizeof(float)); |
||
191 | else |
||
192 | memcpy(buffer, &input[idx][start_comp], |
||
193 | num_comps * sizeof(float)); |
||
194 | #if 0 |
||
195 | { |
||
196 | int j; |
||
197 | debug_printf("VERT[%d], offset = %d, slot[%d] sc = %d, num_c = %d, idx = %d = [", |
||
198 | i + draw->so.targets[ob]->emitted_vertices, |
||
199 | draw->so.targets[ob]->internal_offset, |
||
200 | slot, start_comp, num_comps, idx); |
||
201 | for (j = 0; j < num_comps; ++j) { |
||
202 | unsigned *ubuffer = (unsigned*)buffer; |
||
203 | debug_printf("%d (0x%x), ", ubuffer[j], ubuffer[j]); |
||
204 | } |
||
205 | debug_printf("]\n"); |
||
206 | } |
||
207 | #endif |
||
208 | } |
||
209 | for (ob = 0; ob < draw->so.num_targets; ++ob) { |
||
210 | struct draw_so_target *target = draw->so.targets[ob]; |
||
211 | if (target && buffer_written[ob]) { |
||
212 | target->internal_offset += state->stride[ob] * sizeof(float); |
||
213 | target->emitted_vertices += 1; |
||
214 | } |
||
215 | } |
||
216 | } |
||
217 | so->emitted_vertices += num_vertices; |
||
218 | ++so->emitted_primitives; |
||
219 | } |
||
220 | |||
221 | static void so_point(struct pt_so_emit *so, int idx) |
||
222 | { |
||
223 | unsigned indices[1]; |
||
224 | |||
225 | indices[0] = idx; |
||
226 | |||
227 | so_emit_prim(so, indices, 1); |
||
228 | } |
||
229 | |||
230 | static void so_line(struct pt_so_emit *so, int i0, int i1) |
||
231 | { |
||
232 | unsigned indices[2]; |
||
233 | |||
234 | indices[0] = i0; |
||
235 | indices[1] = i1; |
||
236 | |||
237 | so_emit_prim(so, indices, 2); |
||
238 | } |
||
239 | |||
240 | static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2) |
||
241 | { |
||
242 | unsigned indices[3]; |
||
243 | |||
244 | indices[0] = i0; |
||
245 | indices[1] = i1; |
||
246 | indices[2] = i2; |
||
247 | |||
248 | so_emit_prim(so, indices, 3); |
||
249 | } |
||
250 | |||
251 | |||
252 | #define FUNC so_run_linear |
||
253 | #define GET_ELT(idx) (start + (idx)) |
||
254 | #include "draw_so_emit_tmp.h" |
||
255 | |||
256 | |||
257 | #define FUNC so_run_elts |
||
258 | #define LOCAL_VARS const ushort *elts = input_prims->elts; |
||
259 | #define GET_ELT(idx) (elts[start + (idx)]) |
||
260 | #include "draw_so_emit_tmp.h" |
||
261 | |||
262 | |||
263 | void draw_pt_so_emit( struct pt_so_emit *emit, |
||
264 | const struct draw_vertex_info *input_verts, |
||
265 | const struct draw_prim_info *input_prims ) |
||
266 | { |
||
267 | struct draw_context *draw = emit->draw; |
||
268 | struct vbuf_render *render = draw->render; |
||
269 | unsigned start, i; |
||
270 | |||
271 | if (!emit->has_so) |
||
272 | return; |
||
273 | |||
274 | if (!draw->so.num_targets) |
||
275 | return; |
||
276 | |||
277 | emit->emitted_vertices = 0; |
||
278 | emit->emitted_primitives = 0; |
||
279 | emit->generated_primitives = 0; |
||
280 | emit->input_vertex_stride = input_verts->stride; |
||
281 | if (emit->use_pre_clip_pos) |
||
282 | emit->pre_clip_pos = input_verts->verts->pre_clip_pos; |
||
283 | |||
284 | emit->inputs = (const float (*)[4])input_verts->verts->data; |
||
285 | |||
286 | /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/ |
||
287 | draw_do_flush( draw, DRAW_FLUSH_BACKEND ); |
||
288 | |||
289 | for (start = i = 0; i < input_prims->primitive_count; |
||
290 | start += input_prims->primitive_lengths[i], i++) |
||
291 | { |
||
292 | unsigned count = input_prims->primitive_lengths[i]; |
||
293 | |||
294 | if (input_prims->linear) { |
||
295 | so_run_linear(emit, input_prims, input_verts, |
||
296 | start, count); |
||
297 | } else { |
||
298 | so_run_elts(emit, input_prims, input_verts, |
||
299 | start, count); |
||
300 | } |
||
301 | } |
||
302 | |||
303 | render->set_stream_output_info(render, |
||
304 | emit->emitted_primitives, |
||
305 | emit->emitted_vertices, |
||
306 | emit->generated_primitives); |
||
307 | } |
||
308 | |||
309 | |||
310 | struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw ) |
||
311 | { |
||
312 | struct pt_so_emit *emit = CALLOC_STRUCT(pt_so_emit); |
||
313 | if (!emit) |
||
314 | return NULL; |
||
315 | |||
316 | emit->draw = draw; |
||
317 | |||
318 | return emit; |
||
319 | } |
||
320 | |||
321 | void draw_pt_so_emit_destroy( struct pt_so_emit *emit ) |
||
322 | { |
||
323 | FREE(emit); |
||
324 | }>>>>>>>>>> |