[5/7] libcamera: software_isp: debayer_egl: Add LSC support
diff mbox series

Message ID 20260126104256.119697-6-rick.w.ten.wolde@gmail.com
State New
Headers show
Series
  • LSC for SoftISP simple pipeline
Related show

Commit Message

Rick ten Wolde Jan. 26, 2026, 10:42 a.m. UTC
From: Xander Pronk <xander.c.pronk@gmail.com>

Add support for passing the LSC tables from debayerParams to
the shaders.

Co-authored-by: Rick ten Wolde <rick_libcamera@wolde.info>
Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info>
Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com>
---
 src/libcamera/software_isp/debayer_egl.cpp | 21 +++++++++++++++++++++
 src/libcamera/software_isp/debayer_egl.h   |  9 +++++++++
 2 files changed, 30 insertions(+)

Comments

Barnabás Pőcze Jan. 26, 2026, 11:30 a.m. UTC | #1
Hi

2026. 01. 26. 11:42 keltezéssel, Rick ten Wolde írta:
> From: Xander Pronk <xander.c.pronk@gmail.com>
> 
> Add support for passing the LSC tables from debayerParams to
> the shaders.
> 
> Co-authored-by: Rick ten Wolde <rick_libcamera@wolde.info>
> Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info>
> Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com>
> ---
>   src/libcamera/software_isp/debayer_egl.cpp | 21 +++++++++++++++++++++
>   src/libcamera/software_isp/debayer_egl.h   |  9 +++++++++
>   2 files changed, 30 insertions(+)
> 
> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
> index 8e089032..0f36b149 100644
> --- a/src/libcamera/software_isp/debayer_egl.cpp
> +++ b/src/libcamera/software_isp/debayer_egl.cpp
> @@ -111,6 +111,10 @@ int DebayerEGL::getShaderVariableLocations(void)
>   	textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red");
>   	textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix");
>   
> +	textureUniformLSCRed_ = glGetUniformLocation(programId_, "lsc_tex_red");
> +	textureUniformLSCGreen_ = glGetUniformLocation(programId_, "lsc_tex_green");
> +	textureUniformLSCBlue_ = glGetUniformLocation(programId_, "lsc_tex_blue");
> +
>   	LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
>   			    << " tex_y " << textureUniformBayerDataIn_
>   			    << " ccm " << ccmUniformDataIn_
> @@ -140,6 +144,9 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
>   	/* Specify GL_OES_EGL_image_external */
>   	egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable");
>   
> +	/* Always use LSC */
> +	egl_.pushEnv(shaderEnv, "#define DO_LSC");
> +
>   	/*
>   	 * Tell shaders how to re-order output taking account of how the
>   	 * pixels are actually stored by GBM
> @@ -349,6 +356,12 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,
>   	 */
>   	stats_->setWindow(Rectangle(window_.size()));
>   
> +	eglImageLSCLookupRed_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
> +	eglImageLSCLookupGreen_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
> +	eglImageLSCLookupBlue_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
> +	if (!eglImageLSCLookupRed_ || !eglImageLSCLookupGreen_ || !eglImageLSCLookupBlue_)

These operator new calls never return nullptr. But see below.


> +		return -ENOMEM;
> +
>   	return 0;
>   }
>   
> @@ -488,6 +501,14 @@ void DebayerEGL::setShaderVariableValues(DebayerParams &params)
>   	glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm);
>   	LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.ccm;
>   
> +	egl_.createTexture2D(*eglImageLSCLookupRed_, GL_LUMINANCE, 16, 16, &params.LSC_red, GL_LINEAR);
> +	egl_.createTexture2D(*eglImageLSCLookupBlue_, GL_LUMINANCE, 16, 16, &params.LSC_green, GL_LINEAR);
> +	egl_.createTexture2D(*eglImageLSCLookupGreen_, GL_LUMINANCE, 16, 16, &params.LSC_blue, GL_LINEAR);
> +
> +	glUniform1i(textureUniformLSCRed_, eglImageLSCLookupRed_->texture_unit_uniform_id_);
> +	glUniform1i(textureUniformLSCGreen_, eglImageLSCLookupGreen_->texture_unit_uniform_id_);
> +	glUniform1i(textureUniformLSCBlue_, eglImageLSCLookupBlue_->texture_unit_uniform_id_);
> +
>   	/*
>   	 * 0 = Red, 1 = Green, 2 = Blue
>   	 */
> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
> index a5033bc6..61feadab 100644
> --- a/src/libcamera/software_isp/debayer_egl.h
> +++ b/src/libcamera/software_isp/debayer_egl.h
> @@ -85,6 +85,11 @@ private:
>   	std::unique_ptr<eGLImage> eglImageBayerIn_;
>   	std::unique_ptr<eGLImage> eglImageBayerOut_;
>   
> +	/* Pointer to object representing input texture */
> +	eGLImage *eglImageLSCLookupRed_;
> +	eGLImage *eglImageLSCLookupBlue_;
> +	eGLImage *eglImageLSCLookupGreen_;

