[Mesa-dev] [PATCH 01/11] mesa: Compute effective buffer bindings in the vao.

Mathias.Froehlich at gmx.net Mathias.Froehlich at gmx.net
Sun Apr 1 18:13:01 UTC 2018


From: Mathias Fröhlich <mathias.froehlich at web.de>

Compute VAO buffer binding information past the position/generic0 mapping.
Also scan for duplicate buffer bindings and collapse them into derived
effective buffer binding index and effective attribute mask variables.
Also provide a set of helper functions to access the distilled
information in the VAO. All of them prefixed with _mesa_draw_...
to indicate that they are meant to query draw information.

Signed-off-by: Mathias Fröhlich <Mathias.Froehlich at web.de>
---
 src/mesa/main/arrayobj.c   | 292 ++++++++++++++++++++++++++++++++++++++++++++-
 src/mesa/main/arrayobj.h   | 171 ++++++++++++++++++++++++++
 src/mesa/main/attrib.c     |   1 +
 src/mesa/main/mtypes.h     |  38 ++++++
 src/mesa/main/varray.c     |   2 +
 src/mesa/vbo/vbo.h         |   8 ++
 src/mesa/vbo/vbo_context.c |  17 +++
 7 files changed, 523 insertions(+), 6 deletions(-)

diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index 0d2f7a918a..4ef4046c4b 100644
--- a/src/mesa/main/arrayobj.c
+++ b/src/mesa/main/arrayobj.c
@@ -452,8 +452,69 @@ _mesa_initialize_vao(struct gl_context *ctx,
 
 
 /**
- * Updates the derived gl_vertex_arrays when a gl_array_attributes
- * or a gl_vertex_buffer_binding has changed.
+ * Update the unique binding and pos/generic0 map tracking in the vao.
+ *
+ * The idea is to build up information in the vao so that a consuming
+ * backend can execute the following to set up buffer and vertex element
+ * information:
+ *
+ * const GLbitfield inputs_read = VERT_BIT_ALL; // backend vp inputs
+ *
+ * // Attribute data is in a VBO.
+ * GLbitfield vbomask = inputs_read & _mesa_draw_vbo_array_bits(ctx);
+ * while (vbomask) {
+ *    // The attribute index to start pulling a binding
+ *    const gl_vert_attrib i = ffs(vbomask) - 1;
+ *    const struct gl_vertex_buffer_binding *const binding
+ *       = _mesa_draw_buffer_binding(vao, i);
+ *
+ *    <insert code to handle the vertex buffer object at binding>
+ *
+ *    const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
+ *    GLbitfield attrmask = vbomask & boundmask;
+ *    assert(attrmask);
+ *    // Walk attributes belonging to the binding
+ *    while (attrmask) {
+ *       const gl_vert_attrib attr = u_bit_scan(&attrmask);
+ *       const struct gl_array_attributes *const attrib
+ *          = _mesa_draw_array_attrib(vao, attr);
+ *
+ *       <insert code to handle the vertex element refering to the binding>
+ *    }
+ *    vbomask &= ~boundmask;
+ * }
+ *
+ * // Process user space buffers
+ * GLbitfield usermask = inputs_read & _mesa_draw_user_array_bits(ctx);
+ * while (usermask) {
+ *    // The attribute index to start pulling a binding
+ *    const gl_vert_attrib i = ffs(usermask) - 1;
+ *    const struct gl_vertex_buffer_binding *const binding
+ *       = _mesa_draw_buffer_binding(vao, i);
+ *
+ *    const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
+ *    GLbitfield attrmask = usermask & boundmask;
+ *    assert(attrmask);
+ *    // Walk attributes with a common stride and instance divisor
+ *    while (attrmask) {
+ *       const gl_vert_attrib attr = u_bit_scan(&attrmask);
+ *       const struct gl_array_attributes *const attrib
+ *          = _mesa_draw_array_attrib(vao, attr);
+ *
+ *       <insert code to handle non vbo vertex arrays>
+ *    }
+ *    usermask &= ~boundmask;
+ * }
+ *
+ * // Process values that should have better been uniforms in the application
+ * GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
+ * while (curmask) {
+ *    const gl_vert_attrib attr = u_bit_scan(&curmask);
+ *    const struct gl_array_attributes *const attrib
+ *       = _mesa_draw_current_attrib(ctx, attr);
+ *
+ *    <insert code to handle current values>
+ * }
  */
 void
 _mesa_update_vao_derived_arrays(struct gl_context *ctx,
@@ -462,11 +523,230 @@ _mesa_update_vao_derived_arrays(struct gl_context *ctx,
    /* Make sure we do not run into problems with shared objects */
    assert(!vao->SharedAndImmutable || vao->NewArrays == 0);
 
-   /*
-    * Stay tuned, the next series scans for duplicate bindings in this
-    * function. So that drivers can easily know the minimum unique set
-    * of bindings.
+   /* Limit used for common binding scanning below. */
+   const int MaxRelativeOffset =
+      (0 < ctx->Const.MaxVertexAttribRelativeOffset) ?
+      ctx->Const.MaxVertexAttribRelativeOffset : 2047;
+
+   /* The gl_vertex_array_object::_AttributeMapMode denotes the way
+    * VERT_ATTRIB_{POS,GENERIC0} mapping is done.
+    *
+    * This mapping is used to map between the OpenGL api visible
+    * VERT_ATTRIB_* arrays to mesa driver arrayinputs or shader inputs.
+    * The mapping only depends on the enabled bits of the
+    * VERT_ATTRIB_{POS,GENERIC0} arrays and is tracked in the VAO.
     */
+   const gl_attribute_map_mode map_mode = vao->_AttributeMapMode;
+   const unsigned char *const map =_mesa_vao_attribute_map[map_mode];
+   /* Enabled array bits past VERT_ATTRIB_{POS,GENERIC0} mapping. */
+   const GLbitfield enabled =
+      _mesa_vao_enable_to_vp_inputs(map_mode, vao->_Enabled);
+   /* VBO array bits past VERT_ATTRIB_{POS,GENERIC0} mapping. */
+   const GLbitfield vbos =
+      _mesa_vao_enable_to_vp_inputs(map_mode, vao->VertexAttribBufferMask);
+
+   /* Compute and store effectively enabled and mapped vbo arrays */
+   vao->_EffEnabledVBO = enabled & vbos;
+   /* Walk those enabled arrays that have a real vbo attached */
+   GLbitfield mask = enabled;
+   while (mask) {
+      /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
+      const int i = ffs(mask) - 1;
+      /* The binding from the first to be processed attribute. */
+      const GLuint bindex = vao->VertexAttrib[map[i]].BufferBindingIndex;
+      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
+      /* The bound arrays past past VERT_ATTRIB_{POS,GENERIC0} mapping. */
+      const GLbitfield bound =
+         _mesa_vao_enable_to_vp_inputs(map_mode, binding->_BoundArrays);
+
+      /* Start this current effective binding with the actual bound arrays */
+      GLbitfield eff_bound_arrays = enabled & bound;
+
+      /* The scan goes different for user space arrays than vbos */
+      if (_mesa_is_bufferobj(binding->BufferObj)) {
+         /*
+          * If there is nothing left to scan just update the effective binding
+          * information. If the VAO is already only using a single binding point
+          * we end up here. So the overhead of this scan for an application
+          * carefully preparing the VAO for draw is relatively low.
+          */
+
+         GLbitfield scanmask = mask & vbos & ~bound;
+         /* Is there something left to scan? */
+         if (scanmask == 0) {
+            /* Just update the back reference from the attrib to the binding and
+             * the effective offset.
+             */
+            GLbitfield attrmask = eff_bound_arrays;
+            while (attrmask) {
+               const int j = u_bit_scan(&attrmask);
+               struct gl_array_attributes *attrib2 = &vao->VertexAttrib[map[j]];
+
+               /* Update the index into the common binding point and offset */
+               attrib2->_EffBufferBindingIndex = bindex;
+               attrib2->_EffRelativeOffset = attrib2->RelativeOffset;
+
+               /* Only enabled arrays shall appear in the unique bindings */
+               assert(attrib2->Enabled);
+            }
+            /* Finally this is the set of effectively bound arrays with the
+             * original binding offset.
+             */
+            binding->_EffBoundArrays = eff_bound_arrays;
+            binding->_EffOffset = binding->Offset;
+
+         } else {
+            /* In the VBO case, scan for attribute/binding
+             * combinations with relative bindings in the range of
+             * ctx->Const.MaxVertexAttribRelativeOffset.
+             */
+
+            /* Start with the range of relative offsets of *binding. */
+            GLintptr min_offset = binding->BufferObj->Size;
+            GLintptr max_offset = 0;
+            GLbitfield offsetmask = bound & enabled;
+            while (offsetmask) {
+               const int k = u_bit_scan(&offsetmask);
+               const struct gl_array_attributes *attrib
+                  = &vao->VertexAttrib[map[k]];
+               const GLintptr off = binding->Offset + attrib->RelativeOffset;
+               min_offset = MIN2(off, min_offset);
+               max_offset = MAX2(off, max_offset);
+            }
+
+            /* Now scan. */
+            while (scanmask) {
+               /* Do not use u_bit_scan as we can walk multiple
+                * attrib arrays at once
+                */
+               const int j = ffs(scanmask) - 1;
+               const struct gl_array_attributes *attrib2 =
+                  &vao->VertexAttrib[map[j]];
+               const struct gl_vertex_buffer_binding *binding2 =
+                  &vao->BufferBinding[attrib2->BufferBindingIndex];
+
+               /* Remove those attrib bits from the mask that are bound to the
+                * same effective binding point.
+                */
+               const GLbitfield bound2 =
+                  _mesa_vao_enable_to_vp_inputs(map_mode, binding2->_BoundArrays);
+               scanmask &= ~bound2;
+
+               /* Check if we have an identical binding */
+               if (binding->Stride != binding2->Stride)
+                  continue;
+               if (binding->InstanceDivisor != binding2->InstanceDivisor)
+                  continue;
+               if (binding->BufferObj != binding2->BufferObj)
+                  continue;
+               /* Easy case, just identical binding a second time. */
+               if (binding->Offset == binding2->Offset) {
+                  /* Add the bindings from binding2 to the binding mask. */
+                  eff_bound_arrays |= enabled & bound2;
+                  /* Update the offset range. */
+                  GLbitfield attrmask = bound2 & enabled;
+                  while (attrmask) {
+                     const int k = u_bit_scan(&attrmask);
+                     const struct gl_array_attributes *attrib2
+                        = &vao->VertexAttrib[map[k]];
+                     const GLintptr offset2 =
+                        binding2->Offset + attrib2->RelativeOffset;
+                     min_offset = MIN2(offset2, min_offset);
+                     max_offset = MAX2(offset2, max_offset);
+                  }
+               } else {
+                  /* Check if we can fold both bindings into a common binding */
+                  GLbitfield attrmask = bound2 & enabled;
+                  while (attrmask) {
+                     const int k = u_bit_scan(&attrmask);
+                     const struct gl_array_attributes *attrib2
+                        = &vao->VertexAttrib[map[k]];
+                     const GLintptr offset2 =
+                        binding2->Offset + attrib2->RelativeOffset;
+                     /* If the relative offset is within the limits ... */
+                     if (offset2 + MaxRelativeOffset < max_offset)
+                        continue;
+                     if (min_offset + MaxRelativeOffset < offset2)
+                        continue;
+                     /* ... add this array to the effective binding */
+                     eff_bound_arrays |= 1u << k;
+                     min_offset = MIN2(offset2, min_offset);
+                     max_offset = MAX2(offset2, max_offset);
+                  }
+               }
+            }
+
+            /* Update the back reference from the attrib to the binding */
+            GLbitfield attrmask = eff_bound_arrays;
+            while (attrmask) {
+               const int j = u_bit_scan(&attrmask);
+               struct gl_array_attributes *attrib2 = &vao->VertexAttrib[map[j]];
+               const struct gl_vertex_buffer_binding *binding2 =
+                  &vao->BufferBinding[attrib2->BufferBindingIndex];
+
+               /* Update the index into the common binding point and offset */
+               attrib2->_EffBufferBindingIndex = bindex;
+               attrib2->_EffRelativeOffset =
+                  binding2->Offset + attrib2->RelativeOffset - min_offset;
+
+               /* Only enabled arrays shall appear in the unique bindings */
+               assert(attrib2->Enabled);
+            }
+            /* Finally this is the set of effectively bound arrays */
+            binding->_EffBoundArrays = eff_bound_arrays;
+            binding->_EffOffset = min_offset;
+         }
+
+      } else {
+         /* Scanning of common bindings for user space arrays.
+          * This only checks for common Stride and InstanceDivisor.
+          */
+         GLbitfield scanmask = mask & ~vbos & ~bound;
+         while (scanmask) {
+            /* Do not use u_bit_scan as we can walk multiple
+             * attrib arrays at once
+             */
+            const int j = ffs(scanmask) - 1;
+            const struct gl_array_attributes *attrib2 =
+               &vao->VertexAttrib[map[j]];
+            const struct gl_vertex_buffer_binding *binding2 =
+               &vao->BufferBinding[attrib2->BufferBindingIndex];
+
+            /* Remove those attrib bits from the mask that are bound to the
+             * same effective binding point.
+             */
+            const GLbitfield bound2 =
+               _mesa_vao_enable_to_vp_inputs(map_mode, binding2->_BoundArrays);
+            scanmask &= ~bound2;
+
+            /* Check if we have an identical binding */
+            if (binding->Stride != binding2->Stride)
+               continue;
+            if (binding->InstanceDivisor != binding2->InstanceDivisor)
+               continue;
+            /* User space buffer object */
+            assert(binding->BufferObj == binding2->BufferObj);
+         }
+
+         /* Update the back reference from the attrib to the binding */
+         GLbitfield attrmask = eff_bound_arrays;
+         while (attrmask) {
+            const int j = u_bit_scan(&attrmask);
+            struct gl_array_attributes *attrib2 = &vao->VertexAttrib[map[j]];
+
+            /* Update the index into the common binding point and the offset */
+            attrib2->_EffBufferBindingIndex = bindex;
+
+            /* Only enabled arrays shall appear in the unique bindings */
+            assert(attrib2->Enabled);
+         }
+         /* Finally this is the set of effectively bound arrays */
+         binding->_EffBoundArrays = eff_bound_arrays;
+      }
+
+      /* Mark all the effective bound arrays as processed. */
+      mask &= ~eff_bound_arrays;
+   }
 }
 
 
diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h
index 8da5c9ffe0..e8857ebc43 100644
--- a/src/mesa/main/arrayobj.h
+++ b/src/mesa/main/arrayobj.h
@@ -30,6 +30,7 @@
 #include "glheader.h"
 #include "mtypes.h"
 #include "glformats.h"
+#include "vbo/vbo.h"
 
 struct gl_context;
 
@@ -146,6 +147,176 @@ _mesa_get_vao_vp_inputs(const struct gl_vertex_array_object *vao)
 }
 
 
+/**
+ * Helper functions for consuming backends to walk the
+ * ctx->Array._DrawVAO for array setup.
+ * Note that mesa privides preprocessed minimal binding information
+ * in the VAO. See the _mesa_update_vao_derived_arrays documentation.
+ */
+
+/**
+ * Return enabled vertex attribute bits for draw.
+ */
+static inline GLbitfield
+_mesa_draw_array_bits(const struct gl_context *ctx)
+{
+   return ctx->Array._DrawVAOEnabledAttribs;
+}
+
+
+/**
+ * Return enabled buffer object vertex attribute bits for draw.
+ *
+ * Needs the a fully updated VAO ready for draw.
+ */
+static inline GLbitfield
+_mesa_draw_vbo_array_bits(const struct gl_context *ctx)
+{
+   const struct gl_vertex_array_object *const vao = ctx->Array._DrawVAO;
+   assert(vao->NewArrays == 0);
+   return vao->_EffEnabledVBO & ctx->Array._DrawVAOEnabledAttribs;
+}
+
+
+/**
+ * Return enabled user space vertex attribute bits for draw.
+ *
+ * Needs the a fully updated VAO ready for draw.
+ */
+static inline GLbitfield
+_mesa_draw_user_array_bits(const struct gl_context *ctx)
+{
+   const struct gl_vertex_array_object *const vao = ctx->Array._DrawVAO;
+   assert(vao->NewArrays == 0);
+   return ~vao->_EffEnabledVBO & ctx->Array._DrawVAOEnabledAttribs;
+}
+
+
+/**
+ * Return enabled current values attribute bits for draw.
+ */
+static inline GLbitfield
+_mesa_draw_current_bits(const struct gl_context *ctx)
+{
+   return ~ctx->Array._DrawVAOEnabledAttribs & VERT_BIT_ALL;
+}
+
+
+/**
+ * Return vertex buffer binding provided the attribute struct.
+ *
+ * Needs the a fully updated VAO ready for draw.
+ */
+static inline const struct gl_vertex_buffer_binding*
+_mesa_draw_buffer_binding_from_attrib(const struct gl_vertex_array_object *vao,
+                                      const struct gl_array_attributes *attrib)
+{
+   assert(vao->NewArrays == 0);
+   return &vao->BufferBinding[attrib->_EffBufferBindingIndex];
+}
+
+
+/**
+ * Return vertex array attribute provided the attribute number.
+ */
+static inline const struct gl_array_attributes*
+_mesa_draw_array_attrib(const struct gl_vertex_array_object *vao,
+                        gl_vert_attrib attr)
+{
+   assert(vao->NewArrays == 0);
+   const gl_attribute_map_mode map_mode = vao->_AttributeMapMode;
+   return &vao->VertexAttrib[_mesa_vao_attribute_map[map_mode][attr]];
+}
+
+
+/**
+ * Return vertex buffer binding provided an attribute number.
+ */
+static inline const struct gl_vertex_buffer_binding*
+_mesa_draw_buffer_binding(const struct gl_vertex_array_object *vao,
+                          gl_vert_attrib attr)
+{
+   const struct gl_array_attributes *const attrib
+      = _mesa_draw_array_attrib(vao, attr);
+   return _mesa_draw_buffer_binding_from_attrib(vao, attrib);
+}
+
+
+/**
+ * Return vertex attribute bits bound at the provided binding.
+ *
+ * Needs the a fully updated VAO ready for draw.
+ */
+static inline GLbitfield
+_mesa_draw_bound_attrib_bits(const struct gl_vertex_buffer_binding *binding)
+{
+   return binding->_EffBoundArrays;
+}
+
+
+/**
+ * Return the vertex offset bound at the provided binding.
+ *
+ * Needs the a fully updated VAO ready for draw.
+ */
+static inline GLintptr
+_mesa_draw_binding_offset(const struct gl_vertex_buffer_binding *binding)
+{
+   return binding->_EffOffset;
+}
+
+
+/**
+ * Return the relative offset of the provided attrib.
+ *
+ * Needs the a fully updated VAO ready for draw.
+ */
+static inline GLushort
+_mesa_draw_attributes_relative_offset(const struct gl_array_attributes *attrib)
+{
+   return attrib->_EffRelativeOffset;
+}
+
+
+/**
+ * Return a current value vertex array attribute provided the attribute number.
+ */
+static inline const struct gl_array_attributes*
+_mesa_draw_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr)
+{
+   return _vbo_current_attrib(ctx, attr);
+}
+
+
+/**
+ * Return true if we have the VERT_ATTRIB_EDGEFLAG array enabled.
+ */
+static inline bool
+_mesa_draw_edge_flag_array_enabled(const struct gl_context *ctx)
+{
+   return ctx->Array._DrawVAOEnabledAttribs & VERT_BIT_EDGEFLAG;
+}
+
+
+/**
+ * Return the attrib, binding pair for the given attribute.
+ */
+static inline void
+_mesa_draw_attrib_and_binding(const struct gl_context *ctx, gl_vert_attrib attr,
+                              const struct gl_array_attributes **attrib,
+                              const struct gl_vertex_buffer_binding **binding)
+{
+   if (ctx->Array._DrawVAOEnabledAttribs & VERT_BIT(attr)) {
+      const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
+      *attrib = _mesa_draw_array_attrib(vao, attr);
+      *binding = _mesa_draw_buffer_binding_from_attrib(vao, *attrib);
+   } else {
+      *attrib = _vbo_current_attrib(ctx, attr);
+      *binding = _vbo_current_binding(ctx);
+   }
+}
+
+
 /*
  * API functions
  */
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 9c632ffb51..3330e451ce 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -1513,6 +1513,7 @@ copy_array_object(struct gl_context *ctx,
 
    /* _Enabled must be the same than on push */
    dest->_Enabled = src->_Enabled;
+   dest->_EffEnabledVBO = src->_EffEnabledVBO;
    /* The bitmask of bound VBOs needs to match the VertexBinding array */
    dest->VertexAttribBufferMask = src->VertexAttribBufferMask;
    dest->_AttributeMapMode = src->_AttributeMapMode;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index b7a7b34a09..ac05a2aa4f 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1548,6 +1548,23 @@ struct gl_array_attributes
    unsigned _ElementSize:8; /**< Size of each element in bytes */
    /** Index into gl_vertex_array_object::BufferBinding[] array */
    unsigned BufferBindingIndex:6;
+
+   /**
+    * Derived effective buffer binding index
+    *
+    * Index into the gl_vertex_buffer_binding array of the vao.
+    * Similar to BufferBindingIndex, but with the mapping of the
+    * position/generic0 attributes applied and with identical
+    * gl_vertex_buffer_binding entries collapsed to a single
+    * entry within the vao.
+    */
+   unsigned _EffBufferBindingIndex:6;
+   /**
+    * Derived effective relative offset.
+    *
+    * Relative offset to the effective buffers offset.
+    */
+   GLushort _EffRelativeOffset;
 };
 
 
