mesa: Check that all buffers are bound in BeginTransformFeedback.
authorPaul Berry <stereotype441@gmail.com>
Thu, 29 Dec 2011 23:55:01 +0000 (15:55 -0800)
committerPaul Berry <stereotype441@gmail.com>
Wed, 4 Jan 2012 22:54:48 +0000 (14:54 -0800)
From the EXT_transform_feedback spec:

    The error INVALID_OPERATION is generated by
    BeginTransformFeedbackEXT if any transform feedback buffer object
    binding point used in transform feedback mode does not have a
    buffer object bound.

This required adding a new NumBuffers field to the
gl_transform_feedback_info struct, to keep track of how many transform
feedback buffers are required by the current program.

Fixes Piglit tests:
- EXT_transform_feedback/api-errors interleaved_unbound
- EXT_transform_feedback/api-errors separate_unbound_0_1
- EXT_transform_feedback/api-errors separate_unbound_0_2
- EXT_transform_feedback/api-errors separate_unbound_1_2

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
src/glsl/linker.cpp
src/mesa/main/mtypes.h
src/mesa/main/transformfeedback.c

index 65870087bf50b4d87a258bf28f9f4d658590f2f2..9e8975e887f7f110187b025c257f44a8c1ba7632 100644 (file)
@@ -1865,11 +1865,14 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
                      tfeedback_decl *tfeedback_decls)
 {
    unsigned total_tfeedback_components = 0;
+   bool separate_attribs_mode =
+      prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;
    memset(&prog->LinkedTransformFeedback, 0,
           sizeof(prog->LinkedTransformFeedback));
+   prog->LinkedTransformFeedback.NumBuffers =
+      separate_attribs_mode ? num_tfeedback_decls : 1;
    for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
-      unsigned buffer =
-         prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS ? i : 0;
+      unsigned buffer = separate_attribs_mode ? i : 0;
       if (!tfeedback_decls[i].store(prog, &prog->LinkedTransformFeedback,
                                     buffer))
          return false;
index 107371e5299549b9ca389ed1cd17cbadb17a276a..35458e396ada25be18cab6c6cb49f00dad2a909b 100644 (file)
@@ -1821,6 +1821,11 @@ struct gl_uniform_list;
 struct gl_transform_feedback_info {
    unsigned NumOutputs;
 
+   /**
+    * Number of transform feedback buffers in use by this program.
+    */
+   unsigned NumBuffers;
+
    struct {
       unsigned OutputRegister;
       unsigned OutputBuffer;
index 305589df75aa3b32cacee13af5f3c8d9d6216384..6e93b3b49d163c46e835f93b1c182edcfa8a9b54 100644 (file)
@@ -342,9 +342,12 @@ void GLAPIENTRY
 _mesa_BeginTransformFeedback(GLenum mode)
 {
    struct gl_transform_feedback_object *obj;
+   struct gl_transform_feedback_info *info;
+   int i;
    GET_CURRENT_CONTEXT(ctx);
 
    obj = ctx->TransformFeedback.CurrentObject;
+   info = &ctx->Shader.CurrentVertexProgram->LinkedTransformFeedback;
 
    switch (mode) {
    case GL_POINTS:
@@ -363,6 +366,15 @@ _mesa_BeginTransformFeedback(GLenum mode)
       return;
    }
 
+   for (i = 0; i < info->NumBuffers; ++i) {
+      if (obj->BufferNames[i] == 0) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glBeginTransformFeedback(binding point %d does not have "
+                     "a buffer object bound)", i);
+         return;
+      }
+   }
+
    FLUSH_VERTICES(ctx, _NEW_TRANSFORM_FEEDBACK);
    obj->Active = GL_TRUE;
    ctx->TransformFeedback.Mode = mode;