1de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/*
2de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Mesa 3-D graphics library
3de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
4de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Copyright (C) 2010  VMware, Inc.  All Rights Reserved.
5de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
6de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
7de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * copy of this software and associated documentation files (the "Software"),
8de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to deal in the Software without restriction, including without limitation
9de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * and/or sell copies of the Software, and to permit persons to whom the
11de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Software is furnished to do so, subject to the following conditions:
12de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
13de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * The above copyright notice and this permission notice shall be included
14de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * in all copies or substantial portions of the Software.
15de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
16de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
23de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
24de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
25de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/*
26de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Vertex transform feedback support.
27de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
28de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Authors:
29de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *   Brian Paul
30de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
31de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
32de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
33de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "buffers.h"
34de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "bufferobj.h"
35de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "context.h"
36fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul#include "hash.h"
37db61b9ce39bccc43140357652ceb78baaf2aea44Vinson Lee#include "mfeatures.h"
380117da40cd7edd3d165bb28569c289b37eca12b9Vinson Lee#include "mtypes.h"
39de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "transformfeedback.h"
40a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul#include "shaderapi.h"
41a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul#include "shaderobj.h"
42b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#include "main/dispatch.h"
43de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
44ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_parameter.h"
45de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
46de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
47b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#if FEATURE_EXT_transform_feedback
48b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
49b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
50de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
51fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Do reference counting of transform feedback buffers.
52fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
53fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
54fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulreference_transform_feedback_object(struct gl_transform_feedback_object **ptr,
55fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                    struct gl_transform_feedback_object *obj)
56fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
57fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (*ptr == obj)
58fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
59fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
60fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (*ptr) {
61fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      /* Unreference the old object */
62fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      struct gl_transform_feedback_object *oldObj = *ptr;
63fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
64fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ASSERT(oldObj->RefCount > 0);
65fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      oldObj->RefCount--;
66fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
67fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      if (oldObj->RefCount == 0) {
68fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         GET_CURRENT_CONTEXT(ctx);
69fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (ctx)
70fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            ctx->Driver.DeleteTransformFeedback(ctx, oldObj);
71fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
72fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
73fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      *ptr = NULL;
74fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
75fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT(!*ptr);
76fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
77fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj) {
78fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      /* reference new object */
79fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      if (obj->RefCount == 0) {
80fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_problem(NULL, "referencing deleted transform feedback object");
81fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         *ptr = NULL;
82fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
83fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      else {
84fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         obj->RefCount++;
85fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         *ptr = obj;
86fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
87fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
88fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
89fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
90fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
91fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
92de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check that all the buffer objects currently bound for transform
93de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * feedback actually exist.  Raise a GL_INVALID_OPERATION error if
94de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * any buffers are missing.
95de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE for success, GL_FALSE if error
96de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
97de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean
98f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_validate_transform_feedback_buffers(struct gl_context *ctx)
99de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
100fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* XXX to do */
101de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   return GL_TRUE;
102de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
103de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
104de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
105de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
106de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
107de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context init for transform feedback.
108de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
109de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
110f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_transform_feedback(struct gl_context *ctx)
111de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
11232a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   /* core mesa expects this, even a dummy one, to be available */
11332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ASSERT(ctx->Driver.NewTransformFeedback);
114fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
115fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.DefaultObject =
116fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ctx->Driver.NewTransformFeedback(ctx, 0);
117fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
118fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->TransformFeedback.DefaultObject->RefCount == 1);
119fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
120fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject,
121fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                       ctx->TransformFeedback.DefaultObject);
122fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
123fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->TransformFeedback.DefaultObject->RefCount == 2);
124fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
125fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.Objects = _mesa_NewHashTable();
126fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
127de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
128de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
129de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 ctx->Shared->NullBufferObj);
130de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
131de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
132de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
133fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
134fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
135fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Callback for _mesa_HashDeleteAll().
136fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
137fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
138fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldelete_cb(GLuint key, void *data, void *userData)
139fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
140f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
141fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
142fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      (struct gl_transform_feedback_object *) data;
143fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
144fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.DeleteTransformFeedback(ctx, obj);
145fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
146fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
147fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
148de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
149de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context free/clean-up for transform feedback.
150de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
151de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
152f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_free_transform_feedback(struct gl_context *ctx)
153de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
15432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   /* core mesa expects this, even a dummy one, to be available */
15532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ASSERT(ctx->Driver.NewTransformFeedback);
156fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
157de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
158de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
159de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 NULL);
160fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
161fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* Delete all feedback objects */
162fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   _mesa_HashDeleteAll(ctx->TransformFeedback.Objects, delete_cb, ctx);
1635b90f83aee89d051983485cdec5b5db2f3659256Brian Paul   _mesa_DeleteHashTable(ctx->TransformFeedback.Objects);
164fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
165fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* Delete the default feedback object */
166fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.DeleteTransformFeedback);
16739c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul   ctx->Driver.DeleteTransformFeedback(ctx,
16839c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul                                       ctx->TransformFeedback.DefaultObject);
169fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
170fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.CurrentObject = NULL;
171de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
172de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
173de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
17432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu#else /* FEATURE_EXT_transform_feedback */
17532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
17632a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu/* forward declarations */
17732a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wustatic struct gl_transform_feedback_object *
178f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnew_transform_feedback(struct gl_context *ctx, GLuint name);
17932a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
18032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wustatic void
181f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergdelete_transform_feedback(struct gl_context *ctx,
18232a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                          struct gl_transform_feedback_object *obj);
18332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
18432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu/* dummy per-context init/clean-up for transform feedback */
18532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wuvoid
186f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_transform_feedback(struct gl_context *ctx)
18732a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu{
18832a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ctx->TransformFeedback.DefaultObject = new_transform_feedback(ctx, 0);
18932a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ctx->TransformFeedback.CurrentObject = ctx->TransformFeedback.DefaultObject;
19032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   _mesa_reference_buffer_object(ctx,
19132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 &ctx->TransformFeedback.CurrentBuffer,
19232a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 ctx->Shared->NullBufferObj);
19332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu}
19432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
19532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wuvoid
196f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_free_transform_feedback(struct gl_context *ctx)
19732a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu{
19832a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   _mesa_reference_buffer_object(ctx,
19932a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 &ctx->TransformFeedback.CurrentBuffer,
20032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 NULL);
20132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ctx->TransformFeedback.CurrentObject = NULL;
20232a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   delete_transform_feedback(ctx, ctx->TransformFeedback.DefaultObject);
20332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu}
20432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
20532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu#endif /* FEATURE_EXT_transform_feedback */
20632a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
20732a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
208fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.NewTransformFeedback() */
209fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic struct gl_transform_feedback_object *
210f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnew_transform_feedback(struct gl_context *ctx, GLuint name)
211fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
212fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
213fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = CALLOC_STRUCT(gl_transform_feedback_object);
214fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj) {
215fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      obj->Name = name;
216fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      obj->RefCount = 1;
217fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
218fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   return obj;
219fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
220fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
221fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.DeleteTransformFeedback() */
222fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
223f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergdelete_transform_feedback(struct gl_context *ctx,
224fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                          struct gl_transform_feedback_object *obj)
225fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
226fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLuint i;
227fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
228fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   for (i = 0; i < Elements(obj->Buffers); i++) {
229fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL);
230fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
231fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
232fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   free(obj);
233fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
234fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
23532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
23632a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu#if FEATURE_EXT_transform_feedback
23732a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
23832a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
239fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.BeginTransformFeedback() */
240fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
241f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergbegin_transform_feedback(struct gl_context *ctx, GLenum mode,
242fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         struct gl_transform_feedback_object *obj)
243fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
244fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
245fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
246fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
247fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.EndTransformFeedback() */
248fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
249f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergend_transform_feedback(struct gl_context *ctx,
250fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                       struct gl_transform_feedback_object *obj)
251fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
252fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
253fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
254fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
255fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.PauseTransformFeedback() */
256fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
257f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergpause_transform_feedback(struct gl_context *ctx,
258fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         struct gl_transform_feedback_object *obj)
259fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
260fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
261fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
262fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
263fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.ResumeTransformFeedback() */
264fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
265f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergresume_transform_feedback(struct gl_context *ctx,
266fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                          struct gl_transform_feedback_object *obj)
267fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
268fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
269fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
270fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
271fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
272fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
273fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Plug in default device driver functions for transform feedback.
274fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Most drivers will override some/all of these.
275fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
276fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid
277fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_init_transform_feedback_functions(struct dd_function_table *driver)
278fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
279fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->NewTransformFeedback = new_transform_feedback;
280fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->DeleteTransformFeedback = delete_transform_feedback;
281fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->BeginTransformFeedback = begin_transform_feedback;
282fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->EndTransformFeedback = end_transform_feedback;
283fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->PauseTransformFeedback = pause_transform_feedback;
284fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->ResumeTransformFeedback = resume_transform_feedback;
285fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
286fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
287fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
288b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wuvoid
289b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu_mesa_init_transform_feedback_dispatch(struct _glapi_table *disp)
290b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu{
29148dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   /* EXT_transform_feedback */
292b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BeginTransformFeedbackEXT(disp, _mesa_BeginTransformFeedback);
293b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_EndTransformFeedbackEXT(disp, _mesa_EndTransformFeedback);
294b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BindBufferOffsetEXT(disp, _mesa_BindBufferOffsetEXT);
295b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_TransformFeedbackVaryingsEXT(disp, _mesa_TransformFeedbackVaryings);
296b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_GetTransformFeedbackVaryingEXT(disp, _mesa_GetTransformFeedbackVarying);
29748dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   /* ARB_transform_feedback2 */
29848dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_BindTransformFeedback(disp, _mesa_BindTransformFeedback);
29948dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_DeleteTransformFeedbacks(disp, _mesa_DeleteTransformFeedbacks);
30048dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_GenTransformFeedbacks(disp, _mesa_GenTransformFeedbacks);
30148dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_IsTransformFeedback(disp, _mesa_IsTransformFeedback);
30248dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_PauseTransformFeedback(disp, _mesa_PauseTransformFeedback);
30348dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_ResumeTransformFeedback(disp, _mesa_ResumeTransformFeedback);
304b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu}
305b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
306fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
307fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
308fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ** Begin API functions
309fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul **/
310fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
311fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
312de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
313de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BeginTransformFeedback(GLenum mode)
314de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
315fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
316ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry   struct gl_transform_feedback_info *info;
317ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry   int i;
318de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
319de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
320fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
32186bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry
32286bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry   if (ctx->Shader.CurrentVertexProgram == NULL) {
32386bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry      _mesa_error(ctx, GL_INVALID_OPERATION,
32486bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry                  "glBeginTransformFeedback(no program active)");
32586bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry      return;
32686bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry   }
32786bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry
328ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry   info = &ctx->Shader.CurrentVertexProgram->LinkedTransformFeedback;
329fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
33086bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry   if (info->NumOutputs == 0) {
33186bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry      _mesa_error(ctx, GL_INVALID_OPERATION,
33286bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry                  "glBeginTransformFeedback(no varyings to record)");
33386bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry      return;
33486bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry   }
33586bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry
336de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (mode) {
337de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_POINTS:
338de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_LINES:
339de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_TRIANGLES:
340de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* legal */
341de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
342de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
343de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)");
344de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
345de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
346de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
347fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
348de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
349de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBeginTransformFeedback(already active)");
350de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
351de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
352de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
353ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry   for (i = 0; i < info->NumBuffers; ++i) {
354ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry      if (obj->BufferNames[i] == 0) {
355ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry         _mesa_error(ctx, GL_INVALID_OPERATION,
356ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry                     "glBeginTransformFeedback(binding point %d does not have "
357ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry                     "a buffer object bound)", i);
358ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry         return;
359ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry      }
360ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry   }
361ebfad9f6a125738b9bfc5d5f7d09a8b57856674aPaul Berry
362a98ceee0ee3692783047c6f8f9f6bf6afbf4dd3bPaul Berry   FLUSH_VERTICES(ctx, _NEW_TRANSFORM_FEEDBACK);
363fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Active = GL_TRUE;
364de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Mode = mode;
365fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
366fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.BeginTransformFeedback);
367fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.BeginTransformFeedback(ctx, mode, obj);
368de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
369de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
370de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
371de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
372de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_EndTransformFeedback(void)
373de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
374fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
375de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
376de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
377fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
378fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
379fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active) {
380de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
381de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glEndTransformFeedback(not active)");
382de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
383de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
384de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
385a98ceee0ee3692783047c6f8f9f6bf6afbf4dd3bPaul Berry   FLUSH_VERTICES(ctx, _NEW_TRANSFORM_FEEDBACK);
386fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.CurrentObject->Active = GL_FALSE;
38708ce48733d9441e1daa779027dbea1ce9964cc77Paul Berry   ctx->TransformFeedback.CurrentObject->Paused = GL_FALSE;
38814bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák   ctx->TransformFeedback.CurrentObject->EndedAnytime = GL_TRUE;
389fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
390fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.EndTransformFeedback);
391fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.EndTransformFeedback(ctx, obj);
392de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
393de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
394de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
395de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
396de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Helper used by BindBufferRange() and BindBufferBase().
397de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
398de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulstatic void
399f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergbind_buffer_range(struct gl_context *ctx, GLuint index,
400de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  struct gl_buffer_object *bufObj,
401de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  GLintptr offset, GLsizeiptr size)
402de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
403fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
404fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ctx->TransformFeedback.CurrentObject;
405291ae4e6396872679fef72ed4fdd46fb7f945c3dPaul Berry
406291ae4e6396872679fef72ed4fdd46fb7f945c3dPaul Berry   /* Note: no need to FLUSH_VERTICES or flag _NEW_TRANSFORM_FEEDBACK, because
407291ae4e6396872679fef72ed4fdd46fb7f945c3dPaul Berry    * transform feedback buffers can't be changed while transform feedback is
408291ae4e6396872679fef72ed4fdd46fb7f945c3dPaul Berry    * active.
409291ae4e6396872679fef72ed4fdd46fb7f945c3dPaul Berry    */
410fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
411de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The general binding point */
412de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
413de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
414de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
415de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
416de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The per-attribute binding point */
417de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
418fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                 &obj->Buffers[index],
419de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
420de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
421fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->BufferNames[index] = bufObj->Name;
422de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
423fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Offset[index] = offset;
424fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Size[index] = size;
425de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
426de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
427de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
428de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
429de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.  Plus,
430de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * specify the starting offset to place the results, and max size.
431d988ea5e810868244eb1a1e7ede32295c9ed9ad4Brian Paul * Called from the glBindBufferRange() function.
432de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
433b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholtvoid
434b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt_mesa_bind_buffer_range_transform_feedback(struct gl_context *ctx,
435b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt					   GLuint index,
436b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt					   struct gl_buffer_object *bufObj,
437b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt					   GLintptr offset,
438b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt					   GLsizeiptr size)
439de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
440fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
441de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
442fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
443fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
444fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
445de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
446de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
447de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
448de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
449de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
45015ac66e331abdab12e882d80a6b4f647bc905298Marek Olšák   if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
451de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
452de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
453de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
454de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
455b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt   if (size & 0x3) {
456b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt      /* must a multiple of four */
4571979e22e13dd28553bcc67cc51e56684e6ee4768Paul Berry      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", (int) size);
458de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
459de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
460de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
461de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (offset & 0x3) {
462de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* must be multiple of four */
463de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
4649eca0e2c3e9409b5da49d9a5052d3665e7d45bb1Brian Paul                  "glBindBufferRange(offset=%d)", (int) offset);
465de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
466de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
467de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
468de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
469de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
470de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
471de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
472de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
473de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.
474de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * As above, but start at offset = 0.
475d988ea5e810868244eb1a1e7ede32295c9ed9ad4Brian Paul * Called from the glBindBufferBase() function.
476de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
477b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholtvoid
478b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt_mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx,
479b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt					  GLuint index,
480b82c47215689d1243d1aa810bff7f06d8288d686Eric Anholt					  struct gl_buffer_object *bufObj)
481de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
482fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
483de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
484de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
485fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
486fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
487fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
488de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
4892be2e1d3ada2d9cb5c1c42e955629d8fbbafcd0bBrian Paul                  "glBindBufferBase(transform feedback active)");
490de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
491de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
492de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
49315ac66e331abdab12e882d80a6b4f647bc905298Marek Olšák   if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
494de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
495de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
496de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
497de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
498de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
499de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
500de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
501de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = bufObj->Size & ~0x3;
502de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
503de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, 0, size);
504de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
505de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
506de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
507de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
508de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results, plus the
509de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * offset in the buffer to start placing results.
510de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function is part of GL_EXT_transform_feedback, but not GL3.
511de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
512de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
513de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
514de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                          GLintptr offset)
515de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
516fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
517de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
518de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
519de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
520de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
521de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
522de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)");
523de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
524de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
525de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
526fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
527fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
528fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
529de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
5302be2e1d3ada2d9cb5c1c42e955629d8fbbafcd0bBrian Paul                  "glBindBufferOffsetEXT(transform feedback active)");
531de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
532de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
533de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
53415ac66e331abdab12e882d80a6b4f647bc905298Marek Olšák   if (index >= ctx->Const.MaxTransformFeedbackBuffers) {
535de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
536de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(index=%d)", index);
537de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
538de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
539de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
54086bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry   if (offset & 0x3) {
54186bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry      /* must be multiple of four */
54286bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry      _mesa_error(ctx, GL_INVALID_VALUE,
54386bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry                  "glBindBufferOffsetEXT(offset=%d)", (int) offset);
54486bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry      return;
54586bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry   }
54686bb45ffc36280263ba99fdca0c341489ad99e7fPaul Berry
54705b086ce934fa2967da736db8db429d0886735a9Kenneth Graunke   if (buffer == 0) {
54805b086ce934fa2967da736db8db429d0886735a9Kenneth Graunke      bufObj = ctx->Shared->NullBufferObj;
54905b086ce934fa2967da736db8db429d0886735a9Kenneth Graunke   } else {
55005b086ce934fa2967da736db8db429d0886735a9Kenneth Graunke      bufObj = _mesa_lookup_bufferobj(ctx, buffer);
55105b086ce934fa2967da736db8db429d0886735a9Kenneth Graunke   }
55205b086ce934fa2967da736db8db429d0886735a9Kenneth Graunke
553de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
554de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
555de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(invalid buffer=%u)", buffer);
556de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
557de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
558de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
559de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
560de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
561de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
562de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = (bufObj->Size - offset) & ~0x3;
563de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
564de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
565de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
566de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
567de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
568de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
569de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function specifies the vertex shader outputs to be written
570de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s), and in what order.
571de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
572de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
573de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
574de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                const GLchar **varyings, GLenum bufferMode)
575de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
576de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_shader_program *shProg;
577de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLuint i;
578de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
579de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
580de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (bufferMode) {
581de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_INTERLEAVED_ATTRIBS:
582de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
583de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_SEPARATE_ATTRIBS:
584de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
585de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
586de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM,
587de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(bufferMode)");
588de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
589de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
590de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
591f77aa278d354bebdbda940b31c9cccf12a5d146fMarek Olšák   if (count < 0 ||
592f77aa278d354bebdbda940b31c9cccf12a5d146fMarek Olšák       (bufferMode == GL_SEPARATE_ATTRIBS &&
59315ac66e331abdab12e882d80a6b4f647bc905298Marek Olšák        (GLuint) count > ctx->Const.MaxTransformFeedbackBuffers)) {
594de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
595de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(count=%d)", count);
596de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
597de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
598de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
599de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
600de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
601de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
602de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(program=%u)", program);
603de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
604de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
605de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
606375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák   if (ctx->Extensions.ARB_transform_feedback3) {
607375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák      if (bufferMode == GL_INTERLEAVED_ATTRIBS) {
608375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák         unsigned buffers = 1;
609375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák
610375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák         for (i = 0; i < count; i++) {
611375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák            if (strcmp(varyings[i], "gl_NextBuffer") == 0)
612375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák               buffers++;
613375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák         }
614375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák
615375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák         if (buffers > ctx->Const.MaxTransformFeedbackBuffers) {
616375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák            _mesa_error(ctx, GL_INVALID_OPERATION,
617375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                        "glTransformFeedbackVaryings(too many gl_NextBuffer "
618375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                        "occurences)");
619375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák            return;
620375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák         }
621375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák      } else {
622375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák         for (i = 0; i < count; i++) {
623375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák            if (strcmp(varyings[i], "gl_NextBuffer") == 0 ||
624375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                strcmp(varyings[i], "gl_SkipComponents1") == 0 ||
625375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                strcmp(varyings[i], "gl_SkipComponents2") == 0 ||
626375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                strcmp(varyings[i], "gl_SkipComponents3") == 0 ||
627375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                strcmp(varyings[i], "gl_SkipComponents4") == 0) {
628375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák               _mesa_error(ctx, GL_INVALID_OPERATION,
629375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                           "glTransformFeedbackVaryings(SEPARATE_ATTRIBS,"
630375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                           "varying=%s)",
631375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák                           varyings[i]);
632375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák               return;
633375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák            }
634375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák         }
635375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák      }
636375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák   }
637375e73d85948b43aa509e25f0a210ebd10238b6fMarek Olšák
638de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* free existing varyings, if any */
639de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
640de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      free(shProg->TransformFeedback.VaryingNames[i]);
641de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
642de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   free(shProg->TransformFeedback.VaryingNames);
643de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
644de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* allocate new memory for varying names */
645de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.VaryingNames =
646de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      (GLchar **) malloc(count * sizeof(GLchar *));
647de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
648de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg->TransformFeedback.VaryingNames) {
649de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()");
650de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
651de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
652de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
653de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* Save the new names and the count */
654de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < (GLuint) count; i++) {
655de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]);
656de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
657de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.NumVarying = count;
658de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
659de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.BufferMode = bufferMode;
660de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
661a98ceee0ee3692783047c6f8f9f6bf6afbf4dd3bPaul Berry   /* No need to set _NEW_TRANSFORM_FEEDBACK (or invoke FLUSH_VERTICES) since
662a98ceee0ee3692783047c6f8f9f6bf6afbf4dd3bPaul Berry    * the varyings won't be used until shader link time.
663a98ceee0ee3692783047c6f8f9f6bf6afbf4dd3bPaul Berry    */
664de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
665de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
666de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
667de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
668de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Get info about the vertex shader's outputs which are to be written
669de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s).
670de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
671de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
672de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
673de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei bufSize, GLsizei *length,
674de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei *size, GLenum *type, GLchar *name)
675de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
676de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   const struct gl_shader_program *shProg;
6779d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   const struct gl_transform_feedback_info *linked_xfb_info;
678de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
679de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
680de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
681de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
682de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
683de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(program=%u)", program);
684de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
685de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
686de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
6879d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   linked_xfb_info = &shProg->LinkedTransformFeedback;
6889d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   if (index >= linked_xfb_info->NumVarying) {
689de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
690de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(index=%u)", index);
691de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
692de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
693de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
6949d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   /* return the varying's name and length */
6959d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   _mesa_copy_string(name, bufSize, length,
6969d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt		     linked_xfb_info->Varyings[index].Name);
697de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
6989d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   /* return the datatype and value's size (in datatype units) */
6999d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   if (type)
7009d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt      *type = linked_xfb_info->Varyings[index].Type;
7019d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt   if (size)
7029d36c96d6ec9f2c05c8e0b9ef18c5462cddee8c1Eric Anholt      *size = linked_xfb_info->Varyings[index].Size;
703de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
704de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
705fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
706fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
70714bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšákstruct gl_transform_feedback_object *
70814bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
709fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
710fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (name == 0) {
711fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return ctx->TransformFeedback.DefaultObject;
712fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
713fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else
714fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return (struct gl_transform_feedback_object *)
715fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_HashLookup(ctx->TransformFeedback.Objects, name);
716fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
717fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
718fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
719fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
720fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Create new transform feedback objects.   Transform feedback objects
721fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * encapsulate the state related to transform feedback to allow quickly
722fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * switching state (and drawing the results, below).
723fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
724fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
725fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
726fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
727fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
728fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLuint first;
729fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
730fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
731fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END(ctx);
732fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
733fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (n < 0) {
734fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)");
735fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
736fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
737fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
738fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!names)
739fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
740fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
741fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* we don't need contiguous IDs, but this might be faster */
742fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   first = _mesa_HashFindFreeKeyBlock(ctx->TransformFeedback.Objects, n);
743fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (first) {
744fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      GLsizei i;
745fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      for (i = 0; i < n; i++) {
746fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         struct gl_transform_feedback_object *obj
747fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            = ctx->Driver.NewTransformFeedback(ctx, first + i);
748fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (!obj) {
749fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
750fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            return;
751fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         }
752fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         names[i] = first + i;
753fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj);
754fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
755fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
756fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else {
757fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
758fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
759fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
760fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
761fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
762fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
763fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Is the given ID a transform feedback object?
764fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
765fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
766fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGLboolean GLAPIENTRY
767fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_IsTransformFeedback(GLuint name)
768fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
769fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
770fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
771fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
772fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
77314bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák   if (name && _mesa_lookup_transform_feedback_object(ctx, name))
774fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return GL_TRUE;
775fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else
776fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return GL_FALSE;
777fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
778fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
779fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
780fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
781fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Bind the given transform feedback object.
782fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
783fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
784fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
785d74f525060f779cfe449c20853b11ba2bbcdea6dVinson Lee_mesa_BindTransformFeedback(GLenum target, GLuint name)
786fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
787fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
788fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
789fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
790fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (target != GL_TRANSFORM_FEEDBACK) {
791fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindTransformFeedback(target)");
792fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
793fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
794fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
795fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (ctx->TransformFeedback.CurrentObject->Active &&
796fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul       !ctx->TransformFeedback.CurrentObject->Paused) {
797fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
79839c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul              "glBindTransformFeedback(transform is active, or not paused)");
799fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
800fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
801fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
80214bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák   obj = _mesa_lookup_transform_feedback_object(ctx, name);
803fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj) {
804fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
805fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                  "glBindTransformFeedback(name=%u)", name);
806fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
807fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
808fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
809fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject,
810fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                       obj);
811fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
812fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
813fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
814fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
815fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Delete the given transform feedback objects.
816fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
817fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
818fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
819fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names)
820fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
821fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLint i;
822fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
823fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
824fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END(ctx);
825fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
826fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (n < 0) {
827fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTransformFeedbacks(n < 0)");
828fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
829fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
830fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
831fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!names)
832fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
833fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
834fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   for (i = 0; i < n; i++) {
835fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      if (names[i] > 0) {
836fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         struct gl_transform_feedback_object *obj
83714bb957b996dcc5392b8fa589bd3ffa5c55cb6b4Marek Olšák            = _mesa_lookup_transform_feedback_object(ctx, names[i]);
838fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (obj) {
839fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            if (obj->Active) {
840fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul               _mesa_error(ctx, GL_INVALID_OPERATION,
841fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                           "glDeleteTransformFeedbacks(object %u is active)",
842fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                           names[i]);
843fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul               return;
844fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            }
845fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            _mesa_HashRemove(ctx->TransformFeedback.Objects, names[i]);
846fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            /* unref, but object may not be deleted until later */
847fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            reference_transform_feedback_object(&obj, NULL);
848fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         }
849fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
850fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
851fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
852fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
853fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
854fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
855fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Pause transform feedback.
856fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
857fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
858fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
859fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_PauseTransformFeedback(void)
860fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
861fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
862fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
863fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
864fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
865fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
866fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active || obj->Paused) {
867fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
868fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul           "glPauseTransformFeedback(feedback not active or already paused)");
869fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
870fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
871fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
872a98ceee0ee3692783047c6f8f9f6bf6afbf4dd3bPaul Berry   FLUSH_VERTICES(ctx, _NEW_TRANSFORM_FEEDBACK);
873fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Paused = GL_TRUE;
874fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
875fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.PauseTransformFeedback);
876fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.PauseTransformFeedback(ctx, obj);
877fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
878fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
879fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
880fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
881fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Resume transform feedback.
882fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
883fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
884fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
885fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_ResumeTransformFeedback(void)
886fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
887fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
888fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
889fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
890fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
891fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
892fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active || !obj->Paused) {
893fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
894076bd11112742ca615880f2c6dc6ed235ab37eb5Brian Paul               "glResumeTransformFeedback(feedback not active or not paused)");
895fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
896fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
897fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
898a98ceee0ee3692783047c6f8f9f6bf6afbf4dd3bPaul Berry   FLUSH_VERTICES(ctx, _NEW_TRANSFORM_FEEDBACK);
899fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Paused = GL_FALSE;
900fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
901fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.ResumeTransformFeedback);
902fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.ResumeTransformFeedback(ctx, obj);
903fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
904fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
905b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#endif /* FEATURE_EXT_transform_feedback */
906