gl_util.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #include "gl_util.h"
  2. #include <assert.h>
  3. #include <gdk/gdk.h>
  4. #include <gio/gio.h>
  5. #include <gmodule.h>
  6. #include <stdint.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. void
  10. gl_util_check_error(const char *file, int line)
  11. {
  12. GLenum error = glGetError();
  13. const char *name;
  14. switch (error) {
  15. case GL_NO_ERROR:
  16. return; // no error
  17. case GL_INVALID_ENUM:
  18. name = "GL_INVALID_ENUM";
  19. break;
  20. case GL_INVALID_VALUE:
  21. name = "GL_INVALID_VALUE";
  22. break;
  23. case GL_INVALID_OPERATION:
  24. name = "GL_INVALID_OPERATION";
  25. break;
  26. case GL_INVALID_FRAMEBUFFER_OPERATION:
  27. name = "GL_INVALID_FRAMEBUFFER_OPERATION";
  28. break;
  29. case GL_OUT_OF_MEMORY:
  30. name = "GL_OUT_OF_MEMORY";
  31. break;
  32. default:
  33. name = "UNKNOWN ERROR!";
  34. break;
  35. }
  36. printf("GL error at %s:%d - %s\n", file, line, name);
  37. // raise(SIGTRAP);
  38. }
  39. GLuint
  40. gl_util_load_shader(const char *resource,
  41. GLenum type,
  42. const char **extra_sources,
  43. size_t num_extra)
  44. {
  45. GdkGLContext *context = gdk_gl_context_get_current();
  46. assert(context);
  47. GLuint shader = glCreateShader(type);
  48. if (shader == 0) {
  49. return 0;
  50. }
  51. GBytes *bytes = g_resources_lookup_data(resource, 0, NULL);
  52. if (!bytes) {
  53. printf("Failed to load shader resource %s\n", resource);
  54. return 0;
  55. }
  56. // Build #define for OpenGL context information
  57. gboolean is_es = gdk_gl_context_get_use_es(context);
  58. int major, minor;
  59. gdk_gl_context_get_version(context, &major, &minor);
  60. char context_info_buf[128];
  61. snprintf(context_info_buf,
  62. 128,
  63. "#define %s\n#define GL_%d\n#define GL_%d_%d\n",
  64. is_es ? "GL_ES" : "GL_NO_ES",
  65. major,
  66. major,
  67. minor);
  68. gsize glib_size = 0;
  69. const GLchar *source = g_bytes_get_data(bytes, &glib_size);
  70. if (glib_size == 0 || glib_size > INT_MAX) {
  71. printf("Invalid size for resource\n");
  72. return 0;
  73. }
  74. const GLchar **sources = malloc((num_extra + 1) * sizeof(GLchar *));
  75. GLint *sizes = malloc((num_extra + 1) * sizeof(GLint));
  76. for (size_t i = 0; i < num_extra; ++i) {
  77. sources[i] = extra_sources[i];
  78. sizes[i] = -1;
  79. }
  80. sources[num_extra] = source;
  81. sizes[num_extra] = glib_size;
  82. glShaderSource(shader, num_extra + 1, sources, sizes);
  83. glCompileShader(shader);
  84. check_gl();
  85. free(sources);
  86. free(sizes);
  87. g_bytes_unref(bytes);
  88. // Check compile status
  89. GLint success;
  90. glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
  91. if (success == GL_FALSE) {
  92. printf("Shader compilation failed for %s\n", resource);
  93. glDeleteShader(shader);
  94. return 0;
  95. }
  96. GLint log_length;
  97. glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
  98. if (log_length > 0) {
  99. char *log = malloc(sizeof(char) * log_length);
  100. glGetShaderInfoLog(shader, log_length - 1, &log_length, log);
  101. printf("Shader %s log: %s\n", resource, log);
  102. free(log);
  103. glDeleteShader(shader);
  104. return 0;
  105. }
  106. return shader;
  107. }
  108. GLuint
  109. gl_util_link_program(GLuint *shaders, size_t num_shaders)
  110. {
  111. GLuint program = glCreateProgram();
  112. for (size_t i = 0; i < num_shaders; ++i) {
  113. glAttachShader(program, shaders[i]);
  114. }
  115. glLinkProgram(program);
  116. check_gl();
  117. GLint success;
  118. glGetProgramiv(program, GL_LINK_STATUS, &success);
  119. if (success == GL_FALSE) {
  120. printf("Program linking failed\n");
  121. }
  122. GLint log_length;
  123. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
  124. if (log_length > 0) {
  125. char *log = malloc(sizeof(char) * log_length);
  126. glGetProgramInfoLog(program, log_length - 1, &log_length, log);
  127. printf("Program log: %s\n", log);
  128. free(log);
  129. }
  130. check_gl();
  131. return program;
  132. }
  133. static const GLfloat quad_data[] = {
  134. // Vertices
  135. -1,
  136. -1,
  137. 1,
  138. -1,
  139. -1,
  140. 1,
  141. 1,
  142. 1,
  143. // Texcoords
  144. 0,
  145. 0,
  146. 1,
  147. 0,
  148. 0,
  149. 1,
  150. 1,
  151. 1,
  152. };
  153. GLuint
  154. gl_util_new_quad()
  155. {
  156. GdkGLContext *context = gdk_gl_context_get_current();
  157. assert(context);
  158. if (gdk_gl_context_get_use_es(context)) {
  159. return 0;
  160. } else {
  161. GLuint buffer;
  162. glGenBuffers(1, &buffer);
  163. glBindBuffer(GL_ARRAY_BUFFER, buffer);
  164. glBufferData(GL_ARRAY_BUFFER,
  165. sizeof(quad_data),
  166. quad_data,
  167. GL_STATIC_DRAW);
  168. check_gl();
  169. glBindBuffer(GL_ARRAY_BUFFER, 0);
  170. check_gl();
  171. return buffer;
  172. }
  173. }
  174. void
  175. gl_util_bind_quad(GLuint buffer)
  176. {
  177. GdkGLContext *context = gdk_gl_context_get_current();
  178. assert(context);
  179. if (gdk_gl_context_get_use_es(context)) {
  180. glVertexAttribPointer(
  181. GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0, quad_data);
  182. check_gl();
  183. glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE);
  184. check_gl();
  185. glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE,
  186. 2,
  187. GL_FLOAT,
  188. 0,
  189. 0,
  190. quad_data + 8);
  191. check_gl();
  192. glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE);
  193. check_gl();
  194. } else {
  195. glBindBuffer(GL_ARRAY_BUFFER, buffer);
  196. check_gl();
  197. glVertexAttribPointer(
  198. GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, 0);
  199. glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE);
  200. check_gl();
  201. glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE,
  202. 2,
  203. GL_FLOAT,
  204. GL_FALSE,
  205. 0,
  206. (void *)(8 * sizeof(float)));
  207. glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE);
  208. check_gl();
  209. }
  210. }
  211. void
  212. gl_util_draw_quad(GLuint buffer)
  213. {
  214. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  215. check_gl();
  216. }