draw_pt_emit.c revision 488dd2c1912132fe7ee5e81b05fb64ba62a46098
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 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 TUNGSTEN GRAPHICS 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 "util/u_memory.h" 29#include "draw/draw_context.h" 30#include "draw/draw_private.h" 31#include "draw/draw_vbuf.h" 32#include "draw/draw_vertex.h" 33#include "draw/draw_pt.h" 34#include "translate/translate.h" 35#include "translate/translate_cache.h" 36 37struct pt_emit { 38 struct draw_context *draw; 39 40 struct translate *translate; 41 42 struct translate_cache *cache; 43 unsigned prim; 44 45 const struct vertex_info *vinfo; 46}; 47 48void draw_pt_emit_prepare( struct pt_emit *emit, 49 unsigned prim, 50 unsigned *max_vertices ) 51{ 52 struct draw_context *draw = emit->draw; 53 const struct vertex_info *vinfo; 54 unsigned dst_offset; 55 struct translate_key hw_key; 56 unsigned i; 57 58 /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 59 */ 60 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 61 62 63 /* XXX: may need to defensively reset this later on as clipping can 64 * clobber this state in the render backend. 65 */ 66 emit->prim = prim; 67 68 draw->render->set_primitive(draw->render, emit->prim); 69 70 /* Must do this after set_primitive() above: 71 */ 72 emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render); 73 74 75 /* Translate from pipeline vertices to hw vertices. 76 */ 77 dst_offset = 0; 78 for (i = 0; i < vinfo->num_attribs; i++) { 79 unsigned emit_sz = 0; 80 unsigned src_buffer = 0; 81 unsigned output_format; 82 unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) ); 83 84 output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit); 85 emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit); 86 87 /* doesn't handle EMIT_OMIT */ 88 assert(emit_sz != 0); 89 90 if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) { 91 src_buffer = 1; 92 src_offset = 0; 93 } 94 95 hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL; 96 hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 97 hw_key.element[i].input_buffer = src_buffer; 98 hw_key.element[i].input_offset = src_offset; 99 hw_key.element[i].instance_divisor = 0; 100 hw_key.element[i].output_format = output_format; 101 hw_key.element[i].output_offset = dst_offset; 102 103 dst_offset += emit_sz; 104 } 105 106 hw_key.nr_elements = vinfo->num_attribs; 107 hw_key.output_stride = vinfo->size * 4; 108 109 if (!emit->translate || 110 translate_key_compare(&emit->translate->key, &hw_key) != 0) 111 { 112 translate_key_sanitize(&hw_key); 113 emit->translate = translate_cache_find(emit->cache, &hw_key); 114 } 115 116 *max_vertices = (draw->render->max_vertex_buffer_bytes / 117 (vinfo->size * 4)); 118} 119 120 121void draw_pt_emit( struct pt_emit *emit, 122 const struct draw_vertex_info *vert_info, 123 const struct draw_prim_info *prim_info) 124{ 125 const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data; 126 unsigned vertex_count = vert_info->count; 127 unsigned stride = vert_info->stride; 128 const ushort *elts = prim_info->elts; 129 struct draw_context *draw = emit->draw; 130 struct translate *translate = emit->translate; 131 struct vbuf_render *render = draw->render; 132 unsigned start, i; 133 void *hw_verts; 134 135 /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 136 */ 137 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 138 139 if (vertex_count == 0) 140 return; 141 142 /* XXX: and work out some way to coordinate the render primitive 143 * between vbuf.c and here... 144 */ 145 draw->render->set_primitive(draw->render, emit->prim); 146 147 render->allocate_vertices(render, 148 (ushort)translate->key.output_stride, 149 (ushort)vertex_count); 150 151 hw_verts = render->map_vertices( render ); 152 if (!hw_verts) { 153 assert(0); 154 return; 155 } 156 157 translate->set_buffer(translate, 158 0, 159 vertex_data, 160 stride, 161 ~0); 162 163 translate->set_buffer(translate, 164 1, 165 &draw->rasterizer->point_size, 166 0, 167 ~0); 168 169 /* fetch/translate vertex attribs to fill hw_verts[] */ 170 translate->run( translate, 171 0, 172 vertex_count, 173 draw->instance_id, 174 hw_verts ); 175 176 render->unmap_vertices( render, 177 0, 178 vertex_count - 1 ); 179 180 for (start = i = 0; 181 i < prim_info->primitive_count; 182 start += prim_info->primitive_lengths[i], i++) 183 { 184 render->draw_elements(render, 185 elts + start, 186 prim_info->primitive_lengths[i]); 187 } 188 189 render->release_vertices(render); 190} 191 192 193void draw_pt_emit_linear(struct pt_emit *emit, 194 const struct draw_vertex_info *vert_info, 195 const struct draw_prim_info *prim_info) 196{ 197 const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data; 198 unsigned stride = vert_info->stride; 199 unsigned count = vert_info->count; 200 struct draw_context *draw = emit->draw; 201 struct translate *translate = emit->translate; 202 struct vbuf_render *render = draw->render; 203 void *hw_verts; 204 unsigned start, i; 205 206#if 0 207 debug_printf("Linear emit\n"); 208#endif 209 /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 210 */ 211 draw_do_flush( draw, DRAW_FLUSH_BACKEND ); 212 213 /* XXX: and work out some way to coordinate the render primitive 214 * between vbuf.c and here... 215 */ 216 draw->render->set_primitive(draw->render, emit->prim); 217 218 if (!render->allocate_vertices(render, 219 (ushort)translate->key.output_stride, 220 (ushort)count)) 221 goto fail; 222 223 hw_verts = render->map_vertices( render ); 224 if (!hw_verts) 225 goto fail; 226 227 translate->set_buffer(translate, 0, 228 vertex_data, stride, count - 1); 229 230 translate->set_buffer(translate, 1, 231 &draw->rasterizer->point_size, 232 0, ~0); 233 234 translate->run(translate, 235 0, 236 count, 237 draw->instance_id, 238 hw_verts); 239 240 if (0) { 241 unsigned i; 242 for (i = 0; i < count; i++) { 243 debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i); 244 draw_dump_emitted_vertex( emit->vinfo, 245 (const uint8_t *)hw_verts + 246 translate->key.output_stride * i ); 247 } 248 } 249 250 render->unmap_vertices( render, 0, count - 1 ); 251 252 for (start = i = 0; 253 i < prim_info->primitive_count; 254 start += prim_info->primitive_lengths[i], i++) 255 { 256 render->draw_arrays(render, 257 start, 258 prim_info->primitive_lengths[i]); 259 } 260 261 render->release_vertices(render); 262 263 return; 264 265fail: 266 assert(0); 267 return; 268} 269 270struct pt_emit *draw_pt_emit_create( struct draw_context *draw ) 271{ 272 struct pt_emit *emit = CALLOC_STRUCT(pt_emit); 273 if (!emit) 274 return NULL; 275 276 emit->draw = draw; 277 emit->cache = translate_cache_create(); 278 if (!emit->cache) { 279 FREE(emit); 280 return NULL; 281 } 282 283 return emit; 284} 285 286void draw_pt_emit_destroy( struct pt_emit *emit ) 287{ 288 if (emit->cache) 289 translate_cache_destroy(emit->cache); 290 291 FREE(emit); 292} 293