gl_util.c 4.9 KB

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