00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00037 #include "pipe/p_debug.h"
00038 #include "util/u_math.h"
00039 #include "util/u_memory.h"
00040
00041 #include "draw_vbuf.h"
00042 #include "draw_private.h"
00043 #include "draw_vertex.h"
00044 #include "draw_pipe.h"
00045 #include "translate/translate.h"
00046 #include "translate/translate_cache.h"
00047
00048
00052 struct vbuf_stage {
00053 struct draw_stage stage;
00055 struct vbuf_render *render;
00056
00057 const struct vertex_info *vinfo;
00058
00060 unsigned vertex_size;
00061
00062 struct translate *translate;
00063
00064
00065
00067 unsigned *vertices;
00068 unsigned *vertex_ptr;
00069 unsigned max_vertices;
00070 unsigned nr_vertices;
00071
00073 ushort *indices;
00074 unsigned max_indices;
00075 unsigned nr_indices;
00076
00077
00078
00079 float point_size;
00080
00081 struct translate_cache *cache;
00082 };
00083
00084
00088 static INLINE struct vbuf_stage *
00089 vbuf_stage( struct draw_stage *stage )
00090 {
00091 assert(stage);
00092 return (struct vbuf_stage *)stage;
00093 }
00094
00095
00096 static void vbuf_flush_indices( struct vbuf_stage *vbuf );
00097 static void vbuf_flush_vertices( struct vbuf_stage *vbuf );
00098 static void vbuf_alloc_vertices( struct vbuf_stage *vbuf );
00099
00100
00101 static INLINE boolean
00102 overflow( void *map, void *ptr, unsigned bytes, unsigned bufsz )
00103 {
00104 unsigned long used = (unsigned long) ((char *)ptr - (char *)map);
00105 return (used + bytes) > bufsz;
00106 }
00107
00108
00109 static INLINE void
00110 check_space( struct vbuf_stage *vbuf, unsigned nr )
00111 {
00112 if (vbuf->nr_vertices + nr > vbuf->max_vertices ) {
00113 vbuf_flush_vertices(vbuf);
00114 vbuf_alloc_vertices(vbuf);
00115 }
00116
00117 if (vbuf->nr_indices + nr > vbuf->max_indices )
00118 vbuf_flush_indices(vbuf);
00119 }
00120
00121
00122
00123
00131 static INLINE ushort
00132 emit_vertex( struct vbuf_stage *vbuf,
00133 struct vertex_header *vertex )
00134 {
00135 if(vertex->vertex_id == UNDEFINED_VERTEX_ID) {
00136
00137
00138
00139
00140
00141
00142 vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0);
00143 vbuf->translate->run(vbuf->translate, 0, 1, vbuf->vertex_ptr);
00144
00145 if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
00146
00147 vbuf->vertex_ptr += vbuf->vertex_size/4;
00148 vertex->vertex_id = vbuf->nr_vertices++;
00149 }
00150
00151 return (ushort)vertex->vertex_id;
00152 }
00153
00154
00155 static void
00156 vbuf_tri( struct draw_stage *stage,
00157 struct prim_header *prim )
00158 {
00159 struct vbuf_stage *vbuf = vbuf_stage( stage );
00160 unsigned i;
00161
00162 check_space( vbuf, 3 );
00163
00164 for (i = 0; i < 3; i++) {
00165 vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
00166 }
00167 }
00168
00169
00170 static void
00171 vbuf_line( struct draw_stage *stage,
00172 struct prim_header *prim )
00173 {
00174 struct vbuf_stage *vbuf = vbuf_stage( stage );
00175 unsigned i;
00176
00177 check_space( vbuf, 2 );
00178
00179 for (i = 0; i < 2; i++) {
00180 vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
00181 }
00182 }
00183
00184
00185 static void
00186 vbuf_point( struct draw_stage *stage,
00187 struct prim_header *prim )
00188 {
00189 struct vbuf_stage *vbuf = vbuf_stage( stage );
00190
00191 check_space( vbuf, 1 );
00192
00193 vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] );
00194 }
00195
00196
00197
00198
00204 static void
00205 vbuf_set_prim( struct vbuf_stage *vbuf, uint prim )
00206 {
00207 struct translate_key hw_key;
00208 unsigned dst_offset;
00209 unsigned i;
00210
00211 vbuf->render->set_primitive(vbuf->render, prim);
00212
00213
00214
00215
00216
00217
00218
00219 vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
00220
00221 if (vbuf->vertex_size != vbuf->vinfo->size * sizeof(float)) {
00222 vbuf_flush_vertices(vbuf);
00223 vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
00224 }
00225
00226
00227
00228 dst_offset = 0;
00229
00230 for (i = 0; i < vbuf->vinfo->num_attribs; i++) {
00231 unsigned emit_sz = 0;
00232 unsigned src_buffer = 0;
00233 unsigned output_format;
00234 unsigned src_offset = (vbuf->vinfo->attrib[i].src_index * 4 * sizeof(float) );
00235
00236 switch (vbuf->vinfo->attrib[i].emit) {
00237 case EMIT_4F:
00238 output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
00239 emit_sz = 4 * sizeof(float);
00240 break;
00241 case EMIT_3F:
00242 output_format = PIPE_FORMAT_R32G32B32_FLOAT;
00243 emit_sz = 3 * sizeof(float);
00244 break;
00245 case EMIT_2F:
00246 output_format = PIPE_FORMAT_R32G32_FLOAT;
00247 emit_sz = 2 * sizeof(float);
00248 break;
00249 case EMIT_1F:
00250 output_format = PIPE_FORMAT_R32_FLOAT;
00251 emit_sz = 1 * sizeof(float);
00252 break;
00253 case EMIT_1F_PSIZE:
00254 output_format = PIPE_FORMAT_R32_FLOAT;
00255 emit_sz = 1 * sizeof(float);
00256 src_buffer = 1;
00257 src_offset = 0;
00258 break;
00259 case EMIT_4UB:
00260 output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
00261 emit_sz = 4 * sizeof(ubyte);
00262 break;
00263 default:
00264 assert(0);
00265 output_format = PIPE_FORMAT_NONE;
00266 emit_sz = 0;
00267 break;
00268 }
00269
00270 hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
00271 hw_key.element[i].input_buffer = src_buffer;
00272 hw_key.element[i].input_offset = src_offset;
00273 hw_key.element[i].output_format = output_format;
00274 hw_key.element[i].output_offset = dst_offset;
00275
00276 dst_offset += emit_sz;
00277 }
00278
00279 hw_key.nr_elements = vbuf->vinfo->num_attribs;
00280 hw_key.output_stride = vbuf->vinfo->size * 4;
00281
00282
00283
00284 if (!vbuf->translate ||
00285 translate_key_compare(&vbuf->translate->key, &hw_key) != 0)
00286 {
00287 translate_key_sanitize(&hw_key);
00288 vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);
00289
00290 vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0);
00291 }
00292
00293 vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;
00294
00295
00296
00297 if (!vbuf->vertices)
00298 vbuf_alloc_vertices(vbuf);
00299 }
00300
00301
00302 static void
00303 vbuf_first_tri( struct draw_stage *stage,
00304 struct prim_header *prim )
00305 {
00306 struct vbuf_stage *vbuf = vbuf_stage( stage );
00307
00308 vbuf_flush_indices( vbuf );
00309 stage->tri = vbuf_tri;
00310 vbuf_set_prim(vbuf, PIPE_PRIM_TRIANGLES);
00311 stage->tri( stage, prim );
00312 }
00313
00314
00315 static void
00316 vbuf_first_line( struct draw_stage *stage,
00317 struct prim_header *prim )
00318 {
00319 struct vbuf_stage *vbuf = vbuf_stage( stage );
00320
00321 vbuf_flush_indices( vbuf );
00322 stage->line = vbuf_line;
00323 vbuf_set_prim(vbuf, PIPE_PRIM_LINES);
00324 stage->line( stage, prim );
00325 }
00326
00327
00328 static void
00329 vbuf_first_point( struct draw_stage *stage,
00330 struct prim_header *prim )
00331 {
00332 struct vbuf_stage *vbuf = vbuf_stage( stage );
00333
00334 vbuf_flush_indices( vbuf );
00335 stage->point = vbuf_point;
00336 vbuf_set_prim(vbuf, PIPE_PRIM_POINTS);
00337 stage->point( stage, prim );
00338 }
00339
00340
00341 static void
00342 vbuf_flush_indices( struct vbuf_stage *vbuf )
00343 {
00344 if(!vbuf->nr_indices)
00345 return;
00346
00347 assert((uint) (vbuf->vertex_ptr - vbuf->vertices) ==
00348 vbuf->nr_vertices * vbuf->vertex_size / sizeof(unsigned));
00349
00350 vbuf->render->draw(vbuf->render, vbuf->indices, vbuf->nr_indices);
00351
00352 vbuf->nr_indices = 0;
00353 }
00354
00355
00363 static void
00364 vbuf_flush_vertices( struct vbuf_stage *vbuf )
00365 {
00366 if(vbuf->vertices) {
00367 vbuf_flush_indices(vbuf);
00368
00369
00370 if(vbuf->nr_vertices)
00371 draw_reset_vertex_ids( vbuf->stage.draw );
00372
00373
00374 vbuf->render->release_vertices(vbuf->render,
00375 vbuf->vertices,
00376 vbuf->vertex_size,
00377 vbuf->nr_vertices);
00378 vbuf->max_vertices = vbuf->nr_vertices = 0;
00379 vbuf->vertex_ptr = vbuf->vertices = NULL;
00380
00381 }
00382 }
00383
00384
00385 static void
00386 vbuf_alloc_vertices( struct vbuf_stage *vbuf )
00387 {
00388 assert(!vbuf->nr_indices);
00389 assert(!vbuf->vertices);
00390
00391
00392 vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
00393
00394
00395 vbuf->max_vertices = vbuf->max_vertices & ~1;
00396
00397
00398
00399
00400
00401
00402 vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render,
00403 (ushort) vbuf->vertex_size,
00404 (ushort) vbuf->max_vertices);
00405 vbuf->vertex_ptr = vbuf->vertices;
00406 }
00407
00408
00409
00410 static void
00411 vbuf_flush( struct draw_stage *stage, unsigned flags )
00412 {
00413 struct vbuf_stage *vbuf = vbuf_stage( stage );
00414
00415 vbuf_flush_indices( vbuf );
00416
00417 stage->point = vbuf_first_point;
00418 stage->line = vbuf_first_line;
00419 stage->tri = vbuf_first_tri;
00420
00421 if (flags & DRAW_FLUSH_BACKEND)
00422 vbuf_flush_vertices( vbuf );
00423 }
00424
00425
00426 static void
00427 vbuf_reset_stipple_counter( struct draw_stage *stage )
00428 {
00429
00430
00431 (void) stage;
00432 }
00433
00434
00435 static void vbuf_destroy( struct draw_stage *stage )
00436 {
00437 struct vbuf_stage *vbuf = vbuf_stage( stage );
00438
00439 if(vbuf->indices)
00440 align_free( vbuf->indices );
00441
00442 if (vbuf->render)
00443 vbuf->render->destroy( vbuf->render );
00444
00445 if (vbuf->cache)
00446 translate_cache_destroy(vbuf->cache);
00447
00448 FREE( stage );
00449 }
00450
00451
00455 struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
00456 struct vbuf_render *render )
00457 {
00458 struct vbuf_stage *vbuf = CALLOC_STRUCT(vbuf_stage);
00459 if (vbuf == NULL)
00460 goto fail;
00461
00462 vbuf->stage.draw = draw;
00463 vbuf->stage.point = vbuf_first_point;
00464 vbuf->stage.line = vbuf_first_line;
00465 vbuf->stage.tri = vbuf_first_tri;
00466 vbuf->stage.flush = vbuf_flush;
00467 vbuf->stage.reset_stipple_counter = vbuf_reset_stipple_counter;
00468 vbuf->stage.destroy = vbuf_destroy;
00469
00470 vbuf->render = render;
00471 vbuf->max_indices = MAX2(render->max_indices, UNDEFINED_VERTEX_ID-1);
00472
00473 vbuf->indices = (ushort *) align_malloc( vbuf->max_indices *
00474 sizeof(vbuf->indices[0]),
00475 16 );
00476 if (!vbuf->indices)
00477 goto fail;
00478
00479 vbuf->cache = translate_cache_create();
00480 if (!vbuf->cache)
00481 goto fail;
00482
00483
00484 vbuf->vertices = NULL;
00485 vbuf->vertex_ptr = vbuf->vertices;
00486
00487 return &vbuf->stage;
00488
00489 fail:
00490 if (vbuf)
00491 vbuf_destroy(&vbuf->stage);
00492
00493 return NULL;
00494 }