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);
63 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
65 draw_do_flush( draw
, DRAW_FLUSH_BACKEND
);
69 is_component_writable(unsigned mask
,
73 case TGSI_WRITEMASK_NONE
:
75 case TGSI_WRITEMASK_X
:
77 case TGSI_WRITEMASK_Y
:
79 case TGSI_WRITEMASK_XY
:
80 return compo
== 0 || compo
== 1;
81 case TGSI_WRITEMASK_Z
:
83 case TGSI_WRITEMASK_XZ
:
84 return compo
== 0 || compo
== 2;
85 case TGSI_WRITEMASK_YZ
:
86 return compo
== 1 || compo
== 2;
87 case TGSI_WRITEMASK_XYZ
:
88 return compo
== 0 || compo
== 1 || compo
== 2;
89 case TGSI_WRITEMASK_W
:
91 case TGSI_WRITEMASK_XW
:
92 return compo
== 0 || compo
== 3;
93 case TGSI_WRITEMASK_YW
:
94 return compo
== 1 || compo
== 3;
95 case TGSI_WRITEMASK_XYW
:
96 return compo
== 0 || compo
== 1 || compo
== 3;
97 case TGSI_WRITEMASK_ZW
:
98 return compo
== 2 || compo
== 3;
99 case TGSI_WRITEMASK_XZW
:
100 return compo
== 0 || compo
== 1 || compo
== 3;
101 case TGSI_WRITEMASK_YZW
:
102 return compo
== 1 || compo
== 2 || compo
== 4;
103 case TGSI_WRITEMASK_XYZW
:
104 return compo
>= 0 && compo
< 4;
106 debug_assert(!"Unknown writemask in stream out");
107 return compo
>= 0 && compo
< 4;
111 static void so_emit_prim(struct pt_so_emit
*so
,
113 unsigned num_vertices
)
116 unsigned input_vertex_stride
= so
->input_vertex_stride
;
117 struct draw_context
*draw
= so
->draw
;
118 const float (*input_ptr
)[4];
119 const struct pipe_stream_output_state
*state
=
123 input_ptr
= so
->inputs
;
125 for (i
= 0; i
< num_vertices
; ++i
) {
126 const float (*input
)[4];
127 /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/
128 input
= (const float (*)[4])(
129 (const char *)input_ptr
+ (indices
[i
] * input_vertex_stride
));
130 for (slot
= 0; slot
< state
->num_outputs
; ++slot
) {
131 unsigned idx
= state
->register_index
[slot
];
132 unsigned writemask
= state
->register_mask
[slot
];
134 unsigned written_compos
= 0;
136 buffer
= (float**)&so
->buffers
[state
->output_buffer
[slot
]];
138 /*debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
139 slot, vs_slot, idx);*/
141 assert(!util_is_inf_or_nan(input
[idx
][0]));
142 assert(!util_is_inf_or_nan(input
[idx
][1]));
143 assert(!util_is_inf_or_nan(input
[idx
][2]));
144 assert(!util_is_inf_or_nan(input
[idx
][3]));
146 for (compo
= 0; compo
< 4; ++compo
) {
147 if (is_component_writable(writemask
, compo
)) {
148 float *buf
= *buffer
;
149 buf
[written_compos
++] = input
[idx
][compo
];
153 debug_printf("\t\t(writemask = %d)%f %f %f %f\n",
160 if (!so
->single_buffer
)
161 *buffer
+= written_compos
;
163 if (so
->single_buffer
)
164 *buffer
= (float*) (((char*)*buffer
) + state
->stride
);
166 so
->emitted_vertices
+= num_vertices
;
167 ++so
->emitted_primitives
;
170 static void so_point(struct pt_so_emit
*so
, int idx
)
176 so_emit_prim(so
, indices
, 1);
179 static void so_line(struct pt_so_emit
*so
, int i0
, int i1
)
186 so_emit_prim(so
, indices
, 2);
189 static void so_tri(struct pt_so_emit
*so
, int i0
, int i1
, int i2
)
197 so_emit_prim(so
, indices
, 3);
201 #define TRIANGLE(gs,i0,i1,i2) so_tri(so,i0,i1,i2)
202 #define LINE(gs,i0,i1) so_line(so,i0,i1)
203 #define POINT(gs,i0) so_point(so,i0)
204 #define FUNC so_run_linear
206 #include "draw_so_emit_tmp.h"
211 #define TRIANGLE(gs,i0,i1,i2) so_tri(gs,elts[i0],elts[i1],elts[i2])
212 #define LINE(gs,i0,i1) so_line(gs,elts[i0],elts[i1])
213 #define POINT(gs,i0) so_point(gs,elts[i0])
214 #define FUNC so_run_elts
216 const ushort *elts = input_prims->elts;
217 #include "draw_so_emit_tmp.h"
222 void draw_pt_so_emit( struct pt_so_emit
*emit
,
223 const struct draw_vertex_info
*input_verts
,
224 const struct draw_prim_info
*input_prims
)
226 struct draw_context
*draw
= emit
->draw
;
227 struct vbuf_render
*render
= draw
->render
;
233 emit
->emitted_vertices
= 0;
234 emit
->emitted_primitives
= 0;
235 emit
->input_vertex_stride
= input_verts
->stride
;
236 emit
->inputs
= (const float (*)[4])input_verts
->verts
->data
;
237 for (i
= 0; i
< draw
->so
.num_buffers
; ++i
)
238 emit
->buffers
[i
] = draw
->so
.buffers
[i
];
239 emit
->single_buffer
= TRUE
;
240 for (i
= 0; i
< draw
->so
.state
.num_outputs
; ++i
) {
241 if (draw
->so
.state
.output_buffer
[i
] != 0)
242 emit
->single_buffer
= FALSE
;
245 /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
246 draw_do_flush( draw
, DRAW_FLUSH_BACKEND
);
248 for (start
= i
= 0; i
< input_prims
->primitive_count
;
249 start
+= input_prims
->primitive_lengths
[i
], i
++)
251 unsigned count
= input_prims
->primitive_lengths
[i
];
253 if (input_prims
->linear
) {
254 so_run_linear(emit
, input_prims
, input_verts
,
257 so_run_elts(emit
, input_prims
, input_verts
,
262 render
->set_stream_output_info(render
,
263 emit
->emitted_primitives
,
264 emit
->emitted_vertices
);
268 struct pt_so_emit
*draw_pt_so_emit_create( struct draw_context
*draw
)
270 struct pt_so_emit
*emit
= CALLOC_STRUCT(pt_so_emit
);
279 void draw_pt_so_emit_destroy( struct pt_so_emit
*emit
)