transformfeedback.c revision de8530e1546733bf21b2e0518d6c5bda560770b9
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"
36de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "enums.h"
37de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "transformfeedback.h"
38de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
39de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "shader/prog_parameter.h"
40de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "shader/shader_api.h"
41de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
42de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
43de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
44de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check if the given primitive mode (as in glBegin(mode)) is compatible
45de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * with the current transform feedback mode (if it's enabled).
46de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This is to be called from glBegin(), glDrawArrays(), glDrawElements(), etc.
47de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *
48de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE if the mode is OK, GL_FALSE otherwise.
49de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
50de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean
51de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_validate_primitive_mode(GLcontext *ctx, GLenum mode)
52de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
53de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (ctx->TransformFeedback.Active) {
54de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      switch (mode) {
55de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_POINTS:
56de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_POINTS;
57de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINES:
58de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINE_STRIP:
59de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      case GL_LINE_LOOP:
60de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_LINES;
61de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      default:
62de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         return ctx->TransformFeedback.Mode == GL_TRIANGLES;
63de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      }
64de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
65de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   return GL_TRUE;
66de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
67de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
68de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
69de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
70de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check that all the buffer objects currently bound for transform
71de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * feedback actually exist.  Raise a GL_INVALID_OPERATION error if
72de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * any buffers are missing.
73de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE for success, GL_FALSE if error
74de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
75de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean
76de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_validate_transform_feedback_buffers(GLcontext *ctx)
77de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
78de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
79de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   return GL_TRUE;
80de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
81de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
82de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
83de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
84de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
85de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context init for transform feedback.
86de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
87de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
88de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_init_transform_feedback(GLcontext *ctx)
89de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
90de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
91de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
92de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 ctx->Shared->NullBufferObj);
93de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
94de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
95de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
96de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
97de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context free/clean-up for transform feedback.
98de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
99de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid
100de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_free_transform_feedback(GLcontext *ctx)
101de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
102de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
103de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
104de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 NULL);
105de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
106de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
107de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
108de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
109de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BeginTransformFeedback(GLenum mode)
110de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
111de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
112de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
113de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (mode) {
114de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_POINTS:
115de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_LINES:
116de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_TRIANGLES:
117de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* legal */
118de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
119de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
120de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)");
121de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
122de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
123de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
124de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (ctx->TransformFeedback.Active) {
125de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
126de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBeginTransformFeedback(already active)");
127de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
128de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
129de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
130de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Active = GL_TRUE;
131de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Mode = mode;
132de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
133de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
134de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
135de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
136de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_EndTransformFeedback(void)
137de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
138de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
139de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
140de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!ctx->TransformFeedback.Active) {
141de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
142de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glEndTransformFeedback(not active)");
143de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
144de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
145de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
146de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Active = GL_FALSE;
147de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
148de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
149de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
150de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
151de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Helper used by BindBufferRange() and BindBufferBase().
152de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
153de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulstatic void
154de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulbind_buffer_range(GLcontext *ctx, GLuint index,
155de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  struct gl_buffer_object *bufObj,
156de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  GLintptr offset, GLsizeiptr size)
157de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
158de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The general binding point */
159de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
160de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.CurrentBuffer,
161de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
162de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
163de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The per-attribute binding point */
164de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   _mesa_reference_buffer_object(ctx,
165de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 &ctx->TransformFeedback.Buffers[index],
166de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                 bufObj);
167de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
168de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.BufferNames[index] = bufObj->Name;
169de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
170de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Offset[index] = offset;
171de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   ctx->TransformFeedback.Size[index] = size;
172de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
173de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
174de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
175de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
176de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.  Plus,
177de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * specify the starting offset to place the results, and max size.
178de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
179de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
180de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferRange(GLenum target, GLuint index,
181de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                      GLuint buffer, GLintptr offset, GLsizeiptr size)
182de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
183de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
184de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
185de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
186de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
187de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
188de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
189de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
190de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
191de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (ctx->TransformFeedback.Active) {
192de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
193de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
194de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
195de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
196de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
197de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
198de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
199de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
200de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
201de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
202de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if ((size <= 0) || (size & 0x3)) {
203de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* must be positive and multiple of four */
204de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size%d)", size);
205de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
206de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
207de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
208de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (offset & 0x3) {
209de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* must be multiple of four */
210de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
211de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(offset=%d)", offset);
212de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
213de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
214de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
215de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
216de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
217de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
218de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(invalid buffer=%u)", buffer);
219de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
220de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
221de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
222de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (offset + size >= bufObj->Size) {
223de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
224de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(offset + size > buffer size)", size);
225de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
226de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
227de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
228de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
229de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
230de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
231de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
232de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
233de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results.
234de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * As above, but start at offset = 0.
235de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
236de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
237de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
238de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
239de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
240de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
241de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
242de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
243de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
244de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
245de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
246de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
247de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
248de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (ctx->TransformFeedback.Active) {
249de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
250de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
251de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
252de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
253de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
254de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
255de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
256de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
257de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
258de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
259de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
260de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
261de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
262de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferBase(invalid buffer=%u)", buffer);
263de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
264de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
265de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
266de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
267de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
268de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
269de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = bufObj->Size & ~0x3;
270de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
271de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, 0, size);
272de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
273de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
274de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
275de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
276de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results, plus the
277de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * offset in the buffer to start placing results.
278de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function is part of GL_EXT_transform_feedback, but not GL3.
279de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
280de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
281de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer,
282de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                          GLintptr offset)
283de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
284de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_buffer_object *bufObj;
285de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
286de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLsizeiptr size;
287de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
288de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (target != GL_TRANSFORM_FEEDBACK_BUFFER) {
289de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)");
290de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
291de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
292de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
293de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (ctx->TransformFeedback.Active) {
294de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
295de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferRange(transform feedback active)");
296de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
297de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
298de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
299de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) {
300de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
301de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(index=%d)", index);
302de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
303de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
304de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
305de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
306de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!bufObj) {
307de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_OPERATION,
308de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glBindBufferOffsetEXT(invalid buffer=%u)", buffer);
309de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
310de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
311de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
312de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* default size is the buffer size rounded down to nearest
313de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    * multiple of four.
314de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul    */
315de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   size = (bufObj->Size - offset) & ~0x3;
316de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
317de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   bind_buffer_range(ctx, index, bufObj, offset, size);
318de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
319de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
320de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
321de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
322de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function specifies the vertex shader outputs to be written
323de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s), and in what order.
324de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
325de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
326de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count,
327de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                const GLchar **varyings, GLenum bufferMode)
328de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
329de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   struct gl_shader_program *shProg;
330de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLuint i;
331de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
332de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
333de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   switch (bufferMode) {
334de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_INTERLEAVED_ATTRIBS:
335de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
336de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   case GL_SEPARATE_ATTRIBS:
337de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      break;
338de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   default:
339de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_ENUM,
340de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(bufferMode)");
341de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
342de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
343de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
344de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (count < 0 || count > ctx->Const.MaxTransformFeedbackSeparateAttribs) {
345de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
346de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(count=%d)", count);
347de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
348de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
349de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
350de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
351de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
352de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
353de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glTransformFeedbackVaryings(program=%u)", program);
354de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
355de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
356de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
357de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* free existing varyings, if any */
358de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
359de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      free(shProg->TransformFeedback.VaryingNames[i]);
360de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
361de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   free(shProg->TransformFeedback.VaryingNames);
362de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
363de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* allocate new memory for varying names */
364de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.VaryingNames =
365de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      (GLchar **) malloc(count * sizeof(GLchar *));
366de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
367de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg->TransformFeedback.VaryingNames) {
368de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()");
369de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
370de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
371de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
372de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* Save the new names and the count */
373de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   for (i = 0; i < (GLuint) count; i++) {
374de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]);
375de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
376de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.NumVarying = count;
377de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
378de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg->TransformFeedback.BufferMode = bufferMode;
379de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
380de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   /* The varyings won't be used until shader link time */
381de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
382de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
383de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
384de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/**
385de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Get info about the vertex shader's outputs which are to be written
386de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s).
387de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */
388de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY
389de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
390de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei bufSize, GLsizei *length,
391de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                                  GLsizei *size, GLenum *type, GLchar *name)
392de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{
393de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   const struct gl_shader_program *shProg;
394de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   const GLchar *varyingName;
395de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GLint v;
396de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   GET_CURRENT_CONTEXT(ctx);
397de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
398de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   shProg = _mesa_lookup_shader_program(ctx, program);
399de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (!shProg) {
400de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
401de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(program=%u)", program);
402de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
403de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
404de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
405de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (index >= shProg->TransformFeedback.NumVarying) {
406de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_error(ctx, GL_INVALID_VALUE,
407de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul                  "glGetTransformFeedbackVaryings(index=%u)", index);
408de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      return;
409de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
410de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
411de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   varyingName = shProg->TransformFeedback.VaryingNames[index];
412de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
413de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   v = _mesa_lookup_parameter_index(shProg->Varying, -1, varyingName);
414de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   if (v >= 0) {
415de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      struct gl_program_parameter *param = &shProg->Varying->Parameters[v];
416de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
417de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* return the varying's name and length */
418de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      _mesa_copy_string(name, bufSize, length, varyingName);
419de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
420de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      /* return the datatype and value's size (in datatype units) */
421de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      if (type)
422de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         *type = param->Type;
423de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul      if (size)
424de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul         *size = param->Size;
425de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul   }
426de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul}
427de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul
428