gl_quickpreview.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "camera.h"
  2. #include "gl_quickpreview.h"
  3. #include "gl_utils.h"
  4. #include <stdlib.h>
  5. #define VERTEX_ATTRIBUTE 0
  6. #define TEX_COORD_ATTRIBUTE 1
  7. struct _GLQuickPreview {
  8. GLuint frame_buffer;
  9. GLuint program;
  10. GLuint uniform_transform;
  11. GLuint uniform_pixel_size;
  12. GLuint uniform_half_image_size;
  13. GLuint uniform_texture;
  14. GLuint uniform_pixel_layout;
  15. GLuint uniform_srgb_map;
  16. GLuint uniform_color_matrix;
  17. GLuint pixel_layout_texture_id;
  18. uint32_t pixel_layout_texture_width;
  19. uint32_t pixel_layout_texture_height;
  20. MPPixelFormat pixel_layout_texture_format;
  21. };
  22. GLQuickPreview *gl_quick_preview_new()
  23. {
  24. GLuint frame_buffer;
  25. glGenFramebuffers(1, &frame_buffer);
  26. check_gl();
  27. GLuint shaders[] = {
  28. gl_load_shader("data/debayer.vert", GL_VERTEX_SHADER),
  29. gl_load_shader("data/debayer.frag", GL_FRAGMENT_SHADER),
  30. };
  31. GLuint program = gl_link_program(shaders, 2);
  32. glBindAttribLocation(program, VERTEX_ATTRIBUTE, "vert");
  33. glBindAttribLocation(program, TEX_COORD_ATTRIBUTE, "tex_coord");
  34. check_gl();
  35. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  36. check_gl();
  37. GLuint pixel_layout_texture_id;
  38. glGenTextures(1, &pixel_layout_texture_id);
  39. check_gl();
  40. GLQuickPreview *self = malloc(sizeof(GLQuickPreview));
  41. self->frame_buffer = frame_buffer;
  42. self->program = program;
  43. self->uniform_transform = glGetUniformLocation(self->program, "transform");
  44. self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size");
  45. self->uniform_half_image_size = glGetUniformLocation(self->program, "half_image_size");
  46. self->uniform_texture = glGetUniformLocation(self->program, "texture");
  47. self->uniform_pixel_layout = glGetUniformLocation(self->program, "pixel_layout");
  48. self->uniform_color_matrix = glGetUniformLocation(self->program, "color_matrix");
  49. self->uniform_srgb_map = glGetUniformLocation(self->program, "srgb_map");
  50. check_gl();
  51. self->pixel_layout_texture_id = pixel_layout_texture_id;
  52. self->pixel_layout_texture_width = 0;
  53. self->pixel_layout_texture_height = 0;
  54. self->pixel_layout_texture_format = MP_PIXEL_FMT_BGGR8;
  55. return self;
  56. }
  57. void gl_quick_preview_free(GLQuickPreview *self)
  58. {
  59. glDeleteFramebuffers(1, &self->frame_buffer);
  60. free(self);
  61. }
  62. bool
  63. ql_quick_preview_supports_format(GLQuickPreview *self, const MPPixelFormat format)
  64. {
  65. return format == MP_PIXEL_FMT_BGGR8;
  66. }
  67. bool
  68. gl_quick_preview(GLQuickPreview *self,
  69. GLuint dst_id,
  70. const uint32_t dst_width, const uint32_t dst_height,
  71. GLuint source_id,
  72. const uint32_t src_width, const uint32_t src_height,
  73. const MPPixelFormat format,
  74. const uint32_t rotation,
  75. const bool mirrored,
  76. const float *colormatrix,
  77. const uint8_t blacklevel)
  78. {
  79. // Generate pixel layout image
  80. if (src_width != self->pixel_layout_texture_width
  81. || src_height != self->pixel_layout_texture_height
  82. || format != self->pixel_layout_texture_format) {
  83. glBindTexture(GL_TEXTURE_2D, self->pixel_layout_texture_id);
  84. uint16_t *buffer = malloc(src_width * src_height * sizeof(uint16_t));
  85. for (size_t y = 0; y < src_height; ++y) {
  86. for (size_t x = 0; x < src_width; ++x) {
  87. buffer[x + y * src_width] =
  88. (y % 2) == 0
  89. ? ((x % 2) == 0 ? 0b1111 << 4 : 0b1111 << 8)
  90. : ((x % 2) == 0 ? 0b1111 << 8 : 0b1111 << 12);
  91. }
  92. }
  93. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  94. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  95. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src_width, src_height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, buffer);
  96. check_gl();
  97. free(buffer);
  98. self->pixel_layout_texture_width = src_width;
  99. self->pixel_layout_texture_height = src_height;
  100. self->pixel_layout_texture_format = format;
  101. glBindTexture(GL_TEXTURE_2D, 0);
  102. check_gl();
  103. }
  104. assert(ql_quick_preview_supports_format(self, format));
  105. glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer);
  106. glBindTexture(GL_TEXTURE_2D, dst_id);
  107. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_id, 0);
  108. check_gl();
  109. glViewport(0, 0, dst_width, dst_height);
  110. check_gl();
  111. assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  112. glUseProgram(self->program);
  113. check_gl();
  114. GLfloat rotation_list[4] = { 0, -1, 0, 1 };
  115. int rotation_index = 4 - rotation / 90;
  116. GLfloat sin_rot = rotation_list[rotation_index];
  117. GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4];
  118. GLfloat scale_x = mirrored ? 1 : -1;
  119. GLfloat matrix[9] = {
  120. cos_rot * scale_x, sin_rot, 0,
  121. -sin_rot * scale_x, cos_rot, 0,
  122. 0, 0, 1,
  123. };
  124. glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix);
  125. check_gl();
  126. glUniform2f(self->uniform_half_image_size, src_width / 2, src_height / 2);
  127. check_gl();
  128. GLfloat pixel_size_x = 1.0f / src_width;
  129. GLfloat pixel_size_y = 1.0f / src_height;
  130. glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y);
  131. check_gl();
  132. glActiveTexture(GL_TEXTURE0);
  133. glBindTexture(GL_TEXTURE_2D, source_id);
  134. glUniform1i(self->uniform_texture, 0);
  135. check_gl();
  136. glActiveTexture(GL_TEXTURE1);
  137. glBindTexture(GL_TEXTURE_2D, self->pixel_layout_texture_id);
  138. glUniform1i(self->uniform_pixel_layout, 1);
  139. check_gl();
  140. if (colormatrix)
  141. {
  142. GLfloat transposed[9];
  143. for (int i = 0; i < 3; ++i)
  144. for (int j = 0; j < 3; ++j)
  145. transposed[i + j * 3] = colormatrix[j + i * 3];
  146. glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, transposed);
  147. }
  148. else
  149. {
  150. static const GLfloat identity[9] = {
  151. 1, 0, 0,
  152. 0, 1, 0,
  153. 0, 0, 1,
  154. };
  155. glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, identity);
  156. }
  157. glVertexAttribPointer(VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0, gl_quad_vertices);
  158. glEnableVertexAttribArray(VERTEX_ATTRIBUTE);
  159. glVertexAttribPointer(TEX_COORD_ATTRIBUTE, 2, GL_FLOAT, 0, 0, gl_quad_texcoords);
  160. glEnableVertexAttribArray(TEX_COORD_ATTRIBUTE);
  161. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  162. check_gl();
  163. // TODO: Render
  164. // glClearColor(0, 0, 1, 0);
  165. // glClear(GL_COLOR_BUFFER_BIT);
  166. // glBindTexture(GL_TEXTURE_2D, 0);
  167. // glBindFramebuffer(GL_FRAMEBUFFER, 0);
  168. return true;
  169. }