Commit Graph

2732 Commits

Author SHA1 Message Date
Hans de Goede
e948ada380 software_isp: debayer_cpu: Add multi-threading support
Add CPU soft ISP multi-threading support.

Benchmark results for the Arduino Uno-Q with a weak CPU which is good for
performance testing, all numbers with an IMX219 running at
3280x2464 -> 3272x2464:

1 thread : 147ms / frame, ~6.5 fps
2 threads:  80ms / frame, ~12.5 fps
3 threads:  65ms / frame, ~15 fps

Adding a 4th thread does not improve performance.

Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ThinkPad X1 Yoga Gen 7 + ov2740
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-04-01 12:06:27 +01:00
Hans de Goede
41d17f8211 software_isp: debayer_cpu: Add DebayerCpuThread class
Add a DebayerCpuThreadclass and use this in the inner render loop.
This contains data which needs to be separate per thread.

This is a preparation patch for making DebayerCpu support multi-threading.

Benchmarking on the Arduino Uno-Q with a weak CPU which is good for
performance testing, shows 146-147ms per 3272x2464 frame both before and
after this change, with things maybe being 0.5 ms slower after this change.

Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ThinkPad X1 Yoga Gen 7 + ov2740
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-04-01 12:05:15 +01:00
Hans de Goede
6e53e72e96 software_isp: swstats_cpu: Prepare for multi-threading support
Make the storage used to accumulate the RGB sums and the Y histogram
value a vector of SwIspStats objects instead of a single object so
that when using multi-threading every thread can use its own storage to
collect intermediate stats to avoid cache-line bouncing.

Benchmarking with the GPU-ISP which does separate swstats benchmarking,
on the Arduino Uno-Q which has a weak CPU which is good for performance
testing, shows 20ms to generate stats for a 3272x2464 frame both before
and after this change.

Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-04-01 12:04:42 +01:00
Barnabás Pőcze
9b6179fdb3 treewide: Use character literal instead of string in some cases
Use character literals instead of single character long strings. The main
purpose of this change is to work around a GCC bug that results in `-Wrestrict`
warnings at certain optimization levels in C++20. libstdc++ 13 has been
adjusted to avoid triggering the compiler warning.

Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105329
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
2026-03-27 16:29:49 +01:00
Barnabás Pőcze
bfd5518d6b libcamera: base: log: Ignore deprecations
`std::atomic_{load,store}()` with `std::shared_ptr` has been deprecated
in C++20 in favour of `std::atomic<std::shared_ptr<>>`. However, it is
not available on all supported platforms. So ignore the deprecation warnings.
The specialization is available since gcc (libstdc++) 12 and llvm (libc++) 15.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
2026-03-27 16:29:49 +01:00
David Plowman
cc74afcdbd libcamera: rpi: Make the controller min frame duration configurable
The controller min frame duration is used to rate limit how often we
run IPAs. Historically this has been set to 33333us, meaning that the
algorithms effectively skip frames when the camera is running faster
than 30fps.

