PageRenderTime 26ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/mesa-20120717/src/mesa/main/shaderobj.c

#
C | 430 lines | 273 code | 57 blank | 100 comment | 55 complexity | ccfca440cef45d9a6e888ef5617c735c MD5 | raw file
Possible License(s): LGPL-2.0
  1. /*
  2. * Mesa 3-D graphics library
  3. *
  4. * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
  5. * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. /**
  25. * \file shaderobj.c
  26. * \author Brian Paul
  27. *
  28. */
  29. #include "main/glheader.h"
  30. #include "main/context.h"
  31. #include "main/hash.h"
  32. #include "main/mfeatures.h"
  33. #include "main/mtypes.h"
  34. #include "main/shaderobj.h"
  35. #include "main/uniforms.h"
  36. #include "program/program.h"
  37. #include "program/prog_parameter.h"
  38. #include "program/hash_table.h"
  39. #include "ralloc.h"
  40. /**********************************************************************/
  41. /*** Shader object functions ***/
  42. /**********************************************************************/
  43. /**
  44. * Set ptr to point to sh.
  45. * If ptr is pointing to another shader, decrement its refcount (and delete
  46. * if refcount hits zero).
  47. * Then set ptr to point to sh, incrementing its refcount.
  48. */
  49. void
  50. _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
  51. struct gl_shader *sh)
  52. {
  53. assert(ptr);
  54. if (*ptr == sh) {
  55. /* no-op */
  56. return;
  57. }
  58. if (*ptr) {
  59. /* Unreference the old shader */
  60. GLboolean deleteFlag = GL_FALSE;
  61. struct gl_shader *old = *ptr;
  62. ASSERT(old->RefCount > 0);
  63. old->RefCount--;
  64. /*printf("SHADER DECR %p (%d) to %d\n",
  65. (void*) old, old->Name, old->RefCount);*/
  66. deleteFlag = (old->RefCount == 0);
  67. if (deleteFlag) {
  68. if (old->Name != 0)
  69. _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
  70. ctx->Driver.DeleteShader(ctx, old);
  71. }
  72. *ptr = NULL;
  73. }
  74. assert(!*ptr);
  75. if (sh) {
  76. /* reference new */
  77. sh->RefCount++;
  78. /*printf("SHADER INCR %p (%d) to %d\n",
  79. (void*) sh, sh->Name, sh->RefCount);*/
  80. *ptr = sh;
  81. }
  82. }
  83. void
  84. _mesa_init_shader(struct gl_context *ctx, struct gl_shader *shader)
  85. {
  86. shader->RefCount = 1;
  87. }
  88. /**
  89. * Allocate a new gl_shader object, initialize it.
  90. * Called via ctx->Driver.NewShader()
  91. */
  92. struct gl_shader *
  93. _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
  94. {
  95. struct gl_shader *shader;
  96. assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER ||
  97. type == GL_GEOMETRY_SHADER_ARB);
  98. shader = rzalloc(NULL, struct gl_shader);
  99. if (shader) {
  100. shader->Type = type;
  101. shader->Name = name;
  102. _mesa_init_shader(ctx, shader);
  103. }
  104. return shader;
  105. }
  106. /**
  107. * Delete a shader object.
  108. * Called via ctx->Driver.DeleteShader().
  109. */
  110. static void
  111. _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh)
  112. {
  113. if (sh->Source)
  114. free((void *) sh->Source);
  115. _mesa_reference_program(ctx, &sh->Program, NULL);
  116. ralloc_free(sh);
  117. }
  118. /**
  119. * Lookup a GLSL shader object.
  120. */
  121. struct gl_shader *
  122. _mesa_lookup_shader(struct gl_context *ctx, GLuint name)
  123. {
  124. if (name) {
  125. struct gl_shader *sh = (struct gl_shader *)
  126. _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  127. /* Note that both gl_shader and gl_shader_program objects are kept
  128. * in the same hash table. Check the object's type to be sure it's
  129. * what we're expecting.
  130. */
  131. if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
  132. return NULL;
  133. }
  134. return sh;
  135. }
  136. return NULL;
  137. }
  138. /**
  139. * As above, but record an error if shader is not found.
  140. */
  141. struct gl_shader *
  142. _mesa_lookup_shader_err(struct gl_context *ctx, GLuint name, const char *caller)
  143. {
  144. if (!name) {
  145. _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  146. return NULL;
  147. }
  148. else {
  149. struct gl_shader *sh = (struct gl_shader *)
  150. _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  151. if (!sh) {
  152. _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  153. return NULL;
  154. }
  155. if (sh->Type == GL_SHADER_PROGRAM_MESA) {
  156. _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
  157. return NULL;
  158. }
  159. return sh;
  160. }
  161. }
  162. /**********************************************************************/
  163. /*** Shader Program object functions ***/
  164. /**********************************************************************/
  165. /**
  166. * Set ptr to point to shProg.
  167. * If ptr is pointing to another object, decrement its refcount (and delete
  168. * if refcount hits zero).
  169. * Then set ptr to point to shProg, incrementing its refcount.
  170. */
  171. void
  172. _mesa_reference_shader_program(struct gl_context *ctx,
  173. struct gl_shader_program **ptr,
  174. struct gl_shader_program *shProg)
  175. {
  176. assert(ptr);
  177. if (*ptr == shProg) {
  178. /* no-op */
  179. return;
  180. }
  181. if (*ptr) {
  182. /* Unreference the old shader program */
  183. GLboolean deleteFlag = GL_FALSE;
  184. struct gl_shader_program *old = *ptr;
  185. ASSERT(old->RefCount > 0);
  186. old->RefCount--;
  187. #if 0
  188. printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
  189. (void *) old, old->Name, old->RefCount);
  190. #endif
  191. deleteFlag = (old->RefCount == 0);
  192. if (deleteFlag) {
  193. if (old->Name != 0)
  194. _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
  195. ctx->Driver.DeleteShaderProgram(ctx, old);
  196. }
  197. *ptr = NULL;
  198. }
  199. assert(!*ptr);
  200. if (shProg) {
  201. shProg->RefCount++;
  202. #if 0
  203. printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
  204. (void *) shProg, shProg->Name, shProg->RefCount);
  205. #endif
  206. *ptr = shProg;
  207. }
  208. }
  209. void
  210. _mesa_init_shader_program(struct gl_context *ctx, struct gl_shader_program *prog)
  211. {
  212. prog->Type = GL_SHADER_PROGRAM_MESA;
  213. prog->RefCount = 1;
  214. prog->AttributeBindings = string_to_uint_map_ctor();
  215. prog->FragDataBindings = string_to_uint_map_ctor();
  216. prog->FragDataIndexBindings = string_to_uint_map_ctor();
  217. #if FEATURE_ARB_geometry_shader4
  218. prog->Geom.VerticesOut = 0;
  219. prog->Geom.InputType = GL_TRIANGLES;
  220. prog->Geom.OutputType = GL_TRIANGLE_STRIP;
  221. #endif
  222. prog->InfoLog = ralloc_strdup(prog, "");
  223. }
  224. /**
  225. * Allocate a new gl_shader_program object, initialize it.
  226. * Called via ctx->Driver.NewShaderProgram()
  227. */
  228. static struct gl_shader_program *
  229. _mesa_new_shader_program(struct gl_context *ctx, GLuint name)
  230. {
  231. struct gl_shader_program *shProg;
  232. shProg = rzalloc(NULL, struct gl_shader_program);
  233. if (shProg) {
  234. shProg->Name = name;
  235. _mesa_init_shader_program(ctx, shProg);
  236. }
  237. return shProg;
  238. }
  239. /**
  240. * Clear (free) the shader program state that gets produced by linking.
  241. */
  242. void
  243. _mesa_clear_shader_program_data(struct gl_context *ctx,
  244. struct gl_shader_program *shProg)
  245. {
  246. if (shProg->UniformStorage) {
  247. unsigned i;
  248. for (i = 0; i < shProg->NumUserUniformStorage; ++i)
  249. _mesa_uniform_detach_all_driver_storage(&shProg->UniformStorage[i]);
  250. ralloc_free(shProg->UniformStorage);
  251. shProg->NumUserUniformStorage = 0;
  252. shProg->UniformStorage = NULL;
  253. }
  254. if (shProg->UniformHash) {
  255. string_to_uint_map_dtor(shProg->UniformHash);
  256. shProg->UniformHash = NULL;
  257. }
  258. assert(shProg->InfoLog != NULL);
  259. ralloc_free(shProg->InfoLog);
  260. shProg->InfoLog = ralloc_strdup(shProg, "");
  261. }
  262. /**
  263. * Free all the data that hangs off a shader program object, but not the
  264. * object itself.
  265. */
  266. void
  267. _mesa_free_shader_program_data(struct gl_context *ctx,
  268. struct gl_shader_program *shProg)
  269. {
  270. GLuint i;
  271. gl_shader_type sh;
  272. assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
  273. _mesa_clear_shader_program_data(ctx, shProg);
  274. if (shProg->AttributeBindings) {
  275. string_to_uint_map_dtor(shProg->AttributeBindings);
  276. shProg->AttributeBindings = NULL;
  277. }
  278. if (shProg->FragDataBindings) {
  279. string_to_uint_map_dtor(shProg->FragDataBindings);
  280. shProg->FragDataBindings = NULL;
  281. }
  282. if (shProg->FragDataIndexBindings) {
  283. string_to_uint_map_dtor(shProg->FragDataIndexBindings);
  284. shProg->FragDataIndexBindings = NULL;
  285. }
  286. /* detach shaders */
  287. for (i = 0; i < shProg->NumShaders; i++) {
  288. _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
  289. }
  290. shProg->NumShaders = 0;
  291. if (shProg->Shaders) {
  292. free(shProg->Shaders);
  293. shProg->Shaders = NULL;
  294. }
  295. /* Transform feedback varying vars */
  296. for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
  297. free(shProg->TransformFeedback.VaryingNames[i]);
  298. }
  299. free(shProg->TransformFeedback.VaryingNames);
  300. shProg->TransformFeedback.VaryingNames = NULL;
  301. shProg->TransformFeedback.NumVarying = 0;
  302. for (sh = 0; sh < MESA_SHADER_TYPES; sh++) {
  303. if (shProg->_LinkedShaders[sh] != NULL) {
  304. ctx->Driver.DeleteShader(ctx, shProg->_LinkedShaders[sh]);
  305. shProg->_LinkedShaders[sh] = NULL;
  306. }
  307. }
  308. }
  309. /**
  310. * Free/delete a shader program object.
  311. * Called via ctx->Driver.DeleteShaderProgram().
  312. */
  313. static void
  314. _mesa_delete_shader_program(struct gl_context *ctx, struct gl_shader_program *shProg)
  315. {
  316. _mesa_free_shader_program_data(ctx, shProg);
  317. ralloc_free(shProg);
  318. }
  319. /**
  320. * Lookup a GLSL program object.
  321. */
  322. struct gl_shader_program *
  323. _mesa_lookup_shader_program(struct gl_context *ctx, GLuint name)
  324. {
  325. struct gl_shader_program *shProg;
  326. if (name) {
  327. shProg = (struct gl_shader_program *)
  328. _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  329. /* Note that both gl_shader and gl_shader_program objects are kept
  330. * in the same hash table. Check the object's type to be sure it's
  331. * what we're expecting.
  332. */
  333. if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
  334. return NULL;
  335. }
  336. return shProg;
  337. }
  338. return NULL;
  339. }
  340. /**
  341. * As above, but record an error if program is not found.
  342. */
  343. struct gl_shader_program *
  344. _mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name,
  345. const char *caller)
  346. {
  347. if (!name) {
  348. _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  349. return NULL;
  350. }
  351. else {
  352. struct gl_shader_program *shProg = (struct gl_shader_program *)
  353. _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  354. if (!shProg) {
  355. _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  356. return NULL;
  357. }
  358. if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
  359. _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
  360. return NULL;
  361. }
  362. return shProg;
  363. }
  364. }
  365. void
  366. _mesa_init_shader_object_functions(struct dd_function_table *driver)
  367. {
  368. driver->NewShader = _mesa_new_shader;
  369. driver->DeleteShader = _mesa_delete_shader;
  370. driver->NewShaderProgram = _mesa_new_shader_program;
  371. driver->DeleteShaderProgram = _mesa_delete_shader_program;
  372. driver->LinkShader = _mesa_ir_link_shader;
  373. }