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_context.h"
29 #include "draw/draw_private.h"
30 #include "draw/draw_vbuf.h"
31 #include "draw/draw_vertex.h"
32 #include "draw/draw_pt.h"
34 #include "util/u_math.h"
35 #include "util/u_memory.h"
38 struct draw_context
*draw
;
40 void *buffers
[PIPE_MAX_SO_BUFFERS
];
42 unsigned input_vertex_stride
;
43 const float (*inputs
)[4];
47 boolean single_buffer
;
49 unsigned emitted_primitives
;
50 unsigned emitted_vertices
;
54 void draw_pt_so_emit_prepare(struct pt_so_emit
*emit
)
56 struct draw_context
*draw
= emit
->draw
;
58 emit
->has_so
= (draw
->so
.state
.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_buffers
; ++i
) {
66 if (draw
->so
.buffers
[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 void so_emit_prim(struct pt_so_emit
*so
,
127 unsigned num_vertices
)
130 unsigned input_vertex_stride
= so
->input_vertex_stride
;
131 struct draw_context
*draw
= so
->draw
;
132 const float (*input_ptr
)[4];
133 const struct pipe_stream_output_info
*state
=
137 input_ptr
= so
->inputs
;
139 for (i
= 0; i
< num_vertices
; ++i
) {
140 const float (*input
)[4];
141 unsigned total_written_compos
= 0;
142 /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/
143 input
= (const float (*)[4])(
144 (const char *)input_ptr
+ (indices
[i
] * input_vertex_stride
));
145 for (slot
= 0; slot
< state
->num_outputs
; ++slot
) {
146 unsigned idx
= state
->output
[slot
].register_index
;
147 unsigned writemask
= state
->output
[slot
].register_mask
;
148 unsigned written_compos
= 0;
151 buffer
= (float**)&so
->buffers
[state
->output
[slot
].output_buffer
];
153 /*debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
154 slot, vs_slot, idx);*/
156 assert(!util_is_inf_or_nan(input
[idx
][0]));
157 assert(!util_is_inf_or_nan(input
[idx
][1]));
158 assert(!util_is_inf_or_nan(input
[idx
][2]));
159 assert(!util_is_inf_or_nan(input
[idx
][3]));
161 for (compo
= 0; compo
< 4; ++compo
) {
162 if (is_component_writable(writemask
, compo
)) {
163 float *buf
= *buffer
;
164 buf
[written_compos
++] = input
[idx
][compo
];
168 debug_printf("\t\t(writemask = %d)%f %f %f %f\n",
175 *buffer
+= written_compos
;
176 total_written_compos
+= written_compos
;
178 if (so
->single_buffer
) {
179 int stride
= (int)state
->stride
-
180 sizeof(float) * total_written_compos
;
182 debug_assert(stride
>= 0);
183 *buffer
= (float*) (((char*)*buffer
) + stride
);
186 so
->emitted_vertices
+= num_vertices
;
187 ++so
->emitted_primitives
;
190 static void so_point(struct pt_so_emit
*so
, int idx
)
196 so_emit_prim(so
, indices
, 1);
199 static void so_line(struct pt_so_emit
*so
, int i0
, int i1
)
206 so_emit_prim(so
, indices
, 2);
209 static void so_tri(struct pt_so_emit
*so
, int i0
, int i1
, int i2
)
217 so_emit_prim(so
, indices
, 3);
221 #define FUNC so_run_linear
222 #define GET_ELT(idx) (start + (idx))
223 #include "draw_so_emit_tmp.h"
226 #define FUNC so_run_elts
227 #define LOCAL_VARS const ushort *elts = input_prims->elts;
228 #define GET_ELT(idx) (elts[start + (idx)])
229 #include "draw_so_emit_tmp.h"
232 void draw_pt_so_emit( struct pt_so_emit
*emit
,
233 const struct draw_vertex_info
*input_verts
,
234 const struct draw_prim_info
*input_prims
)
236 struct draw_context
*draw
= emit
->draw
;
237 struct vbuf_render
*render
= draw
->render
;
243 emit
->emitted_vertices
= 0;
244 emit
->emitted_primitives
= 0;
245 emit
->input_vertex_stride
= input_verts
->stride
;
246 emit
->inputs
= (const float (*)[4])input_verts
->verts
->data
;
247 for (i
= 0; i
< draw
->so
.num_buffers
; ++i
) {
248 emit
->buffers
[i
] = draw
->so
.buffers
[i
];
250 emit
->single_buffer
= TRUE
;
251 for (i
= 0; i
< draw
->so
.state
.num_outputs
; ++i
) {
252 if (draw
->so
.state
.output
[i
].output_buffer
!= 0)
253 emit
->single_buffer
= FALSE
;
256 /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
257 draw_do_flush( draw
, DRAW_FLUSH_BACKEND
);
259 for (start
= i
= 0; i
< input_prims
->primitive_count
;
260 start
+= input_prims
->primitive_lengths
[i
], i
++)
262 unsigned count
= input_prims
->primitive_lengths
[i
];
264 if (input_prims
->linear
) {
265 so_run_linear(emit
, input_prims
, input_verts
,
268 so_run_elts(emit
, input_prims
, input_verts
,
273 render
->set_stream_output_info(render
,
274 emit
->emitted_primitives
,
275 emit
->emitted_vertices
);
279 struct pt_so_emit
*draw_pt_so_emit_create( struct draw_context
*draw
)
281 struct pt_so_emit
*emit
= CALLOC_STRUCT(pt_so_emit
);
290 void draw_pt_so_emit_destroy( struct pt_so_emit
*emit
)