draw_pt_so_emit.c revision 638a80bc075a4b58123cb9ba03993bd8bfd024cd
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_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" 33 34#include "util/u_math.h" 35#include "util/u_memory.h" 36 37struct pt_so_emit { 38 struct draw_context *draw; 39 40 void *buffers[PIPE_MAX_SO_BUFFERS]; 41 42 unsigned input_vertex_stride; 43 const float (*inputs)[4]; 44 45 boolean has_so; 46 47 boolean single_buffer; 48 49 unsigned emitted_primitives; 50 unsigned emitted_vertices; 51}; 52 53 54void draw_pt_so_emit_prepare(struct pt_so_emit *emit) 55{ 56 struct draw_context *draw = emit->draw; 57 58 emit->has_so = (draw->so.state.num_outputs > 0); 59 60 if (!emit->has_so) 61 return; 62 63 /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 64 */ 65 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 66} 67 68static boolean 69is_component_writable(unsigned mask, 70 unsigned compo) 71{ 72 switch (mask) { 73 case TGSI_WRITEMASK_NONE: 74 return FALSE; 75 case TGSI_WRITEMASK_X: 76 return compo == 0; 77 case TGSI_WRITEMASK_Y: 78 return compo == 1; 79 case TGSI_WRITEMASK_XY: 80 return compo == 0 || compo == 1; 81 case TGSI_WRITEMASK_Z: 82 return compo == 2; 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: 90 return compo == 3; 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; 105 default: 106 debug_assert(!"Unknown writemask in stream out"); 107 return compo >= 0 && compo < 4; 108 } 109} 110 111static 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 struct pipe_stream_output_state *state = 120 &draw->so.state; 121 float **buffer = 0; 122 123 input_ptr = so->inputs; 124 125 for (i = 0; i < num_vertices; ++i) { 126 const float (*input)[4]; 127 unsigned total_written_compos = 0; 128 /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/ 129 input = (const float (*)[4])( 130 (const char *)input_ptr + (indices[i] * input_vertex_stride)); 131 for (slot = 0; slot < state->num_outputs; ++slot) { 132 unsigned idx = state->register_index[slot]; 133 unsigned writemask = state->register_mask[slot]; 134 unsigned written_compos = 0; 135 unsigned compo; 136 137 buffer = (float**)&so->buffers[state->output_buffer[slot]]; 138 139 /*debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n", 140 slot, vs_slot, idx);*/ 141#if 1 142 assert(!util_is_inf_or_nan(input[idx][0])); 143 assert(!util_is_inf_or_nan(input[idx][1])); 144 assert(!util_is_inf_or_nan(input[idx][2])); 145 assert(!util_is_inf_or_nan(input[idx][3])); 146#endif 147 for (compo = 0; compo < 4; ++compo) { 148 if (is_component_writable(writemask, compo)) { 149 float *buf = *buffer; 150 buf[written_compos++] = input[idx][compo]; 151 } 152 } 153#if 0 154 debug_printf("\t\t(writemask = %d)%f %f %f %f\n", 155 writemask, 156 input[idx][0], 157 input[idx][1], 158 input[idx][2], 159 input[idx][3]); 160#endif 161 *buffer += written_compos; 162 total_written_compos += written_compos; 163 } 164 if (so->single_buffer) { 165 unsigned stride = state->stride - 166 sizeof(float) * total_written_compos; 167 168 debug_assert(stride >= 0); 169 *buffer = (float*) (((char*)*buffer) + stride); 170 } 171 } 172 so->emitted_vertices += num_vertices; 173 ++so->emitted_primitives; 174} 175 176static void so_point(struct pt_so_emit *so, int idx) 177{ 178 unsigned indices[1]; 179 180 indices[0] = idx; 181 182 so_emit_prim(so, indices, 1); 183} 184 185static void so_line(struct pt_so_emit *so, int i0, int i1) 186{ 187 unsigned indices[2]; 188 189 indices[0] = i0; 190 indices[1] = i1; 191 192 so_emit_prim(so, indices, 2); 193} 194 195static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2) 196{ 197 unsigned indices[3]; 198 199 indices[0] = i0; 200 indices[1] = i1; 201 indices[2] = i2; 202 203 so_emit_prim(so, indices, 3); 204} 205 206 207#define TRIANGLE(gs,i0,i1,i2) so_tri(so,i0,i1,i2) 208#define LINE(gs,i0,i1) so_line(so,i0,i1) 209#define POINT(gs,i0) so_point(so,i0) 210#define FUNC so_run_linear 211#define LOCAL_VARS 212#include "draw_so_emit_tmp.h" 213#undef LOCAL_VARS 214#undef FUNC 215 216 217#define TRIANGLE(gs,i0,i1,i2) so_tri(gs,elts[i0],elts[i1],elts[i2]) 218#define LINE(gs,i0,i1) so_line(gs,elts[i0],elts[i1]) 219#define POINT(gs,i0) so_point(gs,elts[i0]) 220#define FUNC so_run_elts 221#define LOCAL_VARS \ 222 const ushort *elts = input_prims->elts; 223#include "draw_so_emit_tmp.h" 224#undef LOCAL_VARS 225#undef FUNC 226 227 228void draw_pt_so_emit( struct pt_so_emit *emit, 229 const struct draw_vertex_info *input_verts, 230 const struct draw_prim_info *input_prims ) 231{ 232 struct draw_context *draw = emit->draw; 233 struct vbuf_render *render = draw->render; 234 unsigned start, i; 235 236 if (!emit->has_so) 237 return; 238 239 emit->emitted_vertices = 0; 240 emit->emitted_primitives = 0; 241 emit->input_vertex_stride = input_verts->stride; 242 emit->inputs = (const float (*)[4])input_verts->verts->data; 243 for (i = 0; i < draw->so.num_buffers; ++i) 244 emit->buffers[i] = draw->so.buffers[i]; 245 emit->single_buffer = TRUE; 246 for (i = 0; i < draw->so.state.num_outputs; ++i) { 247 if (draw->so.state.output_buffer[i] != 0) 248 emit->single_buffer = FALSE; 249 } 250 251 /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/ 252 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 253 254 for (start = i = 0; i < input_prims->primitive_count; 255 start += input_prims->primitive_lengths[i], i++) 256 { 257 unsigned count = input_prims->primitive_lengths[i]; 258 259 if (input_prims->linear) { 260 so_run_linear(emit, input_prims, input_verts, 261 start, count); 262 } else { 263 so_run_elts(emit, input_prims, input_verts, 264 start, count); 265 } 266 } 267 268 render->set_stream_output_info(render, 269 emit->emitted_primitives, 270 emit->emitted_vertices); 271} 272 273 274struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw ) 275{ 276 struct pt_so_emit *emit = CALLOC_STRUCT(pt_so_emit); 277 if (!emit) 278 return NULL; 279 280 emit->draw = draw; 281 282 return emit; 283} 284 285void draw_pt_so_emit_destroy( struct pt_so_emit *emit ) 286{ 287 FREE(emit); 288} 289