[Mesa-dev] [PATCH 2/2] mesa: implement DrawTransformFeedback from ARB_transform_feedback2

Marek Olšák maraeo at gmail.com
Fri Nov 4 17:42:41 PDT 2011


It's like DrawArrays, but the count is taken from a transform feedback
object.

This removes DrawTransformFeedback from dd_function_table and adds the same
function to GLvertexformat (with the function parameters matching GL).

The vbo_draw_func callback has a new parameter
"struct gl_transform_feedback_object *tfb_vertcount".

The rest of the code just validates states and forwards the transform
feedback object into vbo_draw_func.
---
 src/mesa/drivers/dri/i965/brw_draw.c         |    3 +-
 src/mesa/drivers/dri/i965/brw_draw.h         |    3 +-
 src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c |   15 +++--
 src/mesa/main/api_validate.c                 |   34 +++++++++
 src/mesa/main/api_validate.h                 |   10 +++
 src/mesa/main/dd.h                           |    3 +-
 src/mesa/main/mtypes.h                       |    2 +
 src/mesa/main/transformfeedback.c            |   65 ++----------------
 src/mesa/main/transformfeedback.h            |    6 +-
 src/mesa/main/varray.h                       |    7 ++
 src/mesa/main/vtxfmt.c                       |    1 +
 src/mesa/state_tracker/st_cb_rasterpos.c     |    3 +-
 src/mesa/state_tracker/st_cb_xformfb.c       |   13 ----
 src/mesa/state_tracker/st_draw.c             |    4 +-
 src/mesa/state_tracker/st_draw.h             |    6 +-
 src/mesa/state_tracker/st_draw_feedback.c    |    3 +-
 src/mesa/tnl/t_draw.c                        |    3 +-
 src/mesa/tnl/tnl.h                           |    3 +-
 src/mesa/vbo/vbo.h                           |    4 +-
 src/mesa/vbo/vbo_exec_array.c                |   93 ++++++++++++++++++++++++--
 src/mesa/vbo/vbo_exec_draw.c                 |    3 +-
 src/mesa/vbo/vbo_rebase.c                    |    3 +-
 src/mesa/vbo/vbo_save_api.c                  |   11 +++
 src/mesa/vbo/vbo_save_draw.c                 |    3 +-
 src/mesa/vbo/vbo_split_copy.c                |    3 +-
 src/mesa/vbo/vbo_split_inplace.c             |    3 +-
 26 files changed, 207 insertions(+), 100 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 1571fb7..4c53cf5 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -414,7 +414,8 @@ void brw_draw_prims( struct gl_context *ctx,
 		     const struct _mesa_index_buffer *ib,
 		     GLboolean index_bounds_valid,
 		     GLuint min_index,
-		     GLuint max_index )
+		     GLuint max_index,
+		     struct gl_transform_feedback_object *tfb_vertcount )
 {
    bool retval;
 
diff --git a/src/mesa/drivers/dri/i965/brw_draw.h b/src/mesa/drivers/dri/i965/brw_draw.h
index 1fe4172..b910419 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.h
+++ b/src/mesa/drivers/dri/i965/brw_draw.h
@@ -41,7 +41,8 @@ void brw_draw_prims( struct gl_context *ctx,
 		     const struct _mesa_index_buffer *ib,
 		     GLboolean index_bounds_valid,
 		     GLuint min_index,
-		     GLuint max_index );
+		     GLuint max_index,
+		     struct gl_transform_feedback_object *tfb_vertcount );
 
 void brw_draw_init( struct brw_context *brw );
 void brw_draw_destroy( struct brw_context *brw );
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
index d8b331c..de04d18 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
@@ -219,7 +219,8 @@ TAG(vbo_render_prims)(struct gl_context *ctx, const struct gl_client_array **arr
 		      const struct _mesa_prim *prims, GLuint nr_prims,
 		      const struct _mesa_index_buffer *ib,
 		      GLboolean index_bounds_valid,
-		      GLuint min_index, GLuint max_index);
+		      GLuint min_index, GLuint max_index,
+		      struct gl_transform_feedback_object *tfb_vertcount);
 
 static GLboolean
 vbo_maybe_split(struct gl_context *ctx, const struct gl_client_array **arrays,
@@ -430,7 +431,8 @@ TAG(vbo_render_prims)(struct gl_context *ctx,
 		      const struct _mesa_prim *prims, GLuint nr_prims,
 		      const struct _mesa_index_buffer *ib,
 		      GLboolean index_bounds_valid,
-		      GLuint min_index, GLuint max_index)
+		      GLuint min_index, GLuint max_index,
+		      struct gl_transform_feedback_object *tfb_vertcount)
 {
 	struct nouveau_render_state *render = to_render_state(ctx);
 
@@ -464,7 +466,8 @@ TAG(vbo_check_render_prims)(struct gl_context *ctx,
 			    const struct _mesa_prim *prims, GLuint nr_prims,
 			    const struct _mesa_index_buffer *ib,
 			    GLboolean index_bounds_valid,
-			    GLuint min_index, GLuint max_index)
+			    GLuint min_index, GLuint max_index,
+			    struct gl_transform_feedback_object *tfb_vertcount)
 {
 	struct nouveau_context *nctx = to_nouveau_context(ctx);
 
@@ -472,11 +475,13 @@ TAG(vbo_check_render_prims)(struct gl_context *ctx,
 
 	if (nctx->fallback == HWTNL)
 		TAG(vbo_render_prims)(ctx, arrays, prims, nr_prims, ib,
-				      index_bounds_valid, min_index, max_index);
+				      index_bounds_valid, min_index, max_index,
+				      tfb_vertcount);
 
 	if (nctx->fallback == SWTNL)
 		_tnl_vbo_draw_prims(ctx, arrays, prims, nr_prims, ib,
-				    index_bounds_valid, min_index, max_index);
+				    index_bounds_valid, min_index, max_index,
+				    tfb_vertcount);
 }
 
 void
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index 1fcf5cd..5180af6 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -474,3 +474,37 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
 
    return GL_TRUE;
 }
