From dcc47ff715ef1a8b97df53c810ec0c4b069b06e5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 13 Sep 2020 01:04:20 +0300 Subject: qcam: viewfinder_gl: Add shader to render packed YUV formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shader supports all 4 packed 8-bit YUV variants. Signed-off-by: Laurent Pinchart Acked-by: Niklas Söderlund --- src/qcam/viewfinder_gl.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'src/qcam/viewfinder_gl.cpp') diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp index b8a48272..0b5c9426 100644 --- a/src/qcam/viewfinder_gl.cpp +++ b/src/qcam/viewfinder_gl.cpp @@ -14,12 +14,19 @@ #include static const QList supportedFormats{ + /* Packed (single plane) */ + libcamera::formats::UYVY, + libcamera::formats::VYUY, + libcamera::formats::YUYV, + libcamera::formats::YVYU, + /* Semi planar (two planes) */ libcamera::formats::NV12, libcamera::formats::NV21, libcamera::formats::NV16, libcamera::formats::NV61, libcamera::formats::NV24, libcamera::formats::NV42, + /* Fully planar (three planes) */ libcamera::formats::YUV420, libcamera::formats::YVU420, }; @@ -149,6 +156,22 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format) vertSubSample_ = 2; fragmentShaderFile_ = ":YUV_3_planes.frag"; break; + case libcamera::formats::UYVY: + fragmentShaderDefines_.append("#define YUV_PATTERN_UYVY"); + fragmentShaderFile_ = ":YUV_packed.frag"; + break; + case libcamera::formats::VYUY: + fragmentShaderDefines_.append("#define YUV_PATTERN_VYUY"); + fragmentShaderFile_ = ":YUV_packed.frag"; + break; + case libcamera::formats::YUYV: + fragmentShaderDefines_.append("#define YUV_PATTERN_YUYV"); + fragmentShaderFile_ = ":YUV_packed.frag"; + break; + case libcamera::formats::YVYU: + fragmentShaderDefines_.append("#define YUV_PATTERN_YVYU"); + fragmentShaderFile_ = ":YUV_packed.frag"; + break; default: ret = false; qWarning() << "[ViewFinderGL]:" @@ -235,6 +258,7 @@ bool ViewFinderGL::createFragmentShader() textureUniformY_ = shaderProgram_.uniformLocation("tex_y"); textureUniformU_ = shaderProgram_.uniformLocation("tex_u"); textureUniformV_ = shaderProgram_.uniformLocation("tex_v"); + textureUniformStepX_ = shaderProgram_.uniformLocation("tex_stepx"); if (!textureY_.isCreated()) textureY_.create(); @@ -431,6 +455,38 @@ void ViewFinderGL::doRender() shaderProgram_.setUniformValue(textureUniformU_, 1); break; + case libcamera::formats::UYVY: + case libcamera::formats::VYUY: + case libcamera::formats::YUYV: + case libcamera::formats::YVYU: + /* + * Packed YUV formats are stored in a RGBA texture to match the + * OpenGL texel size with the 4 bytes repeating pattern in YUV. + * The texture width is thus half of the image with. + */ + glActiveTexture(GL_TEXTURE0); + configureTexture(textureY_); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + size_.width() / 2, + size_.height(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + yuvData_); + shaderProgram_.setUniformValue(textureUniformY_, 0); + + /* + * The shader needs the step between two texture pixels in the + * horizontal direction, expressed in texture coordinate units + * ([0, 1]). There are exactly width - 1 steps between the + * leftmost and rightmost texels. + */ + shaderProgram_.setUniformValue(textureUniformStepX_, + 1.0f / (size_.width() / 2 - 1)); + break; + default: break; }; -- cgit v1.2.1