123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- #include "gles2_debayer.h"
- #include "camera.h"
- #include "dcp.h"
- #include "gl_util.h"
- #include "matrix.h"
- #include <stdlib.h>
- #define VERTEX_ATTRIBUTE 0
- #define TEX_COORD_ATTRIBUTE 1
- GLES2Debayer *
- gles2_debayer_new(int format)
- {
- // Cannot run on format 0 (Undefined)
- assert(format != 0);
- uint32_t pixfmt = libmegapixels_format_to_v4l_pixfmt(format);
- int shader = 0;
- if (pixfmt == V4L2_PIX_FMT_SBGGR8 || pixfmt == V4L2_PIX_FMT_SGBRG8 ||
- pixfmt == V4L2_PIX_FMT_SGRBG8 || pixfmt == V4L2_PIX_FMT_SRGGB8 ||
- pixfmt == V4L2_PIX_FMT_SBGGR10P || pixfmt == V4L2_PIX_FMT_SGBRG10P ||
- pixfmt == V4L2_PIX_FMT_SGRBG10P || pixfmt == V4L2_PIX_FMT_SRGGB10P) {
- shader = SHADER_DEBAYER;
- } else if (pixfmt == V4L2_PIX_FMT_YUYV) {
- shader = SHADER_YUV;
- } else {
- return NULL;
- }
- GLuint frame_buffer;
- glGenFramebuffers(1, &frame_buffer);
- check_gl();
- char format_def[64];
- snprintf(format_def,
- 64,
- "#define CFA_%s\n#define BITS_%d\n",
- libmegapixels_format_cfa(format),
- libmegapixels_format_bits_per_pixel(format));
- const GLchar *def[1] = { format_def };
- char shader_vertex[64];
- char shader_fragment[64];
- snprintf(shader_vertex,
- 64,
- "/org/postmarketos/Megapixels/%s.vert",
- shader == SHADER_DEBAYER ? "debayer" : "yuv");
- snprintf(shader_fragment,
- 64,
- "/org/postmarketos/Megapixels/%s.frag",
- shader == SHADER_DEBAYER ? "debayer" : "yuv");
- GLuint shaders[] = {
- gl_util_load_shader(shader_vertex, GL_VERTEX_SHADER, NULL, 0),
- gl_util_load_shader(shader_fragment, GL_FRAGMENT_SHADER, def, 1),
- };
- printf("Using shader %s and %s\n", shader_vertex, shader_fragment);
- GLuint program = gl_util_link_program(shaders, 2);
- glBindAttribLocation(program, VERTEX_ATTRIBUTE, "vert");
- glBindAttribLocation(program, TEX_COORD_ATTRIBUTE, "tex_coord");
- check_gl();
- GLES2Debayer *self = malloc(sizeof(GLES2Debayer));
- self->format = format;
- self->shader = shader;
- self->frame_buffer = frame_buffer;
- self->program = program;
- self->uniform_transform = glGetUniformLocation(self->program, "transform");
- self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size");
- self->uniform_padding_ratio =
- glGetUniformLocation(self->program, "padding_ratio");
- self->uniform_texture = glGetUniformLocation(self->program, "texture");
- self->uniform_color_matrix =
- glGetUniformLocation(self->program, "color_matrix");
- self->uniform_inv_gamma = glGetUniformLocation(self->program, "inv_gamma");
- self->uniform_blacklevel = glGetUniformLocation(self->program, "blacklevel");
- if (libmegapixels_format_bits_per_pixel(self->format) == 10)
- self->uniform_row_length =
- glGetUniformLocation(self->program, "row_length");
- check_gl();
- self->quad = gl_util_new_quad();
- return self;
- }
- void
- gles2_debayer_free(GLES2Debayer *self)
- {
- glDeleteFramebuffers(1, &self->frame_buffer);
- glDeleteProgram(self->program);
- free(self);
- }
- void
- gles2_debayer_use(GLES2Debayer *self)
- {
- assert(self != NULL);
- glUseProgram(self->program);
- check_gl();
- gl_util_bind_quad(self->quad);
- }
- void
- gles2_debayer_set_shading(GLES2Debayer *self,
- float red,
- float blue,
- float blacklevel)
- {
- if (self->forward_matrix[0]) {
- float wb[9] = {
- // clang-format off
- red, 0, 0,
- 0, 1, 0,
- 0, 0, blue,
- // clang-format on
- };
- float colormat[9];
- float xyz[9];
- float xyzd65[9];
- multiply_matrices(wb, self->forward_matrix, xyz);
- multiply_matrices(xyz, XYZD50_to_D65, xyzd65);
- multiply_matrices(xyzd65, XYZD65_to_sRGB, colormat);
- glUniformMatrix3fv(
- self->uniform_color_matrix, 1, GL_FALSE, colormat);
- } else if (self->shader == SHADER_YUV) {
- glUniformMatrix3fv(
- self->uniform_color_matrix, 1, GL_FALSE, YUV_to_RGB);
- } else {
- glUniformMatrix3fv(
- self->uniform_color_matrix, 1, GL_FALSE, IDENTITY);
- }
- check_gl();
- glUniform1f(self->uniform_blacklevel, blacklevel);
- check_gl();
- }
- void
- gles2_debayer_configure(GLES2Debayer *self,
- const uint32_t dst_width,
- const uint32_t dst_height,
- const uint32_t src_width,
- const uint32_t src_height,
- const uint32_t rotation,
- const bool mirrored,
- struct MPCameraCalibration calibration)
- {
- glViewport(0, 0, (int)dst_width, (int)dst_height);
- check_gl();
- /* Rotation matrix for orientation correction */
- GLfloat rotation_list[4] = { 0, -1, 0, 1 };
- int rotation_index = 4 - (int)rotation / 90;
- GLfloat sin_rot = rotation_list[rotation_index];
- GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4];
- GLfloat scale_x = mirrored ? 1 : -1;
- GLfloat matrix[9] = {
- // clang-format off
- cos_rot * scale_x, sin_rot, 0,
- -sin_rot * scale_x, cos_rot, 0,
- 0, 0, 1,
- // clang-format on
- };
- glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix);
- check_gl();
- GLfloat pixel_size_x = 1.0f / src_width;
- GLfloat pixel_size_y = 1.0f / src_height;
- glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y);
- check_gl();
- /* Color calibration curves and matrices */
- float gamma = 1.0f;
- for (int i = 2; i < calibration.tone_curve_length; i += 2) {
- float g = calibration.tone_curve[i + 1] / calibration.tone_curve[i];
- if (g > gamma) {
- gamma = g;
- }
- }
- glUniform1f(self->uniform_inv_gamma, 1.0f / gamma);
- check_gl();
- for (int i = 0; i < 9; i++) {
- self->forward_matrix[i] = calibration.forward_matrix_1[i];
- }
- gles2_debayer_set_shading(self, 1.0f, 1.0f, 0.0f);
- GLuint row_length =
- libmegapixels_mode_width_to_bytes(self->format, src_width);
- if (libmegapixels_format_bits_per_pixel(self->format) == 10) {
- assert(src_width % 4 == 0);
- glUniform1f(self->uniform_row_length, row_length);
- check_gl();
- }
- GLuint padding_bytes =
- libmegapixels_mode_width_to_padding(self->format, src_width);
- GLfloat padding_ratio = (float)row_length / (row_length + padding_bytes);
- glUniform1f(self->uniform_padding_ratio, padding_ratio);
- }
- void
- gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer);
- glBindTexture(GL_TEXTURE_2D, dst_id);
- glFramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_id, 0);
- check_gl();
- assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, source_id);
- glUniform1i(self->uniform_texture, 0);
- check_gl();
- gl_util_draw_quad(self->quad);
- }
|