transformfeedback.c revision 5b90f83aee89d051983485cdec5b5db2f3659256
1de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/* 2de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Mesa 3-D graphics library 3de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * 4de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Copyright (C) 2010 VMware, Inc. All Rights Reserved. 5de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * 6de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a 7de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * copy of this software and associated documentation files (the "Software"), 8de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to deal in the Software without restriction, including without limitation 9de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * and/or sell copies of the Software, and to permit persons to whom the 11de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Software is furnished to do so, subject to the following conditions: 12de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * 13de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * The above copyright notice and this permission notice shall be included 14de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * in all copies or substantial portions of the Software. 15de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * 16de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 23de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 24de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 25de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/* 26de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Vertex transform feedback support. 27de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * 28de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Authors: 29de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Brian Paul 30de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 31de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 32de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 33de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "buffers.h" 34de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "bufferobj.h" 35de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "context.h" 36fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul#include "hash.h" 37de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul#include "transformfeedback.h" 38a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul#include "shaderapi.h" 39a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul#include "shaderobj.h" 40b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#include "main/dispatch.h" 41de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 42ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_parameter.h" 43ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul//#include "program/shader_api.h" 44de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 45de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 46b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#if FEATURE_EXT_transform_feedback 47b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu 48b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu 49de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 50fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Do reference counting of transform feedback buffers. 51fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 52fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 53fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulreference_transform_feedback_object(struct gl_transform_feedback_object **ptr, 54fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj) 55fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 56fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (*ptr == obj) 57fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 58fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 59fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (*ptr) { 60fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* Unreference the old object */ 61fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *oldObj = *ptr; 62fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 63fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ASSERT(oldObj->RefCount > 0); 64fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul oldObj->RefCount--; 65fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 66fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (oldObj->RefCount == 0) { 67fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 68fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (ctx) 69fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.DeleteTransformFeedback(ctx, oldObj); 70fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 71fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 72fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul *ptr = NULL; 73fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 74fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ASSERT(!*ptr); 75fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 76fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj) { 77fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* reference new object */ 78fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj->RefCount == 0) { 79fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_problem(NULL, "referencing deleted transform feedback object"); 80fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul *ptr = NULL; 81fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 82fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul else { 83fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->RefCount++; 84fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul *ptr = obj; 85fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 86fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 87fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 88fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 89fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 90fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 91de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check if the given primitive mode (as in glBegin(mode)) is compatible 92de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * with the current transform feedback mode (if it's enabled). 93de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This is to be called from glBegin(), glDrawArrays(), glDrawElements(), etc. 94de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * 95de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE if the mode is OK, GL_FALSE otherwise. 96de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 97de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean 98de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_validate_primitive_mode(GLcontext *ctx, GLenum mode) 99de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 100fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (ctx->TransformFeedback.CurrentObject->Active) { 101de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul switch (mode) { 102de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_POINTS: 103de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return ctx->TransformFeedback.Mode == GL_POINTS; 104de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_LINES: 105de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_LINE_STRIP: 106de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_LINE_LOOP: 107de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return ctx->TransformFeedback.Mode == GL_LINES; 108de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul default: 109de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return ctx->TransformFeedback.Mode == GL_TRIANGLES; 110de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 111de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 112de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return GL_TRUE; 113de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 114de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 115de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 116de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 117de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Check that all the buffer objects currently bound for transform 118de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * feedback actually exist. Raise a GL_INVALID_OPERATION error if 119de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * any buffers are missing. 120de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * \return GL_TRUE for success, GL_FALSE if error 121de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 122de8530e1546733bf21b2e0518d6c5bda560770b9Brian PaulGLboolean 123de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_validate_transform_feedback_buffers(GLcontext *ctx) 124de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 125fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* XXX to do */ 126de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return GL_TRUE; 127de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 128de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 129de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 130de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 131de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 132de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context init for transform feedback. 133de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 134de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid 135de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_init_transform_feedback(GLcontext *ctx) 136de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 137fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!ctx->Driver.NewTransformFeedback) { 138fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* this feature/extension may not be supported by the driver */ 139fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 140fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 141fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 142fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->TransformFeedback.DefaultObject = 143fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.NewTransformFeedback(ctx, 0); 144fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 145fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->TransformFeedback.DefaultObject->RefCount == 1); 146fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 147fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject, 148fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->TransformFeedback.DefaultObject); 149fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 150fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->TransformFeedback.DefaultObject->RefCount == 2); 151fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 152fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->TransformFeedback.Objects = _mesa_NewHashTable(); 153fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 154de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_reference_buffer_object(ctx, 155de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul &ctx->TransformFeedback.CurrentBuffer, 156de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul ctx->Shared->NullBufferObj); 157de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 158de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 159de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 160fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 161fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 162fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Callback for _mesa_HashDeleteAll(). 163fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 164fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 165fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldelete_cb(GLuint key, void *data, void *userData) 166fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 167fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GLcontext *ctx = (GLcontext *) userData; 168fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj = 169fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul (struct gl_transform_feedback_object *) data; 170fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 171fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.DeleteTransformFeedback(ctx, obj); 172fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 173fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 174fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 175de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 176de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Per-context free/clean-up for transform feedback. 177de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 178de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid 179de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_free_transform_feedback(GLcontext *ctx) 180de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 181fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!ctx->Driver.NewTransformFeedback) { 182fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* this feature/extension may not be supported by the driver */ 183fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 184fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 185fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 186de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_reference_buffer_object(ctx, 187de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul &ctx->TransformFeedback.CurrentBuffer, 188de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul NULL); 189fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 190fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* Delete all feedback objects */ 191fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_HashDeleteAll(ctx->TransformFeedback.Objects, delete_cb, ctx); 1925b90f83aee89d051983485cdec5b5db2f3659256Brian Paul _mesa_DeleteHashTable(ctx->TransformFeedback.Objects); 193fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 194fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* Delete the default feedback object */ 195fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->Driver.DeleteTransformFeedback); 19639c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul ctx->Driver.DeleteTransformFeedback(ctx, 19739c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul ctx->TransformFeedback.DefaultObject); 198fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 199fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->TransformFeedback.CurrentObject = NULL; 200de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 201de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 202de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 203fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.NewTransformFeedback() */ 204fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic struct gl_transform_feedback_object * 205fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulnew_transform_feedback(GLcontext *ctx, GLuint name) 206fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 207fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 208fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = CALLOC_STRUCT(gl_transform_feedback_object); 209fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj) { 210fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->Name = name; 211fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->RefCount = 1; 212fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 213fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return obj; 214fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 215fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 216fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.DeleteTransformFeedback() */ 217fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 218fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldelete_transform_feedback(GLcontext *ctx, 219fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj) 220fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 221fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GLuint i; 222fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 223fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul for (i = 0; i < Elements(obj->Buffers); i++) { 224fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL); 225fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 226fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 227fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul free(obj); 228fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 229fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 230fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.BeginTransformFeedback() */ 231fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 232fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulbegin_transform_feedback(GLcontext *ctx, GLenum mode, 233fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj) 234fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 235fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* nop */ 236fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 237fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 238fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.EndTransformFeedback() */ 239fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 240fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulend_transform_feedback(GLcontext *ctx, 241fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj) 242fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 243fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* nop */ 244fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 245fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 246fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.PauseTransformFeedback() */ 247fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 248fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulpause_transform_feedback(GLcontext *ctx, 249fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj) 250fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 251fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* nop */ 252fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 253fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 254fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.ResumeTransformFeedback() */ 255fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 256fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulresume_transform_feedback(GLcontext *ctx, 257fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj) 258fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 259fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* nop */ 260fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 261fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 262fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** Default fallback for ctx->Driver.DrawTransformFeedback() */ 263fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic void 264fef6e36e0736a68e24d7844bae65a01de8359214Brian Pauldraw_transform_feedback(GLcontext *ctx, GLenum mode, 265fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj) 266fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 267fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* XXX to do */ 268fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* 269fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Get number of vertices in obj's feedback buffer. 270fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Call ctx->Exec.DrawArrays(mode, 0, count); 271fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 272fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 273fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 274fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 275fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 276fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Plug in default device driver functions for transform feedback. 277fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Most drivers will override some/all of these. 278fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 279fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid 280fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_init_transform_feedback_functions(struct dd_function_table *driver) 281fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 282fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul driver->NewTransformFeedback = new_transform_feedback; 283fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul driver->DeleteTransformFeedback = delete_transform_feedback; 284fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul driver->BeginTransformFeedback = begin_transform_feedback; 285fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul driver->EndTransformFeedback = end_transform_feedback; 286fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul driver->PauseTransformFeedback = pause_transform_feedback; 287fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul driver->ResumeTransformFeedback = resume_transform_feedback; 288fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul driver->DrawTransformFeedback = draw_transform_feedback; 289fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 290fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 291fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 292b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wuvoid 293b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu_mesa_init_transform_feedback_dispatch(struct _glapi_table *disp) 294b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu{ 295b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu SET_BeginTransformFeedbackEXT(disp, _mesa_BeginTransformFeedback); 296b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu SET_EndTransformFeedbackEXT(disp, _mesa_EndTransformFeedback); 297b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu SET_BindBufferRangeEXT(disp, _mesa_BindBufferRange); 298b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu SET_BindBufferBaseEXT(disp, _mesa_BindBufferBase); 299b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu SET_BindBufferOffsetEXT(disp, _mesa_BindBufferOffsetEXT); 300b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu SET_TransformFeedbackVaryingsEXT(disp, _mesa_TransformFeedbackVaryings); 301b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu SET_GetTransformFeedbackVaryingEXT(disp, _mesa_GetTransformFeedbackVarying); 302b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu} 303b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu 304fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 305fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 306fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ** Begin API functions 307fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul **/ 308fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 309fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 310de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY 311de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BeginTransformFeedback(GLenum mode) 312de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 313fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 314de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GET_CURRENT_CONTEXT(ctx); 315de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 316fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = ctx->TransformFeedback.CurrentObject; 317fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 318de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul switch (mode) { 319de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_POINTS: 320de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_LINES: 321de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_TRIANGLES: 322de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* legal */ 323de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul break; 324de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul default: 325de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)"); 326de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 327de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 328de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 329fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj->Active) { 330de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 331de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBeginTransformFeedback(already active)"); 332de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 333de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 334de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 335fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->Active = GL_TRUE; 336de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul ctx->TransformFeedback.Mode = mode; 337fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 338fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->Driver.BeginTransformFeedback); 339fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.BeginTransformFeedback(ctx, mode, obj); 340de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 341de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 342de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 343de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY 344de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_EndTransformFeedback(void) 345de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 346fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 347de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GET_CURRENT_CONTEXT(ctx); 348de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 349fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = ctx->TransformFeedback.CurrentObject; 350fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 351fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!obj->Active) { 352de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 353de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glEndTransformFeedback(not active)"); 354de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 355de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 356de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 357fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->TransformFeedback.CurrentObject->Active = GL_FALSE; 358fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 359fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->Driver.EndTransformFeedback); 360fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.EndTransformFeedback(ctx, obj); 361de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 362de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 363de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 364de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 365de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Helper used by BindBufferRange() and BindBufferBase(). 366de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 367de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulstatic void 368de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulbind_buffer_range(GLcontext *ctx, GLuint index, 369de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul struct gl_buffer_object *bufObj, 370de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLintptr offset, GLsizeiptr size) 371de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 372fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj = 373fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->TransformFeedback.CurrentObject; 374fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 375de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* The general binding point */ 376de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_reference_buffer_object(ctx, 377de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul &ctx->TransformFeedback.CurrentBuffer, 378de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bufObj); 379de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 380de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* The per-attribute binding point */ 381de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_reference_buffer_object(ctx, 382fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul &obj->Buffers[index], 383de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bufObj); 384de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 385fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->BufferNames[index] = bufObj->Name; 386de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 387fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->Offset[index] = offset; 388fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->Size[index] = size; 389de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 390de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 391de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 392de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 393de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results. Plus, 394de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * specify the starting offset to place the results, and max size. 395de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 396de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY 397de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferRange(GLenum target, GLuint index, 398de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLuint buffer, GLintptr offset, GLsizeiptr size) 399de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 400fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 401de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul struct gl_buffer_object *bufObj; 402de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GET_CURRENT_CONTEXT(ctx); 403de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 404de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { 405de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)"); 406de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 407de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 408de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 409fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = ctx->TransformFeedback.CurrentObject; 410fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 411fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj->Active) { 412de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 413de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferRange(transform feedback active)"); 414de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 415de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 416de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 417de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { 418de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index); 419de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 420de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 421de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 422de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if ((size <= 0) || (size & 0x3)) { 423de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* must be positive and multiple of four */ 424de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size%d)", size); 425de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 426de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 427de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 428de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (offset & 0x3) { 429de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* must be multiple of four */ 430de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 431de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferRange(offset=%d)", offset); 432de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 433de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 434de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 435de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bufObj = _mesa_lookup_bufferobj(ctx, buffer); 436de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (!bufObj) { 437de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 438de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferRange(invalid buffer=%u)", buffer); 439de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 440de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 441de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 442de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (offset + size >= bufObj->Size) { 443de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 444de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferRange(offset + size > buffer size)", size); 445de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 446de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 447de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 448de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bind_buffer_range(ctx, index, bufObj, offset, size); 449de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 450de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 451de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 452de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 453de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results. 454de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * As above, but start at offset = 0. 455de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 456de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY 457de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) 458de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 459fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 460de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul struct gl_buffer_object *bufObj; 461de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLsizeiptr size; 462fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 463de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 464de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { 465de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)"); 466de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 467de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 468de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 469fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = ctx->TransformFeedback.CurrentObject; 470fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 471fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj->Active) { 472de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 473de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferRange(transform feedback active)"); 474de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 475de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 476de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 477de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { 478de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index); 479de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 480de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 481de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 482de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bufObj = _mesa_lookup_bufferobj(ctx, buffer); 483de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (!bufObj) { 484de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 485de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferBase(invalid buffer=%u)", buffer); 486de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 487de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 488de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 489de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* default size is the buffer size rounded down to nearest 490de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * multiple of four. 491de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 492de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul size = bufObj->Size & ~0x3; 493de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 494de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bind_buffer_range(ctx, index, bufObj, 0, size); 495de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 496de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 497de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 498de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 499de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Specify a buffer object to receive vertex shader results, plus the 500de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * offset in the buffer to start placing results. 501de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function is part of GL_EXT_transform_feedback, but not GL3. 502de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 503de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY 504de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, 505de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLintptr offset) 506de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 507fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 508de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul struct gl_buffer_object *bufObj; 509de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GET_CURRENT_CONTEXT(ctx); 510de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLsizeiptr size; 511de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 512de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { 513de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)"); 514de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 515de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 516de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 517fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = ctx->TransformFeedback.CurrentObject; 518fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 519fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj->Active) { 520de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 521de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferRange(transform feedback active)"); 522de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 523de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 524de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 525de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (index >= ctx->Const.MaxTransformFeedbackSeparateAttribs) { 526de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 527de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferOffsetEXT(index=%d)", index); 528de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 529de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 530de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 531de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bufObj = _mesa_lookup_bufferobj(ctx, buffer); 532de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (!bufObj) { 533de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 534de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glBindBufferOffsetEXT(invalid buffer=%u)", buffer); 535de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 536de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 537de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 538de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* default size is the buffer size rounded down to nearest 539de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * multiple of four. 540de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 541de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul size = (bufObj->Size - offset) & ~0x3; 542de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 543de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul bind_buffer_range(ctx, index, bufObj, offset, size); 544de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 545de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 546de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 547de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 548de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * This function specifies the vertex shader outputs to be written 549de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s), and in what order. 550de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 551de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY 552de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_TransformFeedbackVaryings(GLuint program, GLsizei count, 553de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul const GLchar **varyings, GLenum bufferMode) 554de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 555de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul struct gl_shader_program *shProg; 556de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLuint i; 557de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GET_CURRENT_CONTEXT(ctx); 558de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 559de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul switch (bufferMode) { 560de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_INTERLEAVED_ATTRIBS: 561de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul break; 562de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul case GL_SEPARATE_ATTRIBS: 563de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul break; 564de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul default: 565de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_ENUM, 566de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glTransformFeedbackVaryings(bufferMode)"); 567de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 568de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 569de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 570de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (count < 0 || count > ctx->Const.MaxTransformFeedbackSeparateAttribs) { 571de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 572de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glTransformFeedbackVaryings(count=%d)", count); 573de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 574de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 575de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 576de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul shProg = _mesa_lookup_shader_program(ctx, program); 577de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (!shProg) { 578de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 579de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glTransformFeedbackVaryings(program=%u)", program); 580de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 581de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 582de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 583de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* free existing varyings, if any */ 584de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { 585de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul free(shProg->TransformFeedback.VaryingNames[i]); 586de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 587de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul free(shProg->TransformFeedback.VaryingNames); 588de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 589de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* allocate new memory for varying names */ 590de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul shProg->TransformFeedback.VaryingNames = 591de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul (GLchar **) malloc(count * sizeof(GLchar *)); 592de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 593de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (!shProg->TransformFeedback.VaryingNames) { 594de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings()"); 595de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 596de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 597de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 598de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* Save the new names and the count */ 599de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul for (i = 0; i < (GLuint) count; i++) { 600de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul shProg->TransformFeedback.VaryingNames[i] = _mesa_strdup(varyings[i]); 601de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 602de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul shProg->TransformFeedback.NumVarying = count; 603de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 604de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul shProg->TransformFeedback.BufferMode = bufferMode; 605de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 606de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* The varyings won't be used until shader link time */ 607de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 608de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 609de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 610de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul/** 611de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * Get info about the vertex shader's outputs which are to be written 612de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul * to the feedback buffer(s). 613de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul */ 614de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paulvoid GLAPIENTRY 615de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul_mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, 616de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLsizei bufSize, GLsizei *length, 617de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLsizei *size, GLenum *type, GLchar *name) 618de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul{ 619de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul const struct gl_shader_program *shProg; 620de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul const GLchar *varyingName; 621de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GLint v; 622de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul GET_CURRENT_CONTEXT(ctx); 623de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 624de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul shProg = _mesa_lookup_shader_program(ctx, program); 625de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (!shProg) { 626de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 627de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glGetTransformFeedbackVaryings(program=%u)", program); 628de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 629de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 630de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 631de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (index >= shProg->TransformFeedback.NumVarying) { 632de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 633de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul "glGetTransformFeedbackVaryings(index=%u)", index); 634de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul return; 635de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 636de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 637de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul varyingName = shProg->TransformFeedback.VaryingNames[index]; 638de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 639de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul v = _mesa_lookup_parameter_index(shProg->Varying, -1, varyingName); 640de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (v >= 0) { 641de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul struct gl_program_parameter *param = &shProg->Varying->Parameters[v]; 642de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 643de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* return the varying's name and length */ 644de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul _mesa_copy_string(name, bufSize, length, varyingName); 645de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 646de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul /* return the datatype and value's size (in datatype units) */ 647de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (type) 6483100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul *type = param->DataType; 649de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul if (size) 650de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul *size = param->Size; 651de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul } 6523100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul else { 6533100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul name[0] = 0; 6543100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul if (length) 6553100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul *length = 0; 6563100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul if (type) 6573100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul *type = 0; 6583100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul if (size) 6593100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul *size = 0; 6603100f31b747a3294e1e7043ed9a61d8b90bf423aBrian Paul } 661de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul} 662de8530e1546733bf21b2e0518d6c5bda560770b9Brian Paul 663fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 664fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 665fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulstatic struct gl_transform_feedback_object * 666fef6e36e0736a68e24d7844bae65a01de8359214Brian Paullookup_transform_feedback_object(GLcontext *ctx, GLuint name) 667fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 668fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (name == 0) { 669fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return ctx->TransformFeedback.DefaultObject; 670fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 671fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul else 672fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return (struct gl_transform_feedback_object *) 673fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_HashLookup(ctx->TransformFeedback.Objects, name); 674fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 675fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 676fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 677fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 678fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Create new transform feedback objects. Transform feedback objects 679fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * encapsulate the state related to transform feedback to allow quickly 680fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * switching state (and drawing the results, below). 681fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2. 682fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 683fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY 684fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) 685fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 686fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GLuint first; 687fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 688fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 689fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ASSERT_OUTSIDE_BEGIN_END(ctx); 690fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 691fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (n < 0) { 692fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, "glGenTransformFeedbacks(n < 0)"); 693fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 694fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 695fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 696fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!names) 697fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 698fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 699fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* we don't need contiguous IDs, but this might be faster */ 700fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul first = _mesa_HashFindFreeKeyBlock(ctx->TransformFeedback.Objects, n); 701fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (first) { 702fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GLsizei i; 703fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul for (i = 0; i < n; i++) { 704fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj 705fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul = ctx->Driver.NewTransformFeedback(ctx, first + i); 706fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!obj) { 707fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); 708fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 709fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 710fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul names[i] = first + i; 711fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_HashInsert(ctx->TransformFeedback.Objects, first + i, obj); 712fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 713fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 714fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul else { 715fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTransformFeedbacks"); 716fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 717fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 718fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 719fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 720fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 721fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Is the given ID a transform feedback object? 722fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2. 723fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 724fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGLboolean GLAPIENTRY 725fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_IsTransformFeedback(GLuint name) 726fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 727fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 728fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 729fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 730fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 731fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (name && lookup_transform_feedback_object(ctx, name)) 732fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return GL_TRUE; 733fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul else 734fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return GL_FALSE; 735fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 736fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 737fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 738fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 739fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Bind the given transform feedback object. 740fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2. 741fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 742fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY 743d74f525060f779cfe449c20853b11ba2bbcdea6dVinson Lee_mesa_BindTransformFeedback(GLenum target, GLuint name) 744fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 745fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 746fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 747fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 748fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (target != GL_TRANSFORM_FEEDBACK) { 749fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_ENUM, "glBindTransformFeedback(target)"); 750fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 751fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 752fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 753fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (ctx->TransformFeedback.CurrentObject->Active && 754fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul !ctx->TransformFeedback.CurrentObject->Paused) { 755fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 75639c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul "glBindTransformFeedback(transform is active, or not paused)"); 757fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 758fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 759fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 760fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = lookup_transform_feedback_object(ctx, name); 761fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!obj) { 762fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 763fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul "glBindTransformFeedback(name=%u)", name); 764fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 765fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 766fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 767fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul reference_transform_feedback_object(&ctx->TransformFeedback.CurrentObject, 768fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj); 769fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 770fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 771fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 772fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 773fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Delete the given transform feedback objects. 774fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2. 775fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 776fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY 777fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_DeleteTransformFeedbacks(GLsizei n, const GLuint *names) 778fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 779fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GLint i; 780fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 781fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 782fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ASSERT_OUTSIDE_BEGIN_END(ctx); 783fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 784fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (n < 0) { 785fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTransformFeedbacks(n < 0)"); 786fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 787fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 788fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 789fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!names) 790fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 791fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 792fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul for (i = 0; i < n; i++) { 793fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (names[i] > 0) { 794fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj 795fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul = lookup_transform_feedback_object(ctx, names[i]); 796fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj) { 797fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (obj->Active) { 798fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 799fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul "glDeleteTransformFeedbacks(object %u is active)", 800fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul names[i]); 801fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 802fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 803fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_HashRemove(ctx->TransformFeedback.Objects, names[i]); 804fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* unref, but object may not be deleted until later */ 805fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul reference_transform_feedback_object(&obj, NULL); 806fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 807fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 808fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 809fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 810fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 811fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 812fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 813fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Pause transform feedback. 814fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2. 815fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 816fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY 817fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_PauseTransformFeedback(void) 818fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 819fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 820fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 821fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 822fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = ctx->TransformFeedback.CurrentObject; 823fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 824fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!obj->Active || obj->Paused) { 825fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 826fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul "glPauseTransformFeedback(feedback not active or already paused)"); 827fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 828fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 829fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 830fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->Paused = GL_TRUE; 831fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 832fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->Driver.PauseTransformFeedback); 833fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.PauseTransformFeedback(ctx, obj); 834fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 835fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 836fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 837fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 838fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Resume transform feedback. 839fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2. 840fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 841fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY 842fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_ResumeTransformFeedback(void) 843fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 844fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj; 845fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 846fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 847fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj = ctx->TransformFeedback.CurrentObject; 848fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 849fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!obj->Active || !obj->Paused) { 850fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 85139c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul "glPauseTransformFeedback(feedback not active or not paused)"); 852fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 853fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 854fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 855fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul obj->Paused = GL_FALSE; 856fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 857fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->Driver.ResumeTransformFeedback); 858fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.ResumeTransformFeedback(ctx, obj); 859fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 860fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 861fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 862fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/** 863fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Draw the vertex data in a transform feedback object. 864fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc. 865fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * \param name the transform feedback object 866fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * The number of vertices comes from the transform feedback object. 867fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * User still has to setup of the vertex attribute info with 868fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * glVertexPointer, glColorPointer, etc. 869fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * Part of GL_ARB_transform_feedback2. 870fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 871fef6e36e0736a68e24d7844bae65a01de8359214Brian Paulvoid GLAPIENTRY 872fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul_mesa_DrawTransformFeedback(GLenum mode, GLuint name) 873fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul{ 874fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul GET_CURRENT_CONTEXT(ctx); 875fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul struct gl_transform_feedback_object *obj = 876fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul lookup_transform_feedback_object(ctx, name); 877fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 87839c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul if (mode > GL_POLYGON) { 87939c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul _mesa_error(ctx, GL_INVALID_ENUM, 88039c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul "glDrawTransformFeedback(mode=0x%x)", mode); 88139c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul return; 88239c13a115eb45fb6c711cd86cda3a0c178975b52Brian Paul } 883fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul if (!obj) { 884fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul _mesa_error(ctx, GL_INVALID_VALUE, 885fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul "glDrawTransformFeedback(name = %u)", name); 886fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul return; 887fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul } 888fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 889fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul /* XXX check if EndTransformFeedback has never been called while 890fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul * the object was bound 891fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul */ 892fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 893fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul assert(ctx->Driver.DrawTransformFeedback); 894fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul ctx->Driver.DrawTransformFeedback(ctx, mode, obj); 895fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul} 896fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 897fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 898fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul/* 899fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulXXX misc to do: 900fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 901fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulglGet*() for 902fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul 903fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 904fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 905fef6e36e0736a68e24d7844bae65a01de8359214Brian PaulGL_TRANSFORM_FEEDBACK_BINDING 906fef6e36e0736a68e24d7844bae65a01de8359214Brian Paul*/ 907b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu 908b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu 909b093016bd0660cc4ac6142aa8d4d6add5b6bfce8Chia-I Wu#endif /* FEATURE_EXT_transform_feedback */ 910