diff options
-rw-r--r-- | src/gallium/auxiliary/util/u_vbuf_mgr.c | 56 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_vbuf_mgr.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 9 |
3 files changed, 42 insertions, 27 deletions
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c index 3a1326c24d1..7e36018a044 100644 --- a/src/gallium/auxiliary/util/u_vbuf_mgr.c +++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c @@ -617,44 +617,54 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr, } } -static void u_vbuf_compute_max_index(struct u_vbuf_priv *mgr) +unsigned u_vbuf_draw_max_vertex_count(struct u_vbuf_mgr *mgrb) { + struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; unsigned i, nr = mgr->ve->count; - - mgr->b.max_index = ~0; + struct pipe_vertex_element *velems = + mgr->fallback_ve ? mgr->fallback_velems : mgr->ve->ve; + unsigned result = ~0; for (i = 0; i < nr; i++) { struct pipe_vertex_buffer *vb = - &mgr->b.vertex_buffer[mgr->ve->ve[i].vertex_buffer_index]; - unsigned max_index, src_size, unused; + &mgr->b.real_vertex_buffer[velems[i].vertex_buffer_index]; + unsigned size, max_count, value; + /* We're not interested in constant and per-instance attribs. */ if (!vb->buffer || !vb->stride || - u_vbuf_resource(vb->buffer)->user_ptr || - mgr->ve->ve[i].instance_divisor) { + velems[i].instance_divisor) { continue; } - src_size = mgr->ve->ve[i].src_offset + mgr->ve->src_format_size[i]; + size = vb->buffer->width0; - /* If src_offset is greater than stride (which means it's a buffer - * offset rather than a vertex offset)... */ - if (src_size >= vb->stride) { - unused = 0; - } else { - /* How many bytes is unused after the last vertex. - * width0 may be "count*stride - unused" and we have to compensate - * for that when dividing by stride. */ - unused = vb->stride - src_size; + /* Subtract buffer_offset. */ + value = vb->buffer_offset; + if (value >= size) { + return 0; } + size -= value; - /* Compute the maximum index for this vertex element. */ - max_index = - (vb->buffer->width0 - vb->buffer_offset + (unsigned)unused) / - vb->stride - 1; + /* Subtract src_offset. */ + value = velems[i].src_offset; + if (value >= size) { + return 0; + } + size -= value; + + /* Subtract format_size. */ + value = mgr->ve->native_format_size[i]; + if (value >= size) { + return 0; + } + size -= value; - mgr->b.max_index = MIN2(mgr->b.max_index, max_index); + /* Compute the max count. */ + max_count = 1 + size / vb->stride; + result = MIN2(result, max_count); } + return result; } static boolean u_vbuf_need_minmax_index(struct u_vbuf_priv *mgr) @@ -793,8 +803,6 @@ u_vbuf_draw_begin(struct u_vbuf_mgr *mgrb, struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; int min_index, max_index; - u_vbuf_compute_max_index(mgr); - if (!mgr->incompatible_vb_layout && !mgr->ve->incompatible_layout && !mgr->any_user_vbs) { diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.h b/src/gallium/auxiliary/util/u_vbuf_mgr.h index 8d39db34677..42ca0ac35a4 100644 --- a/src/gallium/auxiliary/util/u_vbuf_mgr.h +++ b/src/gallium/auxiliary/util/u_vbuf_mgr.h @@ -67,8 +67,6 @@ struct u_vbuf_mgr { struct pipe_vertex_buffer real_vertex_buffer[PIPE_MAX_ATTRIBS]; int nr_real_vertex_buffers; - /* Precomputed max_index for hardware vertex buffers. */ - unsigned max_index; /* The index buffer. */ struct pipe_index_buffer index_buffer; @@ -134,6 +132,8 @@ void u_vbuf_set_index_buffer(struct u_vbuf_mgr *mgr, enum u_vbuf_return_flags u_vbuf_draw_begin(struct u_vbuf_mgr *mgr, const struct pipe_draw_info *info); +unsigned u_vbuf_draw_max_vertex_count(struct u_vbuf_mgr *mgr); + void u_vbuf_draw_end(struct u_vbuf_mgr *mgr); diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 84cabc0bac3..b880b0b6416 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -760,8 +760,14 @@ static void r300_draw_vbo(struct pipe_context* pipe, /* Draw. */ if (info.indexed) { + unsigned max_count = u_vbuf_draw_max_vertex_count(r300->vbuf_mgr); + if (!max_count) { + fprintf(stderr, "r300: Skipping a draw command. There is a buffer " + " which is too small to be used for rendering.\n"); + goto done; + } info.start += r300->vbuf_mgr->index_buffer.offset / r300->vbuf_mgr->index_buffer.index_size; - info.max_index = MIN2(r300->vbuf_mgr->max_index, info.max_index); + info.max_index = max_count - 1; if (info.instance_count <= 1) { if (info.count <= 8 && @@ -785,6 +791,7 @@ static void r300_draw_vbo(struct pipe_context* pipe, } } +done: u_vbuf_draw_end(r300->vbuf_mgr); } |