PageRenderTime 25ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/mesa/main/shader_query.cpp

https://bitbucket.org/definitelylion/mesa
C++ | 329 lines | 199 code | 63 blank | 67 comment | 73 complexity | d4ee8ddba5dba1371cec4213b503f920 MD5 | raw file
Possible License(s): LGPL-2.0
  1. /*
  2. * Copyright © 2011 Intel Corporation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. /**
  24. * \file shader_query.cpp
  25. * C-to-C++ bridge functions to query GLSL shader data
  26. *
  27. * \author Ian Romanick <ian.d.romanick@intel.com>
  28. */
  29. #include "main/core.h"
  30. #include "glsl_symbol_table.h"
  31. #include "ir.h"
  32. #include "shaderobj.h"
  33. #include "program/hash_table.h"
  34. #include "../glsl/program.h"
  35. extern "C" {
  36. #include "shaderapi.h"
  37. }
  38. void GLAPIENTRY
  39. _mesa_BindAttribLocationARB(GLhandleARB program, GLuint index,
  40. const GLcharARB *name)
  41. {
  42. GET_CURRENT_CONTEXT(ctx);
  43. struct gl_shader_program *const shProg =
  44. _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
  45. if (!shProg)
  46. return;
  47. if (!name)
  48. return;
  49. if (strncmp(name, "gl_", 3) == 0) {
  50. _mesa_error(ctx, GL_INVALID_OPERATION,
  51. "glBindAttribLocation(illegal name)");
  52. return;
  53. }
  54. if (index >= ctx->Const.VertexProgram.MaxAttribs) {
  55. _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
  56. return;
  57. }
  58. /* Replace the current value if it's already in the list. Add
  59. * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
  60. * between built-in attributes and user-defined attributes.
  61. */
  62. shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
  63. /*
  64. * Note that this attribute binding won't go into effect until
  65. * glLinkProgram is called again.
  66. */
  67. }
  68. void GLAPIENTRY
  69. _mesa_GetActiveAttribARB(GLhandleARB program, GLuint desired_index,
  70. GLsizei maxLength, GLsizei * length, GLint * size,
  71. GLenum * type, GLcharARB * name)
  72. {
  73. GET_CURRENT_CONTEXT(ctx);
  74. struct gl_shader_program *shProg;
  75. shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
  76. if (!shProg)
  77. return;
  78. if (!shProg->LinkStatus) {
  79. _mesa_error(ctx, GL_INVALID_VALUE,
  80. "glGetActiveAttrib(program not linked)");
  81. return;
  82. }
  83. if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
  84. _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
  85. return;
  86. }
  87. exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  88. unsigned current_index = 0;
  89. foreach_list(node, ir) {
  90. const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  91. if (var == NULL
  92. || var->mode != ir_var_in
  93. || var->location == -1)
  94. continue;
  95. if (current_index == desired_index) {
  96. _mesa_copy_string(name, maxLength, length, var->name);
  97. if (size)
  98. *size = (var->type->is_array()) ? var->type->length : 1;
  99. if (type)
  100. *type = var->type->gl_type;
  101. return;
  102. }
  103. current_index++;
  104. }
  105. /* If the loop did not return early, the caller must have asked for
  106. * an index that did not exit. Set an error.
  107. */
  108. _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
  109. }
  110. GLint GLAPIENTRY
  111. _mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name)
  112. {
  113. GET_CURRENT_CONTEXT(ctx);
  114. struct gl_shader_program *const shProg =
  115. _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
  116. if (!shProg) {
  117. return -1;
  118. }
  119. if (!shProg->LinkStatus) {
  120. _mesa_error(ctx, GL_INVALID_OPERATION,
  121. "glGetAttribLocation(program not linked)");
  122. return -1;
  123. }
  124. if (!name)
  125. return -1;
  126. /* Not having a vertex shader is not an error.
  127. */
  128. if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
  129. return -1;
  130. exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  131. foreach_list(node, ir) {
  132. const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  133. /* The extra check against VERT_ATTRIB_GENERIC0 is because
  134. * glGetAttribLocation cannot be used on "conventional" attributes.
  135. *
  136. * From page 95 of the OpenGL 3.0 spec:
  137. *
  138. * "If name is not an active attribute, if name is a conventional
  139. * attribute, or if an error occurs, -1 will be returned."
  140. */
  141. if (var == NULL
  142. || var->mode != ir_var_in
  143. || var->location == -1
  144. || var->location < VERT_ATTRIB_GENERIC0)
  145. continue;
  146. if (strcmp(var->name, name) == 0)
  147. return var->location - VERT_ATTRIB_GENERIC0;
  148. }
  149. return -1;
  150. }
  151. unsigned
  152. _mesa_count_active_attribs(struct gl_shader_program *shProg)
  153. {
  154. if (!shProg->LinkStatus
  155. || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
  156. return 0;
  157. }
  158. exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  159. unsigned i = 0;
  160. foreach_list(node, ir) {
  161. const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  162. if (var == NULL
  163. || var->mode != ir_var_in
  164. || var->location == -1)
  165. continue;
  166. i++;
  167. }
  168. return i;
  169. }
  170. size_t
  171. _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
  172. {
  173. if (!shProg->LinkStatus
  174. || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
  175. return 0;
  176. }
  177. exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  178. size_t longest = 0;
  179. foreach_list(node, ir) {
  180. const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  181. if (var == NULL
  182. || var->mode != ir_var_in
  183. || var->location == -1)
  184. continue;
  185. const size_t len = strlen(var->name);
  186. if (len >= longest)
  187. longest = len + 1;
  188. }
  189. return longest;
  190. }
  191. void GLAPIENTRY
  192. _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
  193. const GLchar *name)
  194. {
  195. GET_CURRENT_CONTEXT(ctx);
  196. struct gl_shader_program *const shProg =
  197. _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocation");
  198. if (!shProg)
  199. return;
  200. if (!name)
  201. return;
  202. if (strncmp(name, "gl_", 3) == 0) {
  203. _mesa_error(ctx, GL_INVALID_OPERATION,
  204. "glBindFragDataLocation(illegal name)");
  205. return;
  206. }
  207. if (colorNumber >= ctx->Const.MaxDrawBuffers) {
  208. _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocation(index)");
  209. return;
  210. }
  211. /* Replace the current value if it's already in the list. Add
  212. * FRAG_RESULT_DATA0 because that's how the linker differentiates
  213. * between built-in attributes and user-defined attributes.
  214. */
  215. shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
  216. /*
  217. * Note that this binding won't go into effect until
  218. * glLinkProgram is called again.
  219. */
  220. }
  221. GLint GLAPIENTRY
  222. _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
  223. {
  224. GET_CURRENT_CONTEXT(ctx);
  225. struct gl_shader_program *const shProg =
  226. _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
  227. if (!shProg) {
  228. return -1;
  229. }
  230. if (!shProg->LinkStatus) {
  231. _mesa_error(ctx, GL_INVALID_OPERATION,
  232. "glGetFragDataLocation(program not linked)");
  233. return -1;
  234. }
  235. if (!name)
  236. return -1;
  237. if (strncmp(name, "gl_", 3) == 0) {
  238. _mesa_error(ctx, GL_INVALID_OPERATION,
  239. "glGetFragDataLocation(illegal name)");
  240. return -1;
  241. }
  242. /* Not having a fragment shader is not an error.
  243. */
  244. if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
  245. return -1;
  246. exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
  247. foreach_list(node, ir) {
  248. const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  249. /* The extra check against FRAG_RESULT_DATA0 is because
  250. * glGetFragDataLocation cannot be used on "conventional" attributes.
  251. *
  252. * From page 95 of the OpenGL 3.0 spec:
  253. *
  254. * "If name is not an active attribute, if name is a conventional
  255. * attribute, or if an error occurs, -1 will be returned."
  256. */
  257. if (var == NULL
  258. || var->mode != ir_var_out
  259. || var->location == -1
  260. || var->location < FRAG_RESULT_DATA0)
  261. continue;
  262. if (strcmp(var->name, name) == 0)
  263. return var->location - FRAG_RESULT_DATA0;
  264. }
  265. return -1;
  266. }