diff options
Diffstat (limited to 'src/qcam/viewfinder_gl.cpp')
-rw-r--r-- | src/qcam/viewfinder_gl.cpp | 433 |
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); |