X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fdraw%2Fdraw_pt_vsplit.c;h=8d448f92a26c19051af950e04f899f38b377d04f;hb=f4caa7d2fcbfd64d8858a502d1deed8e56109464;hp=a6875253094a7731635860c6c0598cd75393bedb;hpb=6c03c576cc49bbb008de66d374f4302ff0fe0390;p=mesa.git diff --git a/src/gallium/auxiliary/draw/draw_pt_vsplit.c b/src/gallium/auxiliary/draw/draw_pt_vsplit.c index a6875253094..8d448f92a26 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vsplit.c +++ b/src/gallium/auxiliary/draw/draw_pt_vsplit.c @@ -1,8 +1,7 @@ /* * Mesa 3-D graphics library - * Version: 7.9 * - * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007-2008 VMware, Inc. * Copyright (C) 2010 LunarG Inc. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -34,6 +33,9 @@ #define SEGMENT_SIZE 1024 #define MAP_SIZE 256 +/* The largest possible index withing an index buffer */ +#define MAX_ELT_IDX 0xffffffff + struct vsplit_frontend { struct draw_pt_front_end base; struct draw_context *draw; @@ -82,12 +84,16 @@ vsplit_flush_cache(struct vsplit_frontend *vsplit, unsigned flags) /** * Add a fetch element and add it to the draw elements. */ -static INLINE void -vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch) +static inline void +vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch, unsigned ofbias) { - unsigned hash = fetch % MAP_SIZE; + unsigned hash; + + hash = fetch % MAP_SIZE; - if (vsplit->cache.fetches[hash] != fetch) { + /* If the value isn't in the cache or it's an overflow due to the + * element bias */ + if (vsplit->cache.fetches[hash] != fetch || ofbias) { /* update cache */ vsplit->cache.fetches[hash] = fetch; vsplit->cache.draws[hash] = vsplit->cache.num_fetch_elts; @@ -100,22 +106,109 @@ vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch) vsplit->draw_elts[vsplit->cache.num_draw_elts++] = vsplit->cache.draws[hash]; } +/** + * Returns the base index to the elements array. + * The value is checked for overflows (both integer overflows + * and the elements array overflow). + */ +static inline unsigned +vsplit_get_base_idx(struct vsplit_frontend *vsplit, + unsigned start, unsigned fetch, unsigned *ofbit) +{ + struct draw_context *draw = vsplit->draw; + unsigned elt_idx = draw_overflow_uadd(start, fetch, MAX_ELT_IDX); + if (ofbit) + *ofbit = 0; + + /* Overflown indices need to wrap to the first element + * in the index buffer */ + if (elt_idx >= draw->pt.user.eltMax) { + if (ofbit) + *ofbit = 1; + elt_idx = 0; + } + + return elt_idx; +} + +/** + * Returns the element index adjust for the element bias. + * The final element index is created from the actual element + * index, plus the element bias, clamped to maximum elememt + * index if that addition overflows. + */ +static inline unsigned +vsplit_get_bias_idx(struct vsplit_frontend *vsplit, + int idx, int bias, unsigned *ofbias) +{ + int res = idx + bias; + + if (ofbias) + *ofbias = 0; + + if (idx > 0 && bias > 0) { + if (res < idx || res < bias) { + res = DRAW_MAX_FETCH_IDX; + if (ofbias) + *ofbias = 1; + } + } else if (idx < 0 && bias < 0) { + if (res > idx || res > bias) { + res = DRAW_MAX_FETCH_IDX; + if (ofbias) + *ofbias = 1; + } + } + + return res; +} + +#define VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias) \ + unsigned elt_idx; \ + unsigned ofbit; \ + unsigned ofbias; \ + elt_idx = vsplit_get_base_idx(vsplit, start, fetch, &ofbit); \ + elt_idx = vsplit_get_bias_idx(vsplit, ofbit ? 0 : DRAW_GET_IDX(elts, elt_idx), elt_bias, &ofbias) + +static inline void +vsplit_add_cache_ubyte(struct vsplit_frontend *vsplit, const ubyte *elts, + unsigned start, unsigned fetch, int elt_bias) +{ + struct draw_context *draw = vsplit->draw; + VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias); + vsplit_add_cache(vsplit, elt_idx, ofbias); +} + +static inline void +vsplit_add_cache_ushort(struct vsplit_frontend *vsplit, const ushort *elts, + unsigned start, unsigned fetch, int elt_bias) +{ + struct draw_context *draw = vsplit->draw; + VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias); + vsplit_add_cache(vsplit, elt_idx, ofbias); +} + /** * Add a fetch element and add it to the draw elements. The fetch element is * in full range (uint). */ -static INLINE void -vsplit_add_cache_uint(struct vsplit_frontend *vsplit, unsigned fetch) +static inline void +vsplit_add_cache_uint(struct vsplit_frontend *vsplit, const uint *elts, + unsigned start, unsigned fetch, int elt_bias) { - /* special care for 0xffffffff */ - if (fetch == 0xffffffff && !vsplit->cache.has_max_fetch) { + struct draw_context *draw = vsplit->draw; + unsigned raw_elem_idx = start + fetch + elt_bias; + VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias); + + /* special care for DRAW_MAX_FETCH_IDX */ + if (raw_elem_idx == DRAW_MAX_FETCH_IDX && !vsplit->cache.has_max_fetch) { unsigned hash = fetch % MAP_SIZE; - vsplit->cache.fetches[hash] = fetch - 1; /* force update */ + vsplit->cache.fetches[hash] = raw_elem_idx - 1; /* force update */ vsplit->cache.has_max_fetch = TRUE; } - vsplit_add_cache(vsplit, fetch); + vsplit_add_cache(vsplit, elt_idx, ofbias); } @@ -124,17 +217,17 @@ vsplit_add_cache_uint(struct vsplit_frontend *vsplit, unsigned fetch) #define FUNC vsplit_run_ubyte #define ELT_TYPE ubyte -#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch) +#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_ubyte(vsplit,ib,start,fetch,bias) #include "draw_pt_vsplit_tmp.h" #define FUNC vsplit_run_ushort #define ELT_TYPE ushort -#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch) +#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_ushort(vsplit,ib,start,fetch, bias) #include "draw_pt_vsplit_tmp.h" #define FUNC vsplit_run_uint #define ELT_TYPE uint -#define ADD_CACHE(vsplit, fetch) vsplit_add_cache_uint(vsplit, fetch) +#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_uint(vsplit, ib, start, fetch, bias) #include "draw_pt_vsplit_tmp.h" @@ -173,11 +266,14 @@ static void vsplit_prepare(struct draw_pt_front_end *frontend, } -static void vsplit_finish(struct draw_pt_front_end *frontend) +static void vsplit_flush(struct draw_pt_front_end *frontend, unsigned flags) { struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; - vsplit->middle->finish(vsplit->middle); - vsplit->middle = NULL; + + if (flags & DRAW_FLUSH_STATE_CHANGE) { + vsplit->middle->finish(vsplit->middle); + vsplit->middle = NULL; + } } @@ -197,7 +293,7 @@ struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw) vsplit->base.prepare = vsplit_prepare; vsplit->base.run = NULL; - vsplit->base.finish = vsplit_finish; + vsplit->base.flush = vsplit_flush; vsplit->base.destroy = vsplit_destroy; vsplit->draw = draw;