shader_query.cpp revision b12b5d9ab5c0153c93ca5ad9cd93cb36e41be4eb
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
11084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	  || var->location == -1
11184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	  || var->location < VERT_ATTRIB_GENERIC0)
11284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	 continue;
11384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick
11484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick      if (current_index == desired_index) {
11584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	 _mesa_copy_string(name, maxLength, length, var->name);
1167a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick
11784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	 if (size)
11884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	    *size = (var->type->is_array()) ? var->type->length : 1;
1197a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick
12084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	 if (type)
12184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	    *type = var->type->gl_type;
12284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick
12384d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick	 return;
12484d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick      }
12584d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick
12684d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick      current_index++;
12784d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick   }
12884d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick
12984d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick   /* If the loop did not return early, the caller must have asked for
13084d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick    * an index that did not exit.  Set an error.
13184d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick    */
13284d71a07bb06fe5fe231b8983558fbd3608ec6f0Ian Romanick   _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
1337a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick}
1347a80c1bbc56b61525634f2b699f995e863dfade2Ian Romanick
135b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan RomanickGLint GLAPIENTRY
136b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name)
137b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick{
138b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   GET_CURRENT_CONTEXT(ctx);
139b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   struct gl_shader_program *const shProg =
140b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
141b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
142b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   if (!shProg) {
143b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      return -1;
144b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   }
145b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
146b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   if (!shProg->LinkStatus) {
147b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      _mesa_error(ctx, GL_INVALID_OPERATION,
148b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick                  "glGetAttribLocation(program not linked)");
149b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      return -1;
150b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   }
151b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
152b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   if (!name)
153b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      return -1;
154b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
155b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   /* Not having a vertex shader is not an error.
156b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick    */
157b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
158b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      return -1;
159b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
160b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
161b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   foreach_list(node, ir) {
162b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      const ir_variable *const var = ((ir_instruction *) node)->as_variable();
163b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
164b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      /* The extra check against VERT_ATTRIB_GENERIC0 is because
165b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick       * glGetAttribLocation cannot be used on "conventional" attributes.
166b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick       *
167b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick       * From page 95 of the OpenGL 3.0 spec:
168b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick       *
169b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick       *     "If name is not an active attribute, if name is a conventional
170b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick       *     attribute, or if an error occurs, -1 will be returned."
171b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick       */
172b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      if (var == NULL
173b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick	  || var->mode != ir_var_in
174b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick	  || var->location == -1
175b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick	  || var->location < VERT_ATTRIB_GENERIC0)
176b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick	 continue;
177b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
178b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick      if (strcmp(var->name, name) == 0)
179b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick	 return var->location - VERT_ATTRIB_GENERIC0;
180b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   }
181b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick
182b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick   return -1;
183b7fa0d0727a3a9e1f64d3cfc7a0f157b35dec09eIan Romanick}
184c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick
185c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick
186c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanickunsigned
187c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick_mesa_count_active_attribs(struct gl_shader_program *shProg)
188c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick{
189c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick   if (!shProg->LinkStatus
190c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick       || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
191c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick      return 0;
192c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick   }
193c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick
194c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick   exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
195c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick   unsigned i = 0;
196c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick
197c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick   foreach_list(node, ir) {
198c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick      const ir_variable *const var = ((ir_instruction *) node)->as_variable();
199c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick
200c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick      if (var == NULL
201c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick	  || var->mode != ir_var_in
202c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick	  || var->location == -1
203c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick	  || var->location < VERT_ATTRIB_GENERIC0)
204c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick	 continue;
205c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick
206c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick      i++;
207c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick   }
208c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick
209c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick   return i;
210c097c63aa880e2b84e6b1d78a8808d42864f72fcIan Romanick}
21124409ba1968cc49cbde6a111464c91271babc68aIan Romanick
21224409ba1968cc49cbde6a111464c91271babc68aIan Romanick
21324409ba1968cc49cbde6a111464c91271babc68aIan Romanicksize_t
21424409ba1968cc49cbde6a111464c91271babc68aIan Romanick_mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
21524409ba1968cc49cbde6a111464c91271babc68aIan Romanick{
21624409ba1968cc49cbde6a111464c91271babc68aIan Romanick   if (!shProg->LinkStatus
21724409ba1968cc49cbde6a111464c91271babc68aIan Romanick       || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
21824409ba1968cc49cbde6a111464c91271babc68aIan Romanick      return 0;
21924409ba1968cc49cbde6a111464c91271babc68aIan Romanick   }
22024409ba1968cc49cbde6a111464c91271babc68aIan Romanick
22124409ba1968cc49cbde6a111464c91271babc68aIan Romanick   exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
22224409ba1968cc49cbde6a111464c91271babc68aIan Romanick   size_t longest = 0;
22324409ba1968cc49cbde6a111464c91271babc68aIan Romanick
22424409ba1968cc49cbde6a111464c91271babc68aIan Romanick   foreach_list(node, ir) {
22524409ba1968cc49cbde6a111464c91271babc68aIan Romanick      const ir_variable *const var = ((ir_instruction *) node)->as_variable();
22624409ba1968cc49cbde6a111464c91271babc68aIan Romanick
22724409ba1968cc49cbde6a111464c91271babc68aIan Romanick      if (var == NULL
22824409ba1968cc49cbde6a111464c91271babc68aIan Romanick	  || var->mode != ir_var_in
22924409ba1968cc49cbde6a111464c91271babc68aIan Romanick	  || var->location == -1
23024409ba1968cc49cbde6a111464c91271babc68aIan Romanick	  || var->location < VERT_ATTRIB_GENERIC0)
23124409ba1968cc49cbde6a111464c91271babc68aIan Romanick	 continue;
23224409ba1968cc49cbde6a111464c91271babc68aIan Romanick
23324409ba1968cc49cbde6a111464c91271babc68aIan Romanick      const size_t len = strlen(var->name);
23424409ba1968cc49cbde6a111464c91271babc68aIan Romanick      if (len >= longest)
23524409ba1968cc49cbde6a111464c91271babc68aIan Romanick	 longest = len + 1;
23624409ba1968cc49cbde6a111464c91271babc68aIan Romanick   }
23724409ba1968cc49cbde6a111464c91271babc68aIan Romanick
23824409ba1968cc49cbde6a111464c91271babc68aIan Romanick   return longest;
23924409ba1968cc49cbde6a111464c91271babc68aIan Romanick}
2404464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick
2414464a4b27b66f832acbe52b0a002c04415924c14Ian Romanickvoid GLAPIENTRY
2424464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
2434464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick			   const GLchar *name)
2444464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick{
2454464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   GET_CURRENT_CONTEXT(ctx);
2464464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick
2474464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   struct gl_shader_program *const shProg =
2484464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick      _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocation");
2494464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   if (!shProg)
2504464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick      return;
2514464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick
2524464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   if (!name)
2534464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick      return;
2544464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick
2554464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   if (strncmp(name, "gl_", 3) == 0) {
2564464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick      _mesa_error(ctx, GL_INVALID_OPERATION,
2574464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick                  "glBindFragDataLocation(illegal name)");
2584464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick      return;
2594464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   }
2604464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick
2614464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   if (colorNumber >= ctx->Const.MaxDrawBuffers) {
2624464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick      _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocation(index)");
2634464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick      return;
2644464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   }
2654464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick
2664464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   /* Replace the current value if it's already in the list.  Add
2674464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick    * FRAG_RESULT_DATA0 because that's how the linker differentiates
2684464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick    * between built-in attributes and user-defined attributes.
2694464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick    */
270b12b5d9ab5c0153c93ca5ad9cd93cb36e41be4ebIan Romanick   shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
2714464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick
2724464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick   /*
2734464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick    * Note that this binding won't go into effect until
2744464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick    * glLinkProgram is called again.
2754464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick    */
2764464a4b27b66f832acbe52b0a002c04415924c14Ian Romanick}
277