[libcamera-devel,v5,3/9] qcam: viewfinder_gl: Add support for RAW12 packed formats
diff mbox series

Message ID 20210622134652.1279260-4-andrey.konovalov@linaro.org
State Accepted
Headers show
Series
  • qcam: viewfinder_gl: add RAW8, RAW10P and RAW12P formats
Related show

Commit Message

Andrey Konovalov June 22, 2021, 1:46 p.m. UTC
All the four Bayer orders are supported.
The 4 LS bits of the 12-bit colour values are dropped as the RGBA
format we convert into has only 8 bits per colour.

Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/qcam/assets/shader/bayer_1x_packed.frag | 43 +++++++++++++++---
 src/qcam/viewfinder_gl.cpp                  | 48 ++++++++++++++++++---
 2 files changed, 80 insertions(+), 11 deletions(-)

Comments

Paul Elder June 28, 2021, 10:23 a.m. UTC | #1
Hi Andrey,

On Tue, Jun 22, 2021 at 04:46:46PM +0300, Andrey Konovalov wrote:
> All the four Bayer orders are supported.
> The 4 LS bits of the 12-bit colour values are dropped as the RGBA
> format we convert into has only 8 bits per colour.
> 
> Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

> ---
>  src/qcam/assets/shader/bayer_1x_packed.frag | 43 +++++++++++++++---
>  src/qcam/viewfinder_gl.cpp                  | 48 ++++++++++++++++++---
>  2 files changed, 80 insertions(+), 11 deletions(-)
> 
> diff --git a/src/qcam/assets/shader/bayer_1x_packed.frag b/src/qcam/assets/shader/bayer_1x_packed.frag
> index fac8c3b8..5da9dce5 100644
> --- a/src/qcam/assets/shader/bayer_1x_packed.frag
> +++ b/src/qcam/assets/shader/bayer_1x_packed.frag
> @@ -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;
> diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
> index ffbbc6c5..a6aa2b44 100644
> --- a/src/qcam/viewfinder_gl.cpp
> +++ b/src/qcam/viewfinder_gl.cpp
> @@ -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);
> -- 
> 2.25.1
>

Patch
diff mbox series

diff --git a/src/qcam/assets/shader/bayer_1x_packed.frag b/src/qcam/assets/shader/bayer_1x_packed.frag
index fac8c3b8..5da9dce5 100644
--- a/src/qcam/assets/shader/bayer_1x_packed.frag
+++ b/src/qcam/assets/shader/bayer_1x_packed.frag
@@ -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;
diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
index ffbbc6c5..a6aa2b44 100644
--- a/src/qcam/viewfinder_gl.cpp
+++ b/src/qcam/viewfinder_gl.cpp
@@ -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);