X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fvbo%2Fvbo_split_inplace.c;h=cff4bcd30ff3de4fa06de6c38c43921ced233871;hb=ab2b6317037cbe6746a3653d37562169e30c13da;hp=3ed6b34fbf079686654597de86b619db66dd492f;hpb=9f6ec50f8c79283583eeebdebd16bf7dcd134816;p=mesa.git diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c index 3ed6b34fbf0..cff4bcd30ff 100644 --- a/src/mesa/vbo/vbo_split_inplace.c +++ b/src/mesa/vbo/vbo_split_inplace.c @@ -1,7 +1,6 @@ /* * Mesa 3-D graphics library - * Version: 6.5 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * @@ -18,27 +17,31 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. * * Authors: - * Keith Whitwell + * Keith Whitwell */ #include "main/mtypes.h" #include "main/macros.h" #include "main/enums.h" +#include "main/glformats.h" #include "vbo_split.h" #define MAX_PRIM 32 -/* Used for splitting without copying. +/* Used for splitting without copying. No attempt is made to handle + * too large indexed vertex buffers: In general you need to copy to do + * that. */ struct split_context { - GLcontext *ctx; + struct gl_context *ctx; const struct gl_client_array **array; const struct _mesa_prim *prim; GLuint nr_prims; @@ -48,6 +51,7 @@ struct split_context { vbo_draw_func draw; const struct split_limits *limits; + GLuint limit; struct _mesa_prim dstprim[MAX_PRIM]; GLuint dstprim_nr; @@ -58,53 +62,46 @@ struct split_context { static void flush_vertex( struct split_context *split ) { - GLuint min_index, max_index; + struct gl_context *ctx = split->ctx; + const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays; + struct _mesa_index_buffer ib; + GLuint i; if (!split->dstprim_nr) return; if (split->ib) { - /* This should basically be multipass rendering over the same - * unchanging set of VBO's. Would like the driver not to - * re-upload the data, or swtnl not to re-transform the - * vertices. - */ - assert(split->max_index - split->min_index < split->limits->max_verts); - min_index = split->min_index; - max_index = split->max_index; - } - else { - /* Non-indexed rendering. Cannot assume that the primitives are - * ordered by increasing vertex, because of entrypoints like - * MultiDrawArrays. - */ - GLuint i; - min_index = split->dstprim[0].start; - max_index = min_index + split->dstprim[0].count - 1; - - for (i = 1; i < split->dstprim_nr; i++) { - GLuint tmp_min = split->dstprim[i].start; - GLuint tmp_max = tmp_min + split->dstprim[i].count - 1; - - if (tmp_min < min_index) - min_index = tmp_min; - - if (tmp_max > max_index) - max_index = tmp_max; - } + ib = *split->ib; + + ib.count = split->max_index - split->min_index + 1; + ib.ptr = (const void *)((const char *)ib.ptr + + split->min_index * _mesa_sizeof_type(ib.type)); + + /* Rebase the primitives to save index buffer entries. */ + for (i = 0; i < split->dstprim_nr; i++) + split->dstprim[i].start -= split->min_index; } - assert(max_index >= min_index); + assert(split->max_index >= split->min_index); + + ctx->Array._DrawArrays = split->array; + ctx->NewDriverState |= ctx->DriverFlags.NewArray; + + split->draw(ctx, + split->dstprim, + split->dstprim_nr, + split->ib ? &ib : NULL, + !split->ib, + split->min_index, + split->max_index, + NULL, 0, NULL); - split->draw( split->ctx, - split->array, - split->dstprim, - split->dstprim_nr, - NULL, - min_index, - max_index); + ctx->Array._DrawArrays = saved_arrays; + ctx->NewDriverState |= ctx->DriverFlags.NewArray; split->dstprim_nr = 0; + split->min_index = ~0; + split->max_index = 0; } @@ -121,84 +118,90 @@ static struct _mesa_prim *next_outprim( struct split_context *split ) } } -static int align(int value, int alignment) +static void update_index_bounds(struct split_context *split, + const struct _mesa_prim *prim) { - return (value + alignment - 1) & ~(alignment - 1); + split->min_index = MIN2(split->min_index, prim->start); + split->max_index = MAX2(split->max_index, prim->start + prim->count - 1); } - +/* Return the maximum amount of vertices that can be emitted for a + * primitive starting at 'prim->start', depending on the previous + * index bounds. + */ +static GLuint get_max_vertices(struct split_context *split, + const struct _mesa_prim *prim) +{ + if ((prim->start > split->min_index && + prim->start - split->min_index >= split->limit) || + (prim->start < split->max_index && + split->max_index - prim->start >= split->limit)) + /* "prim" starts too far away from the old range. */ + return 0; + + return MIN2(split->min_index, prim->start) + split->limit - prim->start; +} /* Break large primitives into smaller ones. If not possible, convert * the primitive to indexed and pass to split_elts(). */ static void split_prims( struct split_context *split) { - GLuint csr = 0; GLuint i; for (i = 0; i < split->nr_prims; i++) { const struct _mesa_prim *prim = &split->prim[i]; GLuint first, incr; GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr); - GLuint count; - - /* Always wrap on an even numbered vertex to avoid problems with - * triangle strips. - */ - GLuint available = align(split->limits->max_verts - csr - 1, 2); - assert(split->limits->max_verts >= csr); + GLuint available = get_max_vertices(split, prim); + GLuint count = prim->count - (prim->count - first) % incr; if (prim->count < first) continue; - - count = prim->count - (prim->count - first) % incr; - - if ((available < count && !split_inplace) || + if ((available < count && !split_inplace) || (available < first && split_inplace)) { flush_vertex(split); - csr = 0; - available = align(split->limits->max_verts - csr - 1, 2); + available = get_max_vertices(split, prim); } if (available >= count) { struct _mesa_prim *outprim = next_outprim(split); + *outprim = *prim; - csr += prim->count; - available = align(split->limits->max_verts - csr - 1, 2); - } + update_index_bounds(split, outprim); + } else if (split_inplace) { GLuint j, nr; - for (j = 0 ; j < count ; ) { GLuint remaining = count - j; struct _mesa_prim *outprim = next_outprim(split); nr = MIN2( available, remaining ); - nr -= (nr - first) % incr; - + outprim->mode = prim->mode; outprim->begin = (j == 0 && prim->begin); outprim->end = (nr == remaining && prim->end); outprim->start = prim->start + j; outprim->count = nr; - + outprim->num_instances = prim->num_instances; + outprim->base_instance = prim->base_instance; + + update_index_bounds(split, outprim); + if (nr == remaining) { /* Finished. */ - j += nr; - csr += nr; - available = align(split->limits->max_verts - csr - 1, 2); + j += nr; } else { /* Wrapped the primitive: */ j += nr - (first - incr); flush_vertex(split); - csr = 0; - available = align(split->limits->max_verts - csr - 1, 2); + available = get_max_vertices(split, prim); } } } @@ -223,11 +226,13 @@ static void split_prims( struct split_context *split) ib.type = GL_UNSIGNED_INT; ib.obj = split->ctx->Shared->NullBufferObj; ib.ptr = elts; - + tmpprim = *prim; tmpprim.indexed = 1; tmpprim.start = 0; tmpprim.count = count; + tmpprim.num_instances = 1; + tmpprim.base_instance = 0; flush_vertex(split); @@ -256,7 +261,7 @@ static void split_prims( struct split_context *split) } -void vbo_split_inplace( GLcontext *ctx, +void vbo_split_inplace( struct gl_context *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, @@ -275,10 +280,14 @@ void vbo_split_inplace( GLcontext *ctx, split.prim = prim; split.nr_prims = nr_prims; split.ib = ib; - split.min_index = min_index; - split.max_index = max_index; + + /* Empty interval, makes calculations simpler. */ + split.min_index = ~0; + split.max_index = 0; + split.draw = draw; split.limits = limits; + split.limit = ib ? limits->max_indices : limits->max_verts; split_prims( &split ); }