@@ -23,6 +23,40 @@
precision mediump float;
#endif
+/*
+ * These constants are used to select the bytes containing the HS part of
+ * the pixel value:
+ * BPP - bytes per pixel,
+ * THRESHOLD_L = fract(BPP) * 0.5 + 0.02
+ * THRESHOLD_H = 1.0 - fract(BPP) * 1.5 + 0.02
+ * Let X is the x coordinate in the texture measured in bytes (so that the
+ * range is from 0 to (stride_-1)) aligned on the nearest pixel.
+ * E.g. for RAW10P:
+ * -------------+-------------------+-------------------+--
+ * pixel No | 0 1 2 3 | 4 5 6 7 | ...
+ * -------------+-------------------+-------------------+--
+ * byte offset | 0 1 2 3 4 | 5 6 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 */
@@ -66,10 +100,7 @@ void main(void)
* Add a small number (a few mantissa's LSBs) to avoid float
* representation issues. Maybe paranoic.
*/
- center_bytes.x = BPP_X * center_pixel.x + 0.02;
-
- const float threshold_l = 0.127 /* fract(BPP_X) * 0.5 + 0.02 */;
- const float threshold_h = 0.625 /* 1.0 - fract(BPP_X) * 1.5 */;
+ center_bytes.x = BPP * center_pixel.x + 0.02;
float fract_x = fract(center_bytes.x);
@@ -90,14 +121,14 @@ void main(void)
* of the previous group of the pixels, move xcoords[0] one
* byte back.
*/
- xcoords[0] += (fract_x < threshold_l) ? -tex_step.x : 0.0;
+ 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;
+ 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;
@@ -41,6 +41,11 @@ static const QList<libcamera::PixelFormat> supportedFormats{
libcamera::formats::SGBRG10_CSI2P,
libcamera::formats::SGRBG10_CSI2P,
libcamera::formats::SRGGB10_CSI2P,
+ /* Raw Bayer 12-bit packed */
+ libcamera::formats::SBGGR12_CSI2P,
+ libcamera::formats::SGBRG12_CSI2P,
+ libcamera::formats::SGRBG12_CSI2P,
+ libcamera::formats::SRGGB12_CSI2P,
};
ViewFinderGL::ViewFinderGL(QWidget *parent)
@@ -218,28 +223,56 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
case libcamera::formats::SBGGR10_CSI2P:
firstRed_.setX(1.0);
firstRed_.setY(1.0);
- fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderDefines_.append("#define RAW10P");
fragmentShaderFile_ = ":bayer_1x_packed.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
case libcamera::formats::SGBRG10_CSI2P:
firstRed_.setX(0.0);
firstRed_.setY(1.0);
- fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderDefines_.append("#define RAW10P");
fragmentShaderFile_ = ":bayer_1x_packed.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
case libcamera::formats::SGRBG10_CSI2P:
firstRed_.setX(1.0);
firstRed_.setY(0.0);
- fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderDefines_.append("#define RAW10P");
fragmentShaderFile_ = ":bayer_1x_packed.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
case libcamera::formats::SRGGB10_CSI2P:
firstRed_.setX(0.0);
firstRed_.setY(0.0);
- fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderDefines_.append("#define RAW10P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SBGGR12_CSI2P:
+ firstRed_.setX(1.0);
+ firstRed_.setY(1.0);
+ fragmentShaderDefines_.append("#define RAW12P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGBRG12_CSI2P:
+ firstRed_.setX(0.0);
+ firstRed_.setY(1.0);
+ fragmentShaderDefines_.append("#define RAW12P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGRBG12_CSI2P:
+ firstRed_.setX(1.0);
+ firstRed_.setY(0.0);
+ fragmentShaderDefines_.append("#define RAW12P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SRGGB12_CSI2P:
+ firstRed_.setX(0.0);
+ firstRed_.setY(0.0);
+ fragmentShaderDefines_.append("#define RAW12P");
fragmentShaderFile_ = ":bayer_1x_packed.frag";
textureMinMagFilters_ = GL_NEAREST;
break;
@@ -595,8 +628,13 @@ void ViewFinderGL::doRender()
case libcamera::formats::SGBRG10_CSI2P:
case libcamera::formats::SGRBG10_CSI2P:
case libcamera::formats::SRGGB10_CSI2P:
+ case libcamera::formats::SBGGR12_CSI2P:
+ case libcamera::formats::SGBRG12_CSI2P:
+ case libcamera::formats::SGRBG12_CSI2P:
+ case libcamera::formats::SRGGB12_CSI2P:
/*
- * Packed raw Bayer 10-bit formats are stored in GL_RED texture.
+ * Packed raw Bayer 10-bit and 12-bit formats are stored in
+ * GL_RED texture.
* The texture width is equal to the stride.
*/
glActiveTexture(GL_TEXTURE0);