@@ -109,8 +109,8 @@ public:
int createInputDMABufTexture2D(eGLImage &eglImage, int fd);
int createOutputDMABufTexture2D(eGLImage &eglImage, int fd);
- void createTexture2D(eGLImage &eglImage, void *data, GLint filter);
- void updateTexture2D(eGLImage &eglImage, void *data);
+ void createTexture2D(eGLImage &eglImage, const void *data, GLint filter);
+ void updateTexture2D(eGLImage &eglImage, const void *data);
void createOutputTexture2D(eGLImage &eglImage);
int attachTextureToFBO(eGLImage &eglImage);
@@ -33,6 +33,8 @@ struct DebayerParams {
**/
static constexpr unsigned int kLscGridSize = 17;
static constexpr unsigned int kLscValuesPerCell = 4;
+ static constexpr unsigned int kLscBytesPerCell =
+ kLscValuesPerCell * sizeof(uint8_t);
using LscLookupTable =
std::array<uint8_t, kLscGridSize * kLscGridSize * kLscValuesPerCell>;
static constexpr auto identityLscLut = [] {
@@ -286,7 +286,7 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd)
* is useful for uploading static data like lookup tables or uniform color
* matrices to the GPU.
*/
-void eGL::createTexture2D(eGLImage &eglImage, void *data, GLint filter)
+void eGL::createTexture2D(eGLImage &eglImage, const void *data, GLint filter)
{
assertThread();
@@ -339,7 +339,7 @@ EGLDisplay eGL::probeDisplay()
*
* Updates a 2D texture in VRAM.
*/
-void eGL::updateTexture2D(eGLImage &eglImage, void *data)
+void eGL::updateTexture2D(eGLImage &eglImage, const void *data)
{
assertThread();
@@ -53,6 +53,11 @@ namespace libcamera {
* \brief Number of pixel values per each of the lens shading grid areas
*/
+/**
+ * \var DebayerParams::kLscBytesPerCell
+ * \brief Number of bytes per each of the lens shading grid areas
+ */
+
/**
* \typedef DebayerParams::LscLookupTable
* \brief Lookup table for lens shading correction
@@ -115,6 +115,8 @@ int DebayerEGL::getShaderVariableLocations(void)
textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red");
textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix");
+ textureUniformLsc_ = glGetUniformLocation(programId_, "lsc_tex");
+
LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_
<< " tex_y " << textureUniformBayerDataIn_
<< " awb " << awbUniformDataIn_
@@ -126,7 +128,8 @@ int DebayerEGL::getShaderVariableLocations(void)
<< " tex_size " << textureUniformSize_
<< " stride_factor " << textureUniformStrideFactor_
<< " tex_bayer_first_red " << textureUniformBayerFirstRed_
- << " proj_matrix " << textureUniformProjMatrix_;
+ << " proj_matrix " << textureUniformProjMatrix_
+ << " tex_lsc " << textureUniformLsc_;
return 0;
}
@@ -143,6 +146,9 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
/* Specify GL_OES_EGL_image_external */
egl_.pushEnv(shaderEnv, "#extension GL_OES_EGL_image_external: enable");
+ if (lscEnabled_)
+ egl_.pushEnv(shaderEnv, "#define APPLY_LSC");
+
/*
* Tell shaders how to re-order output taking account of how the pixels
* are actually stored by EGL.
@@ -467,6 +473,12 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara
glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_TRUE, params.combinedMatrix.data().data());
LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix;
+ if (lscEnabled_ && params.lscLutVersion != lscLutVersion_) {
+ egl_.updateTexture2D(*eglImageLscLookup_, params.lscLut.data());
+ lscLutVersion_ = params.lscLutVersion;
+ glUniform1i(textureUniformLsc_, eglImageLscLookup_->texture_unit_uniform_id_);
+ }
+
/*
* 0 = Red, 1 = Green, 2 = Blue
*/
@@ -673,6 +685,18 @@ int DebayerEGL::start()
if (initBayerShaders(inputPixelFormat_, outputPixelFormat_))
return -EINVAL;
+ if (lscEnabled_) {
+ constexpr unsigned int gridSize = DebayerParams::kLscGridSize;
+ constexpr unsigned int stride = gridSize * DebayerParams::kLscBytesPerCell;
+ eglImageLscLookup_.emplace(GL_RGBA,
+ gridSize,
+ gridSize,
+ stride,
+ GL_TEXTURE2,
+ 2);
+ egl_.createTexture2D(*eglImageLscLookup_, nullptr, GL_LINEAR);
+ }
+
return 0;
}
@@ -681,6 +705,9 @@ void DebayerEGL::stop()
eglImageOutCache_.clear();
eglImageInCache_.clear();
+ eglImageLscLookup_.reset();
+ lscLutVersion_.reset();
+
if (programId_)
glDeleteProgram(programId_);
@@ -83,7 +83,11 @@ private:
unsigned int inputBufferCount_;
unsigned int outputBufferCount_;
+ /* LSC lookup table */
bool lscEnabled_;
+ std::optional<eGLImage> eglImageLscLookup_;
+ std::optional<uint64_t> lscLutVersion_;
+
/* Shader parameters */
float firstRed_x_;
float firstRed_y_;
@@ -100,6 +104,9 @@ private:
/* Per-frame AWB gains */
GLint awbUniformDataIn_;
+ /* Lens shading correction */
+ GLint textureUniformLsc_;
+
/* Represent per-frame CCM as a uniform vector of floats 3 x 3 */
GLint ccmUniformDataIn_;