summaryrefslogtreecommitdiff
path: root/src/qcam/viewfinder_gl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qcam/viewfinder_gl.cpp')
-rw-r--r--src/qcam/viewfinder_gl.cpp433
1 files changed, 357 insertions, 76 deletions
diff --git a/src/qcam/viewfinder_gl.cpp b/src/qcam/viewfinder_gl.cpp
index fbe21dcf..e7c8620c 100644
--- a/src/qcam/viewfinder_gl.cpp
+++ b/src/qcam/viewfinder_gl.cpp
@@ -7,28 +7,55 @@
#include "viewfinder_gl.h"
+#include <QByteArray>
+#include <QFile>
#include <QImage>
#include <libcamera/formats.h>
static const QList<libcamera::PixelFormat> supportedFormats{
+ /* YUV - packed (single plane) */
+ libcamera::formats::UYVY,
+ libcamera::formats::VYUY,
+ libcamera::formats::YUYV,
+ libcamera::formats::YVYU,
+ /* YUV - semi planar (two planes) */
libcamera::formats::NV12,
libcamera::formats::NV21,
libcamera::formats::NV16,
libcamera::formats::NV61,
libcamera::formats::NV24,
libcamera::formats::NV42,
+ /* YUV - fully planar (three planes) */
libcamera::formats::YUV420,
libcamera::formats::YVU420,
+ /* RGB */
+ libcamera::formats::ABGR8888,
+ libcamera::formats::ARGB8888,
+ libcamera::formats::BGRA8888,
+ libcamera::formats::RGBA8888,
+ libcamera::formats::BGR888,
+ libcamera::formats::RGB888,
+ /* Raw Bayer 8-bit */
+ libcamera::formats::SBGGR8,
+ libcamera::formats::SGBRG8,
+ libcamera::formats::SGRBG8,
+ libcamera::formats::SRGGB8,
+ /* Raw Bayer 10-bit packed */
+ libcamera::formats::SBGGR10_CSI2P,
+ libcamera::formats::SGBRG10_CSI2P,
+ libcamera::formats::SGRBG10_CSI2P,
+ libcamera::formats::SRGGB10_CSI2P,
+ /* Raw Bayer 12-bit packed */
+ libcamera::formats::SBGGR12_CSI2P,
+ libcamera::formats::SGBRG12_CSI2P,
+ libcamera::formats::SGRBG12_CSI2P,
+ libcamera::formats::SRGGB12_CSI2P,
};
ViewFinderGL::ViewFinderGL(QWidget *parent)
- : QOpenGLWidget(parent), buffer_(nullptr), yuvData_(nullptr),
- fragmentShader_(nullptr), vertexShader_(nullptr),
- vertexBuffer_(QOpenGLBuffer::VertexBuffer),
- textureU_(QOpenGLTexture::Target2D),
- textureV_(QOpenGLTexture::Target2D),
- textureY_(QOpenGLTexture::Target2D)
+ : QOpenGLWidget(parent), buffer_(nullptr), data_(nullptr),
+ vertexBuffer_(QOpenGLBuffer::VertexBuffer)
{
}
@@ -45,19 +72,23 @@ const QList<libcamera::PixelFormat> &ViewFinderGL::nativeFormats() const
int ViewFinderGL::setFormat(const libcamera::PixelFormat &format,
const QSize &size)
{
- /* If the fragment is created remove it and create a new one. */
- if (fragmentShader_) {
+ if (format != format_) {
+ /*
+ * If the fragment already exists, remove it and create a new
+ * one for the new format.
+ */
if (shaderProgram_.isLinked()) {
shaderProgram_.release();
- shaderProgram_.removeShader(fragmentShader_);
- delete fragmentShader_;
+ shaderProgram_.removeShader(fragmentShader_.get());
+ fragmentShader_.reset();
}
- }
- if (!selectFormat(format))
- return -1;
+ if (!selectFormat(format))
+ return -1;
+
+ format_ = format;
+ }
- format_ = format;
size_ = size;
updateGeometry();
@@ -89,7 +120,11 @@ void ViewFinderGL::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
if (buffer_)
renderComplete(buffer_);
- yuvData_ = static_cast<unsigned char *>(map->memory);
+ 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;
}
@@ -97,54 +132,185 @@ void ViewFinderGL::render(libcamera::FrameBuffer *buffer, MappedBuffer *map)
bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
{
bool ret = true;
+
+ /* Set min/mag filters to GL_LINEAR by default. */
+ textureMinMagFilters_ = GL_LINEAR;
+
+ /* Use identity.vert as the default vertex shader. */
+ vertexShaderFile_ = ":identity.vert";
+
+ fragmentShaderDefines_.clear();
+
switch (format) {
case libcamera::formats::NV12:
horzSubSample_ = 2;
vertSubSample_ = 2;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_2_planes_UV_f.glsl";
+ fragmentShaderDefines_.append("#define YUV_PATTERN_UV");
+ fragmentShaderFile_ = ":YUV_2_planes.frag";
break;
case libcamera::formats::NV21:
horzSubSample_ = 2;
vertSubSample_ = 2;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_2_planes_VU_f.glsl";
+ fragmentShaderDefines_.append("#define YUV_PATTERN_VU");
+ fragmentShaderFile_ = ":YUV_2_planes.frag";
break;
case libcamera::formats::NV16:
horzSubSample_ = 2;
vertSubSample_ = 1;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_2_planes_UV_f.glsl";
+ fragmentShaderDefines_.append("#define YUV_PATTERN_UV");
+ fragmentShaderFile_ = ":YUV_2_planes.frag";
break;
case libcamera::formats::NV61:
horzSubSample_ = 2;
vertSubSample_ = 1;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_2_planes_VU_f.glsl";
+ fragmentShaderDefines_.append("#define YUV_PATTERN_VU");
+ fragmentShaderFile_ = ":YUV_2_planes.frag";
break;
case libcamera::formats::NV24:
horzSubSample_ = 1;
vertSubSample_ = 1;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_2_planes_UV_f.glsl";
+ fragmentShaderDefines_.append("#define YUV_PATTERN_UV");
+ fragmentShaderFile_ = ":YUV_2_planes.frag";
break;
case libcamera::formats::NV42:
horzSubSample_ = 1;
vertSubSample_ = 1;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_2_planes_VU_f.glsl";
+ fragmentShaderDefines_.append("#define YUV_PATTERN_VU");
+ fragmentShaderFile_ = ":YUV_2_planes.frag";
break;
case libcamera::formats::YUV420:
horzSubSample_ = 2;
vertSubSample_ = 2;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_3_planes_f.glsl";
+ fragmentShaderFile_ = ":YUV_3_planes.frag";
break;
case libcamera::formats::YVU420:
horzSubSample_ = 2;
vertSubSample_ = 2;
- vertexShaderSrc_ = ":NV_vertex_shader.glsl";
- fragmentShaderSrc_ = ":NV_3_planes_f.glsl";
+ 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;
+ case libcamera::formats::ABGR8888:
+ fragmentShaderDefines_.append("#define RGB_PATTERN rgb");
+ fragmentShaderFile_ = ":RGB.frag";
+ break;
+ case libcamera::formats::ARGB8888:
+ fragmentShaderDefines_.append("#define RGB_PATTERN bgr");
+ fragmentShaderFile_ = ":RGB.frag";
+ break;
+ case libcamera::formats::BGRA8888:
+ fragmentShaderDefines_.append("#define RGB_PATTERN gba");
+ fragmentShaderFile_ = ":RGB.frag";
+ break;
+ case libcamera::formats::RGBA8888:
+ fragmentShaderDefines_.append("#define RGB_PATTERN abg");
+ fragmentShaderFile_ = ":RGB.frag";
+ break;
+ case libcamera::formats::BGR888:
+ fragmentShaderDefines_.append("#define RGB_PATTERN rgb");
+ fragmentShaderFile_ = ":RGB.frag";
+ break;
+ case libcamera::formats::RGB888:
+ fragmentShaderDefines_.append("#define RGB_PATTERN bgr");
+ fragmentShaderFile_ = ":RGB.frag";
+ break;
+ case libcamera::formats::SBGGR8:
+ firstRed_.setX(1.0);
+ firstRed_.setY(1.0);
+ vertexShaderFile_ = ":bayer_8.vert";
+ fragmentShaderFile_ = ":bayer_8.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGBRG8:
+ firstRed_.setX(0.0);
+ firstRed_.setY(1.0);
+ vertexShaderFile_ = ":bayer_8.vert";
+ fragmentShaderFile_ = ":bayer_8.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGRBG8:
+ firstRed_.setX(1.0);
+ firstRed_.setY(0.0);
+ vertexShaderFile_ = ":bayer_8.vert";
+ fragmentShaderFile_ = ":bayer_8.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SRGGB8:
+ firstRed_.setX(0.0);
+ firstRed_.setY(0.0);
+ vertexShaderFile_ = ":bayer_8.vert";
+ fragmentShaderFile_ = ":bayer_8.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SBGGR10_CSI2P:
+ firstRed_.setX(1.0);
+ firstRed_.setY(1.0);
+ fragmentShaderDefines_.append("#define RAW10P");
+ 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 RAW10P");
+ 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 RAW10P");
+ 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 RAW10P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SBGGR12_CSI2P:
+ firstRed_.setX(1.0);
+ firstRed_.setY(1.0);
+ fragmentShaderDefines_.append("#define RAW12P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGBRG12_CSI2P:
+ firstRed_.setX(0.0);
+ firstRed_.setY(1.0);
+ fragmentShaderDefines_.append("#define RAW12P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SGRBG12_CSI2P:
+ firstRed_.setX(1.0);
+ firstRed_.setY(0.0);
+ fragmentShaderDefines_.append("#define RAW12P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
+ break;
+ case libcamera::formats::SRGGB12_CSI2P:
+ firstRed_.setX(0.0);
+ firstRed_.setY(0.0);
+ fragmentShaderDefines_.append("#define RAW12P");
+ fragmentShaderFile_ = ":bayer_1x_packed.frag";
+ textureMinMagFilters_ = GL_NEAREST;
break;
default:
ret = false;
@@ -159,15 +325,15 @@ bool ViewFinderGL::selectFormat(const libcamera::PixelFormat &format)
bool ViewFinderGL::createVertexShader()
{
/* Create Vertex Shader */
- vertexShader_ = new QOpenGLShader(QOpenGLShader::Vertex, this);
+ vertexShader_ = std::make_unique<QOpenGLShader>(QOpenGLShader::Vertex, this);
/* Compile the vertex shader */
- if (!vertexShader_->compileSourceFile(vertexShaderSrc_)) {
+ if (!vertexShader_->compileSourceFile(vertexShaderFile_)) {
qWarning() << "[ViewFinderGL]:" << vertexShader_->log();
return false;
}
- shaderProgram_.addShader(vertexShader_);
+ shaderProgram_.addShader(vertexShader_.get());
return true;
}
@@ -176,16 +342,29 @@ bool ViewFinderGL::createFragmentShader()
int attributeVertex;
int attributeTexture;
- /* Create Fragment Shader */
- fragmentShader_ = new QOpenGLShader(QOpenGLShader::Fragment, this);
+ /*
+ * Create the fragment shader, compile it, and add it to the shader
+ * program. The #define macros stored in fragmentShaderDefines_, if
+ * any, are prepended to the source code.
+ */
+ fragmentShader_ = std::make_unique<QOpenGLShader>(QOpenGLShader::Fragment, this);
- /* Compile the fragment shader */
- if (!fragmentShader_->compileSourceFile(fragmentShaderSrc_)) {
+ QFile file(fragmentShaderFile_);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning() << "Shader" << fragmentShaderFile_ << "not found";
+ return false;
+ }
+
+ QString defines = fragmentShaderDefines_.join('\n') + "\n";
+ QByteArray src = file.readAll();
+ src.prepend(defines.toUtf8());
+
+ if (!fragmentShader_->compileSourceCode(src)) {
qWarning() << "[ViewFinderGL]:" << fragmentShader_->log();
return false;
}
- shaderProgram_.addShader(fragmentShader_);
+ shaderProgram_.addShader(fragmentShader_.get());
/* Link shader pipeline */
if (!shaderProgram_.link()) {
@@ -219,27 +398,29 @@ bool ViewFinderGL::createFragmentShader()
textureUniformY_ = shaderProgram_.uniformLocation("tex_y");
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");
- if (!textureY_.isCreated())
- textureY_.create();
+ /* Create the textures. */
+ for (std::unique_ptr<QOpenGLTexture> &texture : textures_) {
+ if (texture)
+ continue;
- if (!textureU_.isCreated())
- textureU_.create();
-
- if (!textureV_.isCreated())
- textureV_.create();
+ texture = std::make_unique<QOpenGLTexture>(QOpenGLTexture::Target2D);
+ texture->create();
+ }
- id_y_ = textureY_.textureId();
- id_u_ = textureU_.textureId();
- id_v_ = textureV_.textureId();
return true;
}
-void ViewFinderGL::configureTexture(unsigned int id)
+void ViewFinderGL::configureTexture(QOpenGLTexture &texture)
{
- glBindTexture(GL_TEXTURE_2D, id);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, texture.textureId());
+ 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);
}
@@ -250,12 +431,6 @@ void ViewFinderGL::removeShader()
shaderProgram_.release();
shaderProgram_.removeAllShaders();
}
-
- if (fragmentShader_)
- delete fragmentShader_;
-
- if (vertexShader_)
- delete vertexShader_;
}
void ViewFinderGL::initializeGL()
@@ -303,7 +478,7 @@ void ViewFinderGL::doRender()
case libcamera::formats::NV42:
/* Activate texture Y */
glActiveTexture(GL_TEXTURE0);
- configureTexture(id_y_);
+ configureTexture(*textures_[0]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
@@ -312,12 +487,12 @@ void ViewFinderGL::doRender()
0,
GL_RED,
GL_UNSIGNED_BYTE,
- yuvData_);
+ data_);
shaderProgram_.setUniformValue(textureUniformY_, 0);
/* Activate texture UV/VU */
glActiveTexture(GL_TEXTURE1);
- configureTexture(id_u_);
+ configureTexture(*textures_[1]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RG,
@@ -326,14 +501,14 @@ void ViewFinderGL::doRender()
0,
GL_RG,
GL_UNSIGNED_BYTE,
- (char *)yuvData_ + size_.width() * size_.height());
+ data_ + size_.width() * size_.height());
shaderProgram_.setUniformValue(textureUniformU_, 1);
break;
case libcamera::formats::YUV420:
/* Activate texture Y */
glActiveTexture(GL_TEXTURE0);
- configureTexture(id_y_);
+ configureTexture(*textures_[0]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
@@ -342,12 +517,12 @@ void ViewFinderGL::doRender()
0,
GL_RED,
GL_UNSIGNED_BYTE,
- yuvData_);
+ data_);
shaderProgram_.setUniformValue(textureUniformY_, 0);
/* Activate texture U */
glActiveTexture(GL_TEXTURE1);
- configureTexture(id_u_);
+ configureTexture(*textures_[1]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
@@ -356,12 +531,12 @@ void ViewFinderGL::doRender()
0,
GL_RED,
GL_UNSIGNED_BYTE,
- (char *)yuvData_ + size_.width() * size_.height());
+ data_ + size_.width() * size_.height());
shaderProgram_.setUniformValue(textureUniformU_, 1);
/* Activate texture V */
glActiveTexture(GL_TEXTURE2);
- configureTexture(id_v_);
+ configureTexture(*textures_[2]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
@@ -370,14 +545,14 @@ void ViewFinderGL::doRender()
0,
GL_RED,
GL_UNSIGNED_BYTE,
- (char *)yuvData_ + size_.width() * size_.height() * 5 / 4);
+ data_ + size_.width() * size_.height() * 5 / 4);
shaderProgram_.setUniformValue(textureUniformV_, 2);
break;
case libcamera::formats::YVU420:
/* Activate texture Y */
glActiveTexture(GL_TEXTURE0);
- configureTexture(id_y_);
+ configureTexture(*textures_[0]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
@@ -386,12 +561,12 @@ void ViewFinderGL::doRender()
0,
GL_RED,
GL_UNSIGNED_BYTE,
- yuvData_);
+ data_);
shaderProgram_.setUniformValue(textureUniformY_, 0);
/* Activate texture V */
glActiveTexture(GL_TEXTURE2);
- configureTexture(id_v_);
+ configureTexture(*textures_[2]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
@@ -400,12 +575,12 @@ void ViewFinderGL::doRender()
0,
GL_RED,
GL_UNSIGNED_BYTE,
- (char *)yuvData_ + size_.width() * size_.height());
+ data_ + size_.width() * size_.height());
shaderProgram_.setUniformValue(textureUniformV_, 2);
/* Activate texture U */
glActiveTexture(GL_TEXTURE1);
- configureTexture(id_u_);
+ configureTexture(*textures_[1]);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RED,
@@ -414,10 +589,116 @@ void ViewFinderGL::doRender()
0,
GL_RED,
GL_UNSIGNED_BYTE,
- (char *)yuvData_ + size_.width() * size_.height() * 5 / 4);
+ data_ + size_.width() * size_.height() * 5 / 4);
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(*textures_[0]);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ size_.width() / 2,
+ size_.height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ data_);
+ 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(textureUniformStep_,
+ 1.0f / (size_.width() / 2 - 1),
+ 1.0f /* not used */);
+ break;
+
+ case libcamera::formats::ABGR8888:
+ case libcamera::formats::ARGB8888:
+ case libcamera::formats::BGRA8888:
+ case libcamera::formats::RGBA8888:
+ glActiveTexture(GL_TEXTURE0);
+ configureTexture(*textures_[0]);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ size_.width(),
+ size_.height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ data_);
+ shaderProgram_.setUniformValue(textureUniformY_, 0);
+ break;
+
+ case libcamera::formats::BGR888:
+ case libcamera::formats::RGB888:
+ glActiveTexture(GL_TEXTURE0);
+ configureTexture(*textures_[0]);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGB,
+ size_.width(),
+ size_.height(),
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
+ data_);
+ shaderProgram_.setUniformValue(textureUniformY_, 0);
+ break;
+
+ case libcamera::formats::SBGGR8:
+ case libcamera::formats::SGBRG8:
+ case libcamera::formats::SGRBG8:
+ case libcamera::formats::SRGGB8:
+ case libcamera::formats::SBGGR10_CSI2P:
+ case libcamera::formats::SGBRG10_CSI2P:
+ case libcamera::formats::SGRBG10_CSI2P:
+ case libcamera::formats::SRGGB10_CSI2P:
+ case libcamera::formats::SBGGR12_CSI2P:
+ case libcamera::formats::SGBRG12_CSI2P:
+ case libcamera::formats::SGRBG12_CSI2P:
+ case libcamera::formats::SRGGB12_CSI2P:
+ /*
+ * Raw Bayer 8-bit, and packed raw Bayer 10-bit/12-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;
};
@@ -431,7 +712,7 @@ void ViewFinderGL::paintGL()
<< "create fragment shader failed.";
}
- if (yuvData_) {
+ if (data_) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);