+
+
+#if FEATURE_EXT_transform_feedback
+
+GLboolean
+_mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
+                                     GLenum mode,
+                                     struct gl_transform_feedback_object *obj)
+{
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+   if (!_mesa_valid_prim_mode(ctx, mode)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glDrawTransformFeedback(mode)");
+      return GL_FALSE;
+   }
+
+   if (!obj) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback(name)");
+      return GL_FALSE;
+   }
+
+   if (!obj->EndedAnytime) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback");
+      return GL_FALSE;
+   }
+
+   if (!check_valid_to_render(ctx, "glDrawTransformFeedback")) {
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+#endif
diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h
index 7d6a660..f494842 100644
--- a/src/mesa/main/api_validate.h
+++ b/src/mesa/main/api_validate.h
@@ -29,9 +29,11 @@
 
 
 #include "glheader.h"
+#include "mfeatures.h"
 
 struct gl_buffer_object;
 struct gl_context;
+struct gl_transform_feedback_object;
 
 
 extern GLuint
@@ -70,5 +72,13 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
                                      const GLvoid *indices, GLsizei primcount,
                                      GLint basevertex);
 
+#if FEATURE_EXT_transform_feedback
+
+extern GLboolean
+_mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
+                                     GLenum mode,
+                                     struct gl_transform_feedback_object *obj);
+
+#endif
 
 #endif
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 9842540..6aa55f6 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -982,8 +982,6 @@ struct dd_function_table {
                                   struct gl_transform_feedback_object *obj);
    void (*ResumeTransformFeedback)(struct gl_context *ctx,
                                    struct gl_transform_feedback_object *obj);
-   void (*DrawTransformFeedback)(struct gl_context *ctx, GLenum mode,
-                                 struct gl_transform_feedback_object *obj);
 
    /**
     * \name GL_NV_texture_barrier interface
@@ -1212,6 +1210,7 @@ typedef struct {
    void (GLAPIENTRYP DrawElementsInstancedBaseVertex)(GLenum mode, GLsizei count,
                                             GLenum type, const GLvoid *indices,
                                             GLsizei primcount, GLint basevertex);
+   void (GLAPIENTRYP DrawTransformFeedback)(GLenum mode, GLuint name);
    /*@}*/
 
    /**
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 48dba4a..61db1b2 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2314,6 +2314,8 @@ struct gl_transform_feedback_object
    GLint RefCount;
    GLboolean Active;  /**< Is transform feedback enabled? */
    GLboolean Paused;  /**< Is transform feedback paused? */
