@@ -61,6 +61,21 @@ int DebayerEGL::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf
formats::XBGR8888,
formats::ABGR8888 };
+ if (bayerFormat.order == BayerFormat::Order::MONO) {
+ if (bayerFormat.packing == BayerFormat::Packing::None) {
+ config.bpp = (bayerFormat.bitDepth + 7) & ~7;
+ config.patternSize.width = 2;
+ config.patternSize.height = 2;
+ } else if (bayerFormat.packing == BayerFormat::Packing::CSI2) {
+ config.bpp = bayerFormat.bitDepth;
+ config.patternSize.width = (bayerFormat.bitDepth == 12) ? 2 : 4;
+ config.patternSize.height = 2;
+ }
+
+ config.outputFormats = outputFormats;
+ return 0;
+ }
+
if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10) &&
bayerFormat.packing == BayerFormat::Packing::None &&
isStandardBayerOrder(bayerFormat.order)) {
@@ -172,6 +187,17 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
shaderStridePixels_ = inputConfig_.stride;
switch (inputFormat) {
+ case libcamera::formats::R8:
+ case libcamera::formats::R10:
+ case libcamera::formats::R12:
+ /*
+ * \todo: Add full conversion testing for R14 once the format is upstreamed
+ case libcamera::formats::R14:
+ */
+ case libcamera::formats::R16:
+ firstRed_x_ = 0.0;
+ firstRed_y_ = 0.0;
+ break;
case libcamera::formats::SBGGR8:
case libcamera::formats::SBGGR10_CSI2P:
case libcamera::formats::SBGGR12_CSI2P:
@@ -203,6 +229,103 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
/* Shader selection */
switch (inputFormat) {
+ case libcamera::formats::R8:
+ egl_.pushEnv(shaderEnv, "#define INV_MAX_VAL (1.0 / 255.0)");
+ egl_.pushEnv(shaderEnv, "#define RAW8");
+ fragmentShaderData = mono_unpacked_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_LUMINANCE;
+ bytesPerPixel_ = 1;
+ break;
+ case libcamera::formats::R10: {
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat);
+
+ egl_.pushEnv(shaderEnv, "#define INV_MAX_VAL (1.0 / 1023.0)");
+ if (bayerFormat.packing == BayerFormat::Packing::None) {
+ egl_.pushEnv(shaderEnv, "#define RAW10");
+ fragmentShaderData = mono_unpacked_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_RG;
+ bytesPerPixel_ = 2;
+ } else {
+ egl_.pushEnv(shaderEnv, "#define BLOCK_PIXELS 4.0");
+ egl_.pushEnv(shaderEnv, "#define BLOCK_BYTES 5.0");
+ egl_.pushEnv(shaderEnv, "#define LSB_SIZE 2.0");
+ egl_.pushEnv(shaderEnv, "#define LSB_MASK_VAL 4.0");
+ egl_.pushEnv(shaderEnv, (std::string("#define TEX_WIDTH ") + std::to_string(inputConfig_.stride) + ".0").c_str());
+ egl_.pushEnv(shaderEnv, (std::string("#define TEX_HEIGHT ") + std::to_string(height_) + ".0").c_str());
+
+ fragmentShaderData = mono_1x_packed_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_LUMINANCE;
+ bytesPerPixel_ = 1;
+ shaderStridePixels_ = inputConfig_.stride;
+ }
+ break;
+ }
+ case libcamera::formats::R12: {
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat);
+
+ egl_.pushEnv(shaderEnv, "#define INV_MAX_VAL (1.0 / 4095.0)");
+ if (bayerFormat.packing == BayerFormat::Packing::None) {
+ egl_.pushEnv(shaderEnv, "#define RAW12");
+ fragmentShaderData = mono_unpacked_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_RG;
+ bytesPerPixel_ = 2;
+ } else {
+ egl_.pushEnv(shaderEnv, "#define BLOCK_PIXELS 2.0");
+ egl_.pushEnv(shaderEnv, "#define BLOCK_BYTES 3.0");
+ egl_.pushEnv(shaderEnv, "#define LSB_SIZE 4.0");
+ egl_.pushEnv(shaderEnv, "#define LSB_MASK_VAL 16.0");
+ egl_.pushEnv(shaderEnv, (std::string("#define TEX_WIDTH ") + std::to_string(inputConfig_.stride) + ".0").c_str());
+ egl_.pushEnv(shaderEnv, (std::string("#define TEX_HEIGHT ") + std::to_string(height_) + ".0").c_str());
+
+ fragmentShaderData = mono_1x_packed_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_LUMINANCE;
+ bytesPerPixel_ = 1;
+ shaderStridePixels_ = inputConfig_.stride;
+ }
+ break;
+ }
+ /*
+ * \todo: Add full conversion testing for R14 once the format is upstreamed
+ case libcamera::formats::R14: {
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat);
+
+ egl_.pushEnv(shaderEnv, "#define INV_MAX_VAL (1.0 / 16383.0)");
+ if (bayerFormat.packing == BayerFormat::Packing::None) {
+ egl_.pushEnv(shaderEnv, "#define RAW14");
+ fragmentShaderData = mono_unpacked_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_RG;
+ bytesPerPixel_ = 2;
+ } else {
+ egl_.pushEnv(shaderEnv, "#define BLOCK_PIXELS 4.0");
+ egl_.pushEnv(shaderEnv, "#define BLOCK_BYTES 7.0");
+ egl_.pushEnv(shaderEnv, "#define LSB_SIZE 6.0");
+ egl_.pushEnv(shaderEnv, "#define LSB_MASK_VAL 64.0");
+ egl_.pushEnv(shaderEnv, (std::string("#define TEX_WIDTH ") + std::to_string(inputConfig_.stride) + ".0").c_str());
+ egl_.pushEnv(shaderEnv, (std::string("#define TEX_HEIGHT ") + std::to_string(height_) + ".0").c_str());
+
+ fragmentShaderData = mono_1x_packed_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_LUMINANCE;
+ bytesPerPixel_ = 1;
+ shaderStridePixels_ = inputConfig_.stride;
+ }
+ break;
+ }
+ */
+ case libcamera::formats::R16:
+ egl_.pushEnv(shaderEnv, "#define INV_MAX_VAL (1.0 / 65535.0)");
+ egl_.pushEnv(shaderEnv, "#define RAW16");
+ fragmentShaderData = mono_unpacked_frag;
+ vertexShaderData = mono_vert;
+ glFormat_ = GL_RG;
+ bytesPerPixel_ = 2;
+ break;
case libcamera::formats::SBGGR8:
case libcamera::formats::SGBRG8:
case libcamera::formats::SGRBG8:
@@ -279,7 +402,7 @@ int DebayerEGL::initBayerShaders(PixelFormat inputFormat, PixelFormat outputForm
int DebayerEGL::configure(const StreamConfiguration &inputCfg,
const std::vector<std::reference_wrapper<const StreamConfiguration>> &outputCfgs,
- [[maybe_unused]] bool ccmEnabled,
+ bool ccmEnabled,
bool lscEnabled)
{
if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0) {
@@ -300,6 +423,7 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,
return -EINVAL;
}
+ ccmEnabled_ = ccmEnabled;
lscEnabled_ = lscEnabled;
inputConfig_.stride = inputCfg.stride;
@@ -331,10 +455,17 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,
outputSize_ = outputCfg.size;
nativeOutputSize_ = outSizeRange.max;
- window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &
- ~(inputConfig_.patternSize.width - 1);
- window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) &
- ~(inputConfig_.patternSize.height - 1);
+ /* Setup the window geometry according to the format type */
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputCfg.pixelFormat);
+ if (bayerFormat.order == BayerFormat::Order::MONO) {
+ window_.x = 0;
+ window_.y = 0;
+ } else {
+ window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &
+ ~(inputConfig_.patternSize.width - 1);
+ window_.y = ((inputCfg.size.height - outputCfg.size.height) / 2) &
+ ~(inputConfig_.patternSize.height - 1);
+ }
window_.width = outputCfg.size.width;
window_.height = outputCfg.size.height;
@@ -474,9 +605,11 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara
<< " textureUniformProjMatrix_ " << textureUniformProjMatrix_;
/* Pre-transpose matrix for GLES 2.0. */
- Matrix<float, 3, 3> ccm = params.combinedMatrix.transpose();
- glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm.data().data());
- LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix;
+ if (ccmEnabled_) {
+ Matrix<float, 3, 3> ccm = params.combinedMatrix.transpose();
+ glUniformMatrix3fv(ccmUniformDataIn_, 1, GL_FALSE, ccm.data().data());
+ LOG(Debayer, Debug) << " ccmUniformDataIn_ " << ccmUniformDataIn_ << " data " << params.combinedMatrix;
+ }
if (lscEnabled_ && params.lscLutVersion != lscLutVersion_) {
egl_.updateTexture2D(*eglImageLscLookup_, params.lscLut.data());
@@ -723,12 +856,11 @@ void DebayerEGL::stop()
SizeRange DebayerEGL::sizes(PixelFormat inputFormat, const Size &inputSize)
{
Size patternSize = this->patternSize(inputFormat);
- unsigned int borderHeight = patternSize.height;
-
if (patternSize.isNull())
return {};
/* No need for top/bottom border with a pattern height of 2 */
+ unsigned int borderHeight = patternSize.height;
if (patternSize.height == 2)
borderHeight = 0;
@@ -743,9 +875,12 @@ SizeRange DebayerEGL::sizes(PixelFormat inputFormat, const Size &inputSize)
return {};
}
+ BayerFormat bayerFormat = BayerFormat::fromPixelFormat(inputFormat);
+ bool localIsMono = (bayerFormat.order == BayerFormat::Order::MONO);
+
return SizeRange(Size(patternSize.width, patternSize.height),
- Size((inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1),
- (inputSize.height - 2 * borderHeight) & ~(patternSize.height - 1)),
+ Size((inputSize.width - (localIsMono ? 0 : 2 * patternSize.width)) & ~(patternSize.width - 1),
+ (inputSize.height - (localIsMono ? 0 : 2 * borderHeight)) & ~(patternSize.height - 1)),
patternSize.width, patternSize.height);
}
@@ -128,6 +128,8 @@ private:
GLint glFormat_;
unsigned int bytesPerPixel_;
uint32_t shaderStridePixels_;
+
+ bool ccmEnabled_;
};
} /* namespace libcamera */
Signed-off-by: Alain CousiniƩ <alain.cousinie@laposte.net> --- src/libcamera/software_isp/debayer_egl.cpp | 159 +++++++++++++++++++-- src/libcamera/software_isp/debayer_egl.h | 2 + 2 files changed, 149 insertions(+), 12 deletions(-) -- 2.55.0