summaryrefslogtreecommitdiff
path: root/src/qcam/viewfinder_gl.cpp
diff options
context:
space:
mode:
authorAndrey Konovalov <andrey.konovalov@linaro.org>2021-06-22 16:46:45 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-06-30 04:07:58 +0300
commitc4259493dc8db1a78bdbf47b912d24b899c0f45c (patch)
treeba5e4d2d8d80559b4f0cdae14179f4248ec47396 /src/qcam/viewfinder_gl.cpp
parentfa52c0f22faa239a3d1ddeede6f3b36ec35bdf5c (diff)
qcam: viewfinder_gl: Add shader to render packed RAW10 formats
The shader supports all 4 packed RAW10 variants. Simple bi-linear Bayer interpolation of nearest pixels is implemented. The 2 LS bits of the 10-bit colour values are dropped as the RGBA format we convert into has only 8 bits per colour. The texture coordinates passed to the fragment shader are adjusted to point to the nearest pixel in the image. This prevents artifacts when the image is scaled from the frame resolution to the window size. Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/qcam/viewfinder_gl.cpp')
-rw-r--r--src/qcam/viewfinder_gl.cpp78
1 files changed, 76 insertions, 2 deletions
diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
index ff719418..ffbbc6c5 100644
--- a/src/qcam/viewfinder_gl.cpp
+++ b/src/qcam/viewfinder_gl.cpp
@@ -36,6 +36,11 @@ static const QList<libcamera::PixelFormat> supportedFormats{
libcamera::formats::RGBA8888,
libcamera::formats::BGR888,
libcamera::formats::RGB888,
+ /* Raw Bayer 10-bit packed */
+ libcamera::formats::SBGGR10_CSI2P,
+ libcamera::formats::SGBRG10_CSI2P,
+ libcamera::formats::SGRBG10_CSI2P,
+ libcamera::formats::SRGGB10_CSI2P,
};
ViewFinderGL::ViewFinderGL(QWidget *parent)
@@ -106,6 +111,10 @@ void ViewFinderGL::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
renderComplete(buffer_);
data_ = static_cast<unsigned char *>(map->memory);
+ /*
+ * \todo Get the stride from the buffer instead of computing it naively
+ */
+ stride_ = buffer->metadata().planes[0].bytesused / size_.height();
update();
buffer_ = buffer;
}
@@ -114,6 +123,9 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
{
bool ret = true;
+ /* Set min/mag filters to GL_LINEAR by default. */
+ textureMinMagFilters_ = GL_LINEAR;
+
fragmentShaderDefines_.clear();
switch (format) {
@@ -203,6 +215,34 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
fragmentShaderDefines_.append("#define RGB_PATTERN bgr");
fragmentShaderFile_ = ":RGB.frag";
break;
+ case libcamera::formats::SBGGR10_CSI2P:
+ firstRed_.setX(1.0);
+ firstRed_.setY(1.0);
+ fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGBRG10_CSI2P:
+ firstRed_.setX(0.0);
+ firstRed_.setY(1.0);
+ fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGRBG10_CSI2P:
+ firstRed_.setX(1.0);
+ firstRed_.setY(0.0);
+ fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SRGGB10_CSI2P:
+ firstRed_.setX(0.0);
+ firstRed_.setY(0.0);
+ fragmentShaderDefines_.append("#define BPP_X 1.25");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
default:
ret = false;
qWarning() << "[ViewFinderGL]:"
@@ -290,6 +330,8 @@ bool ViewFinderGL::createFragmentShader()
textureUniformU_ = shaderProgram_.uniformLocation("tex_u");
textureUniformV_ = shaderProgram_.uniformLocation("tex_v");
textureUniformStep_ = shaderProgram_.uniformLocation("tex_step");
+ textureUniformSize_ = shaderProgram_.uniformLocation("tex_size");
+ textureUniformBayerFirstRed_ = shaderProgram_.uniformLocation("tex_bayer_first_red");
/* Create the textures. */
for (std::unique_ptr<QOpenGLTexture> &texture : textures_) {
@@ -306,8 +348,10 @@ bool ViewFinderGL::createFragmentShader()
void ViewFinderGL::configureTexture(QOpenGLTexture &texture)
{
glBindTexture(GL_TEXTURE_2D, texture.textureId());
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ textureMinMagFilters_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ textureMinMagFilters_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
@@ -547,6 +591,36 @@ void ViewFinderGL::doRender()
shaderProgram_.setUniformValue(textureUniformY_, 0);
break;
+ case libcamera::formats::SBGGR10_CSI2P:
+ case libcamera::formats::SGBRG10_CSI2P:
+ case libcamera::formats::SGRBG10_CSI2P:
+ case libcamera::formats::SRGGB10_CSI2P:
+ /*
+ * Packed raw Bayer 10-bit formats are stored in GL_RED texture.
+ * The texture width is equal to the stride.
+ */
+ glActiveTexture(GL_TEXTURE0);
+ configureTexture(*textures_[0]);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RED,
+ stride_,
+ size_.height(),
+ 0,
+ GL_RED,
+ GL_UNSIGNED_BYTE,
+ data_);
+ shaderProgram_.setUniformValue(textureUniformY_, 0);
+ shaderProgram_.setUniformValue(textureUniformBayerFirstRed_,
+ firstRed_);
+ shaderProgram_.setUniformValue(textureUniformSize_,
+ size_.width(), /* in pixels */
+ size_.height());
+ shaderProgram_.setUniformValue(textureUniformStep_,
+ 1.0f / (stride_ - 1),
+ 1.0f / (size_.height() - 1));
+ break;
+
default:
break;
};