From e6441ec4f4a68518c3f01c753ef179226f56ebfc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 9 Sep 2024 16:13:20 +0300 Subject: qcam: viewfinder_gl: Render image centered in letterbox Mimic the letterbox behaviour of the Qt viewfinder by rendering the image centered. This is done by adding a projection matrix to the vertex shader to scale the rendered rectangle. Another option would have been to keep using glViewport() (which would have needed to be moved to paintGL(), as Qt resets the viewport to span the full widget before calling). Hidpi displays would then need special handling of the device pixel ratio, which is done automatically by Qt when it sets the default viewport. Using a projection matrix avoids this complication. Signed-off-by: Laurent Pinchart Tested-by: Kieran Bingham Reviewed-by: Kieran Bingham --- src/apps/qcam/assets/shader/bayer_8.vert | 4 +++- src/apps/qcam/assets/shader/identity.vert | 3 ++- src/apps/qcam/viewfinder_gl.cpp | 31 ++++++++++++++++++++----------- src/apps/qcam/viewfinder_gl.h | 2 +- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/apps/qcam/assets/shader/bayer_8.vert b/src/apps/qcam/assets/shader/bayer_8.vert index 3695a5e9..fb5109ee 100644 --- a/src/apps/qcam/assets/shader/bayer_8.vert +++ b/src/apps/qcam/assets/shader/bayer_8.vert @@ -19,6 +19,8 @@ Copyright (C) 2021, Linaro attribute vec4 vertexIn; attribute vec2 textureIn; +uniform mat4 proj_matrix; + uniform vec2 tex_size; /* The texture size in pixels */ uniform vec2 tex_step; @@ -47,5 +49,5 @@ void main(void) { yCoord = center.y + vec4(-2.0 * tex_step.y, -tex_step.y, tex_step.y, 2.0 * tex_step.y); - gl_Position = vertexIn; + gl_Position = proj_matrix * vertexIn; } diff --git a/src/apps/qcam/assets/shader/identity.vert b/src/apps/qcam/assets/shader/identity.vert index 12c41377..907e8741 100644 --- a/src/apps/qcam/assets/shader/identity.vert +++ b/src/apps/qcam/assets/shader/identity.vert @@ -9,10 +9,11 @@ attribute vec4 vertexIn; attribute vec2 textureIn; varying vec2 textureOut; +uniform mat4 proj_matrix; uniform float stride_factor; void main(void) { - gl_Position = vertexIn; + gl_Position = proj_matrix * vertexIn; textureOut = vec2(textureIn.x * stride_factor, textureIn.y); } diff --git a/src/apps/qcam/viewfinder_gl.cpp b/src/apps/qcam/viewfinder_gl.cpp index b2096faf..f31956ff 100644 --- a/src/apps/qcam/viewfinder_gl.cpp +++ b/src/apps/qcam/viewfinder_gl.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -464,6 +465,7 @@ bool ViewFinderGL::createFragmentShader() vertexBuffer_.release(); + projMatrixUniform_ = shaderProgram_.uniformLocation("proj_matrix"); textureUniformY_ = shaderProgram_.uniformLocation("tex_y"); textureUniformU_ = shaderProgram_.uniformLocation("tex_u"); textureUniformV_ = shaderProgram_.uniformLocation("tex_v"); @@ -509,7 +511,7 @@ void ViewFinderGL::initializeGL() glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); - static const GLfloat coordinates[2][4][2]{ + const GLfloat coordinates[2][4][2]{ { /* Vertex coordinates */ { -1.0f, -1.0f }, @@ -801,6 +803,17 @@ void ViewFinderGL::doRender() shaderProgram_.setUniformValue(textureUniformStrideFactor_, static_cast(size_.width() - 1) / (stridePixels - 1)); + + /* + * Place the viewfinder in the centre of the widget, preserving the + * aspect ratio of the image. + */ + QMatrix4x4 projMatrix; + QSizeF scaledSize = size_.scaled(size(), Qt::KeepAspectRatio); + projMatrix.scale(scaledSize.width() / size().width(), + scaledSize.height() / size().height()); + + shaderProgram_.setUniformValue(projMatrixUniform_, projMatrix); } void ViewFinderGL::paintGL() @@ -818,18 +831,14 @@ void ViewFinderGL::paintGL() close(); } - if (image_) { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (!image_) + return; - doRender(); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } -} + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -void ViewFinderGL::resizeGL(int w, int h) -{ - glViewport(0, 0, w, h); + doRender(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } QSize ViewFinderGL::sizeHint() const diff --git a/src/apps/qcam/viewfinder_gl.h b/src/apps/qcam/viewfinder_gl.h index 23744b41..23c657bc 100644 --- a/src/apps/qcam/viewfinder_gl.h +++ b/src/apps/qcam/viewfinder_gl.h @@ -51,7 +51,6 @@ Q_SIGNALS: protected: void initializeGL() override; void paintGL() override; - void resizeGL(int w, int h) override; QSize sizeHint() const override; private: @@ -88,6 +87,7 @@ private: /* Common texture parameters */ GLuint textureMinMagFilters_; + GLuint projMatrixUniform_; /* YUV texture parameters */ GLuint textureUniformU_; -- cgit v1.2.1