shader_query.cpp revision a339ee8d852c08ce7af51a518e0b18b9f0ab324c
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 71a339ee8d852c08ce7af51a518e0b18b9f0ab324cIan Romanick /* Replace the current value if it's already in the list. Add 72a339ee8d852c08ce7af51a518e0b18b9f0ab324cIan Romanick * 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 772fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick /* 782fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick * Note that this attribute binding won't go into effect until 792fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick * glLinkProgram is called again. 802fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick */ 812fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick} 822fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 837a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanickvoid GLAPIENTRY 8484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick_mesa_GetActiveAttribARB(GLhandleARB program, GLuint desired_index, 857a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GLsizei maxLength, GLsizei * length, GLint * size, 867a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GLenum * type, GLcharARB * name) 877a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick{ 887a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GET_CURRENT_CONTEXT(ctx); 897a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick struct gl_shader_program *shProg; 907a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 917a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); 927a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick if (!shProg) 937a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick return; 947a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 9584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (!shProg->LinkStatus) { 9684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, 9784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick "glGetActiveAttrib(program not linked)"); 9884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick return; 9984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 1007a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 10184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 10284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)"); 1037a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick return; 1047a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick } 1057a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 10684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 10784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick unsigned current_index = 0; 10884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 10984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick foreach_list(node, ir) { 11084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 11184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 11284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (var == NULL 11384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick || var->mode != ir_var_in 11484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick || var->location == -1 11584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick || var->location < VERT_ATTRIB_GENERIC0) 11684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick continue; 11784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 11884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (current_index == desired_index) { 11984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_copy_string(name, maxLength, length, var->name); 1207a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 12184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (size) 12284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick *size = (var->type->is_array()) ? var->type->length : 1; 1237a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 12484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (type) 12584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick *type = var->type->gl_type; 12684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 12784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick return; 12884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 12984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 13084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick current_index++; 13184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 13284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 13384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick /* If the loop did not return early, the caller must have asked for 13484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick * an index that did not exit. Set an error. 13584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick */ 13684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); 1377a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick} 1387a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 139b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan RomanickGLint GLAPIENTRY 140b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) 141b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick{ 142b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick GET_CURRENT_CONTEXT(ctx); 143b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick struct gl_shader_program *const shProg = 144b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); 145b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 146b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!shProg) { 147b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 148b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 149b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 150b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!shProg->LinkStatus) { 151b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick _mesa_error(ctx, GL_INVALID_OPERATION, 152b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick "glGetAttribLocation(program not linked)"); 153b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 154b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 155b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 156b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!name) 157b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 158b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 159b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick /* Not having a vertex shader is not an error. 160b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 161b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) 162b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 163b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 164b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 165b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick foreach_list(node, ir) { 166b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 167b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 168b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick /* The extra check against VERT_ATTRIB_GENERIC0 is because 169b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * glGetAttribLocation cannot be used on "conventional" attributes. 170b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 171b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * From page 95 of the OpenGL 3.0 spec: 172b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 173b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * "If name is not an active attribute, if name is a conventional 174b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * attribute, or if an error occurs, -1 will be returned." 175b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 176b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (var == NULL 177b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->mode != ir_var_in 178b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->location == -1 179b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->location < VERT_ATTRIB_GENERIC0) 180b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick continue; 181b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 182b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (strcmp(var->name, name) == 0) 183b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return var->location - VERT_ATTRIB_GENERIC0; 184b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 185b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 186b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 187b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick} 188