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