summaryrefslogtreecommitdiff
path: root/src/qcam/viewfinder_gl.h
AgeCommit message (Collapse)Author
2020-11-07qcam: viewfinder_gl: Store textures in an arrayLaurent Pinchart
In preparation for RGB formats support, store the three Y, U and V textures in an array. This makes the code more generic, and will avoid referring to an RGB texture as textureY_. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Andrey Konovalov <andrey.konovalov@linaro.org> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-11-07qcam: viewfinder_gl: Rename yuvData_ to data_Laurent Pinchart
In preparation for RGB formats support, rename the pointer to image data from yuvData_ to data_. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Andrey Konovalov <andrey.konovalov@linaro.org> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-11-07qcam: viewfinder_gl: Fix fragment shader rebuild when setting formatLaurent Pinchart
When setting a new format, the existing fragment shader is deleted and a new shader should be created. However, the shader pointer isn't set to nullptr after deleting it, resulting in the deleter shader being reused. Fix it by managing shader pointers with std::unique_ptr<> to prevent similar bugs from happening in the future. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-10-04qcam: viewfinder_gl: Add shader to render packed YUV formatsLaurent Pinchart
The shader supports all 4 packed 8-bit YUV variants. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-10-04qcam: viewfinder_gl: Support #define in shadersLaurent Pinchart
Prepare the infrastructure to support defining preprocessor macros in shaders: - Rename the fragmentShaderSrc_ member to fragmentShaderFile_ to reflect better that it contains a file name, not shader source code - Add a new fragmentShaderDefines_ member to store preprocessor macros - Prepend the macros to the shader source before compiling it Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-10-04qcam: viewfinder_gl: Hardcode the vertex shader file nameLaurent Pinchart
The GL renderer uses the same vertex shader for all formats. Hardcode the file name instead of storing it in a member variable. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-10-04qcam: viewfinder_gl: Don't store texture IDs in class membersLaurent Pinchart
The texture IDs can easily and cheaply be retrieved from the textures, there's no need to store them in class members. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
2020-09-15qcam: Add ViewFinderGL class to accelerate the format conversionShow Liu
The viewfinderGL accelerates the format conversion by using OpenGL ES shader. The minimum Qt version is bumped to v5.4, as QOpenGLWidget wasn't available before that. Signed-off-by: Show Liu <show.liu@linaro.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7 8 9 | ... * -------------+-------------------+-------------------+-- * X | 0.0 1.25 2.5 3.75 | 5.0 6.25 7.5 8.75 | ... * -------------+-------------------+-------------------+-- * If fract(X) < THRESHOLD_L then the previous byte contains the LS * bits of the pixel values and needs to be skipped. * If fract(X) > THRESHOLD_H then the next byte contains the LS bits * of the pixel values and needs to be skipped. */ #if defined(RAW10P) #define BPP 1.25 #define THRESHOLD_L 0.14 #define THRESHOLD_H 0.64 #elif defined(RAW12P) #define BPP 1.5 #define THRESHOLD_L 0.27 #define THRESHOLD_H 0.27 #else #error Invalid raw format #endif varying vec2 textureOut; /* the texture size in pixels */ uniform vec2 tex_size; uniform vec2 tex_step; uniform vec2 tex_bayer_first_red; uniform sampler2D tex_y; void main(void) { vec3 rgb; /* * center_bytes holds the coordinates of the MS byte of the pixel * being sampled on the [0, stride-1/height-1] range. * center_pixel holds the coordinates of the pixel being sampled * on the [0, width/height-1] range. */ vec2 center_bytes; vec2 center_pixel; /* * x- and y-positions of the adjacent pixels on the [0, 1] range. */ vec2 xcoords; vec2 ycoords; /* * The coordinates passed to the shader in textureOut may point * to a place in between the pixels if the texture format doesn't * match the image format. In particular, MIPI packed raw Bayer * formats don't have a matching texture format. * In this case align the coordinates to the left nearest pixel * by hand. */ center_pixel = floor(textureOut * tex_size); center_bytes.y = center_pixel.y; /* * Add a small number (a few mantissa's LSBs) to avoid float * representation issues. Maybe paranoic. */ center_bytes.x = BPP * center_pixel.x + 0.02; float fract_x = fract(center_bytes.x); /* * The below floor() call ensures that center_bytes.x points * at one of the bytes representing the 8 higher bits of * the pixel value, not at the byte containing the LS bits * of the group of the pixels. */ center_bytes.x = floor(center_bytes.x); center_bytes *= tex_step; xcoords = center_bytes.x + vec2(-tex_step.x, tex_step.x); ycoords = center_bytes.y + vec2(-tex_step.y, tex_step.y); /* * If xcoords[0] points at the byte containing the LS bits * of the previous group of the pixels, move xcoords[0] one * byte back. */ xcoords[0] += (fract_x < THRESHOLD_L) ? -tex_step.x : 0.0; /* * If xcoords[1] points at the byte containing the LS bits * of the current group of the pixels, move xcoords[1] one * byte forward. */ xcoords[1] += (fract_x > THRESHOLD_H) ? tex_step.x : 0.0; vec2 alternate = mod(center_pixel.xy + tex_bayer_first_red, 2.0); bool even_col = alternate.x < 1.0; bool even_row = alternate.y < 1.0; /* * We need to sample the central pixel and the ones with offset * of -1 to +1 pixel in both X and Y directions. Let's name these * pixels as below, where C is the central pixel: * * +----+----+----+----+ * | \ x| | | | * |y \ | -1 | 0 | +1 | * +----+----+----+----+ * | +1 | D2 | A1 | D3 | * +----+----+----+----+ * | 0 | B0 | C | B1 | * +----+----+----+----+ * | -1 | D0 | A0 | D1 | * +----+----+----+----+ * * In the below equations (0,-1).r means "r component of the texel * shifted by -tex_step.y from the center_bytes one" etc. * * In the even row / even column (EE) case the colour values are: * R = C = (0,0).r, * G = (A0 + A1 + B0 + B1) / 4.0 = * ( (0,-1).r + (0,1).r + (-1,0).r + (1,0).r ) / 4.0, * B = (D0 + D1 + D2 + D3) / 4.0 = * ( (-1,-1).r + (1,-1).r + (-1,1).r + (1,1).r ) / 4.0 * * For even row / odd column (EO): * R = (B0 + B1) / 2.0 = ( (-1,0).r + (1,0).r ) / 2.0, * G = C = (0,0).r, * B = (A0 + A1) / 2.0 = ( (0,-1).r + (0,1).r ) / 2.0 * * For odd row / even column (OE): * R = (A0 + A1) / 2.0 = ( (0,-1).r + (0,1).r ) / 2.0, * G = C = (0,0).r, * B = (B0 + B1) / 2.0 = ( (-1,0).r + (1,0).r ) / 2.0 * * For odd row / odd column (OO): * R = (D0 + D1 + D2 + D3) / 4.0 = * ( (-1,-1).r + (1,-1).r + (-1,1).r + (1,1).r ) / 4.0, * G = (A0 + A1 + B0 + B1) / 4.0 = * ( (0,-1).r + (0,1).r + (-1,0).r + (1,0).r ) / 4.0, * B = C = (0,0).r */ /* * Fetch the values and precalculate the terms: * patterns.x = (A0 + A1) / 2.0 * patterns.y = (B0 + B1) / 2.0 * patterns.z = (A0 + A1 + B0 + B1) / 4.0 * patterns.w = (D0 + D1 + D2 + D3) / 4.0 */ #define fetch(x, y) texture2D(tex_y, vec2(x, y)).r float C = texture2D(tex_y, center_bytes).r; vec4 patterns = vec4( fetch(center_bytes.x, ycoords[0]), /* A0: (0,-1) */ fetch(xcoords[0], center_bytes.y), /* B0: (-1,0) */ fetch(xcoords[0], ycoords[0]), /* D0: (-1,-1) */ fetch(xcoords[1], ycoords[0])); /* D1: (1,-1) */ vec4 temp = vec4( fetch(center_bytes.x, ycoords[1]), /* A1: (0,1) */ fetch(xcoords[1], center_bytes.y), /* B1: (1,0) */ fetch(xcoords[1], ycoords[1]), /* D3: (1,1) */ fetch(xcoords[0], ycoords[1])); /* D2: (-1,1) */ patterns = (patterns + temp) * 0.5; /* .x = (A0 + A1) / 2.0, .y = (B0 + B1) / 2.0 */ /* .z = (D0 + D3) / 2.0, .w = (D1 + D2) / 2.0 */ patterns.w = (patterns.z + patterns.w) * 0.5; patterns.z = (patterns.x + patterns.y) * 0.5; rgb = even_col ? (even_row ? vec3(C, patterns.zw) : vec3(patterns.x, C, patterns.y)) : (even_row ? vec3(patterns.y, C, patterns.x) : vec3(patterns.wz, C)); gl_FragColor = vec4(rgb, 1.0); }