gles2_debayer.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include "gles2_debayer.h"
  2. #include "camera.h"
  3. #include "gl_util.h"
  4. #include <stdlib.h>
  5. #define VERTEX_ATTRIBUTE 0
  6. #define TEX_COORD_ATTRIBUTE 1
  7. struct _GLES2Debayer {
  8. int format;
  9. GLuint frame_buffer;
  10. GLuint program;
  11. GLuint uniform_transform;
  12. GLuint uniform_pixel_size;
  13. GLuint uniform_padding_ratio;
  14. GLuint uniform_texture;
  15. GLuint uniform_color_matrix;
  16. GLuint uniform_row_length;
  17. GLuint quad;
  18. };
  19. GLES2Debayer *
  20. gles2_debayer_new(int format, uint32_t colorspace)
  21. {
  22. uint32_t pixfmt = libmegapixels_format_to_v4l_pixfmt(format);
  23. if (pixfmt != V4L2_PIX_FMT_SBGGR8 && pixfmt != V4L2_PIX_FMT_SGBRG8 &&
  24. pixfmt != V4L2_PIX_FMT_SGRBG8 && pixfmt != V4L2_PIX_FMT_SRGGB8 &&
  25. pixfmt != V4L2_PIX_FMT_SBGGR10P && pixfmt != V4L2_PIX_FMT_SGBRG10P &&
  26. pixfmt != V4L2_PIX_FMT_SGRBG10P && pixfmt != V4L2_PIX_FMT_SRGGB10P) {
  27. return NULL;
  28. }
  29. GLuint frame_buffer;
  30. glGenFramebuffers(1, &frame_buffer);
  31. check_gl();
  32. char format_def[96];
  33. bool is_srgb = colorspace == V4L2_COLORSPACE_SRGB;
  34. snprintf(format_def,
  35. 96,
  36. "#define CFA_%s\n#define BITS_%d\n#define COLORSPACE_%s\n",
  37. libmegapixels_format_cfa(format),
  38. libmegapixels_format_bits_per_pixel(format),
  39. is_srgb ? "SRGB" : "RAW");
  40. const GLchar *def[1] = { format_def };
  41. GLuint shaders[] = {
  42. gl_util_load_shader("/org/postmarketos/Megapixels/debayer.vert",
  43. GL_VERTEX_SHADER,
  44. NULL,
  45. 0),
  46. gl_util_load_shader("/org/postmarketos/Megapixels/debayer.frag",
  47. GL_FRAGMENT_SHADER,
  48. def,
  49. 1),
  50. };
  51. GLuint program = gl_util_link_program(shaders, 2);
  52. glBindAttribLocation(program, VERTEX_ATTRIBUTE, "vert");
  53. glBindAttribLocation(program, TEX_COORD_ATTRIBUTE, "tex_coord");
  54. check_gl();
  55. GLES2Debayer *self = malloc(sizeof(GLES2Debayer));
  56. self->format = format;
  57. self->frame_buffer = frame_buffer;
  58. self->program = program;
  59. self->uniform_transform = glGetUniformLocation(self->program, "transform");
  60. self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size");
  61. self->uniform_padding_ratio =
  62. glGetUniformLocation(self->program, "padding_ratio");
  63. self->uniform_texture = glGetUniformLocation(self->program, "texture");
  64. self->uniform_color_matrix =
  65. glGetUniformLocation(self->program, "color_matrix");
  66. if (libmegapixels_format_bits_per_pixel(self->format) == 10)
  67. self->uniform_row_length =
  68. glGetUniformLocation(self->program, "row_length");
  69. check_gl();
  70. self->quad = gl_util_new_quad();
  71. return self;
  72. }
  73. void
  74. gles2_debayer_free(GLES2Debayer *self)
  75. {
  76. glDeleteFramebuffers(1, &self->frame_buffer);
  77. glDeleteProgram(self->program);
  78. free(self);
  79. }
  80. void
  81. gles2_debayer_use(GLES2Debayer *self)
  82. {
  83. assert(self != NULL);
  84. glUseProgram(self->program);
  85. check_gl();
  86. gl_util_bind_quad(self->quad);
  87. }
  88. void
  89. gles2_debayer_configure(GLES2Debayer *self,
  90. const uint32_t dst_width,
  91. const uint32_t dst_height,
  92. const uint32_t src_width,
  93. const uint32_t src_height,
  94. const uint32_t rotation,
  95. const bool mirrored,
  96. const float *colormatrix,
  97. const uint8_t blacklevel)
  98. {
  99. glViewport(0, 0, (int)dst_width, (int)dst_height);
  100. check_gl();
  101. GLfloat rotation_list[4] = { 0, -1, 0, 1 };
  102. int rotation_index = 4 - (int)rotation / 90;
  103. GLfloat sin_rot = rotation_list[rotation_index];
  104. GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4];
  105. GLfloat scale_x = mirrored ? 1 : -1;
  106. GLfloat matrix[9] = {
  107. // clang-format off
  108. cos_rot * scale_x, sin_rot, 0,
  109. -sin_rot * scale_x, cos_rot, 0,
  110. 0, 0, 1,
  111. // clang-format on
  112. };
  113. glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix);
  114. check_gl();
  115. GLfloat pixel_size_x = 1.0f / src_width;
  116. GLfloat pixel_size_y = 1.0f / src_height;
  117. glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y);
  118. check_gl();
  119. if (colormatrix) {
  120. GLfloat transposed[9];
  121. for (int i = 0; i < 3; ++i)
  122. for (int j = 0; j < 3; ++j)
  123. transposed[i + j * 3] = colormatrix[j + i * 3];
  124. glUniformMatrix3fv(
  125. self->uniform_color_matrix, 1, GL_FALSE, transposed);
  126. } else {
  127. static const GLfloat identity[9] = {
  128. // clang-format off
  129. 1, 0, 0,
  130. 0, 1, 0,
  131. 0, 0, 1,
  132. // clang-format on
  133. };
  134. glUniformMatrix3fv(
  135. self->uniform_color_matrix, 1, GL_FALSE, identity);
  136. }
  137. check_gl();
  138. GLuint row_length =
  139. libmegapixels_mode_width_to_bytes(self->format, src_width);
  140. if (libmegapixels_format_bits_per_pixel(self->format) == 10) {
  141. assert(src_width % 4 == 0);
  142. glUniform1f(self->uniform_row_length, row_length);
  143. check_gl();
  144. }
  145. GLuint padding_bytes =
  146. libmegapixels_mode_width_to_padding(self->format, src_width);
  147. GLfloat padding_ratio = (float)row_length / (row_length + padding_bytes);
  148. glUniform1f(self->uniform_padding_ratio, padding_ratio);
  149. }
  150. void
  151. gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id)
  152. {
  153. glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer);
  154. glBindTexture(GL_TEXTURE_2D, dst_id);
  155. glFramebufferTexture2D(
  156. GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_id, 0);
  157. check_gl();
  158. assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
  159. glActiveTexture(GL_TEXTURE0);
  160. glBindTexture(GL_TEXTURE_2D, source_id);
  161. glUniform1i(self->uniform_texture, 0);
  162. check_gl();
  163. gl_util_draw_quad(self->quad);
  164. }