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