draw_pt_so_emit.c revision f1fc444bb05421404f42e8d08e9085c6fb6ce7a9
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 we have a state with outputs make sure we have 61 * buffers to output to */ 62 if (emit->has_so) { 63 boolean has_valid_buffer = FALSE; 64 unsigned i; 65 for (i = 0; i < draw->so.num_buffers; ++i) { 66 if (draw->so.buffers[i]) { 67 has_valid_buffer = TRUE; 68 break; 69 } 70 } 71 emit->has_so = has_valid_buffer; 72 } 73 74 if (!emit->has_so) 75 return; 76 77 /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 78 */ 79 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 80} 81 82static boolean 83is_component_writable(unsigned mask, 84 unsigned compo) 85{ 86 switch (mask) { 87 case TGSI_WRITEMASK_NONE: 88 return FALSE; 89 case TGSI_WRITEMASK_X: 90 return compo == 0; 91 case TGSI_WRITEMASK_Y: 92 return compo == 1; 93 case TGSI_WRITEMASK_XY: 94 return compo == 0 || compo == 1; 95 case TGSI_WRITEMASK_Z: 96 return compo == 2; 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: 104 return compo == 3; 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: 118 return compo < 4; 119 default: 120 debug_assert(!"Unknown writemask in stream out"); 121 return compo < 4; 122 } 123} 124 125static void so_emit_prim(struct pt_so_emit *so, 126 unsigned *indices, 127 unsigned num_vertices) 128{ 129 unsigned slot, i; 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_state *state = 134 &draw->so.state; 135 float **buffer = 0; 136 137 input_ptr = so->inputs; 138 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->register_index[slot]; 147 unsigned writemask = state->register_mask[slot]; 148 unsigned written_compos = 0; 149 unsigned compo; 150 151 buffer = (float**)&so->buffers[state->output_buffer[slot]]; 152 153 /*debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n", 154 slot, vs_slot, idx);*/ 155#if 1 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])); 160#endif 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]; 165 } 166 } 167#if 0 168 debug_printf("\t\t(writemask = %d)%f %f %f %f\n", 169 writemask, 170 input[idx][0], 171 input[idx][1], 172 input[idx][2], 173 input[idx][3]); 174#endif 175 *buffer += written_compos; 176 total_written_compos += written_compos; 177 } 178 if (so->single_buffer) { 179 int stride = (int)state->stride - 180 sizeof(float) * total_written_compos; 181 182 debug_assert(stride >= 0); 183 *buffer = (float*) (((char*)*buffer) + stride); 184 } 185 } 186 so->emitted_vertices += num_vertices; 187 ++so->emitted_primitives; 188} 189 190static void so_point(struct pt_so_emit *so, int idx) 191{ 192 unsigned indices[1]; 193 194 indices[0] = idx; 195 196 so_emit_prim(so, indices, 1); 197} 198 199static void so_line(struct pt_so_emit *so, int i0, int i1) 200{ 201 unsigned indices[2]; 202 203 indices[0] = i0; 204 indices[1] = i1; 205 206 so_emit_prim(so, indices, 2); 207} 208 209static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2) 210{ 211 unsigned indices[3]; 212 213 indices[0] = i0; 214 indices[1] = i1; 215 indices[2] = i2; 216 217 so_emit_prim(so, indices, 3); 218} 219 220 221#define FUNC so_run_linear 222#define GET_ELT(idx) (start + (idx)) 223#include "draw_so_emit_tmp.h" 224 225 226#define FUNC so_run_elts 227#define LOCAL_VARS const ushort *elts = input_prims->elts; 228#define GET_ELT(idx) (elts[start + (idx)] & ~DRAW_PIPE_FLAG_MASK) 229#include "draw_so_emit_tmp.h" 230 231 232void 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 ) 235{ 236 struct draw_context *draw = emit->draw; 237 struct vbuf_render *render = draw->render; 238 unsigned start, i; 239 240 if (!emit->has_so) 241 return; 242 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]; 249 } 250 emit->single_buffer = TRUE; 251 for (i = 0; i < draw->so.state.num_outputs; ++i) { 252 if (draw->so.state.output_buffer[i] != 0) 253 emit->single_buffer = FALSE; 254 } 255 256 /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/ 257 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 258 259 for (start = i = 0; i < input_prims->primitive_count; 260 start += input_prims->primitive_lengths[i], i++) 261 { 262 unsigned count = input_prims->primitive_lengths[i]; 263 264 if (input_prims->linear) { 265 so_run_linear(emit, input_prims, input_verts, 266 start, count); 267 } else { 268 so_run_elts(emit, input_prims, input_verts, 269 start, count); 270 } 271 } 272 273 render->set_stream_output_info(render, 274 emit->emitted_primitives, 275 emit->emitted_vertices); 276} 277 278 279struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw ) 280{ 281 struct pt_so_emit *emit = CALLOC_STRUCT(pt_so_emit); 282 if (!emit) 283 return NULL; 284 285 emit->draw = draw; 286 287 return emit; 288} 289 290void draw_pt_so_emit_destroy( struct pt_so_emit *emit ) 291{ 292 FREE(emit); 293} 294