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