GCC-16 has updated the warnings enabled and now includes
-Wsfinae-incomplete triggering breakage in the included headers from
Qt6:
/usr/include/qt6/QtCore/qregularexpression.h:31:21: error: defining ‘QRegularExpression’, which previously failed to be complete in a SFINAE context [-Werror=sfinae-incomplete=]
This is a Qt header issue outside of libcamera’s control. Disable the
warning for qcam to restore buildability with newer GCC versions.
Link: https://qt-project.atlassian.net/browse/QTBUG-143470
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Populate qcam viewfinder_gl to set default Bayer values so that the
shaders can be used in their original mode without conditional compilation.
Set an identity CCM, identity Black Level and set Gamma and Contrast to
1.0f respectively.
Once this change is made we can use the Bayer shaders in their original
format in qcam with raw streams.
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Tested-by: Robert Mader <robert.mader@collabora.com>
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # ThinkPad T14s gen 6 (arm64) ov02c10 + X1c gen 12 ov08x40
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> # Lenovo X13s
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
When retrieving the value from a `ControlValue` usually one of two
things happen: a small, trivially copyable object is returned by
value; or a view into the internal buffer is provided. This is true
for everything except strings, which are returned in `std::string`,
incurring the overhead of string construction.
To guarantee no potentially "expensive" copies, use `std::string_view`
pointing to the internal buffer to return the value. This is similar
to how other array-like types are returned with a `Span<>`.
This is an API break, but its scope is limited to just `properties::Model`.
Bug: https://bugs.libcamera.org/show_bug.cgi?id=256
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
If the currently selected camera disappears as reported by the `cameraRemoved`
signal, then `MainWindow::camera_` is reset to `nullptr`. In this case,
pressing the start/stop button will try to start streaming, leading to
a nullptr derefence in `MainWindow::startCapture()` when the configuration
is generated for the camera.
Fix that by returning from `MainWindow::toggleCapture()` if no camera is set.
While this will cause the "checked" status of `startStopAction_` to go out of
sync, this should not be an issue because when a new camera is selected, the
state is synchronized.
Bug: https://bugs.libcamera.org/show_bug.cgi?id=177
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
In Qt 6.9.0 the qtmochelpers.h header introduced a construct that gcc 12
and gcc 13 incorrectly flag as variable shadowing:
In file included from src/apps/qcam/qcam.p/moc_viewfinder_gl.cpp:12:
/usr/include/qt6/QtCore/qtmochelpers.h: In instantiation of ‘constexpr void QtMocHelpers::detail::UintDataStorage<std::integer_sequence<int, Idx ...>, T ...>::forEach(F&&) const [with F = QtMocHelpers::UintData<QtMocHelpers::SignalData<void(libcamera::FrameBuffer*)> >::copyTo<{anonymous}::qt_meta_tag_ZN12ViewFinderGLE_t, QtMocHelpers::MetaObjectContents<24, 10, 60, 3> >(QtMocHelpers::MetaObjectContents<24, 10, 60, 3>&, size_t, uint&) const::<lambda(const auto:39&)>; int ...Idx = {0}; T = {QtMocHelpers::SignalData<void(libcamera::FrameBuffer*)>}]’:
/usr/include/qt6/QtCore/qtmochelpers.h:255:21: required from ‘constexpr const QtMocHelpers::MetaObjectContents<24, 10, 60, 3> ViewFinderGL::qt_staticMetaObjectContent<{anonymous}::qt_meta_tag_ZN12ViewFinderGLE_t>’
src/apps/qcam/qcam.p/../../../../../../src/apps/qcam/viewfinder_gl.h:32:2: required from ‘constexpr const auto ViewFinderGL::qt_staticMetaObjectStaticContent<{anonymous}::qt_meta_tag_ZN12ViewFinderGLE_t>’
src/apps/qcam/qcam.p/moc_viewfinder_gl.cpp:63:5: required from here
src/apps/qcam/qcam.p/../../../../../../src/apps/qcam/viewfinder_gl.h:32:2: in ‘constexpr’ expansion of ‘ViewFinderGL::qt_create_metaobjectdata<{anonymous}::qt_meta_tag_ZN12ViewFinderGLE_t>()’
src/apps/qcam/qcam.p/moc_viewfinder_gl.cpp:58:87: in ‘constexpr’ expansion of ‘QtMocHelpers::metaObjectData<ViewFinderGL, {anonymous}::qt_meta_tag_ZN12ViewFinderGLE_t, StringRefStorage<char [13], char [15], char [1], char [24], char [7]>, UintData<SignalData<void(libcamera::FrameBuffer*)> >, UintData<>, UintData<> >(0, qt_stringData, qt_methods, qt_properties, qt_enums, QtMocHelpers::UintData<>(), const QtMocHelpers::detail::UintDataBlock<0, 0>{uint [1](), uint [1]()})’
/usr/include/qt6/QtCore/qtmochelpers.h:563:36: in ‘constexpr’ expansion of ‘(& methods)->QtMocHelpers::UintData<QtMocHelpers::SignalData<void(libcamera::FrameBuffer*)> >::copyTo<{anonymous}::qt_meta_tag_ZN12ViewFinderGLE_t, QtMocHelpers::MetaObjectContents<24, 10, 60, 3> >(result, ((size_t)dataoffset), metatypeoffset)’
/usr/include/qt6/QtCore/qtmochelpers.h:201:57: error: declaration of ‘entry’ shadows a member of ‘QtMocHelpers::detail::UintDataStorage<std::integer_sequence<int, 0>, QtMocHelpers::SignalData<void(libcamera::FrameBuffer*)> >’ [-Werror=shadow]
201 | [[maybe_unused]] auto invoke = [&f](const auto &entry) { f(entry.entry); return 0; };
| ~~~~~~~~~~~~^~~~~
/usr/include/qt6/QtCore/qtmochelpers.h:180:7: note: shadowed declaration is here
180 | T entry;
| ^~~~~
There is little we can do but silence the warning. Do so selectively
based on the Qt and gcc versions, to still detect variable shadowing
with compilers unaffected by the issue.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <uajain@igalia.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
In commit ee2b011b65 ("apps: cam: Try raw role if default viewfinder
role fails"), the viewfinder role is specified as the default if no role
is yet chosen.
This was unfortunately added by directly accessing the vector rather
than extending the size when the vector is empty. Fix the code to push
the default viewfinder role on to the back of the vector, increasing the
size appropriately.
Fixes: ee2b011b65 ("apps: cam: Try raw role if default viewfinder role fails")
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
cam currently defaults to the viewfinder role when no role is specified.
This means that on platforms that only support the raw role (such as a
raw sensor with no softISP on a simple pipeline platform),
generateConfiguration() would return nullptr and cam would bail out.
At least this is what is supposed to happen based on the little
documentation that we have written regarding generateConfiguration(),
specifically in the application writer's guide, which is probably the
most influential piece of documentation:
The ``Camera::generateConfiguration()`` function accepts a list of
desired roles and generates a ``CameraConfiguration`` with the best
stream parameters configuration for each of the requested roles. If the
camera can handle the requested roles, it returns an initialized
``CameraConfiguration`` and a null pointer if it can't.
Currently the simple pipeline handler will return a raw configuration
anyway (if it only supports raw) even if a non-raw role was requested.
Thus cam receives a raw configuration instead of a nullptr when no role
is specified and viewfinder is requested.
However, in the near future, support for raw streams with softISP on the
simple pipeline handler will be merged. This will notably change the
behavior of the simple pipeline handler to return nullptr if a non-raw
role was requested on a platform that only supports raw. This is proper
behavior according to documentation, but changes cam's behavior as it
used to capture fine with no parameters but will no longer be able to.
Technically this is an issue with the roles API, as we are mixing
roles in the sense of "configuration hints" (eg. viewfinder vs recording
vs still capture) with roles in the sense of "platform capabilities"
(raw vs everything else). In the long term the proper solution is to
rework the roles API.
In the meantime, fix cam so that it will try the raw role if the default
viewfinder role returns no configuration. cam is an app that is capable
of using the raw stream, so this is appropriate behavior. If roles are
specified, then do not retry, as in this situation the user knows what
streams they can use and what they want.
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Support for DNG capture is conditioned by the availability of libtiff,
which is indicated by the HAVE_TIFF macro set by meson. The dng_writer.h
header then defines HAVE_DNG, which is used in a couple of places to
conditionally compile DNG-related code. Most of the other locations
where conditional compilation is required use HAVE_TIFF.
Using both HAVE_TIFF and HAVE_DNG is confusing. HAVE_DNG would be a
better name, but as the macro is defined in dng_writer.h, it would
require all files that need to test for DNG support to include that
header. Failure to include it (directly or indirectly) would result in
the code covered by the macro to be silently disabled.
To avoid the confusion, standardize on using HAVE_TIFF everywhere and
drop HAVE_DNG.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
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 <laurent.pinchart@ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
There's no need to call glClearColor() twice before drawing any GL
content. Drop the first call. This doesn't introduce any functional
change.
While at it, pass floats instead of doubles to glClearColor(), as
required by the function.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Starting in Qt 6.7.0, vertex buffers and shader programs are unbound
just before calling QOpenGLWidget::paintGL(). This breaks rendering in
the GL viewfinder in two ways.
First, we bind the vertex buffer only once at initialization time. There
is therefore no vertex buffer mapped at rendering time, preventing both
the vertex shader from having access to the vertex and texture
coordinates.
Then, we bind the shader program only when rendering the first frame.
There is thus no shader program bound for all subsequent frames,
breaking rendering.
Fix this by binding the vertex buffer where needed, when setting
attribute buffers for the shader program, and binding the shader program
for every frame.
As we use a single vertex buffer, we could bind it at the beginning of
paintGL() and keep it bound indefinitely. That would however fail to
clearly indicate in the source code where the vertex buffer is needed,
making the code more difficult to understand as it would rely on
implicit assumptions. Release the vertex buffer explicitly when we don't
need it anymore to avoid this.
While at it, fix a coding style violation by adding missing curly
brackets.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
When the widget's aspect ratio doesn't match the camera aspect ratio,
the viewfinder is rendered letter-boxed. The side rectangles are not
painted by the viewfinder, and Qt thus renders the parent widget
background to fill that space.
To make it black, we have two options:
- The simplest option is to set the widget's autoFillBackground property
to true. This causes Qt to paint the whole widget with its background
colour before calling paintEvent(). As the camera image typically
covers most (if not all) of the viewfinder widget, this is less
efficient.
- The more complicated option is to paint the letterbox rectangles
manually. We can additionally set the widget's WA_OpaquePaintEvent
attribute to instruct Qt to skip painting the parent widget. This
reduces CPU usage by about 1% (and may reduce GPU usage as well).
Note that the WA_OpaquePaintEvent attribute has to be disabled when we
render the stopped icon, as the icon has a transparent background.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
The Qt 6 qkeysequence.h header has an extra semicolon. This causes a
build failure with clang:
/usr/include/qt6/QtGui/qkeysequence.h:139:26: error: extra ';' after member function definition [-Werror,-Wextra-semi]
139 | Q_ENUM(SequenceMatch);
| ^
We can't fix the issue, so ignore the warning in qcam.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Open source Qt 5 has been effectively end of life since the release
of Qt 6, and Qt 6 has current LTS releases now.
This change ports qcam to Qt 6.2 and drops some of the baggage related
to Qt 5 that is no longer applicable.
Signed-off-by: Neal Gompa <neal@gompa.dev>
Reviewed-by: Eric Curtin <ecurtin@redhat.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Keep the image aspect ratio when displaying in the viewfinder.
When the window is adjusted to a size that differs in aspect ratio to
the image, keep the image centered in the main window.
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Multiple local functions are defined in the global namespace without the
static keyword. This compiles fine for now, but will cause a missing
declaration warning when we enable them. To prepare for that, move the
function declaration to an anonymous namespace.
While at it, for consistency, include an existing static function in the
namespace and drop the static keyword.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Source files in libcamera start by a comment block header, which
includes the file name and a one-line description of the file contents.
While the latter is useful to get a quick overview of the file contents
at a glance, the former is mostly a source of inconvenience. The name in
the comments can easily get out of sync with the file name when files
are renamed, and copy & paste during development have often lead to
incorrect names being used to start with.
Readers of the source code are expected to know which file they're
looking it. Drop the file name from the header comment blocks in all
remaining locations that were not caught by the automated script as they
are out of sync with the file name.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Source files in libcamera start by a comment block header, which
includes the file name and a one-line description of the file contents.
While the latter is useful to get a quick overview of the file contents
at a glance, the former is mostly a source of inconvenience. The name in
the comments can easily get out of sync with the file name when files
are renamed, and copy & paste during development have often lead to
incorrect names being used to start with.
Readers of the source code are expected to know which file they're
looking it. Drop the file name from the header comment block.
The change was generated with the following script:
----------------------------------------
dirs="include/libcamera src test utils"
declare -rA patterns=(
['c']=' \* '
['cpp']=' \* '
['h']=' \* '
['py']='# '
['sh']='# '
)
for ext in ${!patterns[@]} ; do
files=$(for dir in $dirs ; do find $dir -name "*.${ext}" ; done)
pattern=${patterns[${ext}]}
for file in $files ; do
name=$(basename ${file})
sed -i "s/^\(${pattern}\)${name} - /\1/" "$file"
done
done
----------------------------------------
This misses several files that are out of sync with the comment block
header. Those will be addressed separately and manually.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Replace the manual CTRL+Q key sequence with QKeySequence::Quit. This
automatically maps to the native shortcut for the quit action,
regardless of the platform. Even though we don't expect qcam to run on
non-Linux platform, using a QKeySequence is still a good practice when
one exists.
This doesn't change qcam's behaviour, as the native quit key sequence is
CTRL+Q on Linux systems.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Meson uses tags to sort installed files in categories, and makes it
possible to install a subset of the files using the '--tags' argument to
'meson install'. This is typically used by distributions to split the
runtime, development and documentation files into separate packages.
By default, meson tries to guess the correct tag for installed files,
but can't always do so properly. Mark the install targets that meson
can't guess with the correct install_tag.
As the feature has been introduced in meson 0.60, bump the minimum meson
version. The latest LTS release of all major distributions that
libcamera currently targets ship a recent enough meson version.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
The meson style, which libcamera follows, recommends a space before
colons in function parameters. Fix the style violations through the
project.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
Now that `Camera::generateConfiguration()` takes a `libcamera::Span`
of `StreamRole`, remove the `StreamRoles` type, which was an alias
to `std::vector<libcamera::StreamRole>`.
The removal has two reasons:
- it is no longer strictly necessary,
- its presence may suggest that that is the preferred (or correct)
way to build/pass a list of `StreamRole`.
Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
[Kieran: Fix small checkstyle report on roles initialiser]
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Multiple source files in the src/apps/cam/ directory are used by cam,
qcam and lc-compliance. They are compiled separately for each
application. Move them to a new src/apps/common/ directory and compile
them in a static library to decrease the number of compilation
operations.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
libtiff is a shared dependency between cam and qcam, move it to
src/apps/. The shared dependency will be used to condition compilation
of source files in an upcoming application static library.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
The cam and qcam test application share code, currently through a crude
hack that references the cam source files directly from the qcam
meson.build file. To prepare for the introduction of hosting that code
in a static library, move all applications to src/apps/.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>