PageRenderTime 58ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/mesa-20120717/src/mesa/main/shader_query.cpp

#
C++ | 402 lines | 249 code | 76 blank | 77 comment | 95 complexity | fcf8c0db4fb56d115ffcec178f0a701d 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. _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
  196. }
  197. void GLAPIENTRY
  198. _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
  199. GLuint index, const GLchar *name)
  200. {
  201. GET_CURRENT_CONTEXT(ctx);
  202. struct gl_shader_program *const shProg =
  203. _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
  204. if (!shProg)
  205. return;
  206. if (!name)
  207. return;
  208. if (strncmp(name, "gl_", 3) == 0) {
  209. _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
  210. return;
  211. }
  212. if (index > 1) {
  213. _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
  214. return;
  215. }
  216. if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
  217. _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
  218. return;
  219. }
  220. if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
  221. _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
  222. return;
  223. }
  224. /* Replace the current value if it's already in the list. Add
  225. * FRAG_RESULT_DATA0 because that's how the linker differentiates
  226. * between built-in attributes and user-defined attributes.
  227. */
  228. shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
  229. shProg->FragDataIndexBindings->put(index, name);
  230. /*
  231. * Note that this binding won't go into effect until
  232. * glLinkProgram is called again.
  233. */
  234. }
  235. GLint GLAPIENTRY
  236. _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
  237. {
  238. GET_CURRENT_CONTEXT(ctx);
  239. struct gl_shader_program *const shProg =
  240. _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
  241. if (!shProg) {
  242. return -1;
  243. }
  244. if (!shProg->LinkStatus) {
  245. _mesa_error(ctx, GL_INVALID_OPERATION,
  246. "glGetFragDataIndex(program not linked)");
  247. return -1;
  248. }
  249. if (!name)
  250. return -1;
  251. if (strncmp(name, "gl_", 3) == 0) {
  252. _mesa_error(ctx, GL_INVALID_OPERATION,
  253. "glGetFragDataIndex(illegal name)");
  254. return -1;
  255. }
  256. /* Not having a fragment shader is not an error.
  257. */
  258. if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
  259. return -1;
  260. exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
  261. foreach_list(node, ir) {
  262. const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  263. /* The extra check against FRAG_RESULT_DATA0 is because
  264. * glGetFragDataLocation cannot be used on "conventional" attributes.
  265. *
  266. * From page 95 of the OpenGL 3.0 spec:
  267. *
  268. * "If name is not an active attribute, if name is a conventional
  269. * attribute, or if an error occurs, -1 will be returned."
  270. */
  271. if (var == NULL
  272. || var->mode != ir_var_out
  273. || var->location == -1
  274. || var->location < FRAG_RESULT_DATA0)
  275. continue;
  276. if (strcmp(var->name, name) == 0)
  277. return var->index;
  278. }
  279. return -1;
  280. }
  281. GLint GLAPIENTRY
  282. _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
  283. {
  284. GET_CURRENT_CONTEXT(ctx);
  285. struct gl_shader_program *const shProg =
  286. _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
  287. if (!shProg) {
  288. return -1;
  289. }
  290. if (!shProg->LinkStatus) {
  291. _mesa_error(ctx, GL_INVALID_OPERATION,
  292. "glGetFragDataLocation(program not linked)");
  293. return -1;
  294. }
  295. if (!name)
  296. return -1;
  297. if (strncmp(name, "gl_", 3) == 0) {
  298. _mesa_error(ctx, GL_INVALID_OPERATION,
  299. "glGetFragDataLocation(illegal name)");
  300. return -1;
  301. }
  302. /* Not having a fragment shader is not an error.
  303. */
  304. if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
  305. return -1;
  306. exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
  307. foreach_list(node, ir) {
  308. const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  309. /* The extra check against FRAG_RESULT_DATA0 is because
  310. * glGetFragDataLocation cannot be used on "conventional" attributes.
  311. *
  312. * From page 95 of the OpenGL 3.0 spec:
  313. *
  314. * "If name is not an active attribute, if name is a conventional
  315. * attribute, or if an error occurs, -1 will be returned."
  316. */
  317. if (var == NULL
  318. || var->mode != ir_var_out
  319. || var->location == -1
  320. || var->location < FRAG_RESULT_DATA0)
  321. continue;
  322. if (strcmp(var->name, name) == 0)
  323. return var->location - FRAG_RESULT_DATA0;
  324. }
  325. return -1;
  326. }