gl-shader.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include <assert.h>
  15. #include "graphics/vec2.h"
  16. #include "graphics/vec3.h"
  17. #include "graphics/vec4.h"
  18. #include "graphics/matrix3.h"
  19. #include "graphics/matrix4.h"
  20. #include "gl-subsystem.h"
  21. #include "gl-shaderparser.h"
  22. static inline void shader_param_init(struct shader_param *param)
  23. {
  24. memset(param, 0, sizeof(struct shader_param));
  25. }
  26. static inline void shader_param_free(struct shader_param *param)
  27. {
  28. bfree(param->name);
  29. da_free(param->cur_value);
  30. da_free(param->def_value);
  31. }
  32. static void gl_get_program_info(GLuint program, char **error_string)
  33. {
  34. char *errors;
  35. GLint info_len = 0;
  36. GLsizei chars_written = 0;
  37. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_len);
  38. if (!gl_success("glGetProgramiv") || !info_len)
  39. return;
  40. errors = bmalloc(info_len+1);
  41. memset(errors, 0, info_len+1);
  42. glGetProgramInfoLog(program, info_len, &chars_written, errors);
  43. gl_success("glGetProgramInfoLog");
  44. *error_string = errors;
  45. }
  46. static bool gl_add_param(struct gs_shader *shader, struct shader_var *var,
  47. GLint *texture_id)
  48. {
  49. struct shader_param param = {0};
  50. param.array_count = var->array_count;
  51. param.name = bstrdup(var->name);
  52. param.type = get_shader_param_type(var->type);
  53. if (param.type == SHADER_PARAM_TEXTURE) {
  54. param.sampler_id = var->gl_sampler_id;
  55. param.texture_id = (*texture_id)++;
  56. } else {
  57. param.changed = true;
  58. }
  59. da_move(param.def_value, var->default_val);
  60. da_copy(param.cur_value, param.def_value);
  61. param.param = glGetUniformLocation(shader->program, param.name);
  62. if (!gl_success("glGetUniformLocation"))
  63. return false;
  64. return true;
  65. }
  66. static inline bool gl_add_params(struct gs_shader *shader,
  67. struct gl_shader_parser *glsp)
  68. {
  69. size_t i;
  70. GLint tex_id = 0;
  71. for (i = 0; i < glsp->parser.params.num; i++)
  72. if (!gl_add_param(shader, glsp->parser.params.array+i, &tex_id))
  73. return false;
  74. return true;
  75. }
  76. static void gl_add_sampler(struct gs_shader *shader,
  77. struct shader_sampler *sampler)
  78. {
  79. struct gs_sampler_state new_sampler = {0};
  80. struct gs_sampler_info info;
  81. shader_sampler_convert(sampler, &info);
  82. convert_sampler_info(&new_sampler, &info);
  83. da_push_back(shader->samplers, &new_sampler);
  84. }
  85. static inline void gl_add_samplers(struct gs_shader *shader,
  86. struct gl_shader_parser *glsp)
  87. {
  88. size_t i;
  89. for (i = 0; i < glsp->parser.samplers.num; i++) {
  90. struct shader_sampler *sampler = glsp->parser.samplers.array+i;
  91. gl_add_sampler(shader, sampler);
  92. }
  93. }
  94. static bool gl_shader_init(struct gs_shader *shader,
  95. struct gl_shader_parser *glsp,
  96. const char *file, char **error_string)
  97. {
  98. GLenum type = convert_shader_type(shader->type);
  99. int compiled = 0;
  100. bool success = true;
  101. shader->program = glCreateShaderProgramv(type, 1,
  102. &glsp->gl_string.array);
  103. gl_success("glCreateShaderProgramv");
  104. if (!shader->program)
  105. return false;
  106. glGetProgramiv(shader->program, GL_VALIDATE_STATUS, &compiled);
  107. if (!gl_success("glGetProgramiv"))
  108. return false;
  109. if (!compiled)
  110. success = false;
  111. gl_get_program_info(shader->program, error_string);
  112. if (success)
  113. success = gl_add_params(shader, glsp);
  114. if (success)
  115. gl_add_samplers(shader, glsp);
  116. return success;
  117. }
  118. static struct gs_shader *shader_create(device_t device, enum shader_type type,
  119. const char *shader_str, const char *file, char **error_string)
  120. {
  121. struct gs_shader *shader = bmalloc(sizeof(struct gs_shader));
  122. struct gl_shader_parser glsp;
  123. bool success = true;
  124. memset(shader, 0, sizeof(struct gs_shader));
  125. shader->device = device;
  126. shader->type = type;
  127. gl_shader_parser_init(&glsp);
  128. if (!gl_shader_parse(&glsp, shader_str, file))
  129. success = false;
  130. else
  131. success = gl_shader_init(shader, &glsp, file, error_string);
  132. if (!success) {
  133. shader_destroy(shader);
  134. shader = NULL;
  135. }
  136. gl_shader_parser_free(&glsp);
  137. return shader;
  138. }
  139. shader_t device_create_vertexshader(device_t device,
  140. const char *shader, const char *file,
  141. char **error_string)
  142. {
  143. return shader_create(device, SHADER_VERTEX, shader, file, error_string);
  144. }
  145. shader_t device_create_pixelshader(device_t device,
  146. const char *shader, const char *file,
  147. char **error_string)
  148. {
  149. return shader_create(device, SHADER_PIXEL, shader, file, error_string);
  150. }
  151. void shader_destroy(shader_t shader)
  152. {
  153. size_t i;
  154. if (!shader)
  155. return;
  156. for (i = 0; i < shader->params.num; i++)
  157. shader_param_free(shader->params.array+i);
  158. if (shader->program) {
  159. glDeleteProgram(shader->program);
  160. gl_success("glDeleteProgram");
  161. }
  162. da_free(shader->samplers);
  163. da_free(shader->params);
  164. bfree(shader);
  165. }
  166. int shader_numparams(shader_t shader)
  167. {
  168. return (int)shader->params.num;
  169. }
  170. sparam_t shader_getparambyidx(shader_t shader, int param)
  171. {
  172. assert(param < shader->params.num);
  173. return shader->params.array+param;
  174. }
  175. sparam_t shader_getparambyname(shader_t shader, const char *name)
  176. {
  177. size_t i;
  178. for (i = 0; i < shader->params.num; i++) {
  179. struct shader_param *param = shader->params.array+i;
  180. if (strcmp(param->name, name) == 0)
  181. return param;
  182. }
  183. return NULL;
  184. }
  185. void shader_getparaminfo(shader_t shader, sparam_t param,
  186. struct shader_param_info *info)
  187. {
  188. info->type = param->type;
  189. info->name = param->name;
  190. }
  191. sparam_t shader_getviewprojmatrix(shader_t shader)
  192. {
  193. return shader->viewproj;
  194. }
  195. sparam_t shader_getworldmatrix(shader_t shader)
  196. {
  197. return shader->world;
  198. }
  199. void shader_setbool(shader_t shader, sparam_t param, bool val)
  200. {
  201. glProgramUniform1i(shader->program, param->param, (GLint)val);
  202. gl_success("glProgramUniform1i");
  203. }
  204. void shader_setfloat(shader_t shader, sparam_t param, float val)
  205. {
  206. glProgramUniform1f(shader->program, param->param, val);
  207. gl_success("glProgramUniform1f");
  208. }
  209. void shader_setint(shader_t shader, sparam_t param, int val)
  210. {
  211. glProgramUniform1i(shader->program, param->param, val);
  212. gl_success("glProgramUniform1i");
  213. }
  214. void shader_setmatrix3(shader_t shader, sparam_t param,
  215. const struct matrix3 *val)
  216. {
  217. struct matrix4 mat;
  218. matrix4_from_matrix3(&mat, val);
  219. glProgramUniformMatrix4fv(shader->program, param->param, 1, true,
  220. mat.x.ptr);
  221. gl_success("glProgramUniformMatrix4fv");
  222. }
  223. void shader_setmatrix4(shader_t shader, sparam_t param,
  224. const struct matrix4 *val)
  225. {
  226. glProgramUniformMatrix4fv(shader->program, param->param, 1, true,
  227. val->x.ptr);
  228. gl_success("glProgramUniformMatrix4fv");
  229. }
  230. void shader_setvec2(shader_t shader, sparam_t param,
  231. const struct vec2 *val)
  232. {
  233. glProgramUniform2fv(shader->program, param->param, 1, val->ptr);
  234. gl_success("glProgramUniform2fv");
  235. }
  236. void shader_setvec3(shader_t shader, sparam_t param,
  237. const struct vec3 *val)
  238. {
  239. glProgramUniform3fv(shader->program, param->param, 1, val->ptr);
  240. gl_success("glProgramUniform3fv");
  241. }
  242. void shader_setvec4(shader_t shader, sparam_t param,
  243. const struct vec4 *val)
  244. {
  245. glProgramUniform4fv(shader->program, param->param, 1, val->ptr);
  246. gl_success("glProgramUniform4fv");
  247. }
  248. void shader_settexture(shader_t shader, sparam_t param, texture_t val)
  249. {
  250. param->texture = val;
  251. }
  252. static void shader_setval_data(shader_t shader, sparam_t param,
  253. const void *val, int count)
  254. {
  255. if (param->type == SHADER_PARAM_BOOL ||
  256. param->type == SHADER_PARAM_INT) {
  257. glProgramUniform1iv(shader->program, param->param, count, val);
  258. gl_success("glProgramUniform1iv");
  259. } else if (param->type == SHADER_PARAM_FLOAT) {
  260. glProgramUniform1fv(shader->program, param->param, count, val);
  261. gl_success("glProgramUniform1fv");
  262. } else if (param->type == SHADER_PARAM_VEC2) {
  263. glProgramUniform2fv(shader->program, param->param, count, val);
  264. gl_success("glProgramUniform2fv");
  265. } else if (param->type == SHADER_PARAM_VEC3) {
  266. glProgramUniform3fv(shader->program, param->param, count, val);
  267. gl_success("glProgramUniform3fv");
  268. } else if (param->type == SHADER_PARAM_VEC4) {
  269. glProgramUniform4fv(shader->program, param->param, count, val);
  270. gl_success("glProgramUniform4fv");
  271. } else if (param->type == SHADER_PARAM_MATRIX4X4) {
  272. glProgramUniformMatrix4fv(shader->program, param->param,
  273. count, false, val);
  274. gl_success("glProgramUniformMatrix4fv");
  275. }
  276. }
  277. void shader_setval(shader_t shader, sparam_t param, const void *val,
  278. size_t size)
  279. {
  280. int count = param->array_count;
  281. size_t expected_size = 0;
  282. if (!count)
  283. count = 1;
  284. switch (param->type) {
  285. case SHADER_PARAM_FLOAT: expected_size = sizeof(float); break;
  286. case SHADER_PARAM_BOOL:
  287. case SHADER_PARAM_INT: expected_size = sizeof(int); break;
  288. case SHADER_PARAM_VEC2: expected_size = sizeof(float)*2; break;
  289. case SHADER_PARAM_VEC3: expected_size = sizeof(float)*3; break;
  290. case SHADER_PARAM_VEC4: expected_size = sizeof(float)*4; break;
  291. case SHADER_PARAM_MATRIX4X4: expected_size = sizeof(float)*4*4; break;
  292. }
  293. expected_size *= count;
  294. if (!expected_size)
  295. return;
  296. if (expected_size != size) {
  297. blog(LOG_ERROR, "shader_setval (GL): Size of shader param does "
  298. "not match the size of the input");
  299. return;
  300. }
  301. shader_setval_data(shader, param, val, count);
  302. }
  303. void shader_setdefault(shader_t shader, sparam_t param)
  304. {
  305. shader_setval(shader, param, param->def_value.array,
  306. param->def_value.num);
  307. }