These need to become `std::optional<eGLImage>` or `std::unique_ptr<>` at least.
Please no raw owning raw pointers.


Regards,
Barnabás Pőcze


> +
>   	/* Shader parameters */
>   	float firstRed_x_;
>   	float firstRed_y_;
> @@ -98,6 +103,10 @@ private:
>   
>   	GLint textureUniformBayerDataIn_;
>   
> +	GLint textureUniformLSCRed_;
> +	GLint textureUniformLSCGreen_;
> +	GLint textureUniformLSCBlue_;
> +
>   	/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */
>   	GLint ccmUniformDataIn_;
>
Milan Zamazal Jan. 26, 2026, 3:28 p.m. UTC | #2
Hi,

thank you for the patches.

Rick ten Wolde <rick.w.ten.wolde@gmail.com> writes:

> From: Xander Pronk <xander.c.pronk@gmail.com>
>
> Add support for passing the LSC tables from debayerParams to
> the shaders.
>
> Co-authored-by: Rick ten Wolde <rick_libcamera@wolde.info>
> Signed-off-by: Rick ten Wolde <rick_libcamera@wolde.info>
> Signed-off-by: Xander Pronk <xander.c.pronk@gmail.com>
> ---
>  src/libcamera/software_isp/debayer_egl.cpp | 21 +++++++++++++++++++++
>  src/libcamera/software_isp/debayer_egl.h   |  9 +++++++++
>  2 files changed, 30 insertions(+)
>
> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
> index 8e089032..0f36b149 100644
> --- a/src/libcamera/software_isp/debayer_egl.cpp
> +++ b/src/libcamera/software_isp/debayer_egl.cpp
> @@ -111,6 +111,10 @@ int DebayerEGL::getShaderVariableLocations(void)
>  	textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red");
>  	textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix");
>  
> +	textureUniformLSCRed_ = glGetUniformLocation(programId_, "lsc_tex_red");
> +	textureUniformLSCGreen_ = glGetUniformLocation(programId_, "lsc_tex_green");
> +	textureUniformLSCBlue_ = glGetUniformLocation(programId_, "lsc_tex_blue");
> +
>  	LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
>  			    << " tex_y " << textureUniformBayerDataIn_
>  			    << " ccm " << ccmUniformDataIn_
> @@ -140,6 +144,9 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
>  	/* Specify GL_OES_EGL_image_external */
>  	egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable");
>  
> +	/* Always use LSC */
> +	egl_.pushEnv(shaderEnv, "#define DO_LSC");

I think this should be conditional.  For example, what if LSC algorithm
is disabled?  Or LSC parameters are not available in the tuning file?

> +
>  	/*
>  	 * Tell shaders how to re-order output taking account of how the
>  	 * pixels are actually stored by GBM
> @@ -349,6 +356,12 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,
>  	 */
>  	stats_->setWindow(Rectangle(window_.size()));
>  
> +	eglImageLSCLookupRed_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
> +	eglImageLSCLookupGreen_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
> +	eglImageLSCLookupBlue_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
> +	if (!eglImageLSCLookupRed_ || !eglImageLSCLookupGreen_ || !eglImageLSCLookupBlue_)
> +		return -ENOMEM;
> +
>  	return 0;
>  }
>  
> @@ -488,6 +501,14 @@ void DebayerEGL::setShaderVariableValues(DebayerParams &params)
>  	glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm);
>  	LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.ccm;
>  
> +	egl_.createTexture2D(*eglImageLSCLookupRed_, GL_LUMINANCE, 16, 16, &params.LSC_red, GL_LINEAR);
> +	egl_.createTexture2D(*eglImageLSCLookupBlue_, GL_LUMINANCE, 16, 16, &params.LSC_green, GL_LINEAR);
> +	egl_.createTexture2D(*eglImageLSCLookupGreen_, GL_LUMINANCE, 16, 16, &params.LSC_blue, GL_LINEAR);
> +
> +	glUniform1i(textureUniformLSCRed_, eglImageLSCLookupRed_->texture_unit_uniform_id_);
> +	glUniform1i(textureUniformLSCGreen_, eglImageLSCLookupGreen_->texture_unit_uniform_id_);
> +	glUniform1i(textureUniformLSCBlue_, eglImageLSCLookupBlue_->texture_unit_uniform_id_);
> +
>  	/*
>  	 * 0 = Red, 1 = Green, 2 = Blue
>  	 */
> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
> index a5033bc6..61feadab 100644
> --- a/src/libcamera/software_isp/debayer_egl.h
> +++ b/src/libcamera/software_isp/debayer_egl.h
> @@ -85,6 +85,11 @@ private:
>  	std::unique_ptr<eGLImage> eglImageBayerIn_;
>  	std::unique_ptr<eGLImage> eglImageBayerOut_;
>  
> +	/* Pointer to object representing input texture */
> +	eGLImage *eglImageLSCLookupRed_;
> +	eGLImage *eglImageLSCLookupBlue_;
> +	eGLImage *eglImageLSCLookupGreen_;
> +
>  	/* Shader parameters */
>  	float firstRed_x_;
>  	float firstRed_y_;
> @@ -98,6 +103,10 @@ private:
>  
>  	GLint textureUniformBayerDataIn_;
>  
> +	GLint textureUniformLSCRed_;
> +	GLint textureUniformLSCGreen_;
> +	GLint textureUniformLSCBlue_;
> +
>  	/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */
>  	GLint ccmUniformDataIn_;