@@ -1563,6 +1580,24 @@ struct gl_vertex_buffer_binding
    GLuint InstanceDivisor;             /**< GL_ARB_instanced_arrays */
    struct gl_buffer_object *BufferObj; /**< GL_ARB_vertex_buffer_object */
    GLbitfield _BoundArrays;            /**< Arrays bound to this binding point */
+
+   /**
+    * Derived effective bound arrays.
+    *
+    * The effective binding handles enabled arrays past the
+    * position/generic0 attribute mapping and reduces the
+    * refered gl_vertex_buffer_binding entries to a unique
+    * subset. That shall push scanning for duplicate bindings
+    * out of the draw loop of VAO's are used multiple times.
+    */
+   GLbitfield _EffBoundArrays;
+   /**
+    * Derived offset.
+    *
+    * The absolute offset to that we can collapse some attributes
+    * to this effective binding.
+    */
+   GLintptr _EffOffset;
 };
 
 
@@ -1617,6 +1652,9 @@ struct gl_vertex_array_object
    /** Mask of VERT_BIT_* values indicating which arrays are enabled */
    GLbitfield _Enabled;
 
+   /** Mask of VERT_BIT_* enabled arrays past position/generic0 mapping */
+   GLbitfield _EffEnabledVBO;
+
    /** Denotes the way the position/generic0 attribute is mapped */
    gl_attribute_map_mode _AttributeMapMode;
 
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 5df38a14f0..7243d24e9c 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -2868,6 +2868,7 @@ _mesa_copy_vertex_attrib_array(struct gl_context *ctx,
    dst->Ptr            = src->Ptr;
    dst->Enabled        = src->Enabled;
    dst->_ElementSize   = src->_ElementSize;
+   dst->_EffBufferBindingIndex = src->_EffBufferBindingIndex;
 }
 
 void
