main: Added entry point for glTransformFeedbackBufferBase
authorMartin Peres <martin.peres@linux.intel.com>
Tue, 20 Jan 2015 14:30:32 +0000 (16:30 +0200)
committerMartin Peres <martin.peres@linux.intel.com>
Wed, 25 Mar 2015 08:05:45 +0000 (10:05 +0200)
v2: Review from Laura Ekstrand
- give more helpful error messages
- factor the lookup code for the xfb and objBuf
- replace some already-existing tabs with spaces
- add comments to explain the cases where xfb == 0 or buffer == 0
- fix the condition for binding the transform buffer or not

v3: Review from Laura Ekstrand
- rename _mesa_lookup_bufferobj_err to
  _mesa_lookup_transform_feedback_bufferobj_err and make it static to avoid a
  future conflict
- make _mesa_lookup_transform_feedback_object_err static

v4: Review from Laura Ekstrand
- add the pdf page number when quoting the spec
- rename some of the symbols to follow the public/private conventions

v5: Review from Laura Ekstrand
- properly rename some of the symbols to follow the public/private conventions
- fix some alignments
- add quotes around a spec citation
- add back a newline I accidentally deleted
- add spaces around the ternary operator usages

Signed-off-by: Martin Peres <martin.peres@linux.intel.com>
Reviewed-by: Laura Ekstrand <laura@jlekstrand.net>
src/mapi/glapi/gen/ARB_direct_state_access.xml
src/mesa/main/bufferobj.c
src/mesa/main/tests/dispatch_sanity.cpp
src/mesa/main/transformfeedback.c
src/mesa/main/transformfeedback.h

index 0c7e88004eadc5874bd5cff558f3a26332e6ba77..02e33cd4a7557f13181706c44ad1b59dafffbcef 100644 (file)
       <param name="ids" type="GLuint *" />
    </function>
 
+   <function name="TransformFeedbackBufferBase" offset="assign">
+      <param name="xfb" type="GLuint" />
+      <param name="index" type="GLuint" />
+      <param name="buffer" type="GLuint" />
+   </function>
+
    <!-- Buffer object functions -->
 
    <function name="CreateBuffers" offset="assign">
