[PATCH 20/27] libcamera: software_isp: debayer_egl: Extend logic to enable application of softISP RGB debayer params
Bryan O'Donoghue
bryan.odonoghue at linaro.org
Tue Apr 22 23:59:13 CEST 2025
The existing SoftISP calculates RGB gain values as a lookup table of 256
values which shifts for each frame depending on the required correction.
We can pass the required tables into the debayer shaders as textures, one
texture for R, G and B respectively.
The debayer shader will do its debayer interpolation and then if the
appropriate define is specified use the calculated R, G and B values as
indexes into our bayer colour gain table.
TODO:
- Validate the number of available texture units and
bail out if < 4
In reality ~ all hardware has at least 16 units
- Rename the debayer class to something like eglDebayer
to reflect the fact its eGL based.
- Add in the CCM tables too.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue at linaro.org>
---
src/libcamera/software_isp/debayer_egl.cpp | 74 +++++++++++++++++-----
src/libcamera/software_isp/debayer_egl.h | 15 +++--
2 files changed, 69 insertions(+), 20 deletions(-)
diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index 008938f8..f02ec8b2 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -26,6 +26,15 @@ DebayerEGL::DebayerEGL(std::unique_ptr<SwStatsCpu> stats)
DebayerEGL::~DebayerEGL()
{
+ if (eglImageBlueLookup_)
+ delete eglImageBlueLookup_;
+
+ if (eglImageGreenLookup_)
+ delete eglImageGreenLookup_;
+
+ if (eglImageRedLookup_)
+ delete eglImageRedLookup_;
+
if (eglImageBayerIn_)
delete eglImageBayerIn_;
}
@@ -87,9 +96,11 @@ int DebayerEGL::getShaderVariableLocations(void)
attributeVertex_ = glGetAttribLocation(programId_, "vertexIn");
attributeTexture_ = glGetAttribLocation(programId_, "textureIn");
- textureUniformY_ = glGetUniformLocation(programId_, "tex_y");
- textureUniformU_ = glGetUniformLocation(programId_, "tex_u");
- textureUniformV_ = glGetUniformLocation(programId_, "tex_v");
+ textureUniformBayerDataIn_ = glGetUniformLocation(programId_, "tex_y");
+ textureUniformRedLookupDataIn_ = glGetUniformLocation(programId_, "red_param");
+ textureUniformGreenLookupDataIn_ = glGetUniformLocation(programId_, "green_param");
+ textureUniformBlueLookupDataIn_ = glGetUniformLocation(programId_, "blue_param");
+
textureUniformStep_ = glGetUniformLocation(programId_, "tex_step");
textureUniformSize_ = glGetUniformLocation(programId_, "tex_size");
textureUniformStrideFactor_ = glGetUniformLocation(programId_, "stride_factor");
@@ -97,9 +108,10 @@ int DebayerEGL::getShaderVariableLocations(void)
textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix");
LOG(Debayer, Info) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
- << " tex_y " << textureUniformY_
- << " tex_u " << textureUniformU_
- << " tex_v " << textureUniformV_
+ << " tex_y " << textureUniformBayerDataIn_
+ << " red_param " << textureUniformRedLookupDataIn_
+ << " red_param " << textureUniformGreenLookupDataIn_
+ << " red_param " << textureUniformBlueLookupDataIn_
<< " tex_step " << textureUniformStep_
<< " tex_size " << textureUniformSize_
<< " stride_factor " << textureUniformStrideFactor_
@@ -202,6 +214,9 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
break;
};
+ // Flag to shaders that we have parameter gain tables
+ egl_.pushEnv(shaderEnv, "#define APPLY_BAYER_PARAMETERS");
+
if (egl_.compileVertexShader(vertexShaderId_, vertexShaderData, vertexShaderDataLen, shaderEnv))
goto compile_fail;
@@ -285,7 +300,24 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,
if (egl_.initEGLContext(&gbmSurface_))
return -ENODEV;
- eglImageBayerIn_ = new eGLImage(width_, height_, 32);
+ // Raw bayer input as texture
+ eglImageBayerIn_ = new eGLImage(width_, height_, 32, GL_TEXTURE0, 0);
+ if (!eglImageBayerIn_)
+ return -ENOMEM;
+
+ /// RGB correction tables as 2d textures
+ // eGL doesn't support glTexImage2D so we do a little hack with 2D to compensate
+ eglImageRedLookup_ = new eGLImage(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE1, 1);
+ if (!eglImageRedLookup_)
+ return -ENOMEM;
+
+ eglImageGreenLookup_ = new eGLImage(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE2, 2);
+ if (!eglImageGreenLookup_)
+ return -ENOMEM;
+
+ eglImageBlueLookup_ = new eGLImage(DebayerParams::kRGBLookupSize, 1, 32, GL_TEXTURE3, 3);
+ if (!eglImageBlueLookup_)
+ return -ENOMEM;
// Create a single BO (calling gbm_surface_lock_front_buffer() again before gbm_surface_release_buffer() would create another BO)
if (gbmSurface_.mapSurface())
@@ -394,7 +426,14 @@ void DebayerEGL::setShaderVariableValues(void)
glVertexAttribPointer(attributeTexture_, 2, GL_FLOAT, GL_TRUE,
2 * sizeof(GLfloat), tcoordinates);
- glUniform1i(textureUniformY_, 0); // tex_y - bayer_8.vert - set for no reason
+ // Set the sampler2D to the respective texture unit for each texutre
+ // To simultaneously sample multiple textures we need to use multiple
+ // texture units
+ glUniform1i(textureUniformBayerDataIn_, eglImageBayerIn_->texture_unit_uniform_id_);
+ glUniform1i(textureUniformRedLookupDataIn_, eglImageRedLookup_->texture_unit_uniform_id_);
+ glUniform1i(textureUniformGreenLookupDataIn_, eglImageGreenLookup_->texture_unit_uniform_id_);
+ glUniform1i(textureUniformBlueLookupDataIn_, eglImageBlueLookup_->texture_unit_uniform_id_);
+
glUniform2fv(textureUniformBayerFirstRed_, 1, firstRed); // tex_bayer_first_red - bayer_8.vert
glUniform2fv(textureUniformSize_, 1, imgSize); // tex_size - bayer_8.vert
glUniform2fv(textureUniformStep_, 1, Step); // tex_step - bayer_8.vert
@@ -403,9 +442,10 @@ void DebayerEGL::setShaderVariableValues(void)
GL_FALSE, projIdentityMatrix); // No scaling
LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
- << " tex_y " << textureUniformY_
- << " tex_u " << textureUniformU_
- << " tex_v " << textureUniformV_
+ << " tex_y " << textureUniformBayerDataIn_
+ << " red_param " << textureUniformRedLookupDataIn_
+ << " red_param " << textureUniformGreenLookupDataIn_
+ << " red_param " << textureUniformBlueLookupDataIn_
<< " tex_step " << textureUniformStep_
<< " tex_size " << textureUniformSize_
<< " stride_factor " << textureUniformStrideFactor_
@@ -423,7 +463,7 @@ void DebayerEGL::setShaderVariableValues(void)
return;
}
-void DebayerEGL::debayerGPU(MappedFrameBuffer &in, MappedFrameBuffer &out)
+void DebayerEGL::debayerGPU(MappedFrameBuffer &in, MappedFrameBuffer &out, DebayerParams ¶ms)
{
LOG(Debayer, Debug)
<< "Input height " << height_
@@ -433,13 +473,15 @@ void DebayerEGL::debayerGPU(MappedFrameBuffer &in, MappedFrameBuffer &out)
// eGL context switch
egl_.makeCurrent();
- // make texture unit 0 explicit this doesn't really matter probably remove ?
- glActiveTexture(GL_TEXTURE0);
-
// Greate a standard texture
// we will replace this with the DMA version at some point
egl_.createTexture2D(eglImageBayerIn_, inputConfig_.stride, height_, in.planes()[0].data());
+ // Populate bayer parameters
+ egl_.createTexture2D(eglImageRedLookup_, DebayerParams::kRGBLookupSize, 1, ¶ms.red);
+ egl_.createTexture2D(eglImageGreenLookup_, DebayerParams::kRGBLookupSize, 1, ¶ms.green);
+ egl_.createTexture2D(eglImageBlueLookup_, DebayerParams::kRGBLookupSize, 1, ¶ms.blue);
+
// Setup the scene
setShaderVariableValues();
glViewport(0, 0, width_, height_);
@@ -482,7 +524,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output
return;
}
- debayerGPU(in, out);
+ debayerGPU(in, out, params);
dmaSyncers.clear();
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index 14f6997a..c8a19c3c 100644
--- a/src/libcamera/software_isp/debayer_egl.h
+++ b/src/libcamera/software_isp/debayer_egl.h
@@ -110,7 +110,7 @@ private:
int getShaderVariableLocations();
void setShaderVariableValues(void);
void configureTexture(GLuint &texture);
- void debayerGPU(MappedFrameBuffer &in, MappedFrameBuffer &out);
+ void debayerGPU(MappedFrameBuffer &in, MappedFrameBuffer &out, DebayerParams ¶ms);
// Shader program identifiers
GLuint vertexShaderId_;
@@ -125,20 +125,27 @@ private:
// Pointer to object representing input texture
eGLImage *eglImageBayerIn_;
+ eGLImage *eglImageRedLookup_;
+ eGLImage *eglImageGreenLookup_;
+ eGLImage *eglImageBlueLookup_;
+
// Shader parameters
float firstRed_x_;
float firstRed_y_;
GLint attributeVertex_;
GLint attributeTexture_;
- GLint textureUniformY_;
- GLint textureUniformU_;
- GLint textureUniformV_;
GLint textureUniformStep_;
GLint textureUniformSize_;
GLint textureUniformStrideFactor_;
GLint textureUniformBayerFirstRed_;
GLint textureUniformProjMatrix_;
+ #define DEBAYER_EGL_MIN_TEXTURE_UNITS 4
+ GLint textureUniformBayerDataIn_;
+ GLint textureUniformRedLookupDataIn_;
+ GLint textureUniformGreenLookupDataIn_;
+ GLint textureUniformBlueLookupDataIn_;
+
Rectangle window_;
std::unique_ptr<SwStatsCpu> stats_;
eGL egl_;
--
2.49.0
More information about the libcamera-devel
mailing list