transformfeedback.c revision 5b90f83aee89d051983485cdec5b5db2f3659256
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"
37de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "transformfeedback.h"
38a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul#include "shaderapi.h"
39a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul#include "shaderobj.h"
40b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#include "main/dispatch.h"
41de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
42ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_parameter.h"
43ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul//#include "program/shader_api.h"
44de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
45de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
46b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#if FEATURE_EXT_transform_feedback
47b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
48b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
49de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
50fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Do reference counting of transform feedback buffers.
51fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
52fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
53fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulreference_transform_feedback_object(struct gl_transform_feedback_object **ptr,
54fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                    struct gl_transform_feedback_object *obj)
55fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
56fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (*ptr == obj)
57fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
58fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
59fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (*ptr) {
60fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      /* Unreference the old object */
61fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      struct gl_transform_feedback_object *oldObj = *ptr;
62fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
63fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ASSERT(oldObj->RefCount > 0);
64fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      oldObj->RefCount--;
65fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
66fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      if (oldObj->RefCount == 0) {
67fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         GET_CURRENT_CONTEXT(ctx);
68fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (ctx)
69fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            ctx->Driver.DeleteTransformFeedback(ctx, oldObj);
70fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
71fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
72fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      *ptr = NULL;
73fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
74fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT(!*ptr);
75fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
76fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj) {
77fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      /* reference new object */
78fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      if (obj->RefCount == 0) {
79fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_problem(NULL, "referencing deleted transform feedback object");
80fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         *ptr = NULL;
81fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
82fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      else {
83fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         obj->RefCount++;
84fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         *ptr = obj;
85fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
86fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
87fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
88fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
89fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
90fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
91de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check if the given primitive mode (as in glBegin(mode)) is compatible
92de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * with the current transform feedback mode (if it's enabled).
93de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This is to be called from glBegin(), glDrawArrays(), glDrawElements(), etc.
94de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
95de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE if the mode is OK, GL_FALSE otherwise.
96de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
97de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean
98de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_validate_primitive_mode(GLcontext *ctx, GLenum mode)
99de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
100fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (ctx->TransformFeedback.CurrentObject->Active) {
101de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      switch (mode) {
102de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_POINTS:
103de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_POINTS;
104de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINES:
105de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINE_STRIP:
106de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINE_LOOP:
107de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_LINES;
108de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      default:
109de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_TRIANGLES;
110de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      }
111de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
112de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   return GL_TRUE;
113de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
114de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
115de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
116de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
117de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check that all the buffer objects currently bound for transform
118de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * feedback actually exist.  Raise a GL_INVALID_OPERATION error if
119de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * any buffers are missing.
120de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE for success, GL_FALSE if error
121de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
122de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean
123de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_validate_transform_feedback_buffers(GLcontext *ctx)
124de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
125fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* XXX to do */
126de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   return GL_TRUE;
127de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
128de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
129de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
130de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
131de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
132de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context init for transform feedback.
133de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
134de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
135de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_init_transform_feedback(GLcontext *ctx)
136de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
137fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!ctx->Driver.NewTransformFeedback) {
138fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      /* this feature/extension may not be supported by the driver */
139fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
140fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
141fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
142fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.DefaultObject =
143fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ctx->Driver.NewTransformFeedback(ctx, 0);
144fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
145fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->TransformFeedback.DefaultObject->RefCount == 1);
146fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
147fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject,
148fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                       ctx->TransformFeedback.DefaultObject);
149fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
150fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->TransformFeedback.DefaultObject->RefCount == 2);
151fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
152fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.Objects = _mesa_NewHashTable();
153fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
154de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
155de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
156de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 ctx->Shared->NullBufferObj);
157de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
158de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
159de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
160fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
161fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
162fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Callback for _mesa_HashDeleteAll().
163fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
164fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
165fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldelete_cb(GLuint key, void *data, void *userData)
166fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
167fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLcontext *ctx = (GLcontext *) userData;
168fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
169fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      (struct gl_transform_feedback_object *) data;
170fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
171fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.DeleteTransformFeedback(ctx, obj);
172fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
173fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
174fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
175de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
176de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context free/clean-up for transform feedback.
177de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
178de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
179de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_free_transform_feedback(GLcontext *ctx)
180de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
181fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!ctx->Driver.NewTransformFeedback) {
182fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      /* this feature/extension may not be supported by the driver */
183fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
184fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
185fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
186de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
187de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
188de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 NULL);
189fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
190fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* Delete all feedback objects */
191fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   _mesa_HashDeleteAll(ctx->TransformFeedback.Objects, delete_cb, ctx);
1925b90f83aee89d051983485cdec5b5db2f3659256Brian Paul   _mesa_DeleteHashTable(ctx->TransformFeedback.Objects);
193fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
194fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* Delete the default feedback object */
195fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.DeleteTransformFeedback);
19639c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul   ctx->Driver.DeleteTransformFeedback(ctx,
19739c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul                                       ctx->TransformFeedback.DefaultObject);
198fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
199fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.CurrentObject = NULL;
200de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
201de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
202de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
203fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.NewTransformFeedback() */
204fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic struct gl_transform_feedback_object *
205fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulnew_transform_feedback(GLcontext *ctx, GLuint name)
206fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
207fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
208fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = CALLOC_STRUCT(gl_transform_feedback_object);
209fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj) {
210fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      obj->Name = name;
211fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      obj->RefCount = 1;
212fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
213fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   return obj;
214fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
215fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
216fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.DeleteTransformFeedback() */
217fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
218fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldelete_transform_feedback(GLcontext *ctx,
219fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                          struct gl_transform_feedback_object *obj)
220fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
221fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLuint i;
222fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
223fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   for (i = 0; i < Elements(obj->Buffers); i++) {
224fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL);
225fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
226fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
227fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   free(obj);
228fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
229fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
230fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.BeginTransformFeedback() */
231fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
232fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulbegin_transform_feedback(GLcontext *ctx, GLenum mode,
233fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         struct gl_transform_feedback_object *obj)
234fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
235fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
236fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
237fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
238fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.EndTransformFeedback() */
239fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
240fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulend_transform_feedback(GLcontext *ctx,
241fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                       struct gl_transform_feedback_object *obj)
242fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
243fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
244fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
245fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
246fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.PauseTransformFeedback() */
247fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
248fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulpause_transform_feedback(GLcontext *ctx,
249fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         struct gl_transform_feedback_object *obj)
250fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
251fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
252fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
253fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
254fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.ResumeTransformFeedback() */
255fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
256fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulresume_transform_feedback(GLcontext *ctx,
257fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                          struct gl_transform_feedback_object *obj)
258fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
259fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
260fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
261fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
262fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.DrawTransformFeedback() */
263fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
264fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldraw_transform_feedback(GLcontext *ctx, GLenum mode,
265fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                        struct gl_transform_feedback_object *obj)
266fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
267fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* XXX to do */
268fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /*
269fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    * Get number of vertices in obj's feedback buffer.
270fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    * Call ctx->Exec.DrawArrays(mode, 0, count);
271fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    */
272fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
273fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
274fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
275fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
276fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Plug in default device driver functions for transform feedback.
277fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Most drivers will override some/all of these.
278fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
279fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid
280fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_init_transform_feedback_functions(struct dd_function_table *driver)
281fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
282fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->NewTransformFeedback = new_transform_feedback;
283fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->DeleteTransformFeedback = delete_transform_feedback;
284fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->BeginTransformFeedback = begin_transform_feedback;
285fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->EndTransformFeedback = end_transform_feedback;
286fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->PauseTransformFeedback = pause_transform_feedback;
287fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->ResumeTransformFeedback = resume_transform_feedback;
288fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->DrawTransformFeedback = draw_transform_feedback;
289fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
290fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
291fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
292b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wuvoid
293b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu_mesa_init_transform_feedback_dispatch(struct _glapi_table *disp)
294b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu{
295b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BeginTransformFeedbackEXT(disp, _mesa_BeginTransformFeedback);
296b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_EndTransformFeedbackEXT(disp, _mesa_EndTransformFeedback);
297b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BindBufferRangeEXT(disp, _mesa_BindBufferRange);
298b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BindBufferBaseEXT(disp, _mesa_BindBufferBase);
299b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BindBufferOffsetEXT(disp, _mesa_BindBufferOffsetEXT);
300b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_TransformFeedbackVaryingsEXT(disp, _mesa_TransformFeedbackVaryings);
301b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_GetTransformFeedbackVaryingEXT(disp, _mesa_GetTransformFeedbackVarying);
302b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu}
303b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
304fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
305fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
306fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ** Begin API functions
307fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul **/
308fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
309fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
310de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
311de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BeginTransformFeedback(GLenum mode)
312de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
313fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
314de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
315de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
316fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
317fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
318de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (mode) {
319de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_POINTS:
320de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_LINES:
321de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_TRIANGLES:
322de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* legal */
323de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
324de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
325de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)");
326de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
327de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
328de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
329fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
330de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
331de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBeginTransformFeedback(already active)");
332de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
333de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
334de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
335fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Active = GL_TRUE;
336de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Mode = mode;
337fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
338fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.BeginTransformFeedback);
339fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.BeginTransformFeedback(ctx, mode, obj);
340de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
341de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
342de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
343de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
344de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_EndTransformFeedback(void)
345de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
346fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
347de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
348de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
349fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
350fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
351fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active) {
352de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
353de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glEndTransformFeedback(not active)");
354de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
355de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
356de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
357fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.CurrentObject->Active = GL_FALSE;
358fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
359fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.EndTransformFeedback);
360fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.EndTransformFeedback(ctx, obj);
361de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
362de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
363de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
364de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
365de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Helper used by BindBufferRange() and BindBufferBase().
366de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
367de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulstatic void
368de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulbind_buffer_range(GLcontext *ctx, GLuint index,
369de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  struct gl_buffer_object *bufObj,
370de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  GLintptr offset, GLsizeiptr size)
371de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
372fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
373fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ctx->TransformFeedback.CurrentObject;
374fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
375de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The general binding point */
376de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
377de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
378de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
379de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
380de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The per-attribute binding point */
381de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
382fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                 &obj->Buffers[index],
383de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
384de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
385fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->BufferNames[index] = bufObj->Name;
386de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
387fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Offset[index] = offset;
388fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Size[index] = size;
389de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
390de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
391de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
392de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
393de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.  Plus,
394de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * specify the starting offset to place the results, and max size.
395de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
396de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
397de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferRange(GLenum target, GLuint index,
398de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                      GLuint buffer, GLintptr offset, GLsizeiptr size)
399de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
400fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
401de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
402de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
403de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
404de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
405de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
406de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
407de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
408de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
409fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
410fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
411fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
412de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
413de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
414de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
415de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
416de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
417de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
418de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
419de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
420de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
421de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
422de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if ((size <= 0) || (size & 0x3)) {
423de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* must be positive and multiple of four */
424de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size%d)", size);
425de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
426de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
427de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
428de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (offset & 0x3) {
429de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* must be multiple of four */
430de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
431de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(offset=%d)", offset);
432de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
433de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
434de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
435de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
436de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
437de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
438de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(invalid buffer=%u)", buffer);
439de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
440de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
441de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
442de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (offset + size >= bufObj->Size) {
443de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
444de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(offset + size > buffer size)", size);
445de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
446de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
447de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
448de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
449de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
450de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
451de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
452de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
453de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.
454de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * As above, but start at offset = 0.
455de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
456de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
457de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
458de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
459fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
460de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
461de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
462fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
463de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
464de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
465de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
466de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
467de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
468de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
469fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
470fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
471fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
472de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
473de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
474de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
475de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
476de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
477de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
478de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
479de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
480de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
481de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
482de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
483de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
484de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
485de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferBase(invalid buffer=%u)", buffer);
486de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
487de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
488de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
489de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
490de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
491de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
492de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = bufObj->Size & ~0x3;
493de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
494de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, 0, size);
495de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
496de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
497de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
498de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
499de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results, plus the
500de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * offset in the buffer to start placing results.
501de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function is part of GL_EXT_transform_feedback, but not GL3.
502de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
503de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
504de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
505de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                          GLintptr offset)
506de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
507fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
508de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
509de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
510de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
511de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
512de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
513de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)");
514de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
515de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
516de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
517fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
518fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
519fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
520de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
521de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
522de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
523de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
524de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
525de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
526de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
527de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(index=%d)", index);
528de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
529de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
530de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
531de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
532de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
533de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
534de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(invalid buffer=%u)", buffer);
535de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
536de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
537de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
538de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
539de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
540de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
541de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = (bufObj->Size - offset) & ~0x3;
542de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
543de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
544de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
545de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
546de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
547de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
548de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function specifies the vertex shader outputs to be written
549de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s), and in what order.
550de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
551de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
552de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
553de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                const GLchar **varyings, GLenum bufferMode)
554de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
555de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_shader_program *shProg;
556de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLuint i;
557de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
558de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
559de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (bufferMode) {
560de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_INTERLEAVED_ATTRIBS:
561de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
562de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_SEPARATE_ATTRIBS:
563de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
564de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
565de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM,
566de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(bufferMode)");
567de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
568de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
569de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
570de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (count < 0 || count > ctx->Const.MaxTransformFeedbackSeparateAttribs) {
571de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
572de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(count=%d)", count);
573de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
574de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
575de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
576de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
577de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
578de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
579de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(program=%u)", program);
580de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
581de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
582de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
583de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* free existing varyings, if any */
584de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
585de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      free(shProg->TransformFeedback.VaryingNames[i]);
586de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
587de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   free(shProg->TransformFeedback.VaryingNames);
588de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
589de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* allocate new memory for varying names */
590de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.VaryingNames =
591de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      (GLchar **) malloc(count * sizeof(GLchar *));
592de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
593de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg->TransformFeedback.VaryingNames) {
594de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()");
595de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
596de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
597de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
598de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* Save the new names and the count */
599de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < (GLuint) count; i++) {
600de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]);
601de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
602de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.NumVarying = count;
603de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
604de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.BufferMode = bufferMode;
605de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
606de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The varyings won't be used until shader link time */
607de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
608de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
609de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
610de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
611de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Get info about the vertex shader's outputs which are to be written
612de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s).
613de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
614de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
615de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
616de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei bufSize, GLsizei *length,
617de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei *size, GLenum *type, GLchar *name)
618de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
619de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   const struct gl_shader_program *shProg;
620de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   const GLchar *varyingName;
621de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLint v;
622de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
623de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
624de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
625de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
626de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
627de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(program=%u)", program);
628de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
629de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
630de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
631de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= shProg->TransformFeedback.NumVarying) {
632de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
633de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(index=%u)", index);
634de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
635de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
636de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
637de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   varyingName = shProg->TransformFeedback.VaryingNames[index];
638de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
639de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   v = _mesa_lookup_parameter_index(shProg->Varying, -1, varyingName);
640de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (v >= 0) {
641de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      struct gl_program_parameter *param = &shProg->Varying->Parameters[v];
642de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
643de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* return the varying's name and length */
644de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_copy_string(name, bufSize, length, varyingName);
645de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
646de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* return the datatype and value's size (in datatype units) */
647de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      if (type)
6483100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *type = param->DataType;
649de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      if (size)
650de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         *size = param->Size;
651de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
6523100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul   else {
6533100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      name[0] = 0;
6543100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      if (length)
6553100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *length = 0;
6563100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      if (type)
6573100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *type = 0;
6583100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      if (size)
6593100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *size = 0;
6603100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul   }
661de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
662de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
663fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
664fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
665fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic struct gl_transform_feedback_object *
666fef6e36e0736a68e24d7844bae65a01de8359214Brian Paullookup_transform_feedback_object(GLcontext *ctx, GLuint name)
667fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
668fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (name == 0) {
669fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return ctx->TransformFeedback.DefaultObject;
670fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
671fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else
672fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return (struct gl_transform_feedback_object *)
673fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_HashLookup(ctx->TransformFeedback.Objects, name);
674fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
675fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
676fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
677fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
678fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Create new transform feedback objects.   Transform feedback objects
679fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * encapsulate the state related to transform feedback to allow quickly
680fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * switching state (and drawing the results, below).
681fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
682fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
683fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
684fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
685fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
686fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLuint first;
687fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
688fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
689fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END(ctx);
690fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
691fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (n < 0) {
692fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)");
693fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
694fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
695fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
696fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!names)
697fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
698fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
699fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* we don't need contiguous IDs, but this might be faster */
700fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   first = _mesa_HashFindFreeKeyBlock(ctx->TransformFeedback.Objects, n);
701fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (first) {
702fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      GLsizei i;
703fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      for (i = 0; i < n; i++) {
704fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         struct gl_transform_feedback_object *obj
705fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            = ctx->Driver.NewTransformFeedback(ctx, first + i);
706fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (!obj) {
707fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
708fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            return;
709fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         }
710fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         names[i] = first + i;
711fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj);
712fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
713fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
714fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else {
715fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
716fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
717fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
718fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
719fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
720fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
721fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Is the given ID a transform feedback object?
722fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
723fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
724fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGLboolean GLAPIENTRY
725fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_IsTransformFeedback(GLuint name)
726fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
727fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
728fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
729fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
730fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
731fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (name && lookup_transform_feedback_object(ctx, name))
732fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return GL_TRUE;
733fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else
734fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return GL_FALSE;
735fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
736fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
737fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
738fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
739fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Bind the given transform feedback object.
740fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
741fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
742fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
743d74f525060f779cfe449c20853b11ba2bbcdea6dVinson Lee_mesa_BindTransformFeedback(GLenum target, GLuint name)
744fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
745fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
746fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
747fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
748fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (target != GL_TRANSFORM_FEEDBACK) {
749fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindTransformFeedback(target)");
750fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
751fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
752fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
753fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (ctx->TransformFeedback.CurrentObject->Active &&
754fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul       !ctx->TransformFeedback.CurrentObject->Paused) {
755fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
75639c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul              "glBindTransformFeedback(transform is active, or not paused)");
757fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
758fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
759fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
760fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = lookup_transform_feedback_object(ctx, name);
761fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj) {
762fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
763fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                  "glBindTransformFeedback(name=%u)", name);
764fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
765fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
766fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
767fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject,
768fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                       obj);
769fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
770fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
771fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
772fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
773fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Delete the given transform feedback objects.
774fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
775fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
776fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
777fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names)
778fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
779fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLint i;
780fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
781fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
782fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END(ctx);
783fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
784fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (n < 0) {
785fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTransformFeedbacks(n < 0)");
786fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
787fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
788fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
789fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!names)
790fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
791fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
792fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   for (i = 0; i < n; i++) {
793fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      if (names[i] > 0) {
794fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         struct gl_transform_feedback_object *obj
795fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            = lookup_transform_feedback_object(ctx, names[i]);
796fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (obj) {
797fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            if (obj->Active) {
798fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul               _mesa_error(ctx, GL_INVALID_OPERATION,
799fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                           "glDeleteTransformFeedbacks(object %u is active)",
800fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                           names[i]);
801fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul               return;
802fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            }
803fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            _mesa_HashRemove(ctx->TransformFeedback.Objects, names[i]);
804fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            /* unref, but object may not be deleted until later */
805fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            reference_transform_feedback_object(&obj, NULL);
806fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         }
807fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
808fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
809fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
810fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
811fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
812fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
813fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Pause transform feedback.
814fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
815fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
816fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
817fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_PauseTransformFeedback(void)
818fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
819fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
820fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
821fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
822fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
823fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
824fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active || obj->Paused) {
825fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
826fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul           "glPauseTransformFeedback(feedback not active or already paused)");
827fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
828fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
829fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
830fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Paused = GL_TRUE;
831fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
832fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.PauseTransformFeedback);
833fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.PauseTransformFeedback(ctx, obj);
834fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
835fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
836fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
837fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
838fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Resume transform feedback.
839fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
840fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
841fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
842fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_ResumeTransformFeedback(void)
843fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
844fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
845fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
846fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
847fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
848fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
849fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active || !obj->Paused) {
850fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
85139c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul               "glPauseTransformFeedback(feedback not active or not paused)");
852fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
853fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
854fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
855fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Paused = GL_FALSE;
856fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
857fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.ResumeTransformFeedback);
858fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.ResumeTransformFeedback(ctx, obj);
859fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
860fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
861fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
862fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
863fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Draw the vertex data in a transform feedback object.
864fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
865fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * \param name  the transform feedback object
866fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * The number of vertices comes from the transform feedback object.
867fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * User still has to setup of the vertex attribute info with
868fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * glVertexPointer, glColorPointer, etc.
869fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
870fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
871fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
872fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
873fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
874fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
875fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
876fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      lookup_transform_feedback_object(ctx, name);
877fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
87839c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul   if (mode > GL_POLYGON) {
87939c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM,
88039c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul                  "glDrawTransformFeedback(mode=0x%x)", mode);
88139c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul      return;
88239c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul   }
883fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj) {
884fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
885fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                  "glDrawTransformFeedback(name = %u)", name);
886fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
887fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
888fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
889fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* XXX check if EndTransformFeedback has never been called while
890fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    * the object was bound
891fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    */
892fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
893fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.DrawTransformFeedback);
894fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.DrawTransformFeedback(ctx, mode, obj);
895fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
896fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
897fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
898fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/*
899fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulXXX misc to do:
900fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
901fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulglGet*() for
902fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
903fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGL_TRANSFORM_FEEDBACK_BUFFER_PAUSED
904fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE
905fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGL_TRANSFORM_FEEDBACK_BINDING
906fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul*/
907b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
908b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
909b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#endif /* FEATURE_EXT_transform_feedback */
910