+   GLboolean EndedAnytime; /**< Has EndTransformFeedback been called
+                                at least once? */
 
    /** The feedback buffers */
    GLuint BufferNames[MAX_FEEDBACK_ATTRIBS];
diff --git a/src/mesa/main/transformfeedback.c b/src/mesa/main/transformfeedback.c
index b5fb98e..e747bd5 100644
--- a/src/mesa/main/transformfeedback.c
+++ b/src/mesa/main/transformfeedback.c
@@ -294,18 +294,6 @@ resume_transform_feedback(struct gl_context *ctx,
    /* nop */
 }
 
-/** Default fallback for ctx->Driver.DrawTransformFeedback() */
-static void
-draw_transform_feedback(struct gl_context *ctx, GLenum mode,
-                        struct gl_transform_feedback_object *obj)
-{
-   /* XXX to do */
-   /*
-    * Get number of vertices in obj's feedback buffer.
-    * Call ctx->Exec.DrawArrays(mode, 0, count);
-    */
-}
-
 
 /**
  * Plug in default device driver functions for transform feedback.
@@ -320,7 +308,6 @@ _mesa_init_transform_feedback_functions(struct dd_function_table *driver)
    driver->EndTransformFeedback = end_transform_feedback;
    driver->PauseTransformFeedback = pause_transform_feedback;
    driver->ResumeTransformFeedback = resume_transform_feedback;
-   driver->DrawTransformFeedback = draw_transform_feedback;
 }
 
 
@@ -342,7 +329,6 @@ _mesa_init_transform_feedback_dispatch(struct _glapi_table *disp)
    SET_IsTransformFeedback(disp, _mesa_IsTransformFeedback);
    SET_PauseTransformFeedback(disp, _mesa_PauseTransformFeedback);
    SET_ResumeTransformFeedback(disp, _mesa_ResumeTransformFeedback);
-   SET_DrawTransformFeedback(disp, _mesa_DrawTransformFeedback);
 }
 
 
@@ -398,10 +384,11 @@ _mesa_EndTransformFeedback(void)
       return;
    }
 
-   ctx->TransformFeedback.CurrentObject->Active = GL_FALSE;
-
    assert(ctx->Driver.EndTransformFeedback);
    ctx->Driver.EndTransformFeedback(ctx, obj);
+
+   ctx->TransformFeedback.CurrentObject->Active = GL_FALSE;
+   ctx->TransformFeedback.CurrentObject->EndedAnytime = GL_TRUE;
 }
 
 
@@ -709,8 +696,8 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
 
 
 
-static struct gl_transform_feedback_object *
-lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
+struct gl_transform_feedback_object *
+_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
 {
    if (name == 0) {
       return ctx->TransformFeedback.DefaultObject;
@@ -775,7 +762,7 @@ _mesa_IsTransformFeedback(GLuint name)
 
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
 
-   if (name && lookup_transform_feedback_object(ctx, name))
+   if (name && _mesa_lookup_transform_feedback_object(ctx, name))
       return GL_TRUE;
    else
       return GL_FALSE;
@@ -804,7 +791,7 @@ _mesa_BindTransformFeedback(GLenum target, GLuint name)
       return;
    }
 
-   obj = lookup_transform_feedback_object(ctx, name);
+   obj = _mesa_lookup_transform_feedback_object(ctx, name);
    if (!obj) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glBindTransformFeedback(name=%u)", name);
@@ -839,7 +826,7 @@ _mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names)
    for (i = 0; i < n; i++) {
       if (names[i] > 0) {
          struct gl_transform_feedback_object *obj
-            = lookup_transform_feedback_object(ctx, names[i]);
+            = _mesa_lookup_transform_feedback_object(ctx, names[i]);
          if (obj) {
             if (obj->Active) {
                _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -905,40 +892,4 @@ _mesa_ResumeTransformFeedback(void)
    ctx->Driver.ResumeTransformFeedback(ctx, obj);
 }
 
-
-/**
- * Draw the vertex data in a transform feedback object.
- * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
- * \param name  the transform feedback object
- * The number of vertices comes from the transform feedback object.
- * User still has to setup of the vertex attribute info with
- * glVertexPointer, glColorPointer, etc.
- * Part of GL_ARB_transform_feedback2.
- */
-void GLAPIENTRY
-_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   struct gl_transform_feedback_object *obj =
-      lookup_transform_feedback_object(ctx, name);
-
-   if (mode > GL_POLYGON) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glDrawTransformFeedback(mode=0x%x)", mode);
-      return;
-   }
-   if (!obj) {
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glDrawTransformFeedback(name = %u)", name);
-      return;
-   }
-
-   /* XXX check if EndTransformFeedback has never been called while
-    * the object was bound
-    */
-
-   assert(ctx->Driver.DrawTransformFeedback);
-   ctx->Driver.DrawTransformFeedback(ctx, mode, obj);
-}
-
 #endif /* FEATURE_EXT_transform_feedback */
