-void
-_mesa_init_transform_feedback_dispatch(struct _glapi_table *disp)
-{
- /* EXT_transform_feedback */
- SET_BeginTransformFeedbackEXT(disp, _mesa_BeginTransformFeedback);
- SET_EndTransformFeedbackEXT(disp, _mesa_EndTransformFeedback);
- SET_BindBufferRangeEXT(disp, _mesa_BindBufferRange);
- SET_BindBufferBaseEXT(disp, _mesa_BindBufferBase);
- SET_BindBufferOffsetEXT(disp, _mesa_BindBufferOffsetEXT);
- SET_TransformFeedbackVaryingsEXT(disp, _mesa_TransformFeedbackVaryings);
- SET_GetTransformFeedbackVaryingEXT(disp, _mesa_GetTransformFeedbackVarying);
- /* ARB_transform_feedback2 */
- SET_BindTransformFeedback(disp, _mesa_BindTransformFeedback);
- SET_DeleteTransformFeedbacks(disp, _mesa_DeleteTransformFeedbacks);
- SET_GenTransformFeedbacks(disp, _mesa_GenTransformFeedbacks);
- SET_IsTransformFeedback(disp, _mesa_IsTransformFeedback);
- SET_PauseTransformFeedback(disp, _mesa_PauseTransformFeedback);
- SET_ResumeTransformFeedback(disp, _mesa_ResumeTransformFeedback);
+/**
+ * Fill in the correct Size value for each buffer in \c obj.
+ *
+ * From the GL 4.3 spec, section 6.1.1 ("Binding Buffer Objects to Indexed
+ * Targets"):
+ *
+ * BindBufferBase binds the entire buffer, even when the size of the buffer
+ * is changed after the binding is established. It is equivalent to calling
+ * BindBufferRange with offset zero, while size is determined by the size of
+ * the bound buffer at the time the binding is used.
+ *
+ * Regardless of the size specified with BindBufferRange, or indirectly with
+ * BindBufferBase, the GL will never read or write beyond the end of a bound
+ * buffer. In some cases this constraint may result in visibly different
+ * behavior when a buffer overflow would otherwise result, such as described
+ * for transform feedback operations in section 13.2.2.
+ */
+static void
+compute_transform_feedback_buffer_sizes(
+ struct gl_transform_feedback_object *obj)
+{
+ unsigned i = 0;
+ for (i = 0; i < MAX_FEEDBACK_BUFFERS; ++i) {
+ GLintptr offset = obj->Offset[i];
+ GLsizeiptr buffer_size
+ = obj->Buffers[i] == NULL ? 0 : obj->Buffers[i]->Size;
+ GLsizeiptr available_space
+ = buffer_size <= offset ? 0 : buffer_size - offset;
+ GLsizeiptr computed_size;
+ if (obj->RequestedSize[i] == 0) {
+ /* No size was specified at the time the buffer was bound, so allow
+ * writing to all available space in the buffer.
+ */
+ computed_size = available_space;
+ } else {
+ /* A size was specified at the time the buffer was bound, however
+ * it's possible that the buffer has shrunk since then. So only
+ * allow writing to the minimum of the specified size and the space
+ * available.
+ */
+ computed_size = MIN2(available_space, obj->RequestedSize[i]);
+ }
+
+ /* Legal sizes must be multiples of four, so round down if necessary. */
+ obj->Size[i] = computed_size & ~0x3;
+ }
+}
+
+
+/**
+ * Compute the maximum number of vertices that can be written to the currently
+ * enabled transform feedback buffers without overflowing any of them.
+ */
+unsigned
+_mesa_compute_max_transform_feedback_vertices(
+ const struct gl_transform_feedback_object *obj,
+ const struct gl_transform_feedback_info *info)
+{
+ unsigned max_index = 0xffffffff;
+ unsigned i;
+
+ for (i = 0; i < info->NumBuffers; ++i) {
+ unsigned stride = info->BufferStride[i];
+ unsigned max_for_this_buffer;
+
+ /* Skip any inactive buffers, which have a stride of 0. */
+ if (stride == 0)
+ continue;
+
+ max_for_this_buffer = obj->Size[i] / (4 * stride);
+ max_index = MIN2(max_index, max_for_this_buffer);
+ }
+
+ return max_index;