transformfeedback.c revision c67d9cfd9d5d04b5b32170616f75b34e0192304b
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 if the given primitive mode (as in glBegin(mode)) is compatible
93de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * with the current transform feedback mode (if it's enabled).
94de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This is to be called from glBegin(), glDrawArrays(), glDrawElements(), etc.
95de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
96de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE if the mode is OK, GL_FALSE otherwise.
97de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
98de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean
99f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_validate_primitive_mode(struct gl_context *ctx, GLenum mode)
100de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
101fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (ctx->TransformFeedback.CurrentObject->Active) {
102de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      switch (mode) {
103de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_POINTS:
104de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_POINTS;
105de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINES:
106de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINE_STRIP:
107de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINE_LOOP:
108de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_LINES;
109de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      default:
110de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_TRIANGLES;
111de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      }
112de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
113de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   return GL_TRUE;
114de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
115de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
116de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
117de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
118de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check that all the buffer objects currently bound for transform
119de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * feedback actually exist.  Raise a GL_INVALID_OPERATION error if
120de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * any buffers are missing.
121de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE for success, GL_FALSE if error
122de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
123de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean
124f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_validate_transform_feedback_buffers(struct gl_context *ctx)
125de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
126fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* XXX to do */
127de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   return GL_TRUE;
128de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
129de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
130de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
131de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
132de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
133de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context init for transform feedback.
134de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
135de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
136f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_transform_feedback(struct gl_context *ctx)
137de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
13832a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   /* core mesa expects this, even a dummy one, to be available */
13932a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ASSERT(ctx->Driver.NewTransformFeedback);
140fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
141fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.DefaultObject =
142fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ctx->Driver.NewTransformFeedback(ctx, 0);
143fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
144fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->TransformFeedback.DefaultObject->RefCount == 1);
145fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
146fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject,
147fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                       ctx->TransformFeedback.DefaultObject);
148fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
149fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->TransformFeedback.DefaultObject->RefCount == 2);
150fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
151fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.Objects = _mesa_NewHashTable();
152fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
153de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
154de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
155de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 ctx->Shared->NullBufferObj);
156de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
157de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
158de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
159fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
160fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
161fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Callback for _mesa_HashDeleteAll().
162fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
163fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
164fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldelete_cb(GLuint key, void *data, void *userData)
165fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
166f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
167fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
168fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      (struct gl_transform_feedback_object *) data;
169fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
170fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.DeleteTransformFeedback(ctx, obj);
171fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
172fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
173fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
174de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
175de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context free/clean-up for transform feedback.
176de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
177de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
178f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_free_transform_feedback(struct gl_context *ctx)
179de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
18032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   /* core mesa expects this, even a dummy one, to be available */
18132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ASSERT(ctx->Driver.NewTransformFeedback);
182fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
183de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
184de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
185de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 NULL);
186fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
187fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* Delete all feedback objects */
188fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   _mesa_HashDeleteAll(ctx->TransformFeedback.Objects, delete_cb, ctx);
1895b90f83aee89d051983485cdec5b5db2f3659256Brian Paul   _mesa_DeleteHashTable(ctx->TransformFeedback.Objects);
190fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
191fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* Delete the default feedback object */
192fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.DeleteTransformFeedback);
19339c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul   ctx->Driver.DeleteTransformFeedback(ctx,
19439c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul                                       ctx->TransformFeedback.DefaultObject);
195fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
196fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.CurrentObject = NULL;
197de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
198de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
199de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
20032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu#else /* FEATURE_EXT_transform_feedback */
20132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
20232a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu/* forward declarations */
20332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wustatic struct gl_transform_feedback_object *
204f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnew_transform_feedback(struct gl_context *ctx, GLuint name);
20532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
20632a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wustatic void
207f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergdelete_transform_feedback(struct gl_context *ctx,
20832a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                          struct gl_transform_feedback_object *obj);
20932a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
21032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu/* dummy per-context init/clean-up for transform feedback */
21132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wuvoid
212f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_transform_feedback(struct gl_context *ctx)
21332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu{
21432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ctx->TransformFeedback.DefaultObject = new_transform_feedback(ctx, 0);
21532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ctx->TransformFeedback.CurrentObject = ctx->TransformFeedback.DefaultObject;
21632a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   _mesa_reference_buffer_object(ctx,
21732a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 &ctx->TransformFeedback.CurrentBuffer,
21832a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 ctx->Shared->NullBufferObj);
21932a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu}
22032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
22132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wuvoid
222f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_free_transform_feedback(struct gl_context *ctx)
22332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu{
22432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   _mesa_reference_buffer_object(ctx,
22532a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 &ctx->TransformFeedback.CurrentBuffer,
22632a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu                                 NULL);
22732a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   ctx->TransformFeedback.CurrentObject = NULL;
22832a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu   delete_transform_feedback(ctx, ctx->TransformFeedback.DefaultObject);
22932a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu}
23032a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
23132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu#endif /* FEATURE_EXT_transform_feedback */
23232a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
23332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
234fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.NewTransformFeedback() */
235fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic struct gl_transform_feedback_object *
236f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnew_transform_feedback(struct gl_context *ctx, GLuint name)
237fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
238fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
239fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = CALLOC_STRUCT(gl_transform_feedback_object);
240fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj) {
241fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      obj->Name = name;
242fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      obj->RefCount = 1;
243fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
244fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   return obj;
245fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
246fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
247fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.DeleteTransformFeedback() */
248fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
249f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergdelete_transform_feedback(struct gl_context *ctx,
250fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                          struct gl_transform_feedback_object *obj)
251fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
252fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLuint i;
253fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
254fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   for (i = 0; i < Elements(obj->Buffers); i++) {
255fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL);
256fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
257fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
258fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   free(obj);
259fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
260fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
26132a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
26232a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu#if FEATURE_EXT_transform_feedback
26332a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
26432a9b2799e5e1254fdf84af8248ea86e234d6dd4Chia-I Wu
265fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.BeginTransformFeedback() */
266fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
267f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergbegin_transform_feedback(struct gl_context *ctx, GLenum mode,
268fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         struct gl_transform_feedback_object *obj)
269fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
270fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
271fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
272fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
273fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.EndTransformFeedback() */
274fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
275f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergend_transform_feedback(struct gl_context *ctx,
276fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                       struct gl_transform_feedback_object *obj)
277fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
278fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
279fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
280fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
281fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.PauseTransformFeedback() */
282fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
283f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergpause_transform_feedback(struct gl_context *ctx,
284fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                         struct gl_transform_feedback_object *obj)
285fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
286fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
287fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
288fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
289fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.ResumeTransformFeedback() */
290fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
291f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergresume_transform_feedback(struct gl_context *ctx,
292fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                          struct gl_transform_feedback_object *obj)
293fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
294fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* nop */
295fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
296fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
297fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.DrawTransformFeedback() */
298fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void
299f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergdraw_transform_feedback(struct gl_context *ctx, GLenum mode,
300fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                        struct gl_transform_feedback_object *obj)
301fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
302fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* XXX to do */
303fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /*
304fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    * Get number of vertices in obj's feedback buffer.
305fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    * Call ctx->Exec.DrawArrays(mode, 0, count);
306fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    */
307fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
308fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
309fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
310fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
311fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Plug in default device driver functions for transform feedback.
312fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Most drivers will override some/all of these.
313fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
314fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid
315fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_init_transform_feedback_functions(struct dd_function_table *driver)
316fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
317fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->NewTransformFeedback = new_transform_feedback;
318fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->DeleteTransformFeedback = delete_transform_feedback;
319fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->BeginTransformFeedback = begin_transform_feedback;
320fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->EndTransformFeedback = end_transform_feedback;
321fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->PauseTransformFeedback = pause_transform_feedback;
322fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->ResumeTransformFeedback = resume_transform_feedback;
323fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   driver->DrawTransformFeedback = draw_transform_feedback;
324fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
325fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
326fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
327b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wuvoid
328b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu_mesa_init_transform_feedback_dispatch(struct _glapi_table *disp)
329b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu{
33048dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   /* EXT_transform_feedback */
331b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BeginTransformFeedbackEXT(disp, _mesa_BeginTransformFeedback);
332b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_EndTransformFeedbackEXT(disp, _mesa_EndTransformFeedback);
333b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BindBufferRangeEXT(disp, _mesa_BindBufferRange);
334b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BindBufferBaseEXT(disp, _mesa_BindBufferBase);
335b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_BindBufferOffsetEXT(disp, _mesa_BindBufferOffsetEXT);
336b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_TransformFeedbackVaryingsEXT(disp, _mesa_TransformFeedbackVaryings);
337b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu   SET_GetTransformFeedbackVaryingEXT(disp, _mesa_GetTransformFeedbackVarying);
33848dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   /* ARB_transform_feedback2 */
33948dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_BindTransformFeedback(disp, _mesa_BindTransformFeedback);
34048dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_DeleteTransformFeedbacks(disp, _mesa_DeleteTransformFeedbacks);
34148dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_GenTransformFeedbacks(disp, _mesa_GenTransformFeedbacks);
34248dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_IsTransformFeedback(disp, _mesa_IsTransformFeedback);
34348dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_PauseTransformFeedback(disp, _mesa_PauseTransformFeedback);
34448dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_ResumeTransformFeedback(disp, _mesa_ResumeTransformFeedback);
34548dcdcffd61c6c3755d818493bc3b7bdc1260ea5Marek Olšák   SET_DrawTransformFeedback(disp, _mesa_DrawTransformFeedback);
346b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu}
347b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu
348fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
349fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
350fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ** Begin API functions
351fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul **/
352fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
353fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
354de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
355de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BeginTransformFeedback(GLenum mode)
356de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
357fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
358de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
359de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
360fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
361fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
362de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (mode) {
363de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_POINTS:
364de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_LINES:
365de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_TRIANGLES:
366de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* legal */
367de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
368de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
369de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)");
370de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
371de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
372de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
373fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
374de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
375de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBeginTransformFeedback(already active)");
376de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
377de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
378de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
379fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Active = GL_TRUE;
380de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Mode = mode;
381fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
382fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.BeginTransformFeedback);
383fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.BeginTransformFeedback(ctx, mode, obj);
384de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
385de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
386de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
387de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
388de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_EndTransformFeedback(void)
389de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
390fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
391de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
392de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
393fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
394fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
395fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active) {
396de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
397de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glEndTransformFeedback(not active)");
398de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
399de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
400de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
401fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->TransformFeedback.CurrentObject->Active = GL_FALSE;
402fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
403fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.EndTransformFeedback);
404fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.EndTransformFeedback(ctx, obj);
405de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
406de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
407de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
408de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
409de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Helper used by BindBufferRange() and BindBufferBase().
410de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
411de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulstatic void
412f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergbind_buffer_range(struct gl_context *ctx, GLuint index,
413de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  struct gl_buffer_object *bufObj,
414de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  GLintptr offset, GLsizeiptr size)
415de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
416fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
417fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      ctx->TransformFeedback.CurrentObject;
418fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
419de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The general binding point */
420de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
421de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
422de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
423de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
424de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The per-attribute binding point */
425de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
426fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                 &obj->Buffers[index],
427de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
428de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
429fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->BufferNames[index] = bufObj->Name;
430de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
431fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Offset[index] = offset;
432fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Size[index] = size;
433de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
434de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
435de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
436de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
437de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.  Plus,
438de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * specify the starting offset to place the results, and max size.
439de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
440de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
441de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferRange(GLenum target, GLuint index,
442de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                      GLuint buffer, GLintptr offset, GLsizeiptr size)
443de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
444fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
445de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
446de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
447de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
448de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
449de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
450de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
451de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
452de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
453fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
454fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
455fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
456de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
457de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
458de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
459de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
460de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
461de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
462de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
463de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
464de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
465de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
466de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if ((size <= 0) || (size & 0x3)) {
467de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* must be positive and multiple of four */
4689eca0e2c3e9409b5da49d9a5052d3665e7d45bb1Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size%d)", (int) size);
469de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
470de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
471de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
472de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (offset & 0x3) {
473de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* must be multiple of four */
474de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
4759eca0e2c3e9409b5da49d9a5052d3665e7d45bb1Brian Paul                  "glBindBufferRange(offset=%d)", (int) offset);
476de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
477de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
478de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
479de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
480de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
481de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
482de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(invalid buffer=%u)", buffer);
483de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
484de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
485de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
486de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (offset + size >= bufObj->Size) {
487de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
48886af037e6a1643284f87c5e01c3fcb09dd07bf35Eric Anholt                  "glBindBufferRange(offset + size %d > buffer size %d)",
4899eca0e2c3e9409b5da49d9a5052d3665e7d45bb1Brian Paul		  (int) (offset + size), (int) (bufObj->Size));
490de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
491de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
492de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
493de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
494de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
495de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
496de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
497de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
498de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.
499de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * As above, but start at offset = 0.
500de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
501de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
502de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
503de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
504fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
505de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
506de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
507fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
508de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
509de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
510de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
511de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
512de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
513de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
514fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
515fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
516fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
517de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
5182be2e1d3ada2d9cb5c1c42e955629d8fbbafcd0bBrian Paul                  "glBindBufferBase(transform feedback active)");
519de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
520de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
521de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
522de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
523de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
524de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
525de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
526de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
527de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
528de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
529de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
530de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferBase(invalid buffer=%u)", buffer);
531de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
532de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
533de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
534de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
535de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
536de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
537de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = bufObj->Size & ~0x3;
538de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
539de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, 0, size);
540de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
541de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
542de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
543de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
544de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results, plus the
545de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * offset in the buffer to start placing results.
546de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function is part of GL_EXT_transform_feedback, but not GL3.
547de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
548de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
549de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
550de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                          GLintptr offset)
551de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
552fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
553de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
554de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
555de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
556de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
557de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
558de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)");
559de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
560de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
561de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
562fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
563fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
564fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (obj->Active) {
565de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
5662be2e1d3ada2d9cb5c1c42e955629d8fbbafcd0bBrian Paul                  "glBindBufferOffsetEXT(transform feedback active)");
567de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
568de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
569de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
570de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
571de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
572de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(index=%d)", index);
573de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
574de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
575de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
576de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
577de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
578de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
579de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(invalid buffer=%u)", buffer);
580de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
581de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
582de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
583de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
584de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
585de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
586de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = (bufObj->Size - offset) & ~0x3;
587de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
588de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
589de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
590de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
591de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
592de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
593de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function specifies the vertex shader outputs to be written
594de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s), and in what order.
595de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
596de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
597de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
598de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                const GLchar **varyings, GLenum bufferMode)
599de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
600de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_shader_program *shProg;
601de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLuint i;
602de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
603de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
604de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (bufferMode) {
605de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_INTERLEAVED_ATTRIBS:
606de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
607de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_SEPARATE_ATTRIBS:
608de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
609de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
610de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM,
611de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(bufferMode)");
612de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
613de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
614de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
615f77aa278d354bebdbda940b31c9cccf12a5d146fMarek Olšák   if (count < 0 ||
616f77aa278d354bebdbda940b31c9cccf12a5d146fMarek Olšák       (bufferMode == GL_SEPARATE_ATTRIBS &&
617c67d9cfd9d5d04b5b32170616f75b34e0192304bBrian Paul        (GLuint) count > ctx->Const.MaxTransformFeedbackSeparateAttribs)) {
618de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
619de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(count=%d)", count);
620de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
621de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
622de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
623de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
624de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
625de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
626de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(program=%u)", program);
627de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
628de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
629de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
630de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* free existing varyings, if any */
631de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
632de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      free(shProg->TransformFeedback.VaryingNames[i]);
633de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
634de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   free(shProg->TransformFeedback.VaryingNames);
635de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
636de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* allocate new memory for varying names */
637de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.VaryingNames =
638de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      (GLchar **) malloc(count * sizeof(GLchar *));
639de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
640de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg->TransformFeedback.VaryingNames) {
641de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()");
642de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
643de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
644de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
645de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* Save the new names and the count */
646de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < (GLuint) count; i++) {
647de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]);
648de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
649de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.NumVarying = count;
650de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
651de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.BufferMode = bufferMode;
652de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
653de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The varyings won't be used until shader link time */
654de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
655de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
656de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
657de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
658de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Get info about the vertex shader's outputs which are to be written
659de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s).
660de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
661de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
662de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
663de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei bufSize, GLsizei *length,
664de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei *size, GLenum *type, GLchar *name)
665de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
666de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   const struct gl_shader_program *shProg;
667de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   const GLchar *varyingName;
668de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLint v;
669de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
670de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
671de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
672de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
673de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
674de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(program=%u)", program);
675de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
676de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
677de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
678de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= shProg->TransformFeedback.NumVarying) {
679de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
680de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(index=%u)", index);
681de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
682de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
683de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
684de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   varyingName = shProg->TransformFeedback.VaryingNames[index];
685de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
686de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   v = _mesa_lookup_parameter_index(shProg->Varying, -1, varyingName);
687de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (v >= 0) {
688de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      struct gl_program_parameter *param = &shProg->Varying->Parameters[v];
689de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
690de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* return the varying's name and length */
691de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_copy_string(name, bufSize, length, varyingName);
692de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
693de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* return the datatype and value's size (in datatype units) */
694de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      if (type)
6953100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *type = param->DataType;
696de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      if (size)
697de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         *size = param->Size;
698de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
6993100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul   else {
7003100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      name[0] = 0;
7013100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      if (length)
7023100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *length = 0;
7033100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      if (type)
7043100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *type = 0;
7053100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul      if (size)
7063100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul         *size = 0;
7073100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul   }
708de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
709de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
710fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
711fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
712fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic struct gl_transform_feedback_object *
713f9995b30756140724f41daf963fa06167912be7fKristian Høgsberglookup_transform_feedback_object(struct gl_context *ctx, GLuint name)
714fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
715fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (name == 0) {
716fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return ctx->TransformFeedback.DefaultObject;
717fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
718fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else
719fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return (struct gl_transform_feedback_object *)
720fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_HashLookup(ctx->TransformFeedback.Objects, name);
721fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
722fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
723fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
724fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
725fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Create new transform feedback objects.   Transform feedback objects
726fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * encapsulate the state related to transform feedback to allow quickly
727fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * switching state (and drawing the results, below).
728fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
729fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
730fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
731fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names)
732fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
733fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLuint first;
734fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
735fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
736fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END(ctx);
737fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
738fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (n < 0) {
739fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)");
740fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
741fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
742fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
743fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!names)
744fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
745fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
746fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* we don't need contiguous IDs, but this might be faster */
747fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   first = _mesa_HashFindFreeKeyBlock(ctx->TransformFeedback.Objects, n);
748fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (first) {
749fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      GLsizei i;
750fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      for (i = 0; i < n; i++) {
751fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         struct gl_transform_feedback_object *obj
752fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            = ctx->Driver.NewTransformFeedback(ctx, first + i);
753fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (!obj) {
754fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
755fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            return;
756fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         }
757fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         names[i] = first + i;
758fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj);
759fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
760fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
761fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else {
762fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks");
763fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
764fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
765fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
766fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
767fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
768fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Is the given ID a transform feedback object?
769fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
770fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
771fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGLboolean GLAPIENTRY
772fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_IsTransformFeedback(GLuint name)
773fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
774fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
775fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
776fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
777fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
778fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (name && lookup_transform_feedback_object(ctx, name))
779fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return GL_TRUE;
780fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   else
781fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return GL_FALSE;
782fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
783fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
784fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
785fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
786fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Bind the given transform feedback object.
787fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
788fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
789fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
790d74f525060f779cfe449c20853b11ba2bbcdea6dVinson Lee_mesa_BindTransformFeedback(GLenum target, GLuint name)
791fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
792fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
793fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
794fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
795fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (target != GL_TRANSFORM_FEEDBACK) {
796fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindTransformFeedback(target)");
797fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
798fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
799fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
800fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (ctx->TransformFeedback.CurrentObject->Active &&
801fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul       !ctx->TransformFeedback.CurrentObject->Paused) {
802fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
80339c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul              "glBindTransformFeedback(transform is active, or not paused)");
804fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
805fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
806fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
807fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = lookup_transform_feedback_object(ctx, name);
808fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj) {
809fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
810fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                  "glBindTransformFeedback(name=%u)", name);
811fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
812fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
813fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
814fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject,
815fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                                       obj);
816fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
817fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
818fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
819fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
820fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Delete the given transform feedback objects.
821fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
822fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
823fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
824fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names)
825fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
826fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GLint i;
827fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
828fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
829fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ASSERT_OUTSIDE_BEGIN_END(ctx);
830fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
831fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (n < 0) {
832fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTransformFeedbacks(n < 0)");
833fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
834fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
835fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
836fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!names)
837fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
838fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
839fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   for (i = 0; i < n; i++) {
840fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      if (names[i] > 0) {
841fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         struct gl_transform_feedback_object *obj
842fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            = lookup_transform_feedback_object(ctx, names[i]);
843fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         if (obj) {
844fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            if (obj->Active) {
845fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul               _mesa_error(ctx, GL_INVALID_OPERATION,
846fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                           "glDeleteTransformFeedbacks(object %u is active)",
847fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                           names[i]);
848fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul               return;
849fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            }
850fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            _mesa_HashRemove(ctx->TransformFeedback.Objects, names[i]);
851fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            /* unref, but object may not be deleted until later */
852fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul            reference_transform_feedback_object(&obj, NULL);
853fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul         }
854fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      }
855fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
856fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
857fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
858fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
859fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
860fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Pause transform feedback.
861fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
862fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
863fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
864fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_PauseTransformFeedback(void)
865fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
866fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
867fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
868fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
869fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
870fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
871fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active || obj->Paused) {
872fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
873fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul           "glPauseTransformFeedback(feedback not active or already paused)");
874fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
875fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
876fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
877fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Paused = GL_TRUE;
878fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
879fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.PauseTransformFeedback);
880fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.PauseTransformFeedback(ctx, obj);
881fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
882fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
883fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
884fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
885fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Resume transform feedback.
886fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
887fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
888fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
889fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_ResumeTransformFeedback(void)
890fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
891fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj;
892fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
893fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
894fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj = ctx->TransformFeedback.CurrentObject;
895fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
896fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj->Active || !obj->Paused) {
897fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
898076bd11112742ca615880f2c6dc6ed235ab37eb5Brian Paul               "glResumeTransformFeedback(feedback not active or not paused)");
899fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
900fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
901fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
902fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   obj->Paused = GL_FALSE;
903fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
904fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.ResumeTransformFeedback);
905fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.ResumeTransformFeedback(ctx, obj);
906fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
907fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
908fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
909fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/**
910fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Draw the vertex data in a transform feedback object.
911fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
912fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * \param name  the transform feedback object
913fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * The number of vertices comes from the transform feedback object.
914fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * User still has to setup of the vertex attribute info with
915fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * glVertexPointer, glColorPointer, etc.
916fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2.
917fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */
918fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY
919fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
920fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{
921fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   GET_CURRENT_CONTEXT(ctx);
922fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   struct gl_transform_feedback_object *obj =
923fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      lookup_transform_feedback_object(ctx, name);
924fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
92539c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul   if (mode > GL_POLYGON) {
92639c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM,
92739c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul                  "glDrawTransformFeedback(mode=0x%x)", mode);
92839c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul      return;
92939c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul   }
930fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   if (!obj) {
931fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
932fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul                  "glDrawTransformFeedback(name = %u)", name);
933fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul      return;
934fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   }
935fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
936fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   /* XXX check if EndTransformFeedback has never been called while
937fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    * the object was bound
938fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul    */
939fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
940fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   assert(ctx->Driver.DrawTransformFeedback);
941fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul   ctx->Driver.DrawTransformFeedback(ctx, mode, obj);
942fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul}
943fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul
944b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#endif /* FEATURE_EXT_transform_feedback */
945