/*
* 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
#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;
/**
* 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)
{
- struct draw_context *draw = vsplit->draw;
unsigned hash;
- fetch = MIN2(fetch, draw->pt.max_index);
-
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;
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);
}
#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"