draw: minor indentation fix
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_vsplit.c
index a6875253094a7731635860c6c0598cd75393bedb..8d448f92a26c19051af950e04f899f38b377d04f 100644 (file)
@@ -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;