This patch adds a small amount of plumbing that allows this value to
be set in the Raspberry Pi configuration file. Some applications or
platforms (such as Pi 5) are easily capable of running these more
often, should there be a need to do so.

Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-02-26 10:17:36 +00:00
Barnabás Pőcze
71c5c08fcf libcamera: software_isp: debayer_egl: Remove frameSize()
The base class (`Debayer`) already contains a non-virtual function with
the same name and implementation, so remove it from the derived class.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
2026-02-24 18:01:30 +01:00
Laurent Pinchart
993968d80e libcamera: Standardize on 'const auto'
'const auto' and 'auto const' are interchangeable in C++. There are 446
occurrences of the former in the code base, and 67 occurrences of the
latter. Standardize on the winner.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
2026-02-20 13:34:30 +01:00
Laurent Pinchart
be88125af1 libcamera: Replace iterators with structured bindings
Use structured bindings when iterating over a map in range-based for
loops. This improves readability.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
2026-02-20 13:34:21 +01:00
van Veen, Stephan
da967ed63d libcamera: controls: Define a new core Hue control
Define a new control to support configuration of Hue adjustments when
supported by the available platform.

Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
Signed-off-by: van Veen, Stephan <stephan.vanveen@karlstorz.com>
[Kieran: Rework to define as a rotation in degrees]
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-02-19 15:06:21 +00:00
Kieran Bingham
da12b1854f libcamera: software_isp: Fix LIBCAMERA_SOFTISP_MODE log print
When an invalid parameter is specified to LIBCAMERA_SOFTISP_MODE, the
error log has a typo. Fix the typo and reflow the line while here.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
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>
2026-02-18 16:48:56 +00:00
Milan Zamazal
d97d2a58ad libcamera: software_isp: Remove redundant include of time.h
The header file is not used in debayer_cpu.cpp any more.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-02-18 11:09:51 +00:00
Hans de Goede
7bcc2168bf software_isp: benchmark: Print what is being benchmarked
With the GPU accelerated softISP 2 separate benchmark results are printed,
1 for the generation of the output images on the GPU and a separate one
for generating the statistics on the CPU.

