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 struct gl_shader_program *const shProg = 492fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation"); 502fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (!shProg) 512fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 522fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 532fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (!name) 542fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 552fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 562fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (strncmp(name, "gl_", 3) == 0) { 572fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick _mesa_error(ctx, GL_INVALID_OPERATION, 582fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick "glBindAttribLocation(illegal name)"); 592fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 602fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick } 612fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 622fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick if (index >= ctx->Const.VertexProgram.MaxAttribs) { 632fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)"); 642fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick return; 652fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick } 662fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 67a339ee8d852c08ce7af51a518e0b18b9f0ab324cIan Romanick /* Replace the current value if it's already in the list. Add 68a339ee8d852c08ce7af51a518e0b18b9f0ab324cIan Romanick * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates 69015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick * between built-in attributes and user-defined attributes. 70015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick */ 71015d4f61ef9116c9e844299ab9f2b15c653c0450Ian Romanick shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name); 722fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 732fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick /* 742fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick * Note that this attribute binding won't go into effect until 752fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick * glLinkProgram is called again. 762fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick */ 772fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick} 782fd80534f01a5c684c47eff3946f412192ae3c0bIan Romanick 797a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanickvoid GLAPIENTRY 8084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick_mesa_GetActiveAttribARB(GLhandleARB program, GLuint desired_index, 817a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GLsizei maxLength, GLsizei * length, GLint * size, 827a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GLenum * type, GLcharARB * name) 837a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick{ 847a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick GET_CURRENT_CONTEXT(ctx); 857a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick struct gl_shader_program *shProg; 867a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 877a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); 887a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick if (!shProg) 897a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick return; 907a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 9184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (!shProg->LinkStatus) { 9284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, 9384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick "glGetActiveAttrib(program not linked)"); 9484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick return; 9584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 967a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 9784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 9884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)"); 997a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick return; 1007a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick } 1017a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 10284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 10384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick unsigned current_index = 0; 10484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 10584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick foreach_list(node, ir) { 10684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 10784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 10884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (var == NULL 10984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick || var->mode != ir_var_in 110e6c314f7d2ed99714376fec6b7509a55535fa3ffIan Romanick || var->location == -1) 11184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick continue; 11284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 11384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (current_index == desired_index) { 11484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_copy_string(name, maxLength, length, var->name); 1157a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 11684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (size) 11784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick *size = (var->type->is_array()) ? var->type->length : 1; 1187a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 11984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick if (type) 12084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick *type = var->type->gl_type; 12184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 12284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick return; 12384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 12484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 12584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick current_index++; 12684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick } 12784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick 12884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick /* If the loop did not return early, the caller must have asked for 12984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick * an index that did not exit. Set an error. 13084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick */ 13184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); 1327a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick} 1337a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick 134b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan RomanickGLint GLAPIENTRY 135b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) 136b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick{ 137b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick GET_CURRENT_CONTEXT(ctx); 138b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick struct gl_shader_program *const shProg = 139b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); 140b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 141b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!shProg) { 142b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 143b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 144b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 145b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!shProg->LinkStatus) { 146b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick _mesa_error(ctx, GL_INVALID_OPERATION, 147b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick "glGetAttribLocation(program not linked)"); 148b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 149b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 150b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 151b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (!name) 152b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 153b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 154b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick /* Not having a vertex shader is not an error. 155b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 156b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) 157b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 158b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 159b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 160b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick foreach_list(node, ir) { 161b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 162b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 163b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick /* The extra check against VERT_ATTRIB_GENERIC0 is because 164b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * glGetAttribLocation cannot be used on "conventional" attributes. 165b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 166b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * From page 95 of the OpenGL 3.0 spec: 167b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * 168b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * "If name is not an active attribute, if name is a conventional 169b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick * attribute, or if an error occurs, -1 will be returned." 170b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick */ 171b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (var == NULL 172b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->mode != ir_var_in 173b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->location == -1 174b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick || var->location < VERT_ATTRIB_GENERIC0) 175b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick continue; 176b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 177b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick if (strcmp(var->name, name) == 0) 178b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return var->location - VERT_ATTRIB_GENERIC0; 179b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick } 180b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick 181b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick return -1; 182b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick} 183c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick 184c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick 185c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanickunsigned 186c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick_mesa_count_active_attribs(struct gl_shader_program *shProg) 187c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick{ 188c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick if (!shProg->LinkStatus 189c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 190c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick return 0; 191c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick } 192c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick 193c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 194c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick unsigned i = 0; 195c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick 196c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick foreach_list(node, ir) { 197c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 198c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick 199c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick if (var == NULL 200c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick || var->mode != ir_var_in 201e6c314f7d2ed99714376fec6b7509a55535fa3ffIan Romanick || var->location == -1) 202c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick continue; 203c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick 204c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick i++; 205c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick } 206c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick 207c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick return i; 208c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick} 20924409ba1968cc49cbde6a111464c91271babc68aIan Romanick 21024409ba1968cc49cbde6a111464c91271babc68aIan Romanick 21124409ba1968cc49cbde6a111464c91271babc68aIan Romanicksize_t 21224409ba1968cc49cbde6a111464c91271babc68aIan Romanick_mesa_longest_attribute_name_length(struct gl_shader_program *shProg) 21324409ba1968cc49cbde6a111464c91271babc68aIan Romanick{ 21424409ba1968cc49cbde6a111464c91271babc68aIan Romanick if (!shProg->LinkStatus 21524409ba1968cc49cbde6a111464c91271babc68aIan Romanick || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { 21624409ba1968cc49cbde6a111464c91271babc68aIan Romanick return 0; 21724409ba1968cc49cbde6a111464c91271babc68aIan Romanick } 21824409ba1968cc49cbde6a111464c91271babc68aIan Romanick 21924409ba1968cc49cbde6a111464c91271babc68aIan Romanick exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir; 22024409ba1968cc49cbde6a111464c91271babc68aIan Romanick size_t longest = 0; 22124409ba1968cc49cbde6a111464c91271babc68aIan Romanick 22224409ba1968cc49cbde6a111464c91271babc68aIan Romanick foreach_list(node, ir) { 22324409ba1968cc49cbde6a111464c91271babc68aIan Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 22424409ba1968cc49cbde6a111464c91271babc68aIan Romanick 22524409ba1968cc49cbde6a111464c91271babc68aIan Romanick if (var == NULL 22624409ba1968cc49cbde6a111464c91271babc68aIan Romanick || var->mode != ir_var_in 227e6c314f7d2ed99714376fec6b7509a55535fa3ffIan Romanick || var->location == -1) 22824409ba1968cc49cbde6a111464c91271babc68aIan Romanick continue; 22924409ba1968cc49cbde6a111464c91271babc68aIan Romanick 23024409ba1968cc49cbde6a111464c91271babc68aIan Romanick const size_t len = strlen(var->name); 23124409ba1968cc49cbde6a111464c91271babc68aIan Romanick if (len >= longest) 23224409ba1968cc49cbde6a111464c91271babc68aIan Romanick longest = len + 1; 23324409ba1968cc49cbde6a111464c91271babc68aIan Romanick } 23424409ba1968cc49cbde6a111464c91271babc68aIan Romanick 23524409ba1968cc49cbde6a111464c91271babc68aIan Romanick return longest; 23624409ba1968cc49cbde6a111464c91271babc68aIan Romanick} 2374464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick 2384464a4b27b66f832acbe52b0a002c04415924c14Ian Romanickvoid GLAPIENTRY 2394464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, 2404464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick const GLchar *name) 2414464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick{ 242f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name); 243f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie} 244f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 245f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlievoid GLAPIENTRY 246f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber, 247f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie GLuint index, const GLchar *name) 248f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie{ 2494464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick GET_CURRENT_CONTEXT(ctx); 2504464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick 2514464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick struct gl_shader_program *const shProg = 252f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed"); 2534464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick if (!shProg) 2544464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick return; 2554464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick 2564464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick if (!name) 2574464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick return; 2584464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick 2594464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick if (strncmp(name, "gl_", 3) == 0) { 260f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)"); 261f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return; 262f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie } 263f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 264f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (index > 1) { 265f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)"); 266f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return; 267f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie } 268f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 269f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) { 270f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)"); 2714464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick return; 2724464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick } 2734464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick 274f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) { 275f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)"); 2764464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick return; 2774464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick } 2784464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick 2794464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick /* Replace the current value if it's already in the list. Add 2804464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick * FRAG_RESULT_DATA0 because that's how the linker differentiates 2814464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick * between built-in attributes and user-defined attributes. 2824464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick */ 283b12b5d9ab5c0153c93ca5ad9cd93cb36e41be4ebIan Romanick shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name); 284f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie shProg->FragDataIndexBindings->put(index, name); 2854464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick /* 2864464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick * Note that this binding won't go into effect until 2874464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick * glLinkProgram is called again. 2884464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick */ 289f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 290f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie} 291f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 292f8cf79936b42405a8366613b80e3bde21aadaa02Dave AirlieGLint GLAPIENTRY 293f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie_mesa_GetFragDataIndex(GLuint program, const GLchar *name) 294f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie{ 295f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie GET_CURRENT_CONTEXT(ctx); 296f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie struct gl_shader_program *const shProg = 297f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex"); 298f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 299f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (!shProg) { 300f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return -1; 301f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie } 302f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 303f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (!shProg->LinkStatus) { 304f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_error(ctx, GL_INVALID_OPERATION, 305f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie "glGetFragDataIndex(program not linked)"); 306f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return -1; 307f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie } 308f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 309f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (!name) 310f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return -1; 311f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 312f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (strncmp(name, "gl_", 3) == 0) { 313f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie _mesa_error(ctx, GL_INVALID_OPERATION, 314f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie "glGetFragDataIndex(illegal name)"); 315f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return -1; 316f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie } 317f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 318f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie /* Not having a fragment shader is not an error. 319f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie */ 320f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) 321f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return -1; 322f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 323f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; 324f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie foreach_list(node, ir) { 325f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 326f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 327f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie /* The extra check against FRAG_RESULT_DATA0 is because 328f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie * glGetFragDataLocation cannot be used on "conventional" attributes. 329f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie * 330f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie * From page 95 of the OpenGL 3.0 spec: 331f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie * 332f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie * "If name is not an active attribute, if name is a conventional 333f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie * attribute, or if an error occurs, -1 will be returned." 334f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie */ 335f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (var == NULL 336f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie || var->mode != ir_var_out 337f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie || var->location == -1 338f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie || var->location < FRAG_RESULT_DATA0) 339f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie continue; 340f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 341f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie if (strcmp(var->name, name) == 0) 342f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return var->index; 343f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie } 344f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie 345f8cf79936b42405a8366613b80e3bde21aadaa02Dave Airlie return -1; 3464464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick} 34759012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 34859012c31337f104aedfe69ca6d3cf784581df544Ian RomanickGLint GLAPIENTRY 34959012c31337f104aedfe69ca6d3cf784581df544Ian Romanick_mesa_GetFragDataLocation(GLuint program, const GLchar *name) 35059012c31337f104aedfe69ca6d3cf784581df544Ian Romanick{ 35159012c31337f104aedfe69ca6d3cf784581df544Ian Romanick GET_CURRENT_CONTEXT(ctx); 35259012c31337f104aedfe69ca6d3cf784581df544Ian Romanick struct gl_shader_program *const shProg = 35359012c31337f104aedfe69ca6d3cf784581df544Ian Romanick _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation"); 35459012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 35559012c31337f104aedfe69ca6d3cf784581df544Ian Romanick if (!shProg) { 35659012c31337f104aedfe69ca6d3cf784581df544Ian Romanick return -1; 35759012c31337f104aedfe69ca6d3cf784581df544Ian Romanick } 35859012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 35959012c31337f104aedfe69ca6d3cf784581df544Ian Romanick if (!shProg->LinkStatus) { 36059012c31337f104aedfe69ca6d3cf784581df544Ian Romanick _mesa_error(ctx, GL_INVALID_OPERATION, 36159012c31337f104aedfe69ca6d3cf784581df544Ian Romanick "glGetFragDataLocation(program not linked)"); 36259012c31337f104aedfe69ca6d3cf784581df544Ian Romanick return -1; 36359012c31337f104aedfe69ca6d3cf784581df544Ian Romanick } 36459012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 36559012c31337f104aedfe69ca6d3cf784581df544Ian Romanick if (!name) 36659012c31337f104aedfe69ca6d3cf784581df544Ian Romanick return -1; 36759012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 36859012c31337f104aedfe69ca6d3cf784581df544Ian Romanick if (strncmp(name, "gl_", 3) == 0) { 36959012c31337f104aedfe69ca6d3cf784581df544Ian Romanick _mesa_error(ctx, GL_INVALID_OPERATION, 37059012c31337f104aedfe69ca6d3cf784581df544Ian Romanick "glGetFragDataLocation(illegal name)"); 37159012c31337f104aedfe69ca6d3cf784581df544Ian Romanick return -1; 37259012c31337f104aedfe69ca6d3cf784581df544Ian Romanick } 37359012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 37459012c31337f104aedfe69ca6d3cf784581df544Ian Romanick /* Not having a fragment shader is not an error. 37559012c31337f104aedfe69ca6d3cf784581df544Ian Romanick */ 37659012c31337f104aedfe69ca6d3cf784581df544Ian Romanick if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) 37759012c31337f104aedfe69ca6d3cf784581df544Ian Romanick return -1; 37859012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 37959012c31337f104aedfe69ca6d3cf784581df544Ian Romanick exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir; 38059012c31337f104aedfe69ca6d3cf784581df544Ian Romanick foreach_list(node, ir) { 38159012c31337f104aedfe69ca6d3cf784581df544Ian Romanick const ir_variable *const var = ((ir_instruction *) node)->as_variable(); 38259012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 38359012c31337f104aedfe69ca6d3cf784581df544Ian Romanick /* The extra check against FRAG_RESULT_DATA0 is because 38459012c31337f104aedfe69ca6d3cf784581df544Ian Romanick * glGetFragDataLocation cannot be used on "conventional" attributes. 38559012c31337f104aedfe69ca6d3cf784581df544Ian Romanick * 38659012c31337f104aedfe69ca6d3cf784581df544Ian Romanick * From page 95 of the OpenGL 3.0 spec: 38759012c31337f104aedfe69ca6d3cf784581df544Ian Romanick * 38859012c31337f104aedfe69ca6d3cf784581df544Ian Romanick * "If name is not an active attribute, if name is a conventional 38959012c31337f104aedfe69ca6d3cf784581df544Ian Romanick * attribute, or if an error occurs, -1 will be returned." 39059012c31337f104aedfe69ca6d3cf784581df544Ian Romanick */ 39159012c31337f104aedfe69ca6d3cf784581df544Ian Romanick if (var == NULL 39259012c31337f104aedfe69ca6d3cf784581df544Ian Romanick || var->mode != ir_var_out 39359012c31337f104aedfe69ca6d3cf784581df544Ian Romanick || var->location == -1 39459012c31337f104aedfe69ca6d3cf784581df544Ian Romanick || var->location < FRAG_RESULT_DATA0) 39559012c31337f104aedfe69ca6d3cf784581df544Ian Romanick continue; 39659012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 39759012c31337f104aedfe69ca6d3cf784581df544Ian Romanick if (strcmp(var->name, name) == 0) 39859012c31337f104aedfe69ca6d3cf784581df544Ian Romanick return var->location - FRAG_RESULT_DATA0; 39959012c31337f104aedfe69ca6d3cf784581df544Ian Romanick } 40059012c31337f104aedfe69ca6d3cf784581df544Ian Romanick 40159012c31337f104aedfe69ca6d3cf784581df544Ian Romanick return -1; 40259012c31337f104aedfe69ca6d3cf784581df544Ian Romanick} 403