diff --git a/src/mesa/main/transformfeedback.h b/src/mesa/main/transformfeedback.h
index 9447eff..8a6672d 100644
--- a/src/mesa/main/transformfeedback.h
+++ b/src/mesa/main/transformfeedback.h
@@ -87,6 +87,9 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
 
 /*** GL_ARB_transform_feedback2 ***/
 
+struct gl_transform_feedback_object *
+_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name);
+
 extern void GLAPIENTRY
 _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names);
 
@@ -105,9 +108,6 @@ _mesa_PauseTransformFeedback(void);
 extern void GLAPIENTRY
 _mesa_ResumeTransformFeedback(void);
 
-extern void GLAPIENTRY
-_mesa_DrawTransformFeedback(GLenum mode, GLuint name);
-
 #else /* FEATURE_EXT_transform_feedback */
 
 static inline GLboolean
diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
index 6fcc0a3..b6041bd 100644
--- a/src/mesa/main/varray.h
+++ b/src/mesa/main/varray.h
@@ -245,6 +245,13 @@ _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
 				  const GLvoid *indices,
 				  GLint basevertex);
 
+#if FEATURE_EXT_transform_feedback
+
+extern void GLAPIENTRY
+_mesa_DrawTransformFeedback(GLenum mode, GLuint name);
+
+#endif
+
 extern void GLAPIENTRY
 _mesa_PrimitiveRestartIndex(GLuint index);
 
diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c
index 03735d7..f3cca93 100644
--- a/src/mesa/main/vtxfmt.c
+++ b/src/mesa/main/vtxfmt.c
@@ -107,6 +107,7 @@ install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt )
    SET_DrawArraysInstancedARB(tab, vfmt->DrawArraysInstanced);
    SET_DrawElementsInstancedARB(tab, vfmt->DrawElementsInstanced);
    SET_DrawElementsInstancedBaseVertex(tab, vfmt->DrawElementsInstancedBaseVertex);
+   SET_DrawTransformFeedback(tab, vfmt->DrawTransformFeedback);
 
    /* GL_NV_vertex_program */
    SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV);
diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c
index 32d465c..2c21dc9 100644
--- a/src/mesa/state_tracker/st_cb_rasterpos.c
+++ b/src/mesa/state_tracker/st_cb_rasterpos.c
@@ -251,7 +251,8 @@ st_RasterPos(struct gl_context *ctx, const GLfloat v[4])
    rs->array[0].Ptr = (GLubyte *) v;
 
    /* draw the point */