Add a new name argument to the Benchmark class descriptor and print this
out when printing the benchmark result.

Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-02-18 10:48:52 +00:00
Hans de Goede
f0a79dd68b software_isp: benchmark: Add missing _ postfix to measure data member
All class data members should have a _ postifx, add the missing _ postfix
to the Benchmark::measure_ data member.

Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-02-18 10:48:52 +00:00
Stefan Klug
1dcf9957a4 libcamera: converter: converter_dw100_vertexmap: Fix dewarp parameter p2 handling
The lens dewarp implementation done in commit 1784e08be3 ("libcamera:
dw100_vertexmap: Implement parametric dewarping") handles the dewarp
parameter p2 incorrectly because it uses the already dewarped x value as
input for the calculation of the y value. Fix that by using separate
variables for the output value. Do so for x and y to keep the code
symmetric even if it is only strictly required for y.

Fixes: 1784e08be3 ("libcamera: dw100_vertexmap: Implement parametric dewarping")
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-02-11 14:06:20 +01:00
Barnabás Pőcze
78b9890a0f libcamera: software_isp: debayer: Take DebayerParams by ref
When calling `Debayer::process()` from `SoftwareIsp::process()`, the
`DebayerParams` object is copied multiple times:

  (1) call of `BoundMethodMember<...>::activate()`
      inside `Object::invokeMethod()`
  (2) constructor of `BoundMethodArgs<...>`
      inside `BoundMethodMember<...>::activate()`
  (3) call of `BoundMethodMember<...>::invoke()`
      inside `BoundMethodArgs::invokePack()`
  (4) call of the actual pointer to member function
      inside `BoundMethodMember::invoke()`

While compilers might avoid one or two of the above copies, this is still
not ideal. By making `Debayer::process()` take the parameter object by
const lvalue reference, only the copy in the `BoundMethodArgs` constructor
remains. So do that.

Before:
	[0:12:51.133836595] [12424] DEBUG SoftwareIsp software_isp.cpp:399 params=0x7d0a691f57d0
	copy from 0x7d0a691f57d0 into 0x7baa65f2bf30
	copy from 0x7baa65f2bf30 into 0x7c6a69209758
	copy from 0x7c6a69209758 into 0x7baa63223930
	copy from 0x7baa63223930 into 0x7baa63223a70
	[0:12:51.134559602] [12426] DEBUG eGL debayer_egl.cpp:538 params=0x7baa63223a70
	771.099877 (30.06 fps) cam0-stream0 seq: 000031 bytesused: 8666112

After:
	[0:13:42.861691943] [12543] DEBUG SoftwareIsp software_isp.cpp:399 params=0x7cfaad5f57d0
	copy from 0x7cfaad5f57d0 into 0x7c5aad609758
	[0:13:42.862453917] [12545] DEBUG eGL debayer_egl.cpp:538 params=0x7c5aad609758
	822.827388 (30.02 fps) cam0-stream0 seq: 000031 bytesused: 8666112

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
2026-02-09 09:14:24 +01:00
Barnabás Pőcze
c6c5a8bc5b meson: Add libdw option to control libdw dependency
Previously it was not possible to disable libdw usage if it was
detected. Fix that by adding a meson feature option.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-02-06 09:57:56 +01:00
Barnabás Pőcze
79c31f0707 libcamera: base: utils: Fix namespace of operator<< for Duration
In order for ADL to find the function, it must be in the namespace of any of
its arguments. Previously, however, that was not the case, and it has only
really worked by accident and could be easily made to fail by introducing
other `operator<<` overloads.

For example, a user of this function in `libcamera::ipa` would no longer
compile after introducing an `operator<<` into the `libcamera::ipa`
namespace as that would essentially hide this overload, and without ADL
it would not be found.

So move the function into the `utils` namespace.

Fixes: 5055ca747c ("libcamera: utils: Add helper class for std::chrono::duration")
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2026-01-28 18:26:28 +01:00
Barnabás Pőcze
461e7d3d73 libcamera: base: utils: Simplify operator<< for Duration
There is no real need for a function template. It is not defined in a
header file, so it has limited availability, and there exists only a
single instantion.

So convert it to use `std::ostream` directly, like most `operator<<`
in the code base.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2026-01-28 18:26:28 +01:00
Laurent Pinchart
67fd7d720b libcamera: yaml_parser: Fix uninitialized variable warning
gcc 14.3.0, cross-compiling from amd64 to arm64, warns about a possibly
uninitialized variable in YamlObject::Getter<>::get():

In file included from ../../include/libcamera/internal/yaml_parser.h:12,
                 from ../../src/libcamera/yaml_parser.cpp:8:
In constructor ‘constexpr std::_Optional_payload_base<_Tp>::_Storage<_Up, <anonymous> >::_Storage(std::in_place_t, _Args&& ...) [with _Args = {unsigned char}; _Up = unsigned char; bool <anonymous> = true; _Tp = unsigned char]’,
    inlined from ‘constexpr std::_Optional_payload_base<_Tp>::_Optional_payload_base(std::in_place_t, _Args&& ...) [with _Args = {unsigned char}; _Tp = unsigned char]’ at include/c++/14.3.0/optional:122:4,
    inlined from ‘constexpr std::_Optional_payload<unsigned char, true, true, true>::_Optional_payload(std::in_place_t, _Args&& ...) [with _Args = {unsigned char}][inherited from std::_Optional_payload_base<unsigned char>]’ at include/c++/14.3.0/optional:337:42,
    inlined from ‘constexpr std::_Optional_base<_Tp, true, true>::_Optional_base(std::in_place_t, _Args&& ...) [with _Args = {unsigned char}; typename std::enable_if<is_constructible_v<_Tp, _Args ...>, bool>::type <anonymous> = false; _Tp = unsigned char]’ at include/c++/14.3.0/optional:648:4,
    inlined from ‘constexpr std::optional<_Tp>::optional(_Up&&) [with _Up = unsigned char; typename std::enable_if<__and_v<std::__not_<std::is_same<std::optional<_Tp>, typename std::remove_cv<typename std::remove_reference<_Up>::type>::type> >, std::__not_<std::is_same<std::in_place_t, typename std::remove_cv<typename std::remove_reference<_Up>::type>::type> >, std::is_constructible<_T1, _U1>, std::is_convertible<_Iter, _Iterator> >, bool>::type <anonymous> = true; _Tp = unsigned char]’ at include/c++/14.3.0/optional:747:47,
    inlined from ‘std::optional<_Tp> libcamera::YamlObject::Getter<T, typename std::enable_if<(((((is_same_v<signed char, T> || is_same_v<unsigned char, T>) || is_same_v<short int, T>) || is_same_v<short unsigned int, T>) || is_same_v<int, T>) || is_same_v<unsigned int, T>), void>::type>::get(const libcamera::YamlObject&) const [with T = unsigned char]’ at ../../src/libcamera/yaml_parser.cpp:172:10:
include/c++/14.3.0/optional:210:15: error: ‘value’ may be used uninitialized [-Werror=maybe-uninitialized]
  210 |             : _M_value(std::forward<_Args>(__args)...)
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../src/libcamera/yaml_parser.cpp: In member function ‘std::optional<_Tp> libcamera::YamlObject::Getter<T, typename std::enable_if<(((((is_same_v<signed char, T> || is_same_v<unsigned char, T>) || is_same_v<short int, T>) || is_same_v<short unsigned int, T>) || is_same_v<int, T>) || is_same_v<unsigned int, T>), void>::type>::get(const libcamera::YamlObject&) const [with T = unsigned char]’:
../../src/libcamera/yaml_parser.cpp:165:19: note: ‘value’ was declared here
  165 |                 T value;
      |                   ^~~~~

This appears to be a false positive, as the std::from_chars() function
should set value when it returns without an error. Commit bb1d216113
("libcamera: base: log: Fix uninitialized variable warning") fixed a
similar warning with gcc 13.3.0.

The warning is easy to work around by initializing the variable, and
doing so shouldn't be too costly as the type T is restricted to being an
integer. Fix the build by doing so.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
2026-01-28 18:47:15 +02:00
Stefan Klug
1355e29f31 libcamera: control_ids: Introduce LensShadingCorrectionEnable
Introduce a LensShadingCorrectionEnable control to enable and disable
LSC. This is useful to assess the working and quality of the lens
shading correction at runtime.

While at it drop the reference to the tuning file in the description of
the LensDewarpEnable control, as that information doesn't belong to the
controls.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2026-01-28 17:10:01 +01:00
Milan Zamazal
60f150bf87 libcamera: ipa: simple: Disable Ccm algorithm by default again
The default CCM in uncalibrated.yaml is just an identity transformation
and has been enabled by default only to always provide a correction
matrix to GPU ISP.  It slows down CPU ISP when CCM is not used.

Now, when a default correction matrix is always provided to GPU ISP, we
can disable the Ccm algorithm in uncalibrated.yaml again.  The check for
ccmEnabled in GPU ISP is no longer needed and it must be removed in
order not to fail when Ccm algorithm is not enabled.  ccmEnabled flag is
still needed in CPU ISP where the processing differs based on whether
CCM is present or not.

Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Robert Mader <robert.mader@collabora.com>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-28 15:20:34 +00:00
Milan Zamazal
3ffaa4c0e2 libcamera: ipa: simple: Remove Lut algorithm
The Lut algorithm is not really an algorithm.  Moreover, algorithms may
be enabled or disabled but with Lut disabled, nothing will work.

Let's move the construction of lookup tables to CPU debayering, where it
is used.  The implied and related changes are:

- DebayerParams is changed to contain the real params rather than lookup
  tables.
- contrastExp parameter introduced by GPU ISP is used for CPU ISP too.
- The params must be initialised so that debayering gets meaningful
  parameter values even when some algorithms are disabled.
- combinedMatrix must be put to params everywhere where it is modified.
- Matrix changes needn't be tracked in the algorithms any more.
- CPU debayering must watch for changes of the corresponding parameters
  to update the lookup tables when and only when needed.
- Swapping red and blue is integrated into lookup table constructions.
- gpuIspEnabled flags are removed as they are not needed any more.

Reviewed-by: Robert Mader <robert.mader@collabora.com>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-28 15:20:34 +00:00
Milan Zamazal
07240afa12 libcamera: simple: Fix black level offsets in AWB
The black level offset subtracted in AWB is wrong.  It assumes that the
stats contain sums of the individual colour pixels.  But they actually
contain sums of the colour channels of larger "superpixels" consisting
of the individual colour pixels.  Each of the RGB colour values and the
computed luminosity (a histogram entry) are added once to the stats per
such a superpixel.  This means the offset computed from the black level
and the number of pixels should be used as it is, not divided.

The patch fixes the subtracted offset.  Since the evaluation is the same
for all the three colours now, the individual class variables are
replaced with a single RGB variable.

Fixes: 4e13c6f55b ("Honor black level in AWB")
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Robert Mader <robert.mader@collabora.com>
Tested-by: Robert Mader <robert.mader@collabora.com>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-28 12:08:21 +00:00
Barnabás Pőcze
9b477c114b libcamera: v4l2_subdevice: Avoid unnecessary copy
There is no reason make a copy of the name, so don't do it,
and instead use a reference.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
2026-01-27 15:53:25 +01:00
Barnabás Pőcze
ddef786eee libcamera: v4l2_subdevice: Avoid reconstructing the std::regex object
Make the `std::regex` object have static lifetime to avoid
reconstructing it on every call.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
2026-01-27 15:53:22 +01:00
Barnabás Pőcze
330c390e6f libcamera: v4l2_subdevice: Remove unnecessary variable
`model` is not used, so remove it.

Fixes: 5d2aad02e8 ("libcamera: add model() for retrieving model name in V4L2Subdevice")
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2026-01-27 15:53:18 +01:00
Barnabás Pőcze
9e6fcab87c libcamera: pipeline: virtual: Don't use span iterator as pointer
Pointer to the contiguous data of a container is to be retrieved
using the `data()` member function. Using `begin()` in contexts
that require pointers is not correct as the iterator may be
something entirely different. So use `data()` where applicable.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
2026-01-23 16:49:03 +01:00
Robert Mader
7350d6cc5d Revert "libcamera: software_isp: gbm: Add a GBM helper class for GPU surface access"
GBM is not used any more - remove the helper class.

This reverts commit c60b1ce819.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sm8250/rb5, x1e/Dell Insprion14p
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>
2026-01-21 12:05:00 +00:00
Robert Mader
0c2ed9ebf9 egl: Use the Mesa surfaceless platform instead of GBM
Mesa surfaceless platform appears to be a better fit for the use-case at hand:
1. Like GBM it is Mesa specific, so no change in supported setups is
   expected. If ever required, a fallback to the generic device platform
   could be added on top.
2. It leaves the complexity of selecting a renderer device to the
   driver, reducing code and dependencies.
3. It allows to use llvmpipe / software drivers without dri device,
   which can be useful on CI or debugging (with LIBGL_ALWAYS_SOFTWARE=1).

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sm8250/rb5, x1e/Dell Insprion14p
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Tested-by: Milan Zamazal <mzamazal@redhat.com> # TI AM69
Tested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> # ThinkPad X1 Yoga Gen 7 + ov2740
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-21 12:05:00 +00:00
Robert Mader
4a5ebcf675 libcamera: simple: Enable SoftISP for imx7-csi
Since commit "libcamera: simple: Make raw streams working" apps that rely
on raw streams - such as Millipixels - can work with the SoftISP being
enabled. Thus let's enable the later by default.

Tested on a Librem5.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Acked-by: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-20 17:31:40 +00:00
Barnabás Pőcze
75c963146e libcamera: base: log: Remove LogInvalid check
A `LogMessage` instance cannot be moved or copied, so a severity of
`LogInvalid` is only possible if the message was constructed with that
log level explicitly. However, being a completely internal type, this
does not occur. So remove the check. And even if it does, it's probably
still better to print the message than to drop it silently.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2026-01-20 14:03:02 +01:00
Barnabás Pőcze
140dd0de85 libcamera: base: log: Do not check severity before printing
Now that the severity of the log message and the category is compared in
the expansion of the `LOG()` macro, there is no need to do it again in the
destructor.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2026-01-20 14:03:02 +01:00
Barnabás Pőcze
95bf04298e treewide: Remove libcamera::LOG(...) occurrences
When a class inherits from `Loggable`, it will have a protected `_log()`
function and that will be used instead of the global `_log()` function in the
expansion of the `LOG()` macro. However, if such a class has static member
functions, then simply writing `LOG()` will not work because name lookup will
find the non-static member function and not the global function, resulting in
a compiler error because the non-static member cannot be invoked without an
object, and there is no object in a static member function.

This can be avoided by using `using libcamera::_log;`, thereby bringing the
global declaration into the current scope.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-20 14:02:44 +01:00
Robert Mader
6725ea8edd egl: Print GLES version
It might come in handy to know whether 2.0 or e.g. 3.2 is used.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # Thinkpad X1 Carbon G13 IPU7 ov08x40
Tested-by: Milan Zamazal <mzamazal@redhat.com> # TI AM69
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-19 10:25:53 +00:00
Robert Mader
07335cbeb1 egl: Remove duplicated logging of EGL version
The line below already prints it.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # Thinkpad X1 Carbon G13 IPU7 ov08x40
Tested-by: Milan Zamazal <mzamazal@redhat.com> # TI AM69
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-19 10:25:49 +00:00
Robert Mader
22b15ff683 egl: Remove bpp variable
It's unused and, in one case, was set wrongly.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # Thinkpad X1 Carbon G13 IPU7 ov08x40
Tested-by: Milan Zamazal <mzamazal@redhat.com> # TI AM69
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-19 10:25:44 +00:00
Robert Mader
7c1527cd44 egl: Remove unused functions
They are left-overs from older iterations of the GPU-ISP.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Hans de Goede <johannes.goede@oss.qualcomm.com> # Thinkpad X1 Carbon G13 IPU7 ov08x40
Tested-by: Milan Zamazal <mzamazal@redhat.com> # TI AM69
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-19 10:25:05 +00:00
Barnabás Pőcze
fa22b4ffef libcamera: base: event_dispatcher_poll: Dispatch POLLPRI first
When `poll()` returns multiple events for a given file descriptor, while there
is no general rule that requires it, for the use cases of libcamera, it is
better to service priority events first. So dispatch those first, and not last.

For example, a V4L2 capture device might be a source of V4L2 events (e.g. frame
start) as well as a source of dequeue-able buffers. In such cases, given the
appropriate scheduling, it is possible with the current event dispatch order
that dequeueing the buffer happens before processing the corresponding frame
start event. Such occurrence will most likely trip up any internal state machine.

The above is suspected to contribute to [0], however, that is not confirmed.

[0]: https://gitlab.freedesktop.org/camera/libcamera/-/issues/267

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
2026-01-14 12:30:11 +01:00
Paul Elder
5e59969dbb libcamera: control_serializer: Remove unnecessary allocation
In between versions of the patch "libcamera: control_serializer: Add
array info to serialized ControlValue", ipa_control_value_entry was
changed to be members of ipa_control_info_entry as opposed to being
serialized at the same level. The binarySize/entriesSize computation was
not updated, however, leaving some extra memory allocated for the
serialized form of ControlInfoMap.

Fix this by removing the extra size for 3 * ipa_control_value_entry.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Reviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2026-01-08 11:00:10 +09:00
Bryan O'Donoghue
aaa48bb276 libcamera: software_isp: Add a gpuisp todo list
List the series of things to do in GPU ISP in perceived order of
difficulty.

Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:58 +00:00
Bryan O'Donoghue
2cf92d00c2 libcamera: software_isp: debayer_egl: Make gpuisp default softisp mode
In some cases the GPU can deliver 15x performance in Debayer with the
CCM on, reference hardware Qualcomm RB5 with IMX512 sensor.

Given this large performance difference it makes sense to make GPUISP
the default for the Software ISP.

If LIBCAMERA_SOFTISP_MODE is omitted gpu will be the default. If
libcamera is compiled without gpuisp support, CPU Debayer will be used.

It is still possible to select CPU mode with LIBCAMERA_SOFISP_MODE=cpu.

Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:58 +00:00
Bryan O'Donoghue
fe9e143702 ipa: simple: Add a flag to indicate gpuIspEnabled
Flag gpuIspEnabled in the simple IPA context. This flag will allow to
selectively avoid some calculations or to generate a default CCM.

Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00
Bryan O'Donoghue
a92cc12fb5 libcamera: software_isp: debayer_egl: Make DebayerEGL an environment option
If GPUISP support is available make it so an environment variable can
switch it on.

Given we don't have full feature parity with CPUISP just yet on pixel
format output, we should default to CPUISP mode giving the user the option
to switch on GPUISP by setting LIBCAMERA_SOFTISP_MODE=gpu

Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00
Milan Zamazal
999d446475 libcamera: software_isp: GPU support for unpacked 10/12-bit formats
The GPU processing supports 8-bit sensor formats and 10/12-bit packed
formats.  Support for 10/12-bit unpacked formats is missing, let's add
it.

10/12-bit unpacked formats use two adjacent bytes to store the value.
This means the 8-bit shaders can be used if we can modify them for
additional support of 16-bit addressing.  This requires the following
modifications:

- Using GL_RG (two bytes per pixel) instead of GL_LUMINANCE (one byte
  per pixel) as the texture format for the given input formats.

- Setting the texture width to the number of pixels rather than the
  number of bytes.

- Making the definition of `fetch' macro variable, according to the
  pixel format.

- Using only `fetch' for accessing the texture.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00
Bryan O'Donoghue
6a478459f3 libcamera: software_isp: debayer_cpu: Make getInputConfig and getOutputConfig static
Make getInputConfig and getOutputConfig static so as to allow for
interrogation of the supported pixel formats prior to object instantiation.
Do this so as to allow the higher level logic make an informed choice
between CPU and GPU ISP based on which pixel formats are supported.

Currently CPU ISP supports more diverse input and output schemes.

Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00
Bryan O'Donoghue
f520b29fe9 libcamera: software_isp: debayer_egl: Add an eGL Debayer class
Add a class to run the existing glsl debayer shaders on a GBM surface.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Co-developed-by: Robert Mader <robert.mader@collabora.com>
[bod: took scaling and buffer size fixes from Robert]
[bod: took fix for center byte calculation from Hans]
[bod: took formatting fixes from Milan]
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Co-developed-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Robert Mader <robert.mader@collabora.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00
Bryan O'Donoghue
db09fcd8b6 libcamera: software_isp: Add a Size_ member variable to pass to eGL later
We will be initialising eGL from Debayer::start(). We need a copy of the
size data passed in configure() to tell the fragment shaders the right
output size.

Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00
Bryan O'Donoghue
7e72e84f3d libcamera: software_isp: Add member variables to track selected input/output pixelFormat
In order to have Debayer::start() tell the eGL shader compilation routine what
the input and output pixel format is, we need to have a copy of the
selected format available. Add variables to the inputConfig and
outputConfig structures to allow tracking of this data for later use.

Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00
Hans de Goede
5b609e7a44 libcamera: shaders: Fix input sampling when width != stride
When bayer_unpacked.vert is calculating the center and x/yCoord values
stride != width is taken into account for x/yCoord deltas since it is taken
into account by debayer_egl when setting the x part of tex_step uniform.

But it is not taken into account for the center.x which is just directly
copied from textureIn, leading to the input width sampling covering
the entire input stride instead of just covering the input width.

Use the existing and currently unused stride_factor uniform to pass
the width/stride ratio and correct center.x for this. This fixes
the misrendering seen on x86 laptops which is caused by the CSI2 receiver
there requiring a stride which is a multiple of 32 often leading to
stride != width.

Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.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: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2026-01-07 17:02:57 +00:00