index 965877084235842e4b2454095b240e3e813df121..e73793638c9a550bf8212761fa06c223621ac1df 100644 (file)
@@ -3885,8 +3885,9 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
 
    switch (target) {
    case GL_TRANSFORM_FEEDBACK_BUFFER:
-      _mesa_bind_buffer_range_transform_feedback(ctx, index, bufObj,
-                                                offset, size);
+      _mesa_bind_buffer_range_transform_feedback(ctx,
+                                                 ctx->TransformFeedback.CurrentObject,
+                                                 index, bufObj, offset, size);
       return;
    case GL_UNIFORM_BUFFER:
       bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
@@ -3950,7 +3951,9 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
 
    switch (target) {
    case GL_TRANSFORM_FEEDBACK_BUFFER:
-      _mesa_bind_buffer_base_transform_feedback(ctx, index, bufObj);
+      _mesa_bind_buffer_base_transform_feedback(ctx,
+                                                ctx->TransformFeedback.CurrentObject,
+                                                index, bufObj, false);
       return;
    case GL_UNIFORM_BUFFER:
       bind_buffer_base_uniform_buffer(ctx, index, bufObj);
index 899a1881d3483a7d8acda1a8807ec657bac89e76..315571d6fedba32ad63112b2a8267aa4c8b60f7d 100644 (file)
@@ -923,6 +923,7 @@ const struct function gl_core_functions_possible[] = {
 
    /* GL_ARB_direct_state_access */
    { "glCreateTransformFeedbacks", 45, -1 },
+   { "glTransformFeedbackBufferBase", 45, -1 },
    { "glCreateBuffers", 45, -1 },
    { "glNamedBufferStorage", 45, -1 },
    { "glNamedBufferData", 45, -1 },
index 3c19406a55da7c84bdd7e4e0a75f55f05e689b53..1b2bd8d77afe342097bdf11d8d21fb09db1f67a3 100644 (file)
@@ -514,22 +514,24 @@ _mesa_EndTransformFeedback(void)
  * Helper used by BindBufferRange() and BindBufferBase().
  */
 static void
-bind_buffer_range(struct gl_context *ctx, GLuint index,
+bind_buffer_range(struct gl_context *ctx,
+                  struct gl_transform_feedback_object *obj,
+                  GLuint index,
                   struct gl_buffer_object *bufObj,
-                  GLintptr offset, GLsizeiptr size)
+                  GLintptr offset, GLsizeiptr size,
+                  bool dsa)
 {
-   struct gl_transform_feedback_object *obj =
-      ctx->TransformFeedback.CurrentObject;
-
    /* Note: no need to FLUSH_VERTICES or flag NewTransformFeedback, because
     * transform feedback buffers can't be changed while transform feedback is
     * active.
     */
 
-   /* The general binding point */
-   _mesa_reference_buffer_object(ctx,
-                                 &ctx->TransformFeedback.CurrentBuffer,
-                                 bufObj);
+   if (!dsa) {
+      /* The general binding point */
+      _mesa_reference_buffer_object(ctx,
+                                    &ctx->TransformFeedback.CurrentBuffer,
+                                    bufObj);
+   }
 
    /* The per-attribute binding point */
    _mesa_set_transform_feedback_binding(ctx, obj, index, bufObj, offset, size);
@@ -543,15 +545,12 @@ bind_buffer_range(struct gl_context *ctx, GLuint index,
  */
 void
 _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
-                                          GLuint index,
-                                          struct gl_buffer_object *bufObj,
-                                          GLintptr offset,
-                                          GLsizeiptr size)
+                                           struct gl_transform_feedback_object *obj,
+                                           GLuint index,
+                                           struct gl_buffer_object *bufObj,
+                                           GLintptr offset,
+                                           GLsizeiptr size)
 {
-   struct gl_transform_feedback_object *obj;
-
-   obj = ctx->TransformFeedback.CurrentObject;
-
    if (obj->Active) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glBindBufferRange(transform feedback active)");
@@ -559,13 +558,15 @@ _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
    }
 
    if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d "
+                  "out of bounds)", index);
       return;
    }
 
    if (size & 0x3) {
       /* must a multiple of four */
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", (int) size);
+      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)",
+                  (int) size);
       return;
    }  
 
@@ -576,38 +577,109 @@ _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
       return;
    }  
 
-   bind_buffer_range(ctx, index, bufObj, offset, size);
+   bind_buffer_range(ctx, obj, index, bufObj, offset, size, false);
 }
 
 
 /**
  * Specify a buffer object to receive transform feedback results.
  * As above, but start at offset = 0.
- * Called from the glBindBufferBase() function.
+ * Called from the glBindBufferBase() and glTransformFeedbackBufferBase()
+ * functions.
  */
 void
 _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
-                                         GLuint index,
-                                         struct gl_buffer_object *bufObj)
+                                          struct gl_transform_feedback_object *obj,
+                                          GLuint index,
+                                          struct gl_buffer_object *bufObj,
+                                          bool dsa)
 {
-   struct gl_transform_feedback_object *obj;
-
-   obj = ctx->TransformFeedback.CurrentObject;
-
    if (obj->Active) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glBindBufferBase(transform feedback active)");
+                  "%s(transform feedback active)",
+                  dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase");
       return;
    }
 
    if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d out of bounds)",
+                  dsa ? "glTransformFeedbackBufferBase" : "glBindBufferBase",
+                  index);
       return;
    }
 
-   bind_buffer_range(ctx, index, bufObj, 0, 0);
+   bind_buffer_range(ctx, obj, index, bufObj, 0, 0, dsa);
 }
 
