| Message ID | 20260708201816.299983-7-mzamazal@redhat.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
Milan Zamazal <mzamazal@redhat.com> writes: > From: Xander Pronk <xander.c.pronk@gmail.com> > > Add support for passing the LSC table from debayerParams to the shaders. > > The LSC table values are floats, we must add `type' parameter to > createTexture2D to support this. Moreover, we use 16-bit internal > format for the values, primarily because this works for me, unlike > 32-bit floats. > > Co-developed-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> > Signed-off-by: Milan Zamazal <mzamazal@redhat.com> > --- > include/libcamera/internal/egl.h | 6 +++- > .../internal/software_isp/debayer_params.h | 2 ++ > src/libcamera/egl.cpp | 10 ++++-- > src/libcamera/software_isp/debayer.cpp | 5 +++ > src/libcamera/software_isp/debayer_egl.cpp | 32 +++++++++++++++++-- > src/libcamera/software_isp/debayer_egl.h | 7 ++++ > 6 files changed, 57 insertions(+), 5 deletions(-) > > diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h > index 030c813a5..37da2b18a 100644 > --- a/include/libcamera/internal/egl.h > +++ b/include/libcamera/internal/egl.h > @@ -107,7 +107,11 @@ public: > > int createInputDMABufTexture2D(eGLImage &eglImage, int fd); > int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); > - void createTexture2D(eGLImage &eglImage, void *data, GLint filter); > + void createTexture2D(eGLImage &eglImage, > + GLint internalFormat, > + GLenum type, > + const void *data, > + GLint filter); > > void pushEnv(std::vector<std::string> &shaderEnv, const char *str); > void makeCurrent(); > diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h > index 4eb6c7e8d..0b96d4ffe 100644 > --- a/include/libcamera/internal/software_isp/debayer_params.h > +++ b/include/libcamera/internal/software_isp/debayer_params.h > @@ -30,6 +30,8 @@ struct DebayerParams { > static constexpr unsigned int kLscGridSize = 16; > static constexpr unsigned int kLscValuesPerCell = 3; > using LscValueType = float; > + static constexpr unsigned int kLscBytesPerCell = > + kLscValuesPerCell * sizeof(LscValueType); > using LscLookupTable = > std::array<LscValueType, kLscGridSize * kLscGridSize * kLscValuesPerCell>; > LscLookupTable lscLut{}; > diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp > index aeac5d313..c2a158ce7 100644 > --- a/src/libcamera/egl.cpp > +++ b/src/libcamera/egl.cpp > @@ -241,6 +241,8 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) > /** > * \brief Create a 2D texture from a memory buffer > * \param[in,out] eglImage EGL image to associate with the texture > + * \param[in] internalFormat OpenGL internal storage format (e.g., GL_RGB8, GL_RGBA8) > + * \param[in] type OpenGL pixel data type (e.g., GL_UNSIGNED_BYTE, GL_FLOAT) > * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture > * \param[in] filter GL texture filter setting > * > @@ -249,7 +251,11 @@ 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, > + GLint internalFormat, > + GLenum type, > + const void *data, > + GLint filter) > { > ASSERT(tid_ == Thread::currentId()); > > @@ -257,7 +263,7 @@ void eGL::createTexture2D(eGLImage &eglImage, void *data, GLint filter) > glBindTexture(GL_TEXTURE_2D, eglImage.texture_); > > // Generate texture, bind, associate image to texture, configure, unbind > - glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); > + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, eglImage.width_, eglImage.height_, 0, eglImage.format_, type, data); > > // Nearest filtering > glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); > diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp > index 5c4bd914b..2bf64e570 100644 > --- a/src/libcamera/software_isp/debayer.cpp > +++ b/src/libcamera/software_isp/debayer.cpp > @@ -58,6 +58,11 @@ namespace libcamera { > * \brief Type of LSC grid values > */ > > +/** > + * \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 > diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp > index 562e9fc7a..a73a00759 100644 > --- a/src/libcamera/software_isp/debayer_egl.cpp > +++ b/src/libcamera/software_isp/debayer_egl.cpp > @@ -128,6 +128,9 @@ int DebayerEGL::getShaderVariableLocations(void) > textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); > textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); > > + textureUniformLsc_ = glGetUniformLocation(programId_, "lsc_tex"); > + lscEnabledUniform_ = glGetUniformLocation(programId_, "lsc_enabled"); > + > LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ > << " tex_y " << textureUniformBayerDataIn_ > << " awb " << awbUniformDataIn_ > @@ -139,7 +142,9 @@ int DebayerEGL::getShaderVariableLocations(void) > << " tex_size " << textureUniformSize_ > << " stride_factor " << textureUniformStrideFactor_ > << " tex_bayer_first_red " << textureUniformBayerFirstRed_ > - << " proj_matrix " << textureUniformProjMatrix_; > + << " proj_matrix " << textureUniformProjMatrix_ > + << " tex_lsc " << textureUniformLsc_ > + << " lsc_enabled" << lscEnabledUniform_; > return 0; > } > > @@ -156,6 +161,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. > @@ -348,6 +356,18 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, > */ > stats_->setWindow(Rectangle(window_.size())); > > + if (lscEnabled_) { > + constexpr unsigned int gridSize = DebayerParams::kLscGridSize; > + const unsigned int stride = gridSize * DebayerParams::kLscBytesPerCell; > + eglImageLscLookup_ = > + std::make_unique<eGLImage>(GL_RGB, > + gridSize, > + gridSize, > + stride, > + GL_TEXTURE2, > + 2); > + } > + > return 0; > } > > @@ -483,6 +503,13 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) > glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_TRUE, params.combinedMatrix.data().data()); > LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; > > + if (lscEnabled_) { > + egl_.createTexture2D(*eglImageLscLookup_, GL_RGB16F, GL_FLOAT, > + params.lscLut.data(), GL_LINEAR); > + glUniform1i(textureUniformLsc_, eglImageLscLookup_->texture_unit_uniform_id_); > + glUniform1i(lscEnabledUniform_, params.lscEnabled); > + } > + > /* > * 0 = Red, 1 = Green, 2 = Blue > */ > @@ -530,7 +557,8 @@ int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye > LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; > return -ENODEV; > } > - egl_.createTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data(), GL_NEAREST); > + egl_.createTexture2D(*eglImageBayerIn_, glFormat_, GL_UNSIGNED_BYTE, > + inMapped->value().planes()[0].data(), GL_NEAREST); > } > > /* Generate the output render framebuffer as render to texture */ > diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h > index 82ed1305d..2af26fb74 100644 > --- a/src/libcamera/software_isp/debayer_egl.h > +++ b/src/libcamera/software_isp/debayer_egl.h > @@ -78,7 +78,10 @@ private: > std::unique_ptr<eGLImage> eglImageBayerIn_; > std::unique_ptr<eGLImage> eglImageBayerOut_; > > + /* LSC lookup table */ > + std::unique_ptr<eGLImage> eglImageLscLookup_; > bool lscEnabled_; > + > /* Shader parameters */ > float firstRed_x_; > float firstRed_y_; > @@ -95,6 +98,10 @@ private: > /* Per-frame AWB gains */ > GLint awbUniformDataIn_; > > + /* Lens shading correction */ > + GLint textureUniformLsc_; > + GLboolean lscEnabledUniform_; This must be GLint. > + > /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ > GLint ccmUniformDataIn_;
diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h index 030c813a5..37da2b18a 100644 --- a/include/libcamera/internal/egl.h +++ b/include/libcamera/internal/egl.h @@ -107,7 +107,11 @@ public: int createInputDMABufTexture2D(eGLImage &eglImage, int fd); int createOutputDMABufTexture2D(eGLImage &eglImage, int fd); - void createTexture2D(eGLImage &eglImage, void *data, GLint filter); + void createTexture2D(eGLImage &eglImage, + GLint internalFormat, + GLenum type, + const void *data, + GLint filter); void pushEnv(std::vector<std::string> &shaderEnv, const char *str); void makeCurrent(); diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h index 4eb6c7e8d..0b96d4ffe 100644 --- a/include/libcamera/internal/software_isp/debayer_params.h +++ b/include/libcamera/internal/software_isp/debayer_params.h @@ -30,6 +30,8 @@ struct DebayerParams { static constexpr unsigned int kLscGridSize = 16; static constexpr unsigned int kLscValuesPerCell = 3; using LscValueType = float; + static constexpr unsigned int kLscBytesPerCell = + kLscValuesPerCell * sizeof(LscValueType); using LscLookupTable = std::array<LscValueType, kLscGridSize * kLscGridSize * kLscValuesPerCell>; LscLookupTable lscLut{}; diff --git a/src/libcamera/egl.cpp b/src/libcamera/egl.cpp index aeac5d313..c2a158ce7 100644 --- a/src/libcamera/egl.cpp +++ b/src/libcamera/egl.cpp @@ -241,6 +241,8 @@ int eGL::createOutputDMABufTexture2D(eGLImage &eglImage, int fd) /** * \brief Create a 2D texture from a memory buffer * \param[in,out] eglImage EGL image to associate with the texture + * \param[in] internalFormat OpenGL internal storage format (e.g., GL_RGB8, GL_RGBA8) + * \param[in] type OpenGL pixel data type (e.g., GL_UNSIGNED_BYTE, GL_FLOAT) * \param[in] data Pointer to pixel data, or nullptr for uninitialised texture * \param[in] filter GL texture filter setting * @@ -249,7 +251,11 @@ 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, + GLint internalFormat, + GLenum type, + const void *data, + GLint filter) { ASSERT(tid_ == Thread::currentId()); @@ -257,7 +263,7 @@ void eGL::createTexture2D(eGLImage &eglImage, void *data, GLint filter) glBindTexture(GL_TEXTURE_2D, eglImage.texture_); // Generate texture, bind, associate image to texture, configure, unbind - glTexImage2D(GL_TEXTURE_2D, 0, eglImage.format_, eglImage.width_, eglImage.height_, 0, eglImage.format_, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, eglImage.width_, eglImage.height_, 0, eglImage.format_, type, data); // Nearest filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 5c4bd914b..2bf64e570 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -58,6 +58,11 @@ namespace libcamera { * \brief Type of LSC grid values */ +/** + * \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 diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 562e9fc7a..a73a00759 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -128,6 +128,9 @@ int DebayerEGL::getShaderVariableLocations(void) textureUniformBayerFirstRed_ = glGetUniformLocation(programId_, "tex_bayer_first_red"); textureUniformProjMatrix_ = glGetUniformLocation(programId_, "proj_matrix"); + textureUniformLsc_ = glGetUniformLocation(programId_, "lsc_tex"); + lscEnabledUniform_ = glGetUniformLocation(programId_, "lsc_enabled"); + LOG(Debayer, Debug) << "vertexIn " << attributeVertex_ << " textureIn " << attributeTexture_ << " tex_y " << textureUniformBayerDataIn_ << " awb " << awbUniformDataIn_ @@ -139,7 +142,9 @@ int DebayerEGL::getShaderVariableLocations(void) << " tex_size " << textureUniformSize_ << " stride_factor " << textureUniformStrideFactor_ << " tex_bayer_first_red " << textureUniformBayerFirstRed_ - << " proj_matrix " << textureUniformProjMatrix_; + << " proj_matrix " << textureUniformProjMatrix_ + << " tex_lsc " << textureUniformLsc_ + << " lsc_enabled" << lscEnabledUniform_; return 0; } @@ -156,6 +161,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. @@ -348,6 +356,18 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, */ stats_->setWindow(Rectangle(window_.size())); + if (lscEnabled_) { + constexpr unsigned int gridSize = DebayerParams::kLscGridSize; + const unsigned int stride = gridSize * DebayerParams::kLscBytesPerCell; + eglImageLscLookup_ = + std::make_unique<eGLImage>(GL_RGB, + gridSize, + gridSize, + stride, + GL_TEXTURE2, + 2); + } + return 0; } @@ -483,6 +503,13 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_TRUE, params.combinedMatrix.data().data()); LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix; + if (lscEnabled_) { + egl_.createTexture2D(*eglImageLscLookup_, GL_RGB16F, GL_FLOAT, + params.lscLut.data(), GL_LINEAR); + glUniform1i(textureUniformLsc_, eglImageLscLookup_->texture_unit_uniform_id_); + glUniform1i(lscEnabledUniform_, params.lscEnabled); + } + /* * 0 = Red, 1 = Green, 2 = Blue */ @@ -530,7 +557,8 @@ int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; return -ENODEV; } - egl_.createTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data(), GL_NEAREST); + egl_.createTexture2D(*eglImageBayerIn_, glFormat_, GL_UNSIGNED_BYTE, + inMapped->value().planes()[0].data(), GL_NEAREST); } /* Generate the output render framebuffer as render to texture */ diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 82ed1305d..2af26fb74 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -78,7 +78,10 @@ private: std::unique_ptr<eGLImage> eglImageBayerIn_; std::unique_ptr<eGLImage> eglImageBayerOut_; + /* LSC lookup table */ + std::unique_ptr<eGLImage> eglImageLscLookup_; bool lscEnabled_; + /* Shader parameters */ float firstRed_x_; float firstRed_y_; @@ -95,6 +98,10 @@ private: /* Per-frame AWB gains */ GLint awbUniformDataIn_; + /* Lens shading correction */ + GLint textureUniformLsc_; + GLboolean lscEnabledUniform_; + /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_;