-   st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1);
+   st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1,
+                        NULL);
 
    /* restore draw's rasterization stage depending on rendermode */
    if (ctx->RenderMode == GL_FEEDBACK) {
diff --git a/src/mesa/state_tracker/st_cb_xformfb.c b/src/mesa/state_tracker/st_cb_xformfb.c
index e415b18..a17b54d 100644
--- a/src/mesa/state_tracker/st_cb_xformfb.c
+++ b/src/mesa/state_tracker/st_cb_xformfb.c
@@ -105,18 +105,6 @@ st_resume_transform_feedback(struct gl_context *ctx,
 }
 
 
-static void
-st_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
-                           struct gl_transform_feedback_object *obj)
-{
-   /* XXX to do */
-   /*
-    * Get number of vertices in obj's feedback buffer.
-    * Call ctx->Exec.DrawArrays(mode, 0, count);
-    */
-}
-
-
 void
 st_init_xformfb_functions(struct dd_function_table *functions)
 {
@@ -128,7 +116,6 @@ st_init_xformfb_functions(struct dd_function_table *functions)
    functions->EndTransformFeedback = st_end_transform_feedback;
    functions->PauseTransformFeedback = st_pause_transform_feedback;
    functions->ResumeTransformFeedback = st_resume_transform_feedback;
-   functions->DrawTransformFeedback = st_draw_transform_feedback;
 }
 
 #endif /* FEATURE_EXT_transform_feedback */
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index ff3008a..4cebf76 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -848,7 +848,8 @@ st_draw_vbo(struct gl_context *ctx,
             const struct _mesa_index_buffer *ib,
 	    GLboolean index_bounds_valid,
             GLuint min_index,
-            GLuint max_index)
+            GLuint max_index,
+            struct gl_transform_feedback_object *tfb_vertcount)
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
@@ -861,6 +862,7 @@ st_draw_vbo(struct gl_context *ctx,
 
    /* Mesa core state should have been validated already */
    assert(ctx->NewState == 0x0);
+   assert(!tfb_vertcount);
 
    if (ib) {
       /* Gallium probably doesn't want this in some cases. */
diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h
index a7b50ce..2623cdb 100644
--- a/src/mesa/state_tracker/st_draw.h
+++ b/src/mesa/state_tracker/st_draw.h
@@ -55,7 +55,8 @@ st_draw_vbo(struct gl_context *ctx,
             const struct _mesa_index_buffer *ib,
 	    GLboolean index_bounds_valid,
             GLuint min_index,
-            GLuint max_index);
+            GLuint max_index,
+            struct gl_transform_feedback_object *tfb_vertcount);
 
 extern void
 st_feedback_draw_vbo(struct gl_context *ctx,
@@ -65,7 +66,8 @@ st_feedback_draw_vbo(struct gl_context *ctx,
                      const struct _mesa_index_buffer *ib,
 		     GLboolean index_bounds_valid,
                      GLuint min_index,
-                     GLuint max_index);
+                     GLuint max_index,
+                     struct gl_transform_feedback_object *tfb_vertcount);
 
 /* Internal function:
  */
diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c
index 96a08b3..1afbd36 100644
--- a/src/mesa/state_tracker/st_draw_feedback.c
+++ b/src/mesa/state_tracker/st_draw_feedback.c
@@ -98,7 +98,8 @@ st_feedback_draw_vbo(struct gl_context *ctx,
                      const struct _mesa_index_buffer *ib,
 		     GLboolean index_bounds_valid,
                      GLuint min_index,
-                     GLuint max_index)
+                     GLuint max_index,
+                     struct gl_transform_feedback_object *tfb_vertcount)
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c
index 03424d7..83ded19 100644
--- a/src/mesa/tnl/t_draw.c
+++ b/src/mesa/tnl/t_draw.c
@@ -430,7 +430,8 @@ void _tnl_vbo_draw_prims(struct gl_context *ctx,
 			 const struct _mesa_index_buffer *ib,
 			 GLboolean index_bounds_valid,
 			 GLuint min_index,
-			 GLuint max_index)
+			 GLuint max_index,
+			 struct gl_transform_feedback_object *tfb_vertcount)
 {
    if (!index_bounds_valid)
       vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h
index 24a0c72..d388981 100644
--- a/src/mesa/tnl/tnl.h
+++ b/src/mesa/tnl/tnl.h
@@ -92,7 +92,8 @@ _tnl_vbo_draw_prims( struct gl_context *ctx,
 		     const struct _mesa_index_buffer *ib,
 		     GLboolean index_bounds_valid,
 		     GLuint min_index,
-		     GLuint max_index);
+		     GLuint max_index,
+		     struct gl_transform_feedback_object *tfb_vertcount );
 
 extern void
 _mesa_load_tracked_matrices(struct gl_context *ctx);
diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index 9fbb07f..f357657 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -36,6 +36,7 @@
 
 struct gl_client_array;
 struct gl_context;
+struct gl_transform_feedback_object;
 
 struct _mesa_prim {
    GLuint mode:8;    /**< GL_POINTS, GL_LINES, GL_QUAD_STRIP, etc */
@@ -77,7 +78,8 @@ typedef void (*vbo_draw_func)( struct gl_context *ctx,
 			       const struct _mesa_index_buffer *ib,
 			       GLboolean index_bounds_valid,
 			       GLuint min_index,
-			       GLuint max_index );
+			       GLuint max_index,
+			       struct gl_transform_feedback_object *tfb_vertcount );
 
 
 
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 7023380..676bf07 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -34,6 +34,7 @@
 #include "main/bufferobj.h"
 #include "main/enums.h"
 #include "main/macros.h"
+#include "main/transformfeedback.h"
 
 #include "vbo_context.h"
 
@@ -638,7 +639,7 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
          /* draw one or two prims */
          check_buffers_are_unmapped(exec->array.inputs);
          vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
-                         GL_TRUE, start, start + count - 1);
+                         GL_TRUE, start, start + count - 1, NULL);
       }
    }
    else {
@@ -648,7 +649,8 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
 
       check_buffers_are_unmapped(exec->array.inputs);
       vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
-                      GL_TRUE, start, start + count - 1);
+                      GL_TRUE, start, start + count - 1,
+                      NULL);
    }
 }
 
@@ -854,7 +856,7 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
 
    check_buffers_are_unmapped(exec->array.inputs);
    vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
-		    index_bounds_valid, start, end );
+		    index_bounds_valid, start, end, NULL );
 }
 
 
@@ -1198,7 +1200,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
 
       check_buffers_are_unmapped(exec->array.inputs);
       vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
-		      GL_FALSE, ~0, ~0);
+		      GL_FALSE, ~0, ~0, NULL);
    } else {
       /* render one prim at a time */
       for (i = 0; i < primcount; i++) {
@@ -1223,7 +1225,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
 
          check_buffers_are_unmapped(exec->array.inputs);
          vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
-                         GL_FALSE, ~0, ~0);
+                         GL_FALSE, ~0, ~0, NULL);
       }
    }
 
@@ -1275,6 +1277,76 @@ vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
 				   basevertex);
 }
 
