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