+/**
+ * Wrapper around lookup_transform_feedback_object that throws
+ * GL_INVALID_OPERATION if id is not in the hash table. After calling
+ * _mesa_error, it returns NULL.
+ */
+static struct gl_transform_feedback_object *
+lookup_transform_feedback_object_err(struct gl_context *ctx,
+                                     GLuint xfb, const char* func)
+{
+   struct gl_transform_feedback_object *obj;
+
+   obj = _mesa_lookup_transform_feedback_object(ctx, xfb);
+   if (!obj) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(xfb=%u: non-generated object name)", func, xfb);
+   }
+
+   return obj;
+}
+
+/**
+ * Wrapper around _mesa_lookup_bufferobj that throws GL_INVALID_VALUE if id
+ * is not in the hash table. Specialised version for the
+ * transform-feedback-related functions. After calling _mesa_error, it
+ * returns NULL.
+ */
+static struct gl_buffer_object *
+lookup_transform_feedback_bufferobj_err(struct gl_context *ctx,
+                                        GLuint buffer, const char* func)
+{
+   struct gl_buffer_object *bufObj;
+
+   /* OpenGL 4.5 core profile, 13.2, pdf page 444: buffer must be zero or the
+    * name of an existing buffer object.
+    */
+   if (buffer == 0) {
+      bufObj = ctx->Shared->NullBufferObj;
+   } else {
+      bufObj = _mesa_lookup_bufferobj(ctx, buffer);
+      if (!bufObj) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid buffer=%u)", func,
+                     buffer);
+      }
+   }
+
+   return bufObj;
+}
+
+void GLAPIENTRY
+_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_transform_feedback_object *obj;
+   struct gl_buffer_object *bufObj;
+
+   obj = lookup_transform_feedback_object_err(ctx, xfb,
+                                              "glTransformFeedbackBufferBase");
+   if(!obj) {
+      return;
+   }
+
+   bufObj = lookup_transform_feedback_bufferobj_err(ctx, buffer,
+                                              "glTransformFeedbackBufferBase");
+   if(!bufObj) {
+      return;
+   }
+
+   _mesa_bind_buffer_base_transform_feedback(ctx, obj, index, bufObj, true);
+}
 
 /**
  * Specify a buffer object to receive transform feedback results, plus the
@@ -660,7 +732,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
       return;
    }
 
-   bind_buffer_range(ctx, index, bufObj, offset, 0);
+   bind_buffer_range(ctx, obj, index, bufObj, offset, 0, false);
 }
 
 
@@ -817,6 +889,10 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
 struct gl_transform_feedback_object *
 _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
 {
+   /* OpenGL 4.5 core profile, 13.2 pdf page 444: "xfb must be zero, indicating
+    * the default transform feedback object, or the name of an existing
+    * transform feedback object."
+    */
    if (name == 0) {
       return ctx->TransformFeedback.DefaultObject;
    }
index 9de1fef21377e3820b2949f2a7fd7b98f3865afe..aac7433d14b282ae5bb3e8517500cd714c6d7a82 100644 (file)
@@ -65,6 +65,7 @@ _mesa_EndTransformFeedback(void);
 
 extern void
 _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
+                                          struct gl_transform_feedback_object *obj,
                                           GLuint index,
                                           struct gl_buffer_object *bufObj,
                                           GLintptr offset,
@@ -72,8 +73,10 @@ _mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
 
 extern void
 _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
+                                         struct gl_transform_feedback_object *obj,
                                          GLuint index,
-                                         struct gl_buffer_object *bufObj);
+                                         struct gl_buffer_object *bufObj,
+                                         bool dsa);
 
 extern void GLAPIENTRY
 _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
@@ -144,4 +147,9 @@ _mesa_set_transform_feedback_binding(struct gl_context *ctx,
    tfObj->RequestedSize[index] = size;
 }
 
+/*** GL_ARB_direct_state_access ***/
+
+extern void GLAPIENTRY
+_mesa_TransformFeedbackBufferBase(GLuint xfb, GLuint index, GLuint buffer);
+
 #endif /* TRANSFORM_FEEDBACK_H */