@@ -2879,6 +2880,7 @@ _mesa_copy_vertex_buffer_binding(struct gl_context *ctx,
    dst->Stride          = src->Stride;
    dst->InstanceDivisor = src->InstanceDivisor;
    dst->_BoundArrays    = src->_BoundArrays;
+   dst->_EffBoundArrays = src->_EffBoundArrays;
 
    _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
 }
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 9b15066291..ca46f9baa7 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -186,6 +186,14 @@ void
 _vbo_update_inputs(struct gl_context *ctx, struct vbo_inputs *inputs);
 
 
+const struct gl_array_attributes*
+_vbo_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr);
+
+
+const struct gl_vertex_buffer_binding*
+_vbo_current_binding(const struct gl_context *ctx);
+
+
 void GLAPIENTRY
 _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
 
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index e50cee7a8c..20e180252c 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -233,6 +233,23 @@ _vbo_DestroyContext(struct gl_context *ctx)
 }
 
 
+const struct gl_array_attributes*
+_vbo_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr)
+{
+   const struct vbo_context *vbo = vbo_context((struct gl_context *)ctx);
+   const gl_vertex_processing_mode vmp = ctx->VertexProgram._VPMode;
+   return &vbo->current[_vbo_attribute_alias_map[vmp][attr]];
+}
+
+
+const struct gl_vertex_buffer_binding*
+_vbo_current_binding(const struct gl_context *ctx)
+{
+   const struct vbo_context *vbo = vbo_context((struct gl_context *)ctx);
+   return &vbo->binding;
+}
+
+
 /*
  * Helper function for _vbo_draw_indirect below that additionally takes a zero
  * initialized array of _mesa_prim scratch space memory as the last argument.
-- 
2.14.3



More information about the mesa-dev mailing list