draw_pt_so_emit.c revision 91862051f98e646647906bb15aec5c5d537f87e4
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 TRIANGLE(gs,i0,i1,i2) so_tri(so,i0,i1,i2) 222#define LINE(gs,i0,i1) so_line(so,i0,i1) 223#define POINT(gs,i0) so_point(so,i0) 224#define FUNC so_run_linear 225#define LOCAL_VARS 226#include "draw_so_emit_tmp.h" 227#undef LOCAL_VARS 228#undef FUNC 229 230 231#define TRIANGLE(gs,i0,i1,i2) so_tri(gs,elts[i0],elts[i1],elts[i2]) 232#define LINE(gs,i0,i1) so_line(gs,elts[i0],elts[i1]) 233#define POINT(gs,i0) so_point(gs,elts[i0]) 234#define FUNC so_run_elts 235#define LOCAL_VARS \ 236 const ushort *elts = input_prims->elts; 237#include "draw_so_emit_tmp.h" 238#undef LOCAL_VARS 239#undef FUNC 240 241 242void draw_pt_so_emit( struct pt_so_emit *emit, 243 const struct draw_vertex_info *input_verts, 244 const struct draw_prim_info *input_prims ) 245{ 246 struct draw_context *draw = emit->draw; 247 struct vbuf_render *render = draw->render; 248 unsigned start, i; 249 250 if (!emit->has_so) 251 return; 252 253 emit->emitted_vertices = 0; 254 emit->emitted_primitives = 0; 255 emit->input_vertex_stride = input_verts->stride; 256 emit->inputs = (const float (*)[4])input_verts->verts->data; 257 for (i = 0; i < draw->so.num_buffers; ++i) { 258 emit->buffers[i] = draw->so.buffers[i]; 259 } 260 emit->single_buffer = TRUE; 261 for (i = 0; i < draw->so.state.num_outputs; ++i) { 262 if (draw->so.state.output_buffer[i] != 0) 263 emit->single_buffer = FALSE; 264 } 265 266 /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/ 267 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 268 269 for (start = i = 0; i < input_prims->primitive_count; 270 start += input_prims->primitive_lengths[i], i++) 271 { 272 unsigned count = input_prims->primitive_lengths[i]; 273 274 if (input_prims->linear) { 275 so_run_linear(emit, input_prims, input_verts, 276 start, count); 277 } else { 278 so_run_elts(emit, input_prims, input_verts, 279 start, count); 280 } 281 } 282 283 render->set_stream_output_info(render, 284 emit->emitted_primitives, 285 emit->emitted_vertices); 286} 287 288 289struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw ) 290{ 291 struct pt_so_emit *emit = CALLOC_STRUCT(pt_so_emit); 292 if (!emit) 293 return NULL; 294 295 emit->draw = draw; 296 297 return emit; 298} 299 300void draw_pt_so_emit_destroy( struct pt_so_emit *emit ) 301{ 302 FREE(emit); 303} 304