466f46abab38b97fcb41e47288e95ad3bb42f2da
1 /**************************************************************************
3 * Copyright 2010 VMware, Inc.
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 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.
26 **************************************************************************/
28 #include "draw/draw_private.h"
29 #include "draw/draw_vs.h"
30 #include "draw/draw_context.h"
31 #include "draw/draw_vbuf.h"
32 #include "draw/draw_vertex.h"
33 #include "draw/draw_pt.h"
35 #include "pipe/p_state.h"
37 #include "util/u_math.h"
38 #include "util/u_memory.h"
41 struct draw_context
*draw
;
43 unsigned input_vertex_stride
;
44 const float (*inputs
)[4];
48 unsigned emitted_primitives
;
49 unsigned emitted_vertices
;
50 unsigned generated_primitives
;
54 void draw_pt_so_emit_prepare(struct pt_so_emit
*emit
)
56 struct draw_context
*draw
= emit
->draw
;
58 emit
->has_so
= (draw
->vs
.vertex_shader
->state
.stream_output
.num_outputs
> 0);
60 /* if we have a state with outputs make sure we have
61 * buffers to output to */
63 boolean has_valid_buffer
= FALSE
;
65 for (i
= 0; i
< draw
->so
.num_targets
; ++i
) {
66 if (draw
->so
.targets
[i
]) {
67 has_valid_buffer
= TRUE
;
71 emit
->has_so
= has_valid_buffer
;
77 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
79 draw_do_flush( draw
, DRAW_FLUSH_BACKEND
);
83 is_component_writable(unsigned mask
,
87 case TGSI_WRITEMASK_NONE
:
89 case TGSI_WRITEMASK_X
:
91 case TGSI_WRITEMASK_Y
:
93 case TGSI_WRITEMASK_XY
:
94 return compo
== 0 || compo
== 1;
95 case TGSI_WRITEMASK_Z
:
97 case TGSI_WRITEMASK_XZ
:
98 return compo
== 0 || compo
== 2;
99 case TGSI_WRITEMASK_YZ
:
100 return compo
== 1 || compo
== 2;
101 case TGSI_WRITEMASK_XYZ
:
102 return compo
== 0 || compo
== 1 || compo
== 2;
103 case TGSI_WRITEMASK_W
:
105 case TGSI_WRITEMASK_XW
:
106 return compo
== 0 || compo
== 3;
107 case TGSI_WRITEMASK_YW
:
108 return compo
== 1 || compo
== 3;
109 case TGSI_WRITEMASK_XYW
:
110 return compo
== 0 || compo
== 1 || compo
== 3;
111 case TGSI_WRITEMASK_ZW
:
112 return compo
== 2 || compo
== 3;
113 case TGSI_WRITEMASK_XZW
:
114 return compo
== 0 || compo
== 1 || compo
== 3;
115 case TGSI_WRITEMASK_YZW
:
116 return compo
== 1 || compo
== 2 || compo
== 4;
117 case TGSI_WRITEMASK_XYZW
:
120 debug_assert(!"Unknown writemask in stream out");
125 static INLINE
int mask_num_comps(int register_mask
)
128 switch (register_mask
) {
129 case TGSI_WRITEMASK_XYZW
:
132 case TGSI_WRITEMASK_XYZ
:
135 case TGSI_WRITEMASK_XY
:
138 case TGSI_WRITEMASK_X
:
148 static void so_emit_prim(struct pt_so_emit
*so
,
150 unsigned num_vertices
)
153 unsigned input_vertex_stride
= so
->input_vertex_stride
;
154 struct draw_context
*draw
= so
->draw
;
155 const float (*input_ptr
)[4];
156 const struct pipe_stream_output_info
*state
=
157 &draw
->vs
.vertex_shader
->state
.stream_output
;
159 int buffer_total_bytes
[PIPE_MAX_SO_BUFFERS
];
161 input_ptr
= so
->inputs
;
163 ++so
->generated_primitives
;
165 for (i
= 0; i
< draw
->so
.num_targets
; i
++) {
166 struct draw_so_target
*target
= draw
->so
.targets
[i
];
167 buffer_total_bytes
[i
] = target
->internal_offset
;
170 /* check have we space to emit prim first - if not don't do anything */
171 for (i
= 0; i
< num_vertices
; ++i
) {
172 for (slot
= 0; slot
< state
->num_outputs
; ++slot
) {
173 unsigned writemask
= state
->output
[slot
].register_mask
;
174 int ob
= state
->output
[slot
].output_buffer
;
176 if ((buffer_total_bytes
[ob
] + mask_num_comps(writemask
) * sizeof(float)) >
177 draw
->so
.targets
[ob
]->target
.buffer_size
) {
180 buffer_total_bytes
[ob
] += mask_num_comps(writemask
) * sizeof(float);
184 for (i
= 0; i
< num_vertices
; ++i
) {
185 const float (*input
)[4];
186 unsigned total_written_compos
= 0;
187 /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/
188 input
= (const float (*)[4])(
189 (const char *)input_ptr
+ (indices
[i
] * input_vertex_stride
));
191 for (slot
= 0; slot
< state
->num_outputs
; ++slot
) {
192 unsigned idx
= state
->output
[slot
].register_index
;
193 unsigned writemask
= state
->output
[slot
].register_mask
;
194 unsigned written_compos
= 0;
196 int ob
= state
->output
[slot
].output_buffer
;
198 buffer
= (float *)((char *)draw
->so
.targets
[ob
]->mapping
+
199 draw
->so
.targets
[ob
]->target
.buffer_offset
+
200 draw
->so
.targets
[ob
]->internal_offset
);
201 for (compo
= 0; compo
< 4; ++compo
) {
202 if (is_component_writable(writemask
, compo
)) {
203 buffer
[written_compos
++] = input
[idx
][compo
];
206 draw
->so
.targets
[ob
]->internal_offset
+= written_compos
* sizeof(float);
207 total_written_compos
+= written_compos
;
210 so
->emitted_vertices
+= num_vertices
;
211 ++so
->emitted_primitives
;
214 static void so_point(struct pt_so_emit
*so
, int idx
)
220 so_emit_prim(so
, indices
, 1);
223 static void so_line(struct pt_so_emit
*so
, int i0
, int i1
)
230 so_emit_prim(so
, indices
, 2);
233 static void so_tri(struct pt_so_emit
*so
, int i0
, int i1
, int i2
)
241 so_emit_prim(so
, indices
, 3);
245 #define FUNC so_run_linear
246 #define GET_ELT(idx) (start + (idx))
247 #include "draw_so_emit_tmp.h"
250 #define FUNC so_run_elts
251 #define LOCAL_VARS const ushort *elts = input_prims->elts;
252 #define GET_ELT(idx) (elts[start + (idx)])
253 #include "draw_so_emit_tmp.h"
256 void draw_pt_so_emit( struct pt_so_emit
*emit
,
257 const struct draw_vertex_info
*input_verts
,
258 const struct draw_prim_info
*input_prims
)
260 struct draw_context
*draw
= emit
->draw
;
261 struct vbuf_render
*render
= draw
->render
;
267 emit
->emitted_vertices
= 0;
268 emit
->emitted_primitives
= 0;
269 emit
->generated_primitives
= 0;
270 emit
->input_vertex_stride
= input_verts
->stride
;
271 emit
->inputs
= (const float (*)[4])input_verts
->verts
->data
;
273 /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
274 draw_do_flush( draw
, DRAW_FLUSH_BACKEND
);
276 for (start
= i
= 0; i
< input_prims
->primitive_count
;
277 start
+= input_prims
->primitive_lengths
[i
], i
++)
279 unsigned count
= input_prims
->primitive_lengths
[i
];
281 if (input_prims
->linear
) {
282 so_run_linear(emit
, input_prims
, input_verts
,
285 so_run_elts(emit
, input_prims
, input_verts
,
290 render
->set_stream_output_info(render
,
291 emit
->emitted_primitives
,
292 emit
->emitted_vertices
,
293 emit
->generated_primitives
);
297 struct pt_so_emit
*draw_pt_so_emit_create( struct draw_context
*draw
)
299 struct pt_so_emit
*emit
= CALLOC_STRUCT(pt_so_emit
);
308 void draw_pt_so_emit_destroy( struct pt_so_emit
*emit
)