+#if FEATURE_EXT_transform_feedback
+
+static void
+vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
+                            struct gl_transform_feedback_object *obj,
+                            GLuint numInstances)
+{
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_exec_context *exec = &vbo->exec;
+   struct _mesa_prim prim[2];
+
+   vbo_bind_arrays(ctx);
+
+   /* Again... because we may have changed the bitmask of per-vertex varying
+    * attributes.  If we regenerate the fixed-function vertex program now
+    * we may be able to prune down the number of vertex attributes which we
+    * need in the shader.
+    */
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   /* init most fields to zero */
+   memset(prim, 0, sizeof(prim));
+   prim[0].begin = 1;
+   prim[0].end = 1;
+   prim[0].mode = mode;
+   prim[0].num_instances = numInstances;
+
+   /* Maybe we should do some primitive splitting for primitive restart
+    * (like in DrawArrays), but we have no way to know how many vertices
+    * will be rendered. */
+
+   check_buffers_are_unmapped(exec->array.inputs);
+   vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
+                   GL_TRUE, 0, 0, obj);
+}
+
+/**
+ * Like DrawArrays, but take the count from a transform feedback object.
+ * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
+ * \param name  the transform feedback object
+ * User still has to setup of the vertex attribute info with
+ * glVertexPointer, glColorPointer, etc.
+ * Part of GL_ARB_transform_feedback2.
+ */
+static void GLAPIENTRY
+vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_transform_feedback_object *obj =
+      _mesa_lookup_transform_feedback_object(ctx, name);
+
+   if (MESA_VERBOSE & VERBOSE_DRAW)
+      _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
+                  _mesa_lookup_enum_by_nr(mode), name);
+
+   if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) {
+      return;
+   }
+
+   FLUSH_CURRENT(ctx, 0);
+
+   if (!_mesa_valid_to_render(ctx, "glDrawTransformFeedback")) {
+      return;
+   }
+
+   vbo_draw_transform_feedback(ctx, mode, obj, 1);
+}
+
+#endif
 
 /**
  * Plug in the immediate-mode vertex array drawing commands into the
@@ -1293,6 +1365,7 @@ vbo_exec_array_init( struct vbo_exec_context *exec )
    exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
    exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
    exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex;
+   exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback;
 }
 
 
@@ -1368,3 +1441,13 @@ _mesa_MultiDrawElementsBaseVertex(GLenum mode,
    vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
 					primcount, basevertex);
 }
+
+#if FEATURE_EXT_transform_feedback
+
+void GLAPIENTRY
+_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
+{
+   vbo_exec_DrawTransformFeedback(mode, name);
+}
+
+#endif
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 8ffaaaa..817c88b 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -383,7 +383,8 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped)
 				       NULL,
 				       GL_TRUE,
 				       0,
-				       exec->vtx.vert_count - 1);
+				       exec->vtx.vert_count - 1,
+				       NULL);
 
 	 /* If using a real VBO, get new storage -- unless asked not to.
           */
diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c
index 97c8d12..597a8f4 100644
--- a/src/mesa/vbo/vbo_rebase.c
+++ b/src/mesa/vbo/vbo_rebase.c
@@ -233,7 +233,8 @@ void vbo_rebase_prims( struct gl_context *ctx,
 	 ib, 
 	 GL_TRUE,
 	 0, 
-	 max_index - min_index );
+	 max_index - min_index,
+	 NULL );
    
    if (tmp_indices)
       free(tmp_indices);
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index 87a52e8..cf448f7 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -933,6 +933,16 @@ _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
 
 
 static void GLAPIENTRY
+_save_DrawTransformFeedback(GLenum mode, GLuint name)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   (void) mode;
+   (void) name;
+   _mesa_compile_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback");
+}
+
+
+static void GLAPIENTRY
 _save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -1233,6 +1243,7 @@ _save_vtxfmt_init(struct gl_context *ctx)
    vfmt->DrawRangeElements = _save_DrawRangeElements;
    vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex;
    vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex;
+   vfmt->DrawTransformFeedback = _save_DrawTransformFeedback;
    /* Loops back into vfmt->DrawElements */
    vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
    vfmt->MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index 6cda831..fdf21ee 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -297,7 +297,8 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
                                       NULL,
                                       GL_TRUE,
                                       0,    /* Node is a VBO, so this is ok */
-                                      node->count - 1);
+                                      node->count - 1,
+                                      NULL);
       }
    }
 
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
index 4dcf71e..b53293c 100644
--- a/src/mesa/vbo/vbo_split_copy.c
+++ b/src/mesa/vbo/vbo_split_copy.c
@@ -196,7 +196,8 @@ flush( struct copy_context *copy )
 	       &copy->dstib,
 	       GL_TRUE,
 	       0,
-	       copy->dstbuf_nr - 1 );
+	       copy->dstbuf_nr - 1,
+	       NULL );
 
    /* Reset all pointers: 
     */
diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c
index f6aa576..9e596f6 100644
--- a/src/mesa/vbo/vbo_split_inplace.c
+++ b/src/mesa/vbo/vbo_split_inplace.c
@@ -89,7 +89,8 @@ static void flush_vertex( struct split_context *split )
 	       split->ib ? &ib : NULL,
 	       !split->ib,
 	       split->min_index,
-	       split->max_index);
+	       split->max_index,
+	       NULL);
 
    split->dstprim_nr = 0;
    split->min_index = ~0;
-- 
1.7.4.1



More information about the mesa-dev mailing list