Patch
diff mbox series

diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index 8e089032..0f36b149 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -111,6 +111,10 @@  int DebayerEGL::getShaderVariableLocations(void)
 	textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red");
 	textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix");
 
+	textureUniformLSCRed_ = glGetUniformLocation(programId_, "lsc_tex_red");
+	textureUniformLSCGreen_ = glGetUniformLocation(programId_, "lsc_tex_green");
+	textureUniformLSCBlue_ = glGetUniformLocation(programId_, "lsc_tex_blue");
+
 	LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
 			    << " tex_y " << textureUniformBayerDataIn_
 			    << " ccm " << ccmUniformDataIn_
@@ -140,6 +144,9 @@  int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
 	/* Specify GL_OES_EGL_image_external */
 	egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable");
 
+	/* Always use LSC */
+	egl_.pushEnv(shaderEnv, "#define DO_LSC");
+
 	/*
 	 * Tell shaders how to re-order output taking account of how the
 	 * pixels are actually stored by GBM
@@ -349,6 +356,12 @@  int DebayerEGL::configure(const StreamConfiguration &inputCfg,
 	 */
 	stats_->setWindow(Rectangle(window_.size()));
 
+	eglImageLSCLookupRed_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
+	eglImageLSCLookupGreen_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
+	eglImageLSCLookupBlue_ = new eGLImage(20, 20, sizeof(GLubyte), GL_TEXTURE5, 5);
+	if (!eglImageLSCLookupRed_ || !eglImageLSCLookupGreen_ || !eglImageLSCLookupBlue_)
+		return -ENOMEM;
+
 	return 0;
 }
 
@@ -488,6 +501,14 @@  void DebayerEGL::setShaderVariableValues(DebayerParams &params)
 	glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm);
 	LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.ccm;
 
+	egl_.createTexture2D(*eglImageLSCLookupRed_, GL_LUMINANCE, 16, 16, &params.LSC_red, GL_LINEAR);
+	egl_.createTexture2D(*eglImageLSCLookupBlue_, GL_LUMINANCE, 16, 16, &params.LSC_green, GL_LINEAR);
+	egl_.createTexture2D(*eglImageLSCLookupGreen_, GL_LUMINANCE, 16, 16, &params.LSC_blue, GL_LINEAR);
+
+	glUniform1i(textureUniformLSCRed_, eglImageLSCLookupRed_->texture_unit_uniform_id_);
+	glUniform1i(textureUniformLSCGreen_, eglImageLSCLookupGreen_->texture_unit_uniform_id_);
+	glUniform1i(textureUniformLSCBlue_, eglImageLSCLookupBlue_->texture_unit_uniform_id_);
+
 	/*
 	 * 0 = Red, 1 = Green, 2 = Blue
 	 */
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index a5033bc6..61feadab 100644
--- a/src/libcamera/software_isp/debayer_egl.h
+++ b/src/libcamera/software_isp/debayer_egl.h
@@ -85,6 +85,11 @@  private:
 	std::unique_ptr<eGLImage> eglImageBayerIn_;
 	std::unique_ptr<eGLImage> eglImageBayerOut_;
 
+	/* Pointer to object representing input texture */
+	eGLImage *eglImageLSCLookupRed_;
+	eGLImage *eglImageLSCLookupBlue_;
+	eGLImage *eglImageLSCLookupGreen_;
+
 	/* Shader parameters */
 	float firstRed_x_;
 	float firstRed_y_;
@@ -98,6 +103,10 @@  private:
 
 	GLint textureUniformBayerDataIn_;
 
+	GLint textureUniformLSCRed_;
+	GLint textureUniformLSCGreen_;
+	GLint textureUniformLSCBlue_;
+
 	/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */
 	GLint ccmUniformDataIn_;