shader_query.cpp revision 84d71a07bb06fe5fe231b8983558fbd3608ec6f0
1b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick/* 2b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * Copyright © 2011 Intel Corporation 3b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 4b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * Permission is hereby granted, free of charge, to any person obtaining a 5b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * copy of this software and associated documentation files (the "Software"), 6b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * to deal in the Software without restriction, including without limitation 7b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * and/or sell copies of the Software, and to permit persons to whom the 9b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * Software is furnished to do so, subject to the following conditions: 10b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 11b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * The above copyright notice and this permission notice (including the next 12b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * paragraph) shall be included in all copies or substantial portions of the 13b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * Software. 14b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 15b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * DEALINGS IN THE SOFTWARE. 22b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 23b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 24b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick/** 25b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * \file shader_query.cpp 26b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * C-to-C++ bridge functions to query GLSL shader data 27b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 28b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * \author Ian Romanick <ian.d.romanick@intel.com> 29b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 30b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 31b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick#include "main/core.h" 32b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick#include "glsl_symbol_table.h" 33b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick#include "ir.h" 34b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick#include "shaderobj.h" 35015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick#include "program/hash_table.h" 3684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick#include "../glsl/program.h" 37b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 38b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanickextern "C" { 39b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick#include "shaderapi.h" 40b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick} 41b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 422fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanickvoid GLAPIENTRY 432fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick_mesa_BindAttribLocationARB(GLhandleARB program, GLuint index, 442fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick const GLcharARB *name) 452fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick{ 462fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick GET_CURRENT_CONTEXT(ctx); 472fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 482fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick const GLint size = -1; /* unknown size */ 492fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick GLint i; 502fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick GLenum datatype = GL_FLOAT_VEC4; 512fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 522fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick struct gl_shader_program *const shProg = 532fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation"); 542fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (!shProg) 552fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 562fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 572fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (!name) 582fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 592fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 602fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (strncmp(name, "gl_", 3) == 0) { 612fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick _mesa_error(ctx, GL_INVALID_OPERATION, 622fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick "glBindAttribLocation(illegal name)"); 632fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 642fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick } 652fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 662fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (index >= ctx->Const.VertexProgram.MaxAttribs) { 672fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)"); 682fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 692fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick } 702fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 712fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick /* this will replace the current value if it's already in the list */ 72015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick /* Add VERT_ATTRIB_GENERIC0 because that's how the linker differentiates 73015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick * between built-in attributes and user-defined attributes. 74015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick */ 75015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name); 762fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index); 772fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (i < 0) { 782fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation"); 792fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 802fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick } 812fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 822fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick /* 832fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick * Note that this attribute binding won't go into effect until 842fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick * glLinkProgram is called again. 852fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick */ 862fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick} 872fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 887a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanickvoid GLAPIENTRY 8984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick_mesa_GetActiveAttribARB(GLhandleARB program, GLuint desired_index, 907a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GLsizei maxLength, GLsizei * length, GLint * size, 917a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GLenum * type, GLcharARB * name) 927a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick{ 937a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GET_CURRENT_CONTEXT(ctx); 947a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick struct gl_shader_program *shProg; 957a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 967a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); 977a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick if (!shProg) 987a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick return; 997a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 10084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (!shProg->LinkStatus) { 10184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, 10284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick "glGetActiveAttrib(program not linked)"); 10384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick return; 10484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 1057a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 10684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 10784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)"); 1087a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick return; 1097a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick } 1107a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 11184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 11284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick unsigned current_index = 0; 11384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 11484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick foreach_list(node, ir) { 11584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 11684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 11784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (var == NULL 11884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick || var->mode != ir_var_in 11984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick || var->location == -1 12084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick || var->location < VERT_ATTRIB_GENERIC0) 12184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick continue; 12284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 12384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (current_index == desired_index) { 12484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_copy_string(name, maxLength, length, var->name); 1257a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 12684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (size) 12784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick *size = (var->type->is_array()) ? var->type->length : 1; 1287a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 12984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (type) 13084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick *type = var->type->gl_type; 13184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 13284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick return; 13384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 13484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 13584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick current_index++; 13684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 13784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 13884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick /* If the loop did not return early, the caller must have asked for 13984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick * an index that did not exit. Set an error. 14084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick */ 14184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); 1427a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick} 1437a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 144b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan RomanickGLint GLAPIENTRY 145b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) 146b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick{ 147b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick GET_CURRENT_CONTEXT(ctx); 148b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick struct gl_shader_program *const shProg = 149b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); 150b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 151b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!shProg) { 152b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 153b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 154b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 155b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!shProg->LinkStatus) { 156b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick _mesa_error(ctx, GL_INVALID_OPERATION, 157b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick "glGetAttribLocation(program not linked)"); 158b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 159b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 160b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 161b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!name) 162b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 163b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 164b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick /* Not having a vertex shader is not an error. 165b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 166b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) 167b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 168b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 169b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 170b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick foreach_list(node, ir) { 171b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 172b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 173b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick /* The extra check against VERT_ATTRIB_GENERIC0 is because 174b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * glGetAttribLocation cannot be used on "conventional" attributes. 175b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 176b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * From page 95 of the OpenGL 3.0 spec: 177b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 178b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * "If name is not an active attribute, if name is a conventional 179b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * attribute, or if an error occurs, -1 will be returned." 180b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 181b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (var == NULL 182b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->mode != ir_var_in 183b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->location == -1 184b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->location < VERT_ATTRIB_GENERIC0) 185b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick continue; 186b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 187b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (strcmp(var->name, name) == 0) 188b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return var->location - VERT_ATTRIB_GENERIC0; 189b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 190b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 191b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 192b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick} 193