Compare commits

...

832 commits

Author SHA1 Message Date
Robert Mader
6389c1ce55 tests: color-representation: Skip dmabuf test if not supported
For systems where udmabuf is not available.

Fixes: 75d75ac6c (tests: Add color-representation tests for DRM and GL)
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 19:00:25 +01:00
Robert Mader
9364282ebd gitlab-ci: Bump mesa from 25.3.0 to 25.3.2
The new color-representation-drm test occasionally crashes Mesa. Update
to the latest point release in case it helps.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 18:52:26 +01:00
Robert Mader
af59ce4058 tests: Add color-representation protocol test
Ensuring that important errors are raised correctly.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:39 +01:00
Robert Mader
75d75ac6cd tests: Add color-representation tests for DRM and GL
Test the various combinations of:
1. Renderer backends - currently GL only.
2. Renderer modes - plane-offloading/vkms, shaders in Mesa, internal
   shaders.
3. Buffer-types - SHM and DMABuf.
4. Coefficient/range combinations.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:39 +01:00
Robert Mader
f709b8a798 tests: client-helper: Add color-representation protocol support
In order to test coefficients and ranges.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:39 +01:00
Robert Mader
adaffa980e backend-drm: Set coefficients and range plane properties
Using values from the color representation protocol. Only supported for
YCbCr formats in KMS drivers for now.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:39 +01:00
Robert Mader
104cd2e813 gl-renderer: Enable support for color representation protocol
All required features were implemeneted in previous commits - enable the
capability.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:39 +01:00
Robert Mader
e8b7997223 gl-renderer: Add coefficients and range support to EGLImage paths
`EGL_YUV_COLOR_SPACE_HINT_EXT` and `EGL_SAMPLE_RANGE_HINT_EXT` have
to be set at image import, which again happens on wl_buffer creation.
This is problematic because in Wayland (and Vulkan) those values are
surface attributes and thus only known once the buffer gets attached
to a particular surface.

We solve that by first importing the dmabuf with default values and,
when attaching a buffer to a surface, creating additional EGLImages
as needed.

Note that we ignore `EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT` and
`EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT` for now, which are neither
required by the Wayland color-representation protocol nor supported by
Mesa shaders (as of 25.3).

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:39 +01:00
Robert Mader
b736066dc9 gl-renderer: Simplify EGLImage paths
Unlike EGL image import, texture creation and binding is quite fast and
cheap. Thus, instead of doing it as early as possible in various places,
do it right before we actually need it in prepare_textured_draw().

This will follow-up changes easier and includes some preparations for
them.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:29 +01:00
Robert Mader
2613db2426 gl-renderer: Add coefficients and range support to internal shader
Add matrix-coefficients and range tracking to more gl-renderer structures
and get the relevant values from the color-representation implementation
instead of hard-coding them in the shader.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:29 +01:00
Robert Mader
32f6148afd libweston: Implement color-representation protocol
For now limited to coefficients and ranges that are typically
supported by KMS drivers. We notably leave out alpha modes and
chroma locations for now.

The protocol initialization is guarded by the WESTON_CAP_COLOR_REP
backend capability and thus not enabled anywhere yet.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:29 +01:00
Robert Mader
f7aa35e9d2 gitlab-ci: Bump wayland-protocols to 1.46
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-19 17:08:29 +01:00
Jonas Ådahl
cdb011ee53 libweston/desktop: Support constraining popups to monitor region
Doesn't yet deal with work area (monitor area excluding panels etc), or
reconstraining while moving, but it's a start.

It's more or less based on the mutter implementation. While the mutter
implementation is GPL, it was authored by me, thus grant permission to
relicense to MIT.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
2025-12-19 09:07:27 -06:00
Derek Foreman
7c8b745249 compositor: Check for EINTR reading timerfd
It's technically correct this way, and it also squashes an unused result
warning.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 15:59:12 -06:00
Derek Foreman
85d8c7a5e5 clients: Add a commit-timing test client
Add a simple client that queues up a few future frames and logs how
accurately the requested presentation times were hit.

This used simple-shm as a skeleton, and those copyrights have been retained.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
a3f0e97a71 compositor: Support the commit-timing protocol
Introduce support for the commit-timing protocol to allow applications
to attach a presentation time to a content update.

We use the repaint timer to schedule content updates in advance of
the frame time when they should be displayed.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
65227cb7d4 compositor: Round repaint times down to possible presentation times
Currently this shouldn't result in any change, since the times we pass in
are real presentation times.

Later when commit-timing lets applications pass in arbitrary times, it
will be more interesting.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
ed77aca2d8 compositor: check repaint_msec with a helper
Validate repaint_msec so it's not longer than a refresh interval.

Negative repaint windows will cause problems for frame scheduling in the
future, so remove them.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
e286cf6e15 core: rename and internally share output_repaint_timer_arm
When we add timed transactions, we'll want to feed them through the repaint
timer, so share it to allow this in the future.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
37256645d6 tests: Listen for the presentation clock id
Add a listener and a roundtrip so test clients using presentation have
access to the presentation clock id.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
0a76cb86ca compositor: Upgrade repaint timer precision to nsec
We can now use 1ns as the minimum timer duration instead of 1ms.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
37acb0c0fd compositor: Directly use a timerfd instead of a wl_event_source
In the near future commit-timing + VRR combined will want to have better
than the 1ms precision we're allowed now.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:58:01 -06:00
Derek Foreman
2bbe222883 compositor: Improve timing information in scene graph dump
After moving the drm-backend's scene graph dump, it now always occurs when
repaint_status is REPAINT_AWAITING_COMPLETION, which loses useful timing
information we used to have.

Add timing information for the REPAINT_AWAITING_COMPLETION state, and also
add the expected presentation time.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:57:29 -06:00
Derek Foreman
eb61323aa1 compositor: Improve VRR timings
When we need to use VRR, we'll miss a potential frame deadline, fail to
deliver a frame, then stop the repaint loop. When a late frame comes
in, we deliver it immediately at the start of a new repaint loop.

The only time we really need to deliver a frame immediately is at
the start of the loop, otherwise we can use the same repaint window
behaviour as any other time.

This still leaves some room for improvement, as we still don't try
to avoid Vactive.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:44 -06:00
Derek Foreman
2dce06179f compositor: Don't return repaint times in the past
If we're late to present, just return the current time instead of a time in
the past.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Derek Foreman
75f2ec4747 compositor: Pull repaint time calculation out of finish_frame
Make this into a separate functions we can call from other places to get
the same results.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Derek Foreman
f36a3a91a8 compositor: Rearrange weston_output_finish_frame
Move some code around so we only derive the next repaint from the next
presentation time and the repaint window once at the end of the function.

In many cases we now subtract the repaint_msec value from "now", but that's
ok because any time earlier than "now" will still result in firing the timer
at the same time.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Derek Foreman
01b7e9d015 compositor: store frame flags from finish frame
These are used to determine if the previous frame was displayed with
tearing, which is useful in determining when the next frame time should
be.

Store these as a step towards breaking the frame time calculations out
of output_finish_frame into a separate function.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Derek Foreman
f1bcedd089 compositor: Track repaint time and expected presentation time
For the upcoming commit-timing protocol, we're interested in when a
scheduled repaint will be displayed, so let's keep track of both the
repaint time and the anticipated presentation time.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Derek Foreman
d88efaea66 backend-drm: More aggressively avoid the stale timestamp workaround
At first we always used this workaround, and then we stopped using it when
VRR was in use.

Turns out it also hurts presentation times when starting the repaint loop,
which makes the commit-timing protocol difficult to implement.

Completely avoid the workaround on any kernel newer than 4.12, based on a
capability check for DRM_CAP_CRTC_IN_VBLANK_EVENT, and log a warning at
startup.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Derek Foreman
fc2e365c1d compositor: Update to presentation-timing version 2
This fixes a bug in version 1 where we should've been giving a 0 refresh
for VRR, and introduces version 2 where we're allowed to give a compositor
chosen rate for VRR.

We currently chose the mode's native refresh rate.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Pekka Paalanen
2e66195546 tests/string: fix false-positive uninitialized val
GCC 14.2 with debugoptimized build complained:

In file included from ../../git/weston/tests/weston-test-assert.h:32,
                 from ../../git/weston/tests/string-test.c:36:
In function ‘strtof_conversions’,
    inlined from ‘wrapstrtof_conversions’ at ../../git/weston/tests/string-test.c:92:1:
../../git/weston/shared/weston-assert.h:60:12: error: ‘val’ may be used uninitialized [-Werror=maybe-uninitialized]
   60 |         if (!cond)                                                              \
      |            ^
../../git/weston/tests/weston-test-assert.h:153:34: note: in expansion of macro ‘weston_assert_’
  153 | #define test_assert_f32_eq(a, b) weston_assert_(NULL, a, b, float, "%.10g", ==)
      |                                  ^~~~~~~~~~~~~~
../../git/weston/tests/string-test.c:97:9: note: in expansion of macro ‘test_assert_f32_eq’
   97 |         test_assert_f32_eq(val, 0.0);
      |         ^~~~~~~~~~~~~~~~~~
../../git/weston/tests/string-test.c: In function ‘wrapstrtof_conversions’:
../../git/weston/tests/string-test.c:94:15: note: ‘val’ was declared here
   94 |         float val;
      |               ^~~

The debug build did not complain.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-16 15:19:02 +00:00
Pekka Paalanen
6af97ec150 tests/paint-node: fix false-positive uninitialized variable
GCC 14.2 with debugoptimized build complained:

../../git/weston/tests/paint-node-test.c: In function ‘get_paint_node_status’:
../../git/weston/tests/paint-node-test.c:105:16: error: ‘changes’ may be used uninitialized [-Werror=maybe-uninitialized]
  105 |         return changes;
      |                ^~~~~~~
../../git/weston/tests/paint-node-test.c:87:39: note: ‘changes’ was declared here
   87 |         enum weston_paint_node_status changes;
      |                                       ^~~~~~~

The debug build did not complain.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-16 15:19:02 +00:00
Pekka Paalanen
66eaeb0c3f tests/fifo: fix false-positive uninitialized width
GCC 14.2 with debugoptimized build complained:

../../git/weston/tests/fifo-test.c: In function ‘get_surface_width’:
../../git/weston/tests/fifo-test.c:493:16: error: ‘width’ may be used uninitialized [-Werror=maybe-uninitialized]
  493 |         return width;
      |                ^~~~~
../../git/weston/tests/fifo-test.c:477:13: note: ‘width’ was declared here
  477 |         int width;
      |             ^~~~~

The debug build did not complain.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-16 15:19:02 +00:00
Pekka Paalanen
92c15464aa tests/client-buffer: fix false-positive uninitialized variables
GCC 14.2 with debugoptimized build complained:

../../git/weston/tests/client-buffer-test.c: In function ‘y_u_v_create_buffer’:
../../git/weston/tests/client-buffer-test.c:1045:33: error: ‘u_row’ may be used uninitialized [-Werror=maybe-uninitialized]
 1045 |                                 x8r8g8b8_to_ycbcr8_bt709(argb, y_row + x,
      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1046 |                                                          u_row + x / pixel_format_hsub(buf->fmt, 1),
      |                                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1047 |                                                          v_row + x / pixel_format_hsub(buf->fmt, 1));
      |                                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../git/weston/tests/client-buffer-test.c:986:18: note: ‘u_row’ was declared here
  986 |         uint8_t *u_row;
      |                  ^~~~~
../../git/weston/tests/client-buffer-test.c:1045:33: error: ‘v_row’ may be used uninitialized [-Werror=maybe-uninitialized]
 1045 |                                 x8r8g8b8_to_ycbcr8_bt709(argb, y_row + x,
      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1046 |                                                          u_row + x / pixel_format_hsub(buf->fmt, 1),
      |                                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1047 |                                                          v_row + x / pixel_format_hsub(buf->fmt, 1));
      |                                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../git/weston/tests/client-buffer-test.c:987:18: note: ‘v_row’ was declared here
  987 |         uint8_t *v_row;
      |                  ^~~~~

The debug build did not complain.

Even though only u_row and v_row were reported, I don't understand why
there is no warning about u_base and v_base, as they are initialized
with a similar switch. So initialize them too, just in case.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-16 15:19:02 +00:00
Pekka Paalanen
c23d028300 libweston: fix false-positive uninitialized variables sx, sy
GCC 14.2 with debugoptimized build complained:

../../git/weston/libweston/input.c: In function ‘weston_pointer_set_focus’:
../../git/weston/libweston/input.c:1988:29: error: ‘sx’ may be used uninitialized [-Werror=maybe-uninitialized]
 1988 |                 pointer->sx = sx;
      |                 ~~~~~~~~~~~~^~~~
../../git/weston/libweston/input.c:1913:20: note: ‘sx’ was declared here
 1913 |         wl_fixed_t sx, sy;
      |                    ^~
../../git/weston/libweston/input.c:1989:29: error: ‘sy’ may be used uninitialized [-Werror=maybe-uninitialized]
 1989 |                 pointer->sy = sy;
      |                 ~~~~~~~~~~~~^~~~
../../git/weston/libweston/input.c:1913:24: note: ‘sy’ was declared here
 1913 |         wl_fixed_t sx, sy;
      |                        ^~

Initialize with an arbitrary value to avoid the warning. This value
should never make it outside of this function.

The debug build did not complain.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-16 15:19:02 +00:00
Pekka Paalanen
6955752b95 doc: fix Meson warning about install_subdir
../../git/weston/doc/sphinx/meson.build:97: WARNING:
Project targets '>= 0.63.0' but uses feature deprecated since '0.60.0':
install_subdir with empty directory. It worked by accident and is buggy.
Use install_emptydir instead.

I get the above warning on a clean build, because the directory in
question is empty at configure time. It gets populated at compile time.

Having to exclude one file from the build complicated fixing this.
custom_target() does not support install-excludes, and it looks like
Sphinx does not allow locating the buildfile elsewhere. One option would
be to use a meson.add_install_script() to delete the unwanted file after
it has been installed, but this seemed more complicated than the
solution I chose.

The intermediate build directory name needs to change from 'doc' to
'weston', so that I don't need to strip_directory which custom_target
does not support. The 'output' array in custom_target() also does not
allow outputs to be speficied in sub-directories.

The sh script is tidied up a little bit with set -e, otherwise it would
have become unreadable.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-16 15:19:02 +00:00
Marius Vlad
c0a6b7c1c9 gitlab-ci: Switch to using Bookworm (LTS) for doing code coverage
The initial step from gcov/lcov gives a few parsing errors like
'mismatched end line' or 'mismatched exception tag for'.

Been trying with llvm-cov, downgrading to gcc-13 and using different
gcov versions including one from oldoldstable -- I'm repeatably getting
these errors.

I turned instead of the idea to use our previous stable version, now the
oldstable/LTS as that was capable of doing code coverage.  So possibly
either gcc-13 is the first version that causes these issues but we're
having gcc-14 in Trixie so it doesn't really matter. For now use this
work-around until we have something better.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-16 11:46:39 +00:00
Marius Vlad
1e55fd2449 gitlab-ci: Bump CI to Trixie and LTS to bookworm
This includes a few changes, but given that we still want to bisect
things when they break I'm pulling some of the changes into a bigger change.

Here's a list of most noticeable that I had to address in order to make
this switch:

- added a PACKAGES_SPECIFIC env variable to able to pass different
  packages to each version. Some packages basically changed their names
  and need to pass a different name
- added USE_DEBIAN_BACKPORTS and use it when adding -backport apt
  sources for each Debian version
- llvm-19 now requires some additional packages for trixie
- add imghdr for sphinx for trixie
- had to keep use_tls=0 and modified the notes to point now to Trixie
  instead of Bookworm

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-16 11:46:39 +00:00
Derek Foreman
0680683539 input: Don't refocus clients when pointer moves against boundary
If we don't clamp the input before updating the pointer surface coords,
we'll trigger the "surface jumped beneath us" logic later when the clamp
really happens. That leads to spurious pointer leave/enter events.

Add clamping to weston_pointer_send_motion() to fix this.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 09:22:05 +00:00
Derek Foreman
613558e69e input: refactor weston_pointer_move_to
Pull the clamping out and expose an internal pre-clamped function, which
will be used elsewhere in a later commit.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 09:22:05 +00:00
Derek Foreman
d830ce962a input: move some pointer functions
These will be used earlier in the file soon, move them now.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 09:22:05 +00:00
vorlunez
025f5a7c45 input: fix setting hint_is_pending
when the hint_is_pending is true, it should assign the hint_pending to the hint and set the hint_is_pending to false, but the hint_is_pending set to true again after setting to false.

remove the redundant line to fix this.

Signed-off-by:  Vorlune Zhang <Vorlune.Zhang@gmail.com>
2025-12-16 15:16:15 +08:00
Marius Vlad
582ae5385b xwayland: Fix some memory leaks on compositor shutdown path
While exiting, on the shutdown compositor path, for instance if we don't have
permission access to create a lock file we will end up reporting some memory
leaks/use-after-free.

This patch addresses of all them:

- api->listen returns NULL and we do not property free wet_xwayland
  struct
- we don't remove the signal handler causing a use-after-free (signal
  handler gets called by the main object has been freed)
- we don't remove/destroy the debug scope causing a mem-leak
- on the same path check for valid event source to avoid deref invalid
  pointers.

Add a simple wrapper which we can call in other call sites.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-15 11:35:04 +02:00
Daniel Stone
119ce40714 drm-backend: Reuse prior state where possible
If we're in a steady state, doing nothing but flipping buffers, we can
try to avoid going through our full routine of brute-forcing an
acceptable plane state, by instead just reusing the old state and
changing only the FB it refers to.

Signed-off-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-12 14:09:50 -06:00
Derek Foreman
e2cda4570e drm/state-propose: Store the type of proposed state
Keeping track of what mode we prepared the state in will be useful
for printing debug information later, when we have a way to reuse
old state.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-12 14:09:50 -06:00
Derek Foreman
eda7e524fd drm/state-propose: Add an invalid state
We're going to add a way to reuse state, but we don't currently have a way
to represent invalid state - such as before we've ever commit any state
at all.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-12 14:09:50 -06:00
Derek Foreman
aefdbb0278 drm: Move enum drm_output_propose_state_mode into internal header
This is in preparation for storing the mode with the state later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-12 14:09:50 -06:00
Derek Foreman
57ad320d86 drm: Refactor some debug statements
These have the same form, and we're about to add a few more with the same
form again, so make a helper function.

This sweeps up the one weird one that printed [view] while failing [state].

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-12 14:09:50 -06:00
Derek Foreman
87776413ba drm: Add whether planes are enabled or not to the drm output state
This will be handy later when trying to determine when it's ok to reuse
output state, as changing this would invalidate previous state.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-12 14:09:50 -06:00
Marius Vlad
2bb8cdba83 backend-drm: Initialize bo_fd
On some aarch64 platforms with GCC13 we're seeing:

../../../weston-14-new/libweston/backend-drm/fb.c:152:15: warning: 'bo_fd' may be used uninitialized [-Wmaybe-uninitialized]
  152 |         ret = drmPrimeFDToHandle(fb->fd, bo_fd, &handle);
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../weston-14-new/libweston/backend-drm/fb.c: In function 'drm_fb_addfb':
../../../weston-14-new/libweston/backend-drm/fb.c:117:13: note: 'bo_fd' was declared here
  117 |         int bo_fd;

Just initialize it to avoid trigger the warning.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-12 11:39:55 +02:00
Robert Mader
42aeea2220 gitlab-ci: Bump kernel to 6.18
The first stable release with everything required to let our tests pass.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-12-10 13:18:14 +01:00
Alyssa Ross
54217f5d88 frontend: don't require XDG_RUNTIME_DIR
Recent versions of libwayland support absolute paths in display names,
and in that case do not require XDG_RUNTIME_DIR to be set.  It's
therefore overly strict for Weston to exit due to XDG_RUNTIME_DIR being
unset when it would work perfectly fine without it.  The messages
displayed for incorrectly set XDG_RUNTIME_DIR are useful though, so keep
them around, but only display them if wl_display_add_socket() fails
i.e. the lack of XDG_RUNTIME_DIR has actually caused a problem.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-12-09 11:46:01 +02:00
Alyssa Ross
85315c4841
backend-headless: fix undeclared FALSE identifier
It looks like FALSE is only used in a few files in Weston, whereas false is much
more commonly used.  Presumably FALSE comes from some library not included in
the headless backend (at least in my case).

	FAILED: [code=1] libweston/backend-headless/headless-backend.so.p/headless.c.o
	gcc -Ilibweston/backend-headless/headless-backend.so.p -Ilibweston/backend-headless -I../../home/qyliss/src/weston/libweston/backend-headless -I. -I../../home/qyliss/src/weston -Iinclude -I../../home/qyliss/src/weston/include -Ilibweston -I../../home/qyliss/src/weston/libweston -Iprotocol -I/nix/store/mvhj7fm6bkmz6ismdp8vcmwn34w94b8n-libglvnd-1.7.0-dev/include -I/nix/store/v7jn3cy1wjaf9pm60ix9y6dfma0bj4a3-wayland-1.24.0-dev/include -I/nix/store/xi04j07bl6bbckky5n8a1k06spxxfg9i-pixman-0.46.4/include/pixman-1 -I/nix/store/xvzhnfwxvl480qpjxm83wwhd287b3lgm-libxkbcommon-1.11.0-dev/include -I/nix/store/22qgb8p593613861117ay4gzmf9b7rns-libdrm-2.4.125-dev/include -I/nix/store/22qgb8p593613861117ay4gzmf9b7rns-libdrm-2.4.125-dev/include/libdrm -I/nix/store/zl58kqaf677skihj840rf05svsmrhmmc-cairo-1.18.4-dev/include/cairo -I/nix/store/6sscd9xxffhjrci2xbw9yv8inc2rc0ry-freetype-2.13.3-dev/include/freetype2 -I/nix/store/6sscd9xxffhjrci2xbw9yv8inc2rc0ry-freetype-2.13.3-dev/include -I/nix/store/z88mxig65mxgyn1yxsz92m4w1rn51aci-libpng-apng-1.6.50-dev/include/libpng16 -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Wpedantic -std=gnu11 -O0 -g -Wmissing-prototypes -Wno-unused-parameter -Wno-shift-negative-value -Wno-missing-field-initializers -Wno-pedantic -Wundef -fvisibility=hidden -Wmissing-prototypes -Wno-unused-parameter -Wno-shift-negative-value -Wno-missing-field-initializers -Wno-pedantic -Wundef -fvisibility=hidden -fPIC -MD -MQ libweston/backend-headless/headless-backend.so.p/headless.c.o -MF libweston/backend-headless/headless-backend.so.p/headless.c.o.d -o libweston/backend-headless/headless-backend.so.p/headless.c.o -c ../../home/qyliss/src/weston/libweston/backend-headless/headless.c
	../../home/qyliss/src/weston/libweston/backend-headless/headless.c: In function ‘config_init_to_defaults’:
	../../home/qyliss/src/weston/libweston/backend-headless/headless.c:788:29: error: ‘FALSE’ undeclared (first use in this function)
	  788 |         config->fake_seat = FALSE;
	      |                             ^~~~~
	../../home/qyliss/src/weston/libweston/backend-headless/headless.c:788:29: note: each undeclared identifier is reported only once for each function it appears in

Fixes: 0126a5b4 ("backend-headless: Add an option to enable a fake seat")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-12-09 09:41:52 +01:00
Alyssa Ross
e4a51996d8
libweston: fix error message for missing PAM
The helpful error message with the hint to set -Dbackend-vnc=false was
unreachable, because libpam would either be found, or the default, less
helpful error message for a missing library would be shown.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
2025-12-08 14:56:49 +01:00
Olivier Fourdan
0126a5b4fc backend-headless: Add an option to enable a fake seat
When running headless, weston will not expose a wl_seat.

This was removed with commit a1046adc ("compositor-headless: do not
create a seat").

However, some applications, namely GTK3 based, will log a warning when
there is no wl_seat:

 | gdk_seat_get_keyboard assertion GDK_IS_SEAT(seat) failed

While this is arguably a bug in GTK3 which should not complain with a
legit setup, that breaks the CI of those projects when using Weston,
while most of the other Wayland compositors will create a fake seat when
running headless, making weston the odd ball there.

This changes adds a new option "--fake-seat" that will instruct weston
to create a seat when running headless. The default remains not to
create a seat though, so backward compatibility is preserved.

This partially reverts commit a1046adc66.

See-also: https://gitlab.freedesktop.org/ofourdan/xwayland-run/-/issues/12
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
2025-12-08 11:44:27 +01:00
Derek Foreman
cb97abd4f7 compositor: Add the fifo-v1 protocol
Add support for the fifo protocol, which allows an application to submit
a content update that can only be applied after the previous content
update has been active for a display refresh.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 14:03:13 -06:00
Derek Foreman
23204eca75 tests: Bind the fifo protocol
Add the fifo protocol to the helper framework.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 14:03:13 -06:00
Derek Foreman
f50296d4e9 compositor: Add a deferred content update framework
Now that we have surface-state application streamlined, it's fairly easy to
add a framework for deferring content updates.

This will be used soon for fifo and commit timing. For now, the
weston_surface_state_ready() call that makes any of this do something
will always return true.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 14:03:10 -06:00
Derek Foreman
73e0bb2829 compositor: Try to remove some unnecessary repaints
If a surface isn't visible, there's no point in performing a repaint when
its state changes. However, we don't know if a surface is visible until
we perform the scene graph updates at repaint.

Use our new visibility tracking API to check whether we need to perform
a repaint, or if we can just skip it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 13:55:23 -06:00
Derek Foreman
61134fa151 compositor: Track view and surface visibility per output
Keep track of whether a view has any unoccluded pixels on an output,
use this information to add a weston_surface_visibility_mask() function
that we'll use later.

Since the visibility information is calculated at repaint, and invalidated
by some (but not all) state updates, we'll keep track of when the previous
repaint's status is still valid by watching surface status bits.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 13:55:20 -06:00
Derek Foreman
6a280a8fad compositor: Push subsurface order application into apply_state
Seems like it makes sense to have it there, and this cleans up a bunch of
paths where we return status bits so a caller can do this.

We can also drop the explicit setting of view_list_needs_rebuild, as it's
going to happen automatically when applying subsurface order.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Derek Foreman
7bfedba650 compositor: move weston_surface_schedule_repaint into surface-state.c
Only user is there, so move it across.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Derek Foreman
08f9d791b5 tests: Refactor get_presentation
In the future more than one test group will want to use presentation
feedback, so let's pull the basics into weston-test-client-helper

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Derek Foreman
5eb5c4991d tests: Refactor get_subcompositor
We open code this in several tests. Move a single implementation to
weston-test-client-helper instead.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Derek Foreman
e4be014f93 compositor: Add an explicit latch point
Latch is the moment when the compositor considers updates for an upcoming
redraw. Nothing that takes place after an output latches for repaint can
change what will be repainted.

This needs a more explicit treatment now that upcoming transactional
protocols require things to happen immediately after the latch (ie:
when it's too late to change the upcoming render).

Add an explicit latch point, a signal to tap for testing, and some asserts
to make sure nothing can violate the inevitability of the current render
state.

Note that currently latch is tied to repaint such that we only claim to
have latched when a repaint will happen. In a future commit this will lead
to forcing the repaint loop to fire without damage when the fifo protocol
needs something to happen after a latch. This could be an area for
future improvement.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Derek Foreman
b700c7cbee compositor: Add flow id into surface state
We're going to be adding protocols (commit-timing, fifo, syncobj) that
allow deferred surface content updates.

It makes sense to start the perfetto flow ids from the surface state so
we can track a flow from creation (ie:commit) to presentation.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Derek Foreman
5e0099ddbb compositor: Dispatch feedback for all content updates
This was discussed in wayland-protocols MR 273, and clarified in wayland
MR 379 - presentation feedback applies to content updates, not buffers.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Marius Vlad
7bb3a7b969 shell-utils: Ensure committed_private is set
This ensures (an unlikely) cases where get_label might be called and the
callback itself would makes use committted_private to retrieve callback
data. Just make sure to set it prior.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-04 11:41:52 -06:00
Pekka Paalanen
015d73cb54 tests: bail on dispatch failure
Originally the test-asserts were abort()'ing. Then they were changed to
record the failure but not abort() anymore. These loops were missed,
accidentally turning them into endless loops on Wayland connection
failure, e.g. a protocol error.

When then loops become endless, they will repeatedly print the assertion
failure message. When run as part of the test suite via Meson, Meson
will collect all printouts in memory. Therefore the meson process will
use memory rapidly without bounds.

Break all these loops.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-04 18:20:27 +02:00
Marius Vlad
4b61e44ad1 gitlab-ci/leak-sanitizer: Add libpangoft2/glib to leak suppression
With the future bump to Trixie we have a few more leaks outside of the
Weston test suite. Add them to leak suppresion file.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-02 18:27:15 +02:00
Marius Vlad
a691dc51d2 tests: Address compilation warns/error on arm32 (format)
Switch to using inttypes for addressing compliation errors on other
platforms (arm32).

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-02 18:27:12 +02:00
Marius Vlad
9215a537e0 compositor: Move repaint_status out of weston_output
To accommodate some future CI bump to Trixie (doxygen/breathe issue)
move out the anonymous enum out of weston_output object.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-12-02 17:25:14 +02:00
Pekka Paalanen
cfb459c2c9 color-lcms: implement media white point scaling
Implement media white point scaling according to ICC.1:2022 (profile
v4.4), section 6.3.2.2 "Translation between media-relative colorimetric
data and ICC-absolute colorimetric data".

This is a lot of code for something that, under the current
circumstances, is a no-change. However, realizing that chromatic
adaptation and media white point scaling are two separate adjustments
was a revelation to me. I want to document in code how they work, even
if the net result is no-op.

The PCS white point is taken from ICC, it does not matter what non-zero
point it is, the result will be the same.

I did skip a bit the media white point scaling. One should first scale
from in to PCS, and then from PCS to out. The code is mathematically
equivalent. If some new operation needs to be done in between, this step
than be split in two, just like I split the chromatic adaptation step in
two in this patch.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-02 11:46:44 +02:00
Pekka Paalanen
6db55fe7e4 color: export weston_CIExy_to_XYZ()
This will be needed by color-lcms.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-02 11:46:44 +02:00
Pekka Paalanen
6a2ddee844 color-lcms: fix ICC-absolute rendering intent CHAD
According to ICC, chromatic adaptation applies also to ICC-absolute
colorimetric rendering intent.

ICC-absolute and media-relative colorimetric rendering intents are
indeed identical as long as medium white point equals adapted white
point.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-02 11:46:44 +02:00
Pekka Paalanen
4479b3c96d color-lcms: rename white_point_adaptation to chromatic_adaptation
This is the correct name for what is implemented.

The term "white point adaptation" cannot be found in ICC.1:2022 (v4.4)
nor at https://cie.co.at/e-ilv .

Personally I am confused whether it would mean chromatic adaptation or
media white point scaling.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-12-02 11:46:44 +02:00
Derek Foreman
b44cf1b6af animation: Change how we seed the initial time
With the addition of the weston_output_set_ready() call, the shell fade
animation is now started during the very first repaint. The first repaint
doesn't have an accurate frame_time for the previous repaint, as none has
occurred yet.

Since we set the time base for an animation based on the output's frame
time the second time the animation is run, we end up setting the shell fade
start time to 0, and the first real repaint advances the timer to the real
time, generating a warning and truncating the animation.

Instead of tracking the number of animation frames, let's just continue to
reset the time base until we finally get a non-zero time.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-11-24 12:29:15 -06:00
Derek Foreman
9b89e7d94e compositor: Conserve paint nodes that leave outputs
A destroyed paint node must be rebuilt at great cost the next time the
view is displayed on an output.

Keep the paint node around and just remove it from the z order list instead
of destroying it outright.

fixes #1072

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-11-19 10:45:23 -06:00
Marius Vlad
f85008bb86 compositor: Embed the paint node status when rebuilding z-ordered list
As weston_compositor_build_view_list() marks all the outputs needing a
paint node rebuild of the re-order list, embed the paint node status
update to ALL_DRITY into straight into weston_output_build_z_order_list().

This way we'll latch it on the view list rebuild.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-11-19 16:08:16 +02:00
Marius Vlad
881ac6a5cf compositor: De-couple paint node ordered list from the view build list
This de-couples the compositor view build list from the paint node
ordered list to allow a more finer grain over what lists we need to
rebuild upon repaints.

As a consequence to that this avoids a trip over from the compositor
when paint nodes are destroyed and no longer re-created upon rebuilding
the view list.

Fixes: #1070
Fixes: abfe874a ("core: Don't rebuild view list on surface-local changes")

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-11-19 15:47:13 +02:00
Marius Vlad
87d2d3e442 gitlab-ci: Build mesa without GLX
And implicitly remove the need to build autoconf and libx11. Removed wget
and xutils-dev as those are not needed anymore.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-11-19 14:49:12 +02:00
Robert Mader
8da9b0baec gitlab-ci: Bump Mesa to 25.3.0
Let's use a stable release again, now that we can.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-11-17 16:39:10 +01:00
Kurt Kanzenbach
c6484574a6 frontend: Fix VNC mirror screen rotation
The following config allows to mirror the LVDS output to VNC:

|[output]
|name=LVDS-1
|transform=rotate-270
|
|[output]
|name=vnc
|mirror-of=LVDS-1

However, the current code only takes the scale into account, not the
relative transformation. In case of rotate 90 or 270 the width and height
have to be swapped. Add it.

Closes: https://gitlab.freedesktop.org/wayland/weston/-/issues/1076
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
2025-11-17 12:11:42 +00:00
Pekka Paalanen
d69e816b54 compositor: fix finish_frame presentation feedback crash
This was brought up in issue 1063. The assertion in
weston_presentation_feedback_present_list() will trigger randomly during
repeated suspend/resume testing, presumably while a client is animating
and asking for presentation feedback.

drm_output_start_repaint_loop() has a path where drmWaitVBlank() is able
to pull a good timestamp for the last vblank. This results in a call to
weston_output_finish_frame() with a good timestamp and
WP_PRESENTATION_FEEDBACK_INVALID in the flags.

Previously it was assumed that in such case the presentation feedback
list cannot have any entries. This assumption is false. It is possible
that while the output is in idle state, a client will post an update to
a surface and ask for presentation feedback on it. This should trigger
drm_output_start_repaint_loop() with a non-empty feedback list.

It is unclear why this problem was not seen in the wild much more often.

Start-repaint-loop does not present anything by definition, it only acts
to synchronize the output repaint loop with the (hardware) scanout
cycle. Therefore no feedback must be sent there. As
WP_PRESENTATION_FEEDBACK_INVALID flag indicates no feedback must be
sent, use it to avoid calling
weston_presentation_feedback_present_list().

References: https://gitlab.freedesktop.org/wayland/weston/-/issues/1063
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-11-13 11:38:34 +02:00
Erico Nunes
1a868b7244 vulkan-renderer: fix VkMemoryDedicatedRequirements usage
This needs to extend the VkMemoryRequirements2 struct, not
VkImageMemoryRequirementsInfo2.

Fixes: ad0f4cf9 ("vulkan-renderer: make dmabuf import dedicated allocation optional")

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-11-07 14:30:29 +01:00
Pekka Paalanen
12334b3e75 tests: break out on client_capture_output() error
If the Wayland connection died, this code path ended up in an endless
loop, because test-asserts do not abort. Break out to fix this. The
test-assert records the failure, so not need to do more.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-11-06 16:02:37 +02:00
Daniel Stone
65554abd88 screenshooter: Emit warning for output recording
Deprecate the screenshooter recording mode, with the intention of
removing it in libweston 16. Using the PipeWire backend (or similar) is
a far better and more flexible way of capturing output content.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-28 07:55:43 +00:00
Daniel Stone
6d18e86b06 backend-drm: Deprecate DRM VA-API recorder
The DRM backend has had a VA-API recorder for a while, which pushes the
frames from every redraw into libva for compositor-side recording.

Implementing this manually in the compositor, and configuring it, is
kind of pain. We now have the PipeWire backend which can do
screencasting in a much more flexible way without having to push
everything into the compositor itself, and without having to hardcode
support for one particular encoder framework.

Deprecate this module with the intention of removing it in the Weston 16
cycle, along with screenshare (for similar reasons).

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-28 07:55:43 +00:00
Erico Nunes
53895cac2f vulkan-renderer: support fragment debug binding
Add a debug binding and mode to highlight (green tint) what has
been rendered through vulkan-renderer composition. This is useful
to visually identify/debug clients which have been offloaded to
DRM planes, since those won't go through the renderer composition
process and therefore won't be highlighted the same way.
Since this is the first debug mode in vulkan-renderer, add some
initial infrastructure to handle debug bindings.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-10-28 07:43:53 +00:00
Erico Nunes
68d3d3badc vulkan-renderer: fix pipeline specialization constant offsets
The VkSpecializationMapEntry use was incorrect here, it requires the
struct offset to be in the second entry.

Fixes: 8f56d03d ("libweston: Vulkan renderer")

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-10-28 07:43:53 +00:00
Marius Vlad
7fa306dd81 ivi-shell: Remove black curtain/set output ready in HMI controller
This is basically a revert of 6f94022e ("ivi-shell/layout: Create a
temporary background curtain") to remove the blank/blank
curtain in ivi-shell and use the weston_output_set_ready to notify the
compositor that it is start issueing repaints.

Introduces a new callback in ivi-layout which controllers can call on
their own.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-10-27 05:55:51 +00:00
Derek Foreman
777a52ef4d Revert "desktop-shell: Add a placeholder curtain on new outputs"
This reverts commit 0ff5ac0f7b.

Now that we have a way to prevent repaints of empty scene graphs from
the shells, remove the curtains and just have our first paint be
proper content.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-27 05:55:51 +00:00
Derek Foreman
0bfcb700b9 compositor/shells: Require shells to flag outputs as ready to allow repaint
We've added a curtain to the shells so at startup we have something to
render, but this causes a flicker if someone is trying to have a seamless
transition from boot to weston.

Add a ready flag that allows the shell to indicate repaints are safe, so
we can remove the curtains and have no wasted frames at startup.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-27 05:55:51 +00:00
Marius Vlad
683d7df164 simple-shm: Allow to make simple-shm fullscreen with just the keyboard
Similarly to simple-egl, teach simple-shm to also do that if pressing
F11. Allows testing stuff much easier -- without installing key-bindings
in the shell.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-10-24 22:31:39 +01:00
Derek Foreman
6070dd8069 compositor: Add a WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY
This already existed for surface, so it is trivial to add.

This will let the upcoming plane state reuse code notice a format change.

This is handy because a client might respond to dmabuf feedback by changing
formats, with the expectation that doing so would land content on a plane.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-23 16:22:00 +01:00
Derek Foreman
008884f289 compositor: Move dirty buffer handling to paint node early update
This was in the late update because attaching buffers is something only
the renderer cares about.

However, the upcoming drm plane state re-use patches need to know if the
buffer changed before assign_planes, so we need this in the early update.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-23 16:22:00 +01:00
Daniel Stone
6155981cc6 drm: No longer force the use of the first cursor fb
The assert added in 78657c5ff3 will cause
problems when we try to reuse cached drm plane layouts in the future -
instead of asserting on an exact gbm fb, assert that the the fb type
corresponds has the cursor type instead.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-23 16:22:00 +01:00
Daniel Stone
58614d4f5b drm-backend: Add separate type for dmabuf renderbuffers
Although Vulkan's renderbuffers are dmabufs, the difference between a
client dmabuf and a backend-allocated dmabuf is a very meaningful one.
Add a separate buffer type for BUFFER_DMABUF_BACKEND instead of
overloading BUFFER_DMABUF for this.

This tangentially allows the Vulkan renderer to do direct scanout of
client buffers in mixed mode.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-23 16:22:00 +01:00
Robert Mader
b688767680 backend-drm: Allow plane-less DRM background for opaque black solid buffers
The DRM documentation states:
> Unless explicitly specified (via CRTC property or otherwise), the active
> area of a CRTC will be black by default. This means portions of the active
> area which are not covered by a plane will be black, and alpha blending of
> any planes with the CRTC background will blend with black at the lowest zpos.

See https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#plane-abstraction

This means the view for the primary plane does not need to cover the
whole output and black areas of the scene-graph can be left out.
Doing so has various benefits - most importantly it:
1. allows us to use the plane-only path in more situations and with one
less plane, reducing memory bandwidth usage.
2. opens the path to offload arbitrary background colors in the future.

Iterate over the all visible paint nodes, remove solid-opaque-black
views so they are not considered for plane assignment and aggregate a
region that is later used to assign the primary plane.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-23 12:40:37 +02:00
Robert Mader
fcb4c2a85b tests/drm-offload: Add additional tests
For changes in the next commit.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-22 10:52:14 +02:00
Robert Mader
c7cdcedbf0 backend-drm: Build scene-graph before assigning planes
So far scene-graph building and plane assignment happened within a single
loop. In the future we want to be able to optimize the scene-graph
before assigning, thus split up the loop into two steps.

No behavioral changes intended.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-22 10:43:14 +02:00
Roland Kaufmann
564f6687eb backend-rdp: Add keyboard mapping for alternate Dvorak layouts
This changeset adds three variants of the U.S. Dvorak layout to the
table that is used to map a keyboard ID in the RDP backend to an Xkb
configuration. This makes it possible to have these variants
propagated seamlessly from an RDP client into the Wayland compositor.

As the backend-rdp module requires at least version 2.3.0 of the
FreeRDP library to build, the symbols for these variants is already
present in include/freerdp/locale/keyboard.h, included by rdp.h here,
and in libfreerdp/locale/xkb_layout_ids.c which translate the selected
layout in Xkb into the keyboard ID sent over the wire for the RDP
protocol.

Signed-off-by: Roland Kaufmann <rlndkfmn+freerdp@gmail.com>
2025-10-21 23:21:55 +01:00
Derek Foreman
c9a6e2721a gl-renderer: Fix up solid buffer attachments
We've been clobbering non-solid buffers with solid buffer attachment in
situations where we override the real buffer with a placeholder.

If the reason (punch hole, censor) that led to the placeholder is no
longer in effect, and new buffer is attached, we won't render what we should.

Instead, let's not attach anything for the paint node draw_solid case, and
allow gl_buffer_state be NULL when the real buffer is solid. gl_buffer_state
can then always be the correct state for the real buffer, even if we don't
use it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 13:56:30 -05:00
Derek Foreman
37a427e4e0 gl-renderer: Set up solids in config_init
Instead of overriding solid draws later on, just set them up in the
init function.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 13:54:59 -05:00
Derek Foreman
727d976e3c gl-renderer: Make prepare_solid_draw stand alone
Currently it uses some values from the existing sconf, instead let's make
it calculate everything on its own

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 13:54:59 -05:00
Derek Foreman
095f511d53 gl-renderer: split out textured draw setup
Refactor textured draw setup into a separate function, preparing for a
future where we set up solid draws from init_for_paint_node as well.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 13:54:21 -05:00
Derek Foreman
37db081f82 gl-renderer: Set texture filters before setting input textures
Turns out gl_shader_config_set_input_textures is what adds the filter
parameters to the sconf, so we must set the filters before calling it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 13:53:37 -05:00
Derek Foreman
21f1c575b3 tests: Add a semi-transparent single pixel buffer test
Now that we have a glClear() region optimization for opaque solid surfaces,
we should make sure we test transparent solid surfaces as well.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 13:53:34 -05:00
Robert Mader
26cab9d562 backend-drm: Use pre-calculated pnode regions from the compositor
Instead of doing duplicated calculations. Apart from being faster and
less code, it should help ensuring correctness of the given regions.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-21 11:00:32 -05:00
Robert Mader
485e1796af compositor: Fixes for the opaque region
is_fully_opaque notably applies to opaque single-pixel-buffer views
without opaque region. Using it should be purely an optimization.
The check for alpha in turn may fix bugs in certain conditions.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-21 16:43:40 +02:00
Derek Foreman
e8b2033d82 compositor: Better instrument transform updates
Let's just make them show up in the perfetto traces when they actually
happen, so it's a little easier to see how much benefit we derive from
trying to defer them.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 08:54:13 -05:00
Pekka Paalanen
d4e39210a3 color-lcms: optimize build_3d_lut()
Previously, inverse_evaluate_lut1d was called 3 * len^3 times. Now it is
called only 3 * len times with the help of pre-computed arrays for red
and green channels. Blue channel does not need an array, because there
were no redundant computations. This is a significant win.

Also, allocate a temporary array rgb_in, so cmsDoTransform() can be
called in batches of len triplets. This seemed to be not that big win. I
tried running cmsDoTransform() over len^2 triplets, but that did not
seem to improve performance.

The test I used creates two 3D LUTs, hence two times for a single run.
My representative timing test results per one 3D LUT:
- before: 16 ms and 19 ms
- after: 7 ms and 10 ms

The measurements were done with this patch:

 static bool
 xform_to_shaper_plus_3dlut(struct weston_color_transform *xform_base,
 			   uint32_t len_shaper, float *shaper,
 			   uint32_t len_lut3d, float *lut3d)
 {
 	struct cmlcms_color_transform *xform = to_cmlcms_xform(xform_base);
 	struct weston_compositor *compositor = xform_base->cm->compositor;
 	bool ret;
+	struct timespec begin, end;
+	unsigned i;

-	ret = build_shaper(xform->lcms_ctx, xform->cmap_3dlut,
+	clock_gettime(CLOCK_MONOTONIC, &begin);
+	for (i = 0; i < 100; i++)
+		ret = build_shaper(xform->lcms_ctx, xform->cmap_3dlut,
 			   len_shaper, shaper);
 	if (!ret)
 		return false;

-	ret = build_3d_lut(compositor, xform->cmap_3dlut,
+	for (i = 0; i < 100; i++)
+		ret = build_3d_lut(compositor, xform->cmap_3dlut,
 			   len_shaper, shaper, len_lut3d, lut3d);
 	if (!ret)
 		return false;
+	clock_gettime(CLOCK_MONOTONIC, &end);
+	fprintf(stderr, "%s: %" PRId64 " ms\n", __func__, timespec_sub_to_msec(&end, &begin));

 	return true;
 }

Using this command:

$ ./tests/test-color-icc-output -f 8 opaque_pixel_conversion

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-21 14:23:37 +03:00
Pekka Paalanen
f69bb08738 color-lcms: constify build_3d_lut()
These arrays are read-only here.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-21 14:23:37 +03:00
Pekka Paalanen
33ee2c9fb4 color: make 3x1d.fill_in populate a vec3 array
This removes the API impedance mismatch between
weston_color_curve_sample() and weston_color_curve_to_3x1D_LUT() that
was temporarily introduced in the previous commit. That mismatch is now
limited to gl_color_curve_lut_3x1d().

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-21 14:23:37 +03:00
Pekka Paalanen
120b88aa0a color: run vec3 through weston_color_curve_sample()
Future development will need to evaluate pipelines with curves and
matrices. Such pipelines naturally operate on vec3, as matrices cannot
be operated one channel at a time. Make weston_color_curve_sample()
operate on arrays of vec3.

Its currently only caller, weston_color_curve_to_3x1D_LUT(), is modified
to employ a temporary array for the API impedance mismatch. This
workaround will be removed later as weston_color_curve_to_3x1D_LUT()
itself will be converted to operate on vec3 arrays.

weston_v3f_array_to_planar() documentation was generated with AI.

weston_color_curve_sample() is restructured a little bit, attempting to
make it simpler to read.

color-operations.h gets the #includes needed to make it self-standing.

Assisted-by: Github Copilot (Claude Sonnet 3.5)
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-21 14:23:37 +03:00
Pekka Paalanen
e87eb19877 color,gl-renderer: handle neg. in linpow/powlin
We can handle the mirroring for negative input without conditional this
way. Maybe it's faster, maybe it's not, but I like this style better.

In color-operations we need only one call to the elementary function
rather than two. This helps a lot with code clarity, when we get a vec3
at a time to handle in the future, doing three trivial calls instead of
six with an if-else hassle.

fragment.glsl sheds one layer of function wrapping, which is nice.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-21 14:23:37 +03:00
Elliot Chen
bef29b8774 libinput: support ignoring all libinput-based input devices by configuration
For some cases such as remote control, need to disable the interaction
between input device and the weston. It will not affect the use of input
device by other modules or applications.

Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
2025-10-21 12:54:42 +03:00
Victoria Brekenfeld
11f7273545 cliients/dnd: Fix self-only mode
Signed-off-by: Victoria Brekenfeld <github@drakulix.de>
2025-10-21 05:47:29 +00:00
Derek Foreman
8591578090 compositor: Update view transform when setting surface size
since abfe874a51 we no longer do a full view list rebuild after a
surface_set_size(), but that was ensuring we always had an up to
date transform in the repaint loop.

Add a weston_view_update_transform() here to dodge the assert in
the repaint loop.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-20 12:51:34 -05:00
Derek Foreman
3ec1e38a62 compositor: Remove obsolete clip region calculation
This was missed in e169b77430
when leaving planes in the scene graph meant we no longer needed
to calculate this clip.

It's just a few wasted cycles, so no backport required.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-20 12:00:53 +01:00
Derek Foreman
58298e2346 compositor: store and use a clipped view in the paint node
Instead of clipping the visible region to the output, clip the entire
region to the output first and save that, then create the visible region
from that.

Now we have both the clipped and visible view regions that the backends
may want to do plane assignment stored in paint nodes, so we can save
some duplicate math.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-20 12:00:53 +01:00
Derek Foreman
48aaf6434d compositor: Move visibility update to before assign_planes
Assign planes in the future could benefit from visibility information on
pnodes being up to date.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-20 12:00:53 +01:00
Derek Foreman
3bd055145b compositor: turn paint_node->visible_next into visible
This is a step towards having correct visibility information in
assign_planes. Instead of visible_next and visible, we now have
visible_previous and visible, with visible being set up in the
visibility update function instead of being copied across in
the late update.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-20 12:00:53 +01:00
Derek Foreman
de0527bce0 compositor: Pass region to paint_node_damage_below()
In the future I plan to move the paint node visibility calculation, and
in doing so the different callers to paint_node_damage_below() will have
different visibility regions.

Add the region as a parameter.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-20 12:00:53 +01:00
Derek Foreman
2abd161023 tests: Add tests for scaled single pixel buffers
Now that we're validating that buffer size must be an integer multiple of
scale, add some tests to make sure it's happening.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-18 11:51:05 -05:00
Derek Foreman
dc27dd7e95 compositor: Validate buffer scale
We're supposed to generate an INVALID_SIZE error if the buffer size isn't
an integer multiple of the scale.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-18 11:51:05 -05:00
Derek Foreman
8cdf3fb709 compositor: Make convert_size_by_transform_scale static inline
It's a tiny function, instead of exporting for test let's just inline it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-18 11:51:05 -05:00
Derek Foreman
5a3f3c7ca7 desktop-shell: Force scale to 1 for single pixel buffer
Now that we use single pixel buffer, we need to be careful to only use
scale of 1, as other scales are supposed to generate an INVALID_SIZE
protocol errors (because the buffer size is not an integer multiple
of the scale).

Right now a bad scale just breaks background repaints, but in the future
we'll properly validate scale, which would cause the shell client to
be disconnected.

Fixes: 6cc8f48cd ("clients: Paint desktop-shell color background with single-pixel-buffer")

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-18 11:51:05 -05:00
Derek Foreman
52503ba9e6 backend-drm: Add EDID parsing for 'color format'
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-10-18 14:02:16 +01:00
Derek Foreman
2c7fd792b5 frontend: Add support for forcing a color format
Allow dictating which color format we'd like to use. This introduces the
front-end side and the core parts, leaving the EDID parsing and DRM
connector property for later patches.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-10-18 14:02:16 +01:00
Daniel Stone
0664d5bdc1 output: Record paint_node_changes during repaint
When we're going through assign_planes and repaint, give the backend an
opportunity to see what's changed during this repaint.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-17 13:51:05 -05:00
Daniel Stone
7f8c5f984e paint-node: Expose weston_paint_node_status
Expose the dirty status as public API so we can use it as a part of
weston_output.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-17 13:51:04 -05:00
Daniel Stone
abfe874a51 core: Don't rebuild view list on surface-local changes
If a surface changes size or opaque region, or a view changes position,
we don't need to rebuild the entire view list from scratch: we can just
rebuild what's changed and nothing else.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-17 13:49:21 -05:00
Daniel Stone
562a368fbd core: Remove flush_damage_for_plane return
Nothing uses this, and it was also being set incorrectly, as it would
return true when there was no damage to actually be flushed.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-17 13:49:21 -05:00
Robert Mader
64c938f5d6 backend-drm: Use paint_node->draw_solid in more cases
In order to streamline our checks and to make it easier to ensure
that we replace paint nodes with solid placeholders correctly.

Fix the failure reason in one case while on it.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-17 15:56:19 +02:00
Robert Mader
4cb7347407 backend-drm: Use visible_view in more cases
Instead of clipped_view. The former is the part of the later that is
not occluded.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-17 15:19:47 +02:00
Robert Mader
900ab0d39f backend-drm: Rename surface_overlap to visible_view
To clarify its meaning, especially relative to clipped_view.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-17 15:07:46 +02:00
Robert Mader
56aeb48f6d backend-drm: Use paint_node->is_fully_opaque in more places
To streamline our checks and to avoid recomputations.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-17 15:07:46 +02:00
Robert Mader
e9fc189189 paint-node: Consider view-alpha for is_fully_opaque
In order to be more in line with weston_view_is_opaque() - which we
use in most cases to set the value - and ensure the expectations of
existing places in the code are honored, see usages in both
draw_paint_node() implementations.

An exception here are holes - these always need to get painted as fully
opaque in the renderer path.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-17 15:06:11 +02:00
Pekka Paalanen
c2b60e6651 ci: stop checking allow-collaboration
I heard rumoours this is mostly unnecessary to check nowdays since it is
the default.

The real reason is that it crashes sometimes:

$ ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
Traceback (most recent call last):
  File "/usr/lib/python3.12/site-packages/gitlab/exceptions.py", line 344, in wrapped_f
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/gitlab/mixins.py", line 125, in get
    server_data = self.gitlab.http_get(path, **kwargs)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/gitlab/client.py", line 813, in http_get
    result = self.http_request(
             ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/gitlab/client.py", line 779, in http_request
    raise gitlab.exceptions.GitlabHttpError(
gitlab.exceptions.GitlabHttpError: 403: 403 Forbidden
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/bin/ci-fairy", line 8, in <module>
    sys.exit(ci_fairy())
             ^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/click/core.py", line 1161, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/click/core.py", line 1082, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/click/core.py", line 1697, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/click/core.py", line 1443, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/ci_fairy.py", line 1795, in check_merge_request
    mr = p.mergerequests.get(merge_request_iid)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/gitlab/v4/objects/merge_requests.py", line 523, in get
    return cast(ProjectMergeRequest, super().get(id=id, lazy=lazy, **kwargs))
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/gitlab/exceptions.py", line 346, in wrapped_f
    raise error(e.error_message, e.response_code, e.response_body) from e
gitlab.exceptions.GitlabGetError: 403: 403 Forbidden

Observed in https://gitlab.freedesktop.org/elliot_chen/weston/-/jobs/86174879

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-17 09:43:12 +00:00
Derek Foreman
5ee711d374 compositor: Add some comments to paint node members
Just a bit of documentation.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 11:12:13 -05:00
Derek Foreman
9700ec3bc4 gl-renderer: Fix clear optimization
This should be checking for a valid transform so it doesn't use corners
of an axis aligned bounding box for free-form transformed views.

It should still check surf_xform for color management, but it should only
do that when surf_xform_valid is true.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 11:12:13 -05:00
Derek Foreman
992ab893f9 compositor: Validate that paint node holes have planes
If the backend says a hole is necessary, it must assign a plane for it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 11:12:13 -05:00
Derek Foreman
62e76ee5fb compositor/drm-backend: Move censor check into paint nodes
This test is critical, so only do it once, and throw some asserts around
to make sure we don't mess it up.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 11:12:13 -05:00
Derek Foreman
25a281a0a8 drm-backend/gl-renderer: move fully transparent check into paint node
Video underlay "holes" are fully transparent but must be rendered
fully opaque. However, they appear to be fully transparent to
the current gl-renderer test which is missing a need_hole check.

Add a paint node attribute for this so it can be more easily
checked in assign_planes and renderers.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 11:04:31 -05:00
Derek Foreman
99ab4ceaca compositor: Rework paint node update stages to correct recent bugs
Remove maybe_replace_paint_node entirely and place the parts of it
properly between early and late updates.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 10:25:42 -05:00
Derek Foreman
889a564695 compositor: refactor out placeholder color setting
We'll need this in both the early and late paint node updates soon,
so this saves a couple of lines of code.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 10:25:42 -05:00
Derek Foreman
cb49b386f2 compositor: Move paint node validation into a function
We're going to assert on a bunch of stuff, so let's put it in a function
to remove clutter.

For now it's trivial, but I'll be adding more tests shortly.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 10:25:42 -05:00
Derek Foreman
59e2a111fa compositor: Remove is_direct from paint node
It's the same as buffer->direct_display essentially 100% of the time,
except maybe if someone set weston_direct on a single-pixel-buffer, but
that's madness.

Just drop it entirely, and let the only existing reader of the variable
get it from the buffer directly.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-16 10:25:42 -05:00
Daniel Stone
4ebb06a94f tests: Add helper to create solid-filled buffer
At the moment this is only replacing two clear calls with one. However,
when client_buffer starts using properly-bracketed CPU access, this will
become much more tedious. Introduce a helper now to make it easier.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
2259ac4e93 tests: Remove impossible condition
We always have the name of a reference image to compare to; comparison
is kind of impossible without one.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
4843199479 tests: Fix screenshot assert
We need to check the each screenshot once, not one twice.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
c00997979c tests: Support decoration capture for screenshots
It's pretty trivial to make verify_screen_content() and
capture_screenshot_from_output() support decorations, so we can reuse
those in output-decorations tests rather than open-coding.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
fe4cb8a546 tests: Remove open-coded verify_screen_content()
We already have a helper which does exactly this!

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
4d98190a98 tests: Remove open-coded fill_image_with_color()
This did exactly that.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
087315e242 tests: Use buffer for width/height in color-effects
We don't need a pixman_image to get the buffer width and height, so
don't use it.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
2c5dd92533 tests: Use pixman_image_t for get_middle_row()
get_middle_row() is a pure CPU accessor which only needs to operate on a
pixman_image_t. Pass this directly instead of struct buffer.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
42a9a54665 tests: Remove struct buffer len
Unused.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
e2b3ab38bd tests: Set optimal refresh rate for tests
A very marginal benefit, but why not. Any tests using screen capture are
now using a refresh rate of 0 (redraw immediately on capture request),
whilst others are using HIGHEST_OUTPUT_REFRESH.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
ef6747a951 tests: Document default refresh-rate value
Document what the magic refresh-rate values are, and which is set by
default.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-16 11:36:33 +03:00
Daniel Stone
47f1c1e694 ci: Retry on spurious failures
When we fail out because we couldn't even start a container or bring the
runner environment up, just retry the job.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-14 19:14:28 +01:00
Daniel Stone
ec6c67780e ci: Quieten seatd output
seatd is working well, so the debug spew serves only to annoy people
trying to read the logs.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-14 19:10:27 +01:00
Robert Mader
79ade4c165 backend-drm: Ignore views with fully transparent solid buffers
Some client use subsurfaces with fully transparent single-pixel buffers
for various reasons, such as making it easier to order trees of
subsurfaces. As they are invisible we can simply ignore them in the
scene graph.

This allows us to use direct-scanout/plane-only in more circumstances,
as ensured in the test.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-10 16:39:40 +02:00
Derek Foreman
1465362e9f compositor: Move paint node censor into early update
Previously I didn't think we needed this set up before assign_planes, but
certainly in the near future we'll want access to these bits for plane
assignment. It should be harmless to move them all now.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-10 09:15:07 -05:00
Robert Mader
e5cbd8536a tests: Add drm offloading test
Recent improvements to llvmpipe made it possible to test dmabuf import
and offloading on vkms. Use our new client-buffer helper and the
presentation protocol to implement tests for simple offloading
scenarios.

Right now this is limited to the vkms default config, only providing us
with one primary and one cursor plane. In the future we can extend the
test to include more advanced scenarios.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-10 12:53:44 +02:00
Robert Mader
8c4e3b7de5 weston-test-desktop-shell: Use output size for the background
The hardcoded size of 2000x2000 may cause unexpected issues.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-10 12:47:04 +02:00
Robert Mader
3ae7a7b457 weston-test-desktop-shell: Implement desktop_surface_fullscreen_requested()
Add a minimal implementation to allow client to use xdg_toplevel_set_fullscreen().

Note that desktest_shell does not yet properly handle various changes of the surface
state once mapped. Thus we don't handle such cases here either and just
assert on the expected behavior where appropriate.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-10 12:42:49 +02:00
Robert Mader
18076228d3 tests: xdg-client-helper: Add maybe_ack_configure() helper
So users are not forced to use xdg_surface_commit_solid().

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-10 11:47:08 +02:00
Robert Mader
a1c0d33700 tests: client-helper: Add various globals by default
To make them more easily available for tests.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-10 11:47:08 +02:00
Pekka Paalanen
a60169e239 tests: add parametric_color_profile_parsing_errors
This test goes through all the errors one can do in weston.ini
color-profile section, and ensures they give the proper error logging.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-09 16:17:57 +00:00
Pekka Paalanen
a06ef0f8aa tests: add color-output-parsing
This tests the [output] section key 'color-profile', which is meant for
setting up parametric color profiles. It tests the special names, and
fetching values from EDID. There are also tests for all accepted keys in
a [color-profile] section.

These tests are all positive. Error messages are tested in another
patch.

The test client helper changes are needed for loading the EDID file.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-09 16:17:57 +00:00
Pekka Paalanen
d00b758cee tests/color-metadata-error: use weston_color_profile_init()
No reason to open-code this.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-09 16:17:57 +00:00
Leandro Ribeiro
854457524c frontend: allow creating custom param color profiles from .ini
This allow users to specify a fully custom parametric color profile in
weston.ini for a certain output.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
Co-authored-by: Pekka Paalanen <pekka.paalanen@collabora.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-09 16:17:57 +00:00
Pekka Paalanen
360eef9663 color: add weston_color_profile_param_builder_set_target_primaries_named()
The protocol does not carry target primaries by enumeration, but in
weston.ini I want to be able to use a name rather than raw values.
Adding this API makes that possible.

main.c cannot look up the enumeration itself, because color-properties.h
is private. As it should be.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-09 16:17:57 +00:00
Pekka Paalanen
9b68277b77 libweston: export weston_color_profile_param_builder_set_primary_luminance()
All the others were already exported, this was forgotten.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-09 16:17:57 +00:00
Pekka Paalanen
c0f79189dd shared: add safe_strtofloat()
This is for parsing multiple numbers from one weston.ini key, which
means I cannot use weston_config_section_get_double(). Also going to use
float type, which has less range than double.

Ironically, the tests fill likely fail on locales that do not use
period as the radix character.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-09 16:17:57 +00:00
Daniel Stone
f0be8d94a5 gl-renderer: Use glClear for solid opaque regions
If we have a solid region which is opaque, we don't need to go through
blending: we can simply emit a glClear, which has a pretty big benefit
on tilers in particular.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
af5f2370af gl-renderer: Move pixman_region_to_egl() up
We'll want to use this from earlier code.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
1377fdf20d gl-renderer: Ignore transparent paint nodes
Skip these completely during repaint, since they by definition won't
have any effect.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
30a807b86f renderer-gl: Move checks into ensure_surface_buffer_is_ready
Instead of predicating the call to ensure_surface_buffer_is_ready() on
various conditions, move those into early exits from there.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
452f148b6c gl-renderer: Remove copy of buffer colour data
We can just get this directly from the paint node.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
6ffb4358e1 renderer-gl: Merge solid-buffer and placeholder paths
Now that paint nodes handle solid buffers properly, we can use the same
codepath through gl-renderer for all solid buffers, regardless of
whether they're a single-pixel buffer from clients, or a weston_curtain,
or a temporary placeholder due to content-protection or direct-display.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
c6b519ab12 paint-node: Set draw_solid for single-pixel buffers
Single-pixel buffers are, by definition, a single-colour fill across the
entire paint node. Use the draw_solid path for these where we can.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
e96a970e56 buffer: Don't lose direct-display when censoring output
When we're censoring output due to a content-protection mismatch, we
were setting draw_solid for the placeholder, but losing is_direct for
the original buffer.

There's no real effect with the current renderers, but best to be
consistent and make pnode->is_direct always accurate.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
8fc62e9ab8 gl-renderer: Rename prepare_placeholder to generic solid
This is, in fact, the path we'll take for all solid draws.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
b9e31d03ba gl-renderer: Use buffer colour for readback
When we're calling weston_surface_copy_content() from a solid buffer,
use the buffer's solid colour directly instead of our local copy.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Daniel Stone
11d721e748 gl-renderer: Resolve open question
The answer is that no, we do not need to be using the view's opaque
region. If the paint node is marked as fully opaque, that's because the
view itself is also opaque, and as we are dealing with surface
co-ordinates we don't need to be handling the transform here.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Ray Smith
930f768bdb backend-drm: Fix double-free of pending state in error path
drm_pending_state_apply_atomic is supposed to leave pending_state
untouched if called as a test-only and that test fails, as per the docs
for drm_pending_state_test. If it gets as far as doing the atomic test
and it fails, it doesn't free pending_state. However if it fails to even
compile the state for the atomic test (for example, if a particular
property is not implemented in the driver for a particular plane), it
frees pending_state. In this case, drm_output_propose_state will free
the contained drm_output_state again, typically leading to a segfault.

Treat failing to compile the state for the atomic test in the same way
as successfully running the atomic test but it failing.

Signed-off-by: Ray Smith <rsmith@brightsign.biz>
2025-10-09 13:39:23 +01:00
Philipp Zabel
847952b711 compositor: Fix warning on 32-bit architectures
On 32-bit ARM, tv_sec is of type long long int. Cast to int64_t and
use PRId64 from inttypes.h instead of %ld to silence these format
warnings:

  .../libweston/compositor.c: In function 'weston_compositor_print_scene_graph':
  .../libweston/compositor.c:9297:14: warning: format '%ld' expects argument of type 'long int', but argument 3 has type '__time64_t' {aka 'long long int'} [-Wformat=]
  .../libweston/compositor.c:9322:16: warning: format '%ld' expects argument of type 'long int', but argument 3 has type '__time64_t' {aka 'long long int'} [-Wformat=]

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
2025-10-09 13:29:01 +01:00
Philipp Zabel
200f4cf461 weston-log: Fix warning on 32-bit architectures
On 32-bit ARM, tv_usec is of type long long int. Cast to int64_t and
use PRId64 from inttypes.h instead of %ld/%li to silence these format
warnings:

  .../libweston/weston-log.c: In function 'weston_log_scope_timestamp':
  .../libweston/weston-log.c:961:22: warning: format '%ld' expects argument of type 'long int', but argument 5 has type '__suseconds64_t' {aka 'long long int'} [-Wformat=]
  .../libweston/weston-log.c: In function 'weston_log_timestamp':
  .../libweston/weston-log.c:1015:27: warning: format '%li' expects argument of type 'long int', but argument 6 has type '__suseconds64_t' {aka 'long long int'} [-Wformat=]

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
2025-10-09 13:29:01 +01:00
Philipp Zabel
de3a3fca1b shell.lua: Fix layer link assertions
Replace two always-true assertions:

        weston_assert_true(wc, &other_shview->view->layer_link.layer);

with what seems to have been the intended check:

        weston_assert_ptr_not_null(wc, other_shview->view->layer_link.layer);

This fixes a build warning:

  .../lua-shell/lua-shell.c: In function 'lua_shell_env_view_move_behind_other_view':
  .../lua-shell/lua-shell.c:1466:1: warning: the comparison will always evaluate as 'true' for the address of 'layer' will never be NULL [-Waddress]
  In file included from .../include/libweston/desktop.h:27,
                   from .../lua-shell/lua-shell.h:27,
                   from .../lua-shell/lua-shell.c:33:
  .../include/libweston/libweston.h:1112:23: note: 'layer' declared here
  .../lua-shell/lua-shell.c: In function 'lua_shell_env_view_move_in_front_of_other_view':
  .../lua-shell/lua-shell.c:1482:1: warning: the comparison will always evaluate as 'true' for the address of 'layer' will never be NULL [-Waddress]
  .../include/libweston/libweston.h:1112:23: note: 'layer' declared here

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
2025-10-09 13:45:47 +02:00
Daniel Stone
dc473a4131 tests/color: Increase sRGB->BT2020 matrix tolerance
The average tolerance was very very close on my AMD machine, but not
enough; the maximum tolerance certainly needed to be increased.

Observed on an AMD Radeon 780M with radeonsi from an October 2025 Mesa
build.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 10:39:31 +01:00
Pekka Paalanen
516f4b9b2f color-lcms: fix transform destroy on error
The error path in cmlcms_color_transform_create() uses
cmlcms_color_transform_destroy() to clean up. cmap_lut3d can be NULL in
that case, and cmsDeleteTransform() chokes on it.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
4890cd6a3d frontend: create automatic color profiles from .ini
This introduces a new key for outputs in weston.ini, "color-profile".
For starters, implement a pre-defined sRGB profile and an automatic
profile.

Automatic color profiles are created based on the colorimetry-mode and
the eotf-mode of the output. EDID can also be taken into account, but it
is opt-in due to its potential unreliability.

This feature is documented as not fully implemented, because color-lcms
does not yet handle parametric color profiles together with ICC
profiles. Specifically, the stock sRGB profile is still an ICC profile,
and would not be able to be used together with a parametric output
profile.

Co-authored-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
fe85ed48fc shared: implement weston_parse_space_separated_list()
This will be useful for parsing config file entries that have several
items on key, like x,y coordinates or a list of flags. Code reading
custom color profiles from weston.ini will use this.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
6ec30279f7 color: weston_color_profile_params_to_str() const
As it should have been. Found, when I temporarily needed to print
'static const struct weston_color_profile_params'.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
e76da2ccd0 color-lcms: shorten parametric profile description
Details are printed separately for logs and debugs, we don't need to
clutter the (short) description with these. The name_part is already
long enough for frontend-created automatic profiles.

Client-created parametric profiles will be indistinguishable from each
other, but we also don't log them anywhere. In debug prints, they are
identified by id numbers and printed in detail.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
e75873d376 color: improve primaries-named builder error
This error gets sent to clients or into the Weston log. Print the name
rather than the meaningless number.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
b8ac69eef1 color: check maxCLL and maxFALL against target lum always
The target luminance range is implied when not explicitly set, so maxCLL
and maxFALL should be checked against target luminances regardless of
whether target luminances are explicit.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
a17d5b4eb2 color: validate luminances more
Make sure the given values are finite, positive, and non-zero where
appropriate.

Because these validations are not mandated in the color-management
protocol, they are not immediate failures. They will fail the final
image description creation.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
6fbc1376ee color: improve profile builder errors
Statements phrased positive are easier to understand than phrased
negative. Use "must" instead of "should".

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
3f150b090b color: fix CIE value validation
The old code checked x for low limit and y for high limit, rather than
checking both for both limits. Fix this.

Check all value pairs rather than the first one four times. Don't stop
at the first error, record them all.

While at it, we might as well print exactly what value was the problem.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Pekka Paalanen
d180517ae4 color: move validate_color_gamut() up the file
This is a simple move of code, no changes. The next patch needs it here.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-10-07 17:23:35 +03:00
Robert Mader
8e30a7efc7 clients: screenshot: YUV support
If any output uses a YUV format, instead of trying to composite into a
png, write the raw data into .yuv files for each output.

These files don't contain any metadata yet, thus one may want to convert
them into y4m files with e.g. a command like the this:
ffmpeg -s 1024x768 -r 1 -pix_fmt yuv420p -i ~/wayland-screenshot-output-0-2025-08-01_15-58-24.yuv -c:v copy screenshot.y4m

Note that this may only work for certain pixel formats, such as
DRM_FORMAT_YUV4[20|22|44], and not for e.g. DRM_FORMAT_P010.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-07 11:48:33 +02:00
Robert Mader
a9fc1fc0f7 clients: screenshot: Fixup --help command line option
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-07 11:48:33 +02:00
Robert Mader
a09895e907 clients: screenshot: Support dmabuf passthrough for writeback connectors
Instead of relying on the compositor to allocate dmabufs for the
writeback connector and copying the results to the client-provided
shm-buffer, support allocating dmabufs in the client. The compositor
will pass them through to the writeback connector, effectively doing
the equivalent to "passthrough"/"plane-offloading"/"zero-copy".

Based on a patch by Chien Phung Van <chien.phungvan@vn.bosch.com>

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-06 16:04:18 +02:00
Robert Mader
722f0a2664 tests: drm-writeback-screenshot: Test client dmabuf support
Which is not supported with Pixman, thus test the GL and VK renderers.

This ensures the code-path for directly forwarding client-allocated
dmabufs to the writeback connector works as expected.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-06 15:53:45 +02:00
Robert Mader
e6b67d2c72 shared/client-buffer-util: Sync for read as well
In the next commit we will need syncing for reading. Thus adapt the sync
helper accordingly. We are not using the helper for performance-critical
tasks yet, thus there's currently no strong reason to allow users to
differentiate between the cases.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-06 14:06:30 +02:00
Robert Mader
203dbd3393 tests: client-helper: Make client_capture_output() take a client_buffer_type
Using the newly introduced create_buffer(), to which the buffer type is
passed on in order to allow taking writeback screenshots with dmabufs.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-06 14:06:30 +02:00
Robert Mader
23f396aa30 tests: client-helper: Add create_buffer() helper
Taking the newly introduced client_buffer_type enum, allowing simple
creation of dmabuf buffers.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-06 14:06:30 +02:00
Robert Mader
e27929e3b3 shared/client-buffer-util: Add buffer type enum
This will be helpful in follow-up commits.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-06 14:06:30 +02:00
Robert Mader
618bfad1d4 libweston: Get framebuffer from dma buffer in drm backend
If the client requests to take a screenshot using the writeback source
with a DMA buffer, Weston will get the framebuffer from that dmabuf
object and attach it to the writeback connector.

Original commit by Chien Phung Van.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Co-authored-by: Chien Phung Van <chien.phungvan@vn.bosch.com>
2025-10-06 14:06:30 +02:00
Erico Nunes
ad0f4cf94b vulkan-renderer: make dmabuf import dedicated allocation optional
This is not strictly always necessary depending on the implementation,
so the extension requirement can be made optional.
Also improve its usage by first checking whether the dedicated
allocation is preferred/required by the driver, before importing
with dedicated allocation.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-10-02 21:22:45 +01:00
Robert Mader
6cc8f48cd8 clients: Paint desktop-shell color background with single-pixel-buffer
So the buffer has the WESTON_BUFFER_SOLID type, which will make
additional optimizations easier going forward.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-02 17:05:22 +01:00
Marius Vlad
2497377af4 libweston/desktop/xwayland: Add MINIMZE state change
This is identical to MAXIMIZE side where we change the state to
MAXIMIZE, and implicitly go through a state surface check.

For XWAYLAND type of windows (non weston_desktop_surface)
that surface state check will be needed. This is a temporary work-around
to avoid Weston crashing as some X11 Window types will hit this path.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-10-02 08:43:46 +03:00
Derek Foreman
cb17b87a65 xwm: Fix crash when querying position of XWAYLAND windows
windows in the XWAYLAND state are popups and other such things that aren't
managed by libweston-desktop, so we crash if we query their position
with weston_desktop_api.

Query the position for these XWAYLAND windows based on their weston_view
and window geometry.

This should result in synthetic configure notify events no longer crashing.

Fixes #831
Fixes #1019

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-02 07:37:04 +03:00
liang zhou
1560cc3f0b compositor: prevent crash when moving view with popup on first output removal
In a multi-screen setup, removing the first screen triggers `handle_output_move`.
If `weston_view_set_position` is called on an output that has an active popup,
it causes a weston crash due to the view has a parent.

Signed-off-by: liang zhou <liang.zhou@gehealthcare.com>
2025-09-30 13:17:23 +00:00
Marco Felsch
4ba62103a6 backend-drm: set DRM_MODE_ATOMIC_ALLOW_MODESET during head disable
A change in the connector state require a possible full modest depending on the
hardware.

The connector wasn't set to unconnect if the head was detached while the output
is still enabled. Fix this by always checking the disable_head_link list during
drm_output_apply_state_atomic().

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
2025-09-30 15:37:37 +03:00
Marco Felsch
9c67c8c0d8 backend-drm: chek DRM_MODE_ATOMIC_TEST_ONLY before remove from list
DRM_MODE_ATOMIC_TEST_ONLY shouldn't remove the head from the
drm_output::disable_head list else the head is lost for the actual modeset
action.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
2025-09-30 15:36:38 +03:00
liang zhou
0b540ba8d6 desktop-shell: Fix crash when fullscreen surface has no output
The shell_set_view_fullscreen function was dereferencing
shsurf->fullscreen_output without checking if it was NULL first. This
could lead to a crash when a fullscreen surface had no associated
output during display hotplug.

Fix issue: https://gitlab.freedesktop.org/wayland/weston/-/issues/1028

Signed-off-by: liang zhou <liang.zhou@gehealthcare.com>
2025-09-30 12:10:41 +00:00
Robert Mader
5e7835bf2b ci: Bump kernel and Mesa version
1. Bump the kernel version to the drm-misc-next-2025-09-04 tag, fixing
   various issues required for vkms testing.

2. Use /sys/bus/faux/devices/vkms/drm/ instead of /sys/devices/platform/vkms/drm/
   for the card basename.

3. Bump Mesa to the commit needed for vkms+lavapipe. This also needs another
   leak workaround, so the code got a small cleanup.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-26 14:12:04 +02:00
Robert Mader
e187420e38 output-capture: Fix protocol event order
The new formats_done event has to be at the end, triggering warnings
like the following otherwise:

warning: since version not increasing

Fixes: 00902a592 (output-capture: Allow multiple formats and add formats_done event)
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-25 17:53:59 +02:00
Robert Mader
b6c1bc872e output-capture: Fix assertions in pull_capture_task()
Fixes: 9ea205e00 (output-capture: Support writeback connector formats)
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-25 17:51:22 +02:00
Pekka Paalanen
be71b5a094 color-lcms: compare parameters with tolerance
Comparing floating-point values for identity is fragile. Comparaing with
a small tolerance allows for matches that differ only due to numerical
precision of computations.

The tolerance is taken from
weston_color_tf_info_from_parametric_curve().

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-25 18:03:31 +03:00
Pekka Paalanen
d7030571c5 frontend,color: print details of the set color profile
It is nice to see the numbers of a parametric color profile when created
from CTA or EDID or just to cross-check with weston.ini.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-25 18:03:31 +03:00
Pekka Paalanen
daec4a0994 color: print name of unsupported TF
Helps debugging when you have the name rather than a number.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-25 18:03:31 +03:00
Pekka Paalanen
f3badf2c2d color: introduce struct weston_color_tf
At first I wanted to wrap

	float tf_params[MAX_PARAMS_TF]

into a struct, so that it would become type-safe to pass into functions,
and it could be copied with a simple assignment. Then I noticed that for
tf_params to be operable, it must always be accompanied by struct
weston_color_tf_info. Hence, struct weston_color_tf was born.

The need for #define MAX_PARAMS_TF got eliminated.

Because struct weston_color_tf is a member of struct
weston_color_profile_params, now both need to not contain implicit
padding.

This patch makes the internal enumerated TF structures follow the
current protocol requests: all color channels use the same curve.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-25 18:03:31 +03:00
Pekka Paalanen
7b5053f7fa color: drop weston_color_curve_from_tf_info()
This was never used, and I happened to write a slightly different
version of it in color-lcms.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-25 18:03:31 +03:00
Pekka Paalanen
bcfa2724d2 color-lcms: fix TF_POWER from type 1 inverse
Forgotten early return. Without it, the code continues to set up LINPOW
instead.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-25 18:03:31 +03:00
Marius Vlad
bcb7676ed7 backend-drm: Add some further debug message for hot-plug events
And also for connector changes. This would allow tracking hot-plug
events from the udev/kernel and figure out that connector properties
changed.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-25 14:07:48 +01:00
Marius Vlad
fdb43447a2 backend-drm: Explicitly set an invalid state
A infinitesimal short-flip in HDMI HDP in-out (hot-plug event) would
cause a discrepancy between kernel's connector's state and Weston
connector state resulting in kernel and Weston disagreeing on the final
connector state.

This has the undesired effect where the output would never turn on when
this short burst of HDP events come through.

To avoid that, just set the device invalid_state as true to go through a
modeset.  Also, schedule a repaint when that happens to go through a
repaint.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-25 14:07:48 +01:00
Marius Vlad
794c1eb490 backend-drm: Allow to pass connector ID
This way we can differentiate when we get a HOTPLUG event that gave us a
CONNECTOR ID to work with.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-25 14:07:48 +01:00
Marius Vlad
aa04d9d4ad backend-drm: Refactor drm_backend_update_connectors
This splits drm_backend_update_connectors into
drm_backend_update_connector and a post destroy phase/function.

There's no functional change, but this allows to pass
drm_backend_update_connector() on its own as we'll need that.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-25 14:07:48 +01:00
Robert Mader
b6f890d249 clients: screenshot: Allow selecting format and capture source
Add support for using writeback connectors as source. Those potentially
support more than one format, thus allow selecting those as well.
While on it, add a verbose flag for useful debug output.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-25 12:39:26 +02:00
Robert Mader
9ea205e007 output-capture: Support writeback connector formats
Writeback connectors often support multiple formats, fully independent
of the input framebuffer. Wire up support for querying formats and send
them to clients.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-25 12:39:23 +02:00
Robert Mader
07a5ec8157 output-capture: Add output_get_writeback_formats helper
And implement it in the DRM backend. This will be used by the next
commit.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-25 11:26:21 +02:00
Robert Mader
00902a5921 output-capture: Allow multiple formats and add formats_done event
The writeback output capture source may allow clients to select from
multiple possible formats. Update the protocol and its users
accordingly, and add formats_done event, making the implementation
easier and following common protocol practice.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-25 11:26:16 +02:00
Robert Mader
967537d525 backend-drm: Populate writeback formats with modifier
The writeback connector UAPI does not mention modifiers explicitly,
however implicitly we assume and use a linear modifier when using
dumb buffers.

Adding that to the format thus makes the assumption more obvious and
allows us to use the weston_drm_format_array as intended.
For example we can now use weston_drm_format_array_count_pairs() to
log the number of supported formats - previously it always returned 0.

See
https://www.kernel.org/doc/html/v6.16/gpu/drm-kms.html#writeback-connectors

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-22 12:25:31 +02:00
Robert Mader
3706d860f1 backend-drm/kms: Log writeback connector format
So it becomes easy to check in test output or when running
`weston-debug drm-backend`.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-22 12:25:31 +02:00
Erico Nunes
042aa06b28 vulkan-renderer: fix gbm_bo destroy in drm backend
Create a linux_dmabuf_memory subclass so that it holds the associated
gbm_bo and it can be properly destroyed with the dmabuf object.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-22 10:12:33 +02:00
Erico Nunes
b0c99998ef vulkan-renderer: drop fb get from create_renderbuffers
This is not required and creates a refcount imbalance,
causing a memory leak at drm-backend teardown.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-22 10:12:33 +02:00
Erico Nunes
41823d237b vulkan-renderer: remove unused allocation in renderbuffer dmabuf
Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-22 10:12:33 +02:00
Leandro Ribeiro
3026c44897 test: add color-effects test
Follow-up of "color: introduce output color effects". This adds a few
sanity tests for color effects.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-18 12:32:15 -03:00
Leandro Ribeiro
6fe0cfc2b8 color: introduce output color effects
Output color effects are applied to the whole output scenegraph. It
depends on color-management being disabled, as the color effects are
applied in sRGB content.

For now we added only a few accessibility options: color inversion,
deuteranopia, protanopia and tritanopia CVD correction.

Note that surfaces presented on outputs that contains a color effect
can't be used for direct scanout (i.e. bypass composition and offloading
to KMS overlay planes). The color effect is applied in our GL-renderer.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-18 12:32:13 -03:00
Derek Foreman
1a9cf3bfb6 compositor: Fix output reflowing when mirroring is in use
When we have a mirror, it will be at the same x,y position as the output
it's mirroring. On hot unplug, the current logic results in the mirroring
output being moved to the left by the width of its target output. The
mirror will then be destroyed, and the views can be left dangling outside
of usable space when a hot plug restores the outputs.

Subtly change the reflow logic to only reflow outputs to the right of the
removed output by testing co-ordinates, instead of assuming that every
output in the list is to the right of the previous.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-17 11:39:03 +00:00
Derek Foreman
a38cc9982b drm: Add more failure reasons that we can't use the scanout tranche for
Now that FAILURE_REASONS_FORCE_RENDERER isn't set for all not-scanout
capable failures, add some other reasons to the test in
dma_feedback_maybe_update.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-16 12:25:15 -05:00
Erico Nunes
6f1d9cdffd backend-drm: fix vulkan output init format
The default output format setting to the backend format was removed and
renderer-specific format picking functions were introduced, but one was
not included for vulkan-renderer.
Vulkan-renderer doesn't yet implement color management features which
would benefit from a full featured format selection here, so for now
just have a base implementation which restores the previous behavior.
This fixes the introduced segfault with vulkan-renderer and drm-backend.

Fixes: 56c27ea2 ("backend-drm: improve code that chooses output->format")

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-16 07:39:20 +00:00
Leandro Ribeiro
39108501b3 libweston: make use of some of the new weston assert
We didn't have many Weston assert macros in place, but now we do.

Make use of a few of the newer macros where they make sense. No big
difference, but just to exercise using the correct ones now that they
exist.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-15 19:16:17 -03:00
Leandro Ribeiro
6d8a15839d shared: add many weston assert that were missing
This adds a ton of weston assert macros that were missing, as well as
tests for all of that.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-15 19:14:00 -03:00
Leandro Ribeiro
81d68a561e shared: few cosmetic changes to weston assert file
Rename parameter "compositor" to "comp", allowing us to have one-line
macros that makes the file easier to read. Also moves a few macros
to other parts of the file.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-15 19:13:50 -03:00
Leandro Ribeiro
a4cefa69a2 shared: rename a few weston assert
Currently weston-test-assert.h has a better naming style than
weston-assert.h: more concise and standardized.

So let's copy the same style to weston-assert.h

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-15 19:13:04 -03:00
Elliot Chen
b268b3827c backend-pipewire: support frame rate configuration
Signed-off-by: Elliot Chen <elliot.chen@nxp.com>
2025-09-15 08:20:52 +00:00
Erico Nunes
1a68480421 backend-drm: use dmabuf renderbuffer for Vulkan
The initial drm backend implementation for Vulkan passes display device
allocated gbm bos directly to the renderer. This is a bit awkward since
it requires the renderer to maintain a custom output creation interface
and another code path for importing specifically gbm bos.
Since then, vulkan-renderer received support to use dmabuf renderbuffers
to support e.g. pipewire dmabuf, in an interface which is also common
with gl-renderer.
The dmabuf renderbuffer code path is similar to what the drm backend
implementation intended to do, so we can unify it to a single interface.
This has the advantages of requiring one less custom output creation
interface, as well as the renderer being able to handle the drm backend
through a single shared dmabuf renderbuffer path.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-12 18:04:57 +01:00
Erico Nunes
aff309fa9f vulkan-renderer: rename output options to surface/surfaceless
The fbo naming inherited from gl-renderer is confusing, and now it
is used in many places.
Rename the two options for output creation to surface and surfaceless
to hopefully make them more meaningful.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-12 18:04:57 +01:00
Erico Nunes
dfad00e8c4 backend-drm: Refactor drm_fb_get_from_dmabuf_attributes
So that it can be used with other dmabuf objects other than
linux_dmabuf_buffer.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-12 18:04:57 +01:00
Marius Vlad
d2cf5a7ba5 frontend: Explicitly add a check for printing warning
Fixes a minor issue with 28bdcb46be ("frontend: Log when exiting due to
insufficient active outputs") to only print that we have
no outputs enabled but we're allowed to continue when we actually get to
that scenario.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-12 15:06:22 +01:00
Marius Vlad
208157f2e4 weston-test: Handle missing layer fini on shutdown path
BUG: layer_list is not empty after shutdown. Calls to
weston_layer_fini() are missing somwhere

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-12 14:46:43 +01:00
Marius Vlad
41bef3caaa weston-test: Fix another mem leak on shutdown path
Fixes the following mem leak:

=================================================================
==191==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 56 byte(s) in 1 object(s) allocated from:
    #0 0x7f6b843f6610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7f6b8302f499 in output_created_listener ../tests/weston-test.c:145
    #2 0x7f6b83032dcd in wet_module_init ../tests/weston-test.c:857
    #3 0x7f6b842b8425 in wet_load_module ../frontend/main.c:989
    #4 0x7f6b842b89eb in load_modules ../frontend/main.c:1069
    #5 0x7f6b842d2711 in wet_main ../frontend/main.c:4865
    #6 0x562862e934d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #7 0x562862e9756b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #8 0x562862e81e1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #9 0x562862e81e9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #10 0x562862e97bb6 in main ../tests/weston-test-runner.c:726
    #11 0x7f6b83d33ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-12 14:46:43 +01:00
Marius Vlad
02a6e45ce5 weston-test: Fix mem leak on shutdown path
Fixes the following memory leak:

=================================================================
==191==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7f18bfa83610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7f18bf890191 in zalloc ../include/libweston/zalloc.h:38
    #2 0x7f18bf89184c in weston_log_ctx_add_log_scope ../libweston/weston-log.c:631
    #3 0x7f18bf891c2c in weston_compositor_add_log_scope ../libweston/weston-log.c:696
    #4 0x7f18be524ef6 in wet_module_init ../tests/weston-test.c:864
    #5 0x7f18bf945425 in wet_load_module ../frontend/main.c:989
    #6 0x7f18bf9459eb in load_modules ../frontend/main.c:1069
    #7 0x7f18bf95f711 in wet_main ../frontend/main.c:4865
    #8 0x557b36c114d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #9 0x557b36c1556b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #10 0x557b36bffe1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #11 0x557b36bffe9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #12 0x557b36c15bb6 in main ../tests/weston-test-runner.c:726
    #13 0x7f18bf3c0ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

Direct leak of 56 byte(s) in 1 object(s) allocated from:
    #0 0x7f18bfa83610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7f18be521499 in output_created_listener ../tests/weston-test.c:145
    #2 0x7f18be524dcd in wet_module_init ../tests/weston-test.c:857
    #3 0x7f18bf945425 in wet_load_module ../frontend/main.c:989
    #4 0x7f18bf9459eb in load_modules ../frontend/main.c:1069
    #5 0x7f18bf95f711 in wet_main ../frontend/main.c:4865
    #6 0x557b36c114d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #7 0x557b36c1556b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #8 0x557b36bffe1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #9 0x557b36bffe9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #10 0x557b36c15bb6 in main ../tests/weston-test-runner.c:726
    #11 0x7f18bf3c0ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

Indirect leak of 33 byte(s) in 1 object(s) allocated from:
    #0 0x7f18bfa7dd60 in strdup ../../../../src/libsanitizer/asan/asan_interceptors.cpp:578
    #1 0x7f18bf8918ed in weston_log_ctx_add_log_scope ../libweston/weston-log.c:639
    #2 0x7f18bf891c2c in weston_compositor_add_log_scope ../libweston/weston-log.c:696
    #3 0x7f18be524ef6 in wet_module_init ../tests/weston-test.c:864
    #4 0x7f18bf945425 in wet_load_module ../frontend/main.c:989
    #5 0x7f18bf9459eb in load_modules ../frontend/main.c:1069
    #6 0x7f18bf95f711 in wet_main ../frontend/main.c:4865
    #7 0x557b36c114d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #8 0x557b36c1556b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #9 0x557b36bffe1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #10 0x557b36bffe9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #11 0x557b36c15bb6 in main ../tests/weston-test-runner.c:726
    #12 0x7f18bf3c0ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-12 14:46:43 +01:00
Marius Vlad
7722b9f443 weston-test: Remove output_destroyed_listener listener on shutdown path
Fixes the following UAF:

==191==ERROR: AddressSanitizer: heap-use-after-free on address 0x518000000360 at pc 0x7f1ee142f5df bp 0x7ffe60aaf010 sp 0x7ffe60aaf008
READ of size 8 at 0x518000000360 thread T0
    #0 0x7f1ee142f5de in output_destroyed_listener ../tests/weston-test.c:166
    #1 0x7f1ee25f08eb in wl_signal_emit_mutable ../src/wayland-server.c:2401
    #2 0x7f1ee274c7f8 in weston_compositor_remove_output ../libweston/compositor.c:7877
    #3 0x7f1ee274fa92 in weston_output_release ../libweston/compositor.c:8641
    #4 0x7f1ee146e5f8 in drm_output_destroy ../libweston/backend-drm/drm.c:2626
    #5 0x7f1ee27552df in weston_compositor_shutdown ../libweston/compositor.c:9941
    #6 0x7f1ee2756a89 in weston_compositor_destroy ../libweston/compositor.c:10369
    #7 0x7f1ee286bed8 in wet_main ../frontend/main.c:4934
    #8 0x56113c4244d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #9 0x56113c42856b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #10 0x56113c412e1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #11 0x56113c412e9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #12 0x56113c428bb6 in main ../tests/weston-test-runner.c:726
    #13 0x7f1ee22ccca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #14 0x7f1ee22ccd64 in __libc_start_main_impl ../csu/libc-start.c:360
    #15 0x56113c412860 in _start (/home/mvlad/vkms/weston/b/tests/test-drm-writeback-screenshot+0xe860) (BuildId: 9f9e2ed12b9317dd859498374500f2406c32e5d3)

0x518000000360 is located 736 bytes inside of 792-byte region [0x518000000080,0x518000000398)
freed by thread T0 here:
    #0 0x7f1ee298e8f8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x7f1ee1433002 in wet_module_init ../tests/weston-test.c:882
    #2 0x7f1ee2851425 in wet_load_module ../frontend/main.c:989
    #3 0x7f1ee28519eb in load_modules ../frontend/main.c:1069
    #4 0x7f1ee286b711 in wet_main ../frontend/main.c:4865
    #5 0x56113c4244d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #6 0x56113c42856b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #7 0x56113c412e1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #8 0x56113c412e9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #9 0x56113c428bb6 in main ../tests/weston-test-runner.c:726
    #10 0x7f1ee22ccca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

previously allocated by thread T0 here:
    #0 0x7f1ee298f610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7f1ee142edc5 in zalloc ../include/libweston/zalloc.h:38
    #2 0x7f1ee1432cba in wet_module_init ../tests/weston-test.c:840
    #3 0x7f1ee2851425 in wet_load_module ../frontend/main.c:989
    #4 0x7f1ee28519eb in load_modules ../frontend/main.c:1069
    #5 0x7f1ee286b711 in wet_main ../frontend/main.c:4865
    #6 0x56113c4244d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #7 0x56113c42856b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #8 0x56113c412e1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #9 0x56113c412e9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #10 0x56113c428bb6 in main ../tests/weston-test-runner.c:726
    #11 0x7f1ee22ccca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-12 14:46:43 +01:00
Marius Vlad
5af8340a00 weston-test: Proper release pointer/seat on shutdown path
For fixing the following UAF.

==191==ERROR: AddressSanitizer: heap-use-after-free on address 0x518000000168 at pc 0x7f7aac77493e bp 0x7ffdd9dddc00 sp 0x7ffdd9dddbf8
READ of size 8 at 0x518000000168 thread T0
    #0 0x7f7aac77493d in udev_input_destroy ../libweston/libinput-seat.c:388
    #1 0x7f7aac73e632 in drm_shutdown ../libweston/backend-drm/drm.c:3623
    #2 0x7f7aad9208b8 in weston_compositor_shutdown_backends ../libweston/compositor.c:10337
    #3 0x7f7aad920a7d in weston_compositor_destroy ../libweston/compositor.c:10367
    #4 0x7f7aada35ed8 in wet_main ../frontend/main.c:4934
    #5 0x561e808014d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #6 0x561e8080556b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #7 0x561e807efe1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #8 0x561e807efe9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #9 0x561e80805bb6 in main ../tests/weston-test-runner.c:726
    #10 0x7f7aad496ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #11 0x7f7aad496d64 in __libc_start_main_impl ../csu/libc-start.c:360
    #12 0x561e807ef860 in _start (/home/mvlad/vkms/weston/b/tests/test-drm-writeback-screenshot+0xe860) (BuildId: 9f9e2ed12b9317dd859498374500f2406c32e5d3)

0x518000000168 is located 232 bytes inside of 792-byte region [0x518000000080,0x518000000398)
freed by thread T0 here:
    #0 0x7f7aadb588f8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x7f7aac3f2f9d in wet_module_init ../tests/weston-test.c:878
    #2 0x7f7aada1b425 in wet_load_module ../frontend/main.c:989
    #3 0x7f7aada1b9eb in load_modules ../frontend/main.c:1069
    #4 0x7f7aada35711 in wet_main ../frontend/main.c:4865
    #5 0x561e808014d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #6 0x561e8080556b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #7 0x561e807efe1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #8 0x561e807efe9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #9 0x561e80805bb6 in main ../tests/weston-test-runner.c:726
    #10 0x7f7aad496ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

previously allocated by thread T0 here:
    #0 0x7f7aadb59610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7f7aac3eedc5 in zalloc ../include/libweston/zalloc.h:38
    #2 0x7f7aac3f2c55 in wet_module_init ../tests/weston-test.c:836
    #3 0x7f7aada1b425 in wet_load_module ../frontend/main.c:989
    #4 0x7f7aada1b9eb in load_modules ../frontend/main.c:1069
    #5 0x7f7aada35711 in wet_main ../frontend/main.c:4865
    #6 0x561e808014d6 in execute_compositor ../tests/weston-test-fixture-compositor.c:431
    #7 0x561e8080556b in weston_test_harness_execute_as_client ../tests/weston-test-runner.c:570
    #8 0x561e807efe1d in fixture_setup ../tests/drm-writeback-screenshot-test.c:48
    #9 0x561e807efe9e in fixture_setup_run_ ../tests/drm-writeback-screenshot-test.c:50
    #10 0x561e80805bb6 in main ../tests/weston-test-runner.c:726
    #11 0x7f7aad496ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

This would be caused by not being able to compile keymaps.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-12 14:46:43 +01:00
Derek Foreman
658f66216a drm: Fix crash on hardware without cursor planes
In a2a6030902 I introduced a crash when no
cursor plane exists. Fix this by pulling the cursor plane tests into their
own function and doing an early return when we have a conclusive no-cursor
failure state.

Fixes a2a6030902
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-10 13:26:12 -05:00
Robert Mader
67de2a1967 tests: drm-smoke: Stop hardcoding output name to Virtual-1
On certain setups - notably virtual machines - the output name can
be already taken (by e.g. virtio).
Given that we only use a single output for the test, do what other
tests do and don't assume any name.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-09 14:03:26 +02:00
Robert Mader
516e86222f gitlab-ci: Bump Mesa to 25.2.2
Notably including
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35915
which is needed for some upcoming MRs.
Returning to a proper release also makes it easier to understand
what we are testing against.

Mesa 25.2 requires Meson >= 1.4 and libX11 >= 1.8. The later requires
autoconf >= 2.70.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-09 11:14:41 +02:00
Robert Mader
68d036e2b1 gitlab-ci: Collapse Vulkan-Headers installation
Fixes: 7bc103e5a (gitlab-ci: Build Vulkan-Headers for CI)

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-09 11:14:41 +02:00
Erico Nunes
811edc0a8c tests/client-buffer: Update Vulkan format mustpass list for CI
Now that new formats are supported by the Vulkan renderer, update
this list to match our driver in CI for a more reasonable coverage.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-08 12:02:11 +01:00
Erico Nunes
f42ccf2140 vulkan-renderer: Add query to populate shm formats
Remove the limited shm formats hardcoded list and add a query to
populate them according to the device.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-08 12:02:11 +01:00
Erico Nunes
9341192f51 vulkan-renderer: Drop dmabuf format print
These are fairly noisy now especially with more formats being added.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-08 12:02:11 +01:00
Erico Nunes
6d20e480a0 pixel-formats: Update Vulkan formats
Update list of Vulkan equivalent of the DRM formats.
Fix some format information to account for endianness according
to the "DRM pixel format guide".

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-08 12:02:11 +01:00
Erico Nunes
fef0de7d72 pixel-formats: Use a single __BYTE_ORDER macro name
This file used both __BYTE_ORDER and __BYTE_ORDER__ which could become
confusing to inspect.
Both appear to be valid, since it is being compared to __LITTLE_ENDIAN
stick to __BYTE_ORDER for all uses.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-08 12:02:11 +01:00
Erico Nunes
8c9f395c6c vulkan-renderer: refactor extensions to extension table
Define extension tables for all extensions that are potentially used,
and use that to enumerate and request extensions which will be used.
This allows for a bitset to hold supported extensions and makes it
less cumbersome to define new ones to use later, as well as requiring
less traversing of the extension string list to decide which extensions
to request.
This also fixes some missing dependency issues which could trigger
validation errors on some drivers with limited extension support.
It also allows some code paths that didn't require some specific
extensions that were in the default list before, by checking for
those in the code path that actually uses them at runtime.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-09-08 12:02:11 +01:00
Leandro Ribeiro
b717030a10 backend-drm: assert that there's a valid output state before repaint
Follow-up of "compositor: let backends handle output->disable_planes".
Now we always call assign_planes() before a repaint, so we must have
a valid output state when we enter assign_planes().

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-08 08:37:28 +00:00
Derek Foreman
439aea0188 compositor: Track DIRTY_POS properly
For clients using old protocol versions, the WESTON_SURFACE_DIRTY_POS bit
currently gets set on any attachment. It should really only be set if
the attachment is non-zero.

Since it's possible to attach mulitple times, or to invoke
wl_surface.offset multiple times, let's allow clearing the bit so it
stays up to date with the state that will actually be used on commmit().

Currently, this is pointlessly pedantic, as we don't really do much with
the bit, but in a future commit I intend to use it to notice states that
may change visibility/occlusion status of a surface.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-08 08:14:09 +00:00
Derek Foreman
eac3d78bc6 compositor: Remove view->visible
This is not what any sensible person would expect it to be. It was updated
by a walk of all the paint nodes on the output most recently repainted,
so if a view spanned outputs the visible region would only make sense
within the most recently painted output's region.

It's basically a scratchpad for a mid-repaint operation. Instead of making
it a view member, put it in the paint node, which are always per-output.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 15:23:08 -05:00
Derek Foreman
ac71d40dec compositor: Add transforms to scene graph debug dump
Add transform information to scene graph debug dumps, which can be
helpful in determining why application surfaces aren't ending up on
hardware planes.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:34:18 -05:00
Derek Foreman
cfaa19a292 libweston: Move transform string code into libweston
Pull this out of the frontend.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:34:18 -05:00
Derek Foreman
628e860ffa compositor: Dump some paint node info with the scene graph
For now I've just added plane failure reasons, but more could follow.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:34:18 -05:00
Derek Foreman
37c94a12d9 drm: Dump scene graph at end of repaint instead of beginning
At the end we'll have the plane failure reasons in their final state for
the frame we're submitting (instead of a stale state from the previous)

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:34:18 -05:00
Derek Foreman
6e7b4d63c2 compositor/drm: Move failure reason stringification into compositor
While this is generally drm specific stuff, it's leaked into paint nodes
a little bit already.

Pushing it into the core gives us the ability to print failure reasons
in the scene graph debug text (in a future commit), which can be very
informative.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:34:17 -05:00
Derek Foreman
b4529320ff drm: Better track plane failure reasons
We have a big bitfield of failure reasons for when we can't place a paint
node on a plane - but between the introduction of this bitfield and now
we added many new reasons, so it's an expecation that the reason
FAILURE_REASON_FORCE_RENDERER only means that the compositor is configured
to force the use of the renderer via the WESTON_FORCE_RENDERER environment
variable, or debug key bind, or similar.

Some of the code retained the older generic use of FORCE_RENDERER to mean
any number of things.

Add some new reasons and use other existing reasons to disambiguate the
FORCE_RENDERER reason.

Since we already print the (somewhat misleading) failure reason strings
late in the repaint pass, we can drop the (currently accurate) debug
prints we fired off along the way, and just print them accurately at the
end.

We also move the failure reason reset point to the start of repaint,
as it is convenient to have it be valid after plane assignment so
we can print it in scene graph debug text in a later commit.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:33:22 -05:00
Derek Foreman
38e6a292a2 drm: Replace dead code with an assert in plane transform check paths
The caller to drm_plane_state_coords_for_paint_node() has already tested
for valid transforms, so drm_plane_state_coords_for_paint_node() is never
called with a transform that needs to be tested.

Replace the test with an assert() - and this also lets us stop returning
a bool, and drop the debug prints that could never trigger.


Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:33:22 -05:00
Derek Foreman
a2a6030902 drm: Test cursor plane transform when finding plane for view
Explicitly test the cursor transform so we can properly set
the plane failure reason.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 13:33:22 -05:00
Derek Foreman
23b9f92398 surface-state: refactor weston_surface_commit
Move some code around so we only have a single call to
weston_surface_apply(). This will simplify having deferred state updates
later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
8966ea79fe surface-state: remove more subsurface specific paths
weston_subsurface_commit_to_cache and weston_subsurface_commit are
trivial functions with single call sites. Eliminate them.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
f322b41b3d surface-state: Remove weston_subsurface_apply_from_cache
Now that we don't have a buffer_ref to manage outside the surface_state
struct, this function is a trivial wrapper.

Just inline it where it's used.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
ed1edb7b5c compositor: replace surface_state->buffer with a buffer_ref
Use a buffer_ref here to allow us to remove the subsurface
cached_buffer_ref and keep it in the surface state struct instead.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
760ca22e8f compositor: Remove unused forward declaration
We don't need to define weston_compositor_build_view_list here, as it's
already defined before it's used.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
cd58c45daa compositor: Move weston_surface_commit()
Moving this later in the file lets us drop the prototype for
weston_subsurface_commit().

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
f4bad074e6 compositor: Move some surface state functions
Just code motion to get rid of an unnecessary prototype.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
0ea8141195 compositor: Move a bunch of surface state handling stuff to another file
compositor.c is too big, let's try to peel off a bit of surface state
handling code into another file.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
72f73f6692 compositor: internally export weston_surface_to_subsurface
I'll want to use this in another file soon, but for now let's just
clean up the extra prototypes.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
3b017341b7 compositor: Make weston_surface_commit handle subsurfaces
Push the subsurface vs surface logic into weston_surface_commit so there's
just one function to call from surface_commit to handle both.

This is mostly preparation for splitting off a bunch of surface handling
functions into their own file later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
76dc730d3d compositor: Move region_init_infinite to a header
We've got it in two places, let's share the code.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
e79c9ceee5 compositor: Move cache flush into weston_subsurface_set_synchronized
Do a subsurface cache flush in weston_subsurface_set_effectively_synchronized
instead of in the protocol handler.

This is just so when I move some functions into another file later, I don't
need to expose weston_subsurface_apply_from_cache().

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
b76e6ebd82 compositor: rename surface_commit_from_cache to apply_from_cache
Finish up renaming functions so that committing state and applying state
have their own function names. This will be useful soon when we have a
mechanism to commit state into a queue and apply it later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
98253554c8 compositor: Remove weston_subsurface_synchronized_commit
This is now just a call to weston_subsurface_commit_from_cache, so just
call that directly.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
93ad388414 compositor: Move parent_apply call into weston_surface_apply
To streamline state handling, push the weston_subsurface_parent_apply
calls and list walks into weston_surface_apply().

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
fb7b3e2880 compositor: Make subsurface state application order consistent
We have several places where we apply surface state, then walk the
subsurface list.

In surface_commit() however, we walk the list first then apply state.

Re-order surface_commit() so it's the same as the other sites.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
051f0ac7d9 compositor: Rename parent_commit to parent_apply
Continue renaming "commit" functions to "apply" in anticipation of
a violent split between the two concepts.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
ae9b99352c compositor: move some prototypes
In a future commit, we'll need weston_subsurface_parent_commit sooner,
so just move both of these prototypes earlier in the file.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
8479772d2d compositor: drop has_cached_data subsurface bit
We don't use it anymore, we just casually commit and expect that
applying clean state is harmless.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
3db7d41642 compositor: Don't check for cached data in synchronized_commit
It really doesn't matter if we do a little extra work here,
weston_subsurface_commit_from_cache() is harmless if called on clean state.

If this turns out to waste some cycles we can add some more dirty bits
later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
26625a4928 compositor: Don't pass parent sync status to subsurface_parent_commit
We called subsurface_parent_commit with a flag to indicate whether we're
committing from a synchronized parent or not - this was used for
determining if a subsurface was effectively synchronized.

Now that we know whether a subsurface is effectively synchronized, we
can drop the parameter.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
c0053057db compositor: Simplify weston_subsurface_commit
Just bouncing everything through the cache makes for a much
simpler flow.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
b5970e6e68 compositor: remove weston_subsurface_is_synchronized
This was used to check if a subsurface was effectively sync,
and we now have a bool to check for that instead.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
1326428f41 compositor: track subsurface effective sync status
Keep track of subsurface effective sync status when it changes instead of
figuring it out when we need to know it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
4afd8961fc compositor: Create a common path for applying surface state
Create a common weston_surface_apply() for both subsurface and normal
surfaces to push state through, as this will let us remove a bunch of
common code in the future.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
2deb5e1dfd compositor: use early return in set sync/desync
Trivial change for clarity.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
3674d9665b compositor: rename commit_subsurface_order to apply_subsurface_order
Continuing to make a split between "commit" and "apply" in preparation
for a future where the application happens later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
a84db969f4 compositor: Rename weston_surface_commit_state
We'll eventually have a hard split between the commit and the application
of state, so rename this function to better indicate what it does.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Derek Foreman
ee90650c8c compositor: Make subsurface->synchronized a bool
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-05 10:01:42 -05:00
Jonas Ådahl
ed6beb1dbf compositor: Make surface state caching reusable
Intended to be used by other inter surface synchronization mechanisms
than subsurfaces.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
2025-09-05 10:01:42 -05:00
Robert Mader
ccce6cfdda clients: screenshot: Use shared client-buffer utils
In preparation for dmabuf support.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-05 11:47:18 +02:00
Robert Mader
4d43e63ab5 clients: screenshot: Sort imports
In preparation for more additions.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-05 11:47:18 +02:00
Robert Mader
106beccc91 weston-test-client-helper: Use shared client-buffer utils
For now just wrap the existing buffer struct around the new shared one.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-05 11:47:18 +02:00
Robert Mader
af834d1419 tests/client-buffer: Use shared client-buffer utils
Use the shared helper in order to avoid duplication. This will also
ensure that any format added to the test will also be usable by other
tests and clients.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-05 11:47:18 +02:00
Robert Mader
6951ff578b shared: Add client-buffer helpers
Factor out client-buffer creation into a helper library in order to
avoid duplication. This notably allows clients and tests to easily reuse
the dmabuf and yuv logic.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-09-05 11:47:18 +02:00
Derek Foreman
bf311ff232 screenshooter: Don't fail the first time an output won't capture
Historically, weston-screenshooter attempts a capture on all
wl_outputs, and if any output fails to capture it exits immediately.

These days it's possible to set up the pipewire backend to mirror
a drm backend output. This leads to surprising behaviour if one
tries to screenshot while no pipewire client is in use. Since the
pipewire backend has no buffer to render into at this point, the
screenshot fails. The drm screenshot is then dropped on the floor
because one of the wl_outputs failed to capture.

Avoid this for now by just continuing in the case of such
"graceful failures". Though maybe in the future we should allow
picking a wl_output by name, or have a command line switch to
decide whether to stop after a failure or not.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-04 08:54:52 -05:00
Derek Foreman
724d3707ec pipewire: Shoot down unsatisfiable capture tasks
If there's no running connection, we can't capture, so just burn down any
waiting tasks so we don't assert later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-04 08:54:52 -05:00
Derek Foreman
c54c421d21 gl-renderer: Listen to capture destroy signals
Listen to the capture destroy signal so we can prevent the async fd
source from causing a UAF.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-04 08:54:52 -05:00
Derek Foreman
263290c677 gl-renderer: Move destroy_capture_task
Simple code motion to help with a later commit.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-04 08:54:52 -05:00
Derek Foreman
d2bab8a5ee libweston: Add an output capture task destroy listener
An output task may be destroyed by a client disconnect. This causes
problems for our drm backend's asynchronous capture task handler, which
currently has no way to notice this.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-04 08:54:52 -05:00
Pekka Paalanen
48cc12cfc5 color-lcms: return cmsHTRANSFORM from xform_realize_chain()
No functional change.

This will help to keep the code more straightforward when
parametric<->ICC color transformations are added, and they need more
operations than just the cmap_3dlut for the 3D LUT.

Particularly, there will be a new flag telling if cmap_3dlut is
populated, and the flag is best set in init_icc_to_icc_chain() instead
of xform_realize_chain().

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-04 10:55:34 +03:00
Pekka Paalanen
13e7a3addb color-lcms: renames in_prof/out_prof
Shorter shorthands are nicer.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-04 10:55:34 +03:00
Pekka Paalanen
4e286bd297 color-lcms: add mask for allowed steps
When crafting an ICC to ICC color transformation, all the steps in
weston_color_transformation are at disposal. In the future also
parametric<->ICC color transformations will be crafted using the same
ICC chain machinery. However, there some steps must be reserved for
additional operations.

Add a bit mask that tells which color steps can be used by
xform_realize_icc_chain().

Unfortunately the mask is most conveniently stored in struct
cmlcms_color_transform. The LittleCMS context user data is the only good
way of passing our own bits into the factory code, but the user data
cannot be reset without destroying the context. It is probably not safe
to destroy the context as long as we have any LittleCMS objects alive
and created in that context. Hence, the user data must out-live the
LittleCMS context.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-04 10:55:34 +03:00
Pekka Paalanen
dfea094772 color-lcms: prefix color_transform_step values
I will be adding a MAPPING value, and it would look odd without any
prefix. This adds a bit of namespacing.

The definition is moved to the header, because I will be needing it in
struct cmlcms_color_transform.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-04 10:55:34 +03:00
Pekka Paalanen
0974359b8f color-lcms: split into xform_realize_icc_chain()
Split init_icc_to_icc_chain() into two parts:
- init_icc_to_icc_chain() is specific for ICC to ICC transformation
- xform_realize_icc_chain() can process any chain of cmsHPROFILEs

xform_realize_icc_chain() will be used by ICC-to-parametric and
parametric-to-ICC transformations in following commits.

No changes to functionality. 'extra' local variable is lost as unused.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-04 10:55:34 +03:00
Pekka Paalanen
9500bbe844 color-lcms: rename xform_realize_chain to init_icc_to_icc_chain
I will be splitting this function, and xform_realize_chain() matches the
parts I'm going to split out of it, while the remainder will be specific
to icc-to-icc transformations.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-09-04 10:55:34 +03:00
Leandro Ribeiro
c594aa22cb backend-drm: offload post-blend color transformation to KMS
In this patch we allow offloading the post-blend color transformation
to KMS.

As KMS currently only supports to offload the transformation in a LUT,
this may result in precision issues. So this introduces the config
option "offload-blend-to-output", which is disabled by default.

This option requires "color-management" to be enabled, otherwise it is
ignored.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
996ec58ce3 frontend: avoid unecessary call to get_section()
We already get the core section a few lines above, and no other call
get_section() call are made in between.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
e77ca25a80 color: fail weston_color_curve_to_3x1D_LUT() when !xform->steps_valid
This is a leftover from "color: do not use color steps for non-optimized
pipelines". If a xform don't have valid steps, it shouldn't have curves.
So this function should fail.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
fceb4151a3 color: allow creating LUT from curve even when bad precision may occur
At this point, the DRM/KMS API supports offloading post-blend color
xform only through LUT's. This is not ideal, and an API to improve that
should be proposed in the future.

But we still want to experiment with offloading pre-blend (not post)
color transformation through the colorop API, which is close to being
accepted upstream. But this requires us to offload post-blend as well.

weston_color_curve_to_3x1D_LUT() currently fails if we detect that
crafting a LUT from the color curve may result in bad precision.
Instead, let's add a boolean param to control if we forbid or not bad
precision. This should allow us to offload post-blend xform through
LUT's.

This also improves the error messages in this function.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
6f969623eb backend-drm: do not disable underlay planes based on b->format
Since commit "backend-drm: improve code that chooses output->format", we
changed how b->format (the GBM format from the config file) is used.

There are config options in weston.ini that allow us to ignore the GBM
format set. So what matters to us is which output->format is being used,
and we compute that in drm_output_pick_format_egl() and
drm_output_pick_format_pixman().

So remove these checks that disable underlay planes based on b->format,
keeping only the ones that depend on the output->format selection.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
56c27ea248 backend-drm: improve code that chooses output->format
Instead of picking an arbitrary format, let's first ensure that the
format is supported by the renderer.

Also, start choosing formats with alpha channel if we have b->underlay.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
ed7ceef37e gl-renderer: do not set compositor capabilities on failure
When gl_renderer_display_create() fails, do not change the compositor
capabilities.

The compositor may not abort when that happens, it may simply decide to
fallback to another renderer. So setting anything on failure is wrong.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
c10857df5d gl-renderer: add function to query supported rendering formats
This goes through all formats available in the EGLConfig's that we
get from EGLDisplay and expose them in a struct weston_drm_format.

Currently backends choose a format for their outputs and hope that
GL-renderer is able to find a compatible EGLConfig. This should help
backends to avoid guessing.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
dd5e1f5047 libweston: rename get_supported_formats to get_supported_dmabuf_formats
Let's be more more specific and rename the renderer interface function
that returns the supported dma-buf formats. I.e. if we pass a dma-buf
with one of these formats for the renderer, it should be able to import
it.

Next we'll introduce a function to query the rendering formats from
the renderer, so this distinction is important.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
fba356e44d gl-renderer: log EGLConfig component type
Now that we also support EGLConfig with floating-point, let's log this
information.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
b5ed927960 gl-renderer: properly log EGLConfig vis id
To log vis id, we call:

eglGetConfigAttrib(egldpy, eglconfig, EGL_NATIVE_VISUAL_ID, &value)
p = pixel_format_get_info(value)

The problem is, EGL_NATIVE_VISUAL_ID represents a DRM format only on
GBM platform. So for other platforms we are calling
pixel_format_get_info() with values that are not DRM formats.

Avoid calling pixel_format_get_info() when the platform is different
from GBM, and log only the hex value in such case.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
0c986257f9 gl-renderer: change params of a few functions
No behavior change, just to make things easier for next commits. They
will need struct gl_renderer *gr in print_egl_config_info().

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
ec646f34d6 gl-renderer: add support to query EGL configs with float-point formats
Currently when we have a blend-to-output color transformation, we have a
16FP shadow buffer representing the blending space. Then we blit from
that to the primary plane fb, which is a regular buffer (fixed-point,
not 16bpc).

The shadow buffer needs to be 16FP because the blending space is linear
with relation to light. So it needs more bits for encoding.

In the next patches we enable the option to offload the blend-to-output
color transformation to KMS, so we'll need the primary plane fb to be
of a 16FP format. In order to do that, we need to be able to find EGL
configs with float-point formats. In this patch we enable that.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Leandro Ribeiro
3cad1c7716 libweston: remove set_gamma()
The plugins cms-static and cms-colord have been deprecated and removed
from our code. They were the only thing holding set_gamma() from being
removed. So remove set_gamma() from the code.

Users can have the same results tweaking the output color profile that
they use.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-09-02 13:34:00 +00:00
Derek Foreman
6b1b3d167d xwm: Add command line option to disable window decor
Our window decor uses cairo-xcb. cairo-xcb stores xcb_connection_t
internally and uses them as kind of a hash key for internal bookkeeping.
This needs to be torn down with a cairo_device_finish, when the last
cairo surface is destroyed, and we are not properly handling that.

Because of this weston bug, if the Xwayland server dies, is restarted,
and the weston X window manager gets the same xcb_connection_t pointer
value for a new connection that it had for a previous connection,
cairo-xcb will use stale state and crash.

Weston is used in some places (like Mesa CI) where Xwayland crashes are
more common than one might usually expect, and weston needs to be robust
against these failures. It's ok to have no window frames in xwl in these
cases, because nobody is interacting with the windows.

The '--no-xwm-decorations' command line option will now remove
cairo-xcb from use entirely, so this crash can no longer happen.

We should still fix the bugs in our cairo usage, but I think long term
it's still ok to have a way to disable this and reduce complexity.

Ref #1042

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-08-28 14:35:30 -05:00
Pablo Saavedra
98d4438265 screen-share: Guard pixman_image_unref call on shared_output_destroy
Prevent crashes during shared_output_destroy when cache_image is not
initialized.

Signed-off-by: Pablo Saavedra <psaavedra@igalia.com>
2025-08-28 11:17:33 +02:00
Robert Mader
092fe3f7ec tests/client-buffer: Sync dmabufs with DMA_BUF_IOCTL_SYNC
As required by the spec when accessing dmabufs from the CPU, see
https://docs.kernel.org/driver-api/dma-buf.html

While effectively a no-op on amd64, this fixes test failures on various
aarch64 devices, including:
 - rk3588 (Panfrost, Rock5)
 - rk3399 (Panfrost, PineBook Pro)
 - Broadcom BCM2712 (V3D, RPi5)
 - Qualcomm SDM845 (freedreno, OnePlus6)

Fixes: 303d88448 (tests: client-buffer: Add dmabuf support)
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-08-25 12:10:10 +02:00
Jaeyoon Jung
e91252a943 desktop-shell: Add scale-fit background type
It is similar to scale-crop but fits to the output so that the image
does not get cropped.

Signed-off-by: Jaeyoon Jung <jaeyoon.jung@lge.com>
2025-08-18 16:42:26 +09:00
Philipp Zabel
683eabb61e build: Allow libdisplay-info 0.3.0
There are no breaking changes for the high-level API that Weston uses.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
2025-08-13 15:36:51 +02:00
Pekka Paalanen
ead6c5b319 frontend: use weston_enum_map for scroll method
Use helpers instead of open-coding.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
72d2b14e6a frontend: use weston_enum_map for colorimetry modes
Use helpers instead of open-coding.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
28808401b2 frontend: use weston_enum_map for EOTF modes
Use helpers instead of open-coding.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
1c14c4ef70 frontend: use weston_enum_map for transforms
Use helpers instead of open-coding.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
6d2ca22a6c frontend: remove trailing whitespace
My editor always does this, and then I had to manually discard that
change.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
868c25b591 frontend: use weston_enum_map for requires_outputs_modes
Use helpers instead of open-coding.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
8694665f4f frontend: use weston_enum_map for renderers
Entrench the use of weston_enum_map more, even though in this case it
doesn't buy much.

Make the array 'static const' which it should have been already.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
0787422248 frontend: convert vrr_mode to enum map
Less open-coding is better?

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Pekka Paalanen
03e7cdb43d shared: helpers for a generic enum map
Mapping between strings and enum values is open-coded in several places.
Introduce helpers here, and use them in the next patch.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-08-05 11:51:23 -05:00
Michael Olbrich
66cdb7d9bc backend-rdp: implement set_dpms
set_dpms() is used for sleep/wakeup. output_repaint_timer_handler() resets the
repaint_status if called while Weston is sleeping. If the timer is still active,
it will trigger a call to weston_output_finish_frame() which then triggers an
assertion, because the repaint_status is not REPAINT_AWAITING_COMPLETION.
Stop the timer and reset the repaint_status in this case to avoid this.

Schedule a repaint for WESTON_DPMS_ON to ensure that the current state is
rendered.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-08-04 14:56:26 +00:00
Michael Olbrich
2a7b4f52e7 backend-x11: implement set_dpms
set_dpms() is used for sleep/wakeup. output_repaint_timer_handler() resets the
repaint_status if called while Weston is sleeping. If the timer is still active,
it will trigger a call to weston_output_finish_frame() which then triggers an
assertion, because the repaint_status is not REPAINT_AWAITING_COMPLETION.
Stop the timer and reset the repaint_status in this case to avoid this.

Schedule a repaint for WESTON_DPMS_ON to ensure that the current state is
rendered.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-08-04 14:56:26 +00:00
Michael Olbrich
afc19c2e94 backend-vnc: implement set_dpms
set_dpms() is used for sleep/wakeup. output_repaint_timer_handler() resets the
repaint_status if called while Weston is sleeping. If the timer is still active,
it will trigger a call to weston_output_finish_frame() which then triggers an
assertion, because the repaint_status is not REPAINT_AWAITING_COMPLETION.
Stop the timer and reset the repaint_status in this case to avoid this.

Schedule a repaint for WESTON_DPMS_ON to ensure that the current state is
rendered.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-08-04 14:56:26 +00:00
Michael Olbrich
d076f2c519 backend-pipewire: implement set_dpms
set_dpms() is used for sleep/wakeup. output_repaint_timer_handler() resets the
repaint_status if called while Weston is sleeping. If the timer is still active,
it will trigger a call to weston_output_finish_frame() which then triggers an
assertion, because the repaint_status is not REPAINT_AWAITING_COMPLETION.
Stop the timer and reset the repaint_status in this case to avoid this.

Schedule a repaint for WESTON_DPMS_ON to ensure that the current state is
rendered.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-08-04 14:56:26 +00:00
Michael Olbrich
b5843ed366 backend-headless: implement set_dpms
set_dpms() is used for sleep/wakeup. output_repaint_timer_handler() resets the
repaint_status if called while Weston is sleeping. If the timer is still active,
it will trigger a call to weston_output_finish_frame() which then triggers an
assertion, because the repaint_status is not REPAINT_AWAITING_COMPLETION.
Stop the timer and reset the repaint_status in this case to avoid this.

Schedule a repaint for WESTON_DPMS_ON to ensure that the current state is
rendered.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-08-04 14:56:26 +00:00
Derek Foreman
5b37b09c8a xwm: Clean up windows so we don't crash when Xwayland crashes
If Xwayland crashes when we have windows lying around, we can get a
surface destroyed callback later that tries to log debug messages by
dereferencing a stale pointer to the defunct window manager to find the
log scope.

Let's finish this FIXME from 2012, and wipe out the windows.

Ref #1042

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-08-01 12:31:55 -05:00
Derek Foreman
f132462df7 compositor: Don't pass a time to weston_output_repaint()
Nothing does anything with this.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-08-01 15:08:00 +00:00
Septatrix
28bdcb46be frontend: Log when exiting due to insufficient active outputs
Signed-off-by: Septatrix <24257556+septatrix@users.noreply.github.com>
2025-08-01 14:58:19 +00:00
Leandro Ribeiro
3a1101be34 gitlab-ci: drop outdated comments related to virtme
Since "gitlab-ci: Use virtme-ng for running our tests" we no longer use
a hacky fork of virtme. Also, wee no longer use "--script-dir", as
virtme-ng properly supports "--script-sh".

So drop outdated comments.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-08-01 11:30:23 -03:00
Pekka Paalanen
72ed2c12d8 color-lcms: parametric to parametric transformations
This implements the basic color transformation from parametric to
parametric image description. The colorimetric rendering intents are
implemented. The perceptual and saturation rendering intents are
equivalent to media-relative + BPC rendering intent, subject to be
implemented better later.

Things missing:
- handling target color volumes
- perceptual dynamic range mapping

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 17:32:11 +03:00
Pekka Paalanen
8c2c429fd5 color-lcms: parametric blend-to-output
Implement blend-to-output transformation for parameteric output image
descriptions.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 13:14:34 +03:00
Pekka Paalanen
3737c9adb6 color-lcms: re-structure transformation creation
We will eventually have 6 different paths for creating color
transformations:
- input to blend, input to output
  - ICC to ICC
  - parametric to parametric
  - ICC to parametric
  - parametric to ICC
- blend to output
  - ICC
  - parametric

Set up their dispatching.

No changes to existing functionality.

xform_realize_chain() is now guaranteed to be called only with ICC
profiles.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 13:14:22 +03:00
Pekka Paalanen
3b3fa61c31 color: add Bradford matrix computation
This function is required for media-relative rendering intents.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 13:14:01 +03:00
Pekka Paalanen
b32f353003 color: add NPM computation
This function is required for producing color transformations from
parametric image descriptions.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 13:13:38 +03:00
Pekka Paalanen
37bee3050e color-lcms: override sRGB two-piece TF on input profile
https://gitlab.freedesktop.org/pq/color-and-hdr/-/blob/main/doc/wayland_qa.md#q-should-srgb-content-be-decoded-with-the-piecewise-srgb-transfer-function

When anything claims to target a display with the sRGB two-piece
transfer function, override it with the power-2.2. That is how sRGB
displays actually work.

This patch includes a small refactoring in
cmlcms_color_transform_create().

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 13:13:26 +03:00
Pekka Paalanen
3999d685bc color-lcms: call it a color transform recipe
I've been wanting a better name than search_param. In the future they
are not always search parameters when we have to replace the input
profile with another one for sRGB power-2.2 decoding purposes.

I think "recipe" describes this struct well: it's the list of
ingredients to cook a color transformation from.

This patch is purely renaming things.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 13:13:14 +03:00
Pekka Paalanen
67cfcaa0ac color-lcms: remove cmlcms_color_transform.status
This field is redundant, and therefore only confusing.

The success or not is returned from xform_realize_chain() directly. The
color processing steps vs. 3D LUT is recorded in
weston_color_transform.steps_valid.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-28 13:12:47 +03:00
Pekka Paalanen
15a9daad9a tests/color-icc-output: relax max error tolerances
Now that we are testing the more robust average error tolerance pretty
tightly, we can relax the tolerances on the maximum error which is more
flaky between GL drivers and hardware.

This makes sRGB->adobeRGB MAT test pass on radeonsi Polaris 11.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-24 11:30:07 +03:00
Pekka Paalanen
a5a2b3abb1 tests/color-icc-output: gate by average error as well
Maximum error is fragile: radeonsi on Polaris 11 has one error spike
that would force the the tolerances for everything to be much higher
than desired, and it masks changes to usual error levels.

Add a new condition to opaque_pixel_conversion: average two-norm error
statistic. The average is not as susceptible to outliers as maximum is.
We still keep the maximum error tolerance as well, to detect gross
outliers that might not sway the average enough to cause a test failure.

The new average error tolerances have been collected from the worst case
among the following + 0.01:
- GL renderer: Mesa Intel(R) HD Graphics 4600 (HSW GT2)
- GL renderer: AMD Radeon RX 550 Series (radeonsi, polaris11, ACO,
  DRM 3.61, 6.12.35+deb13-amd64)
- GL renderer: llvmpipe (LLVM 19.1.7, 256 bits)

(There is no need to separately print matrix vs. clut, it is already in
the fixture name.)

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-24 11:30:07 +03:00
Pekka Paalanen
b55a1d5bff tests/color-icc-output: remove outdated comment
Since around 9002667aa0 the power-law
curves have been implemented.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-24 11:30:07 +03:00
Pekka Paalanen
ef52b0adb4 tests/color-icc-output: re-layout my_setup_args
The concise table style was nice, but is getting more unwieldy as more
fields will be added. The new style won't fall apart.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-24 11:30:07 +03:00
Pekka Paalanen
d254ccdcc5 tests/color-icc-output: rename tolerance to max_tol
I will be adding yet another tolerance. This name disambiguates.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-07-24 11:30:07 +03:00
Derek Foreman
5a1e925759 wayland-backend: Remove unused cairo_device_t
The frame_device variable wasn't used in the commit that added it, and
later another commit that performed a bunch of clean-up bookkeeping added
cairo_device_destroy() for it. This was non-destructive because
cairo_device_destroy() handles NULL gracefully, but still Very Weird.

Remove it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-07-23 08:02:43 -05:00
Derek Foreman
a9958154a9 cairo-util: Remove dead code
Nothing calls this.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-07-23 07:59:36 -05:00
Erico Nunes
1939c732e8 gitlab-ci: Enable vulkan-renderer on debian lts jobs
With newer Vulkan-Headers built in the container, we may un-disable
vulkan-renderer in the debian lts jobs.
This also simplifies the CI script by removing a variant that existed
only for that purpose.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-07-21 12:09:54 +00:00
Erico Nunes
7bc103e5a1 gitlab-ci: Build Vulkan-Headers for CI
The version in Debian 11 (bullseye) is only slightly too old to build
vulkan-renderer.
We already build our own Mesa drivers to a newer version anyway, so it
should be possible to test vulkan-renderer in bullseye if it builds.
The actual Vulkan-Headers version here could actually be older and still
build, but was chosen to be same as in Debian 12 (bookworm) for now as
it is a tested version which has also been available for a while.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-07-21 12:09:54 +00:00
Leandro Ribeiro
3f81d2fd38 compositor: let backends handle output->disable_planes
On weston_output_repaint(), we have:

output_assign_planes(output);
...
output->repaint(output);

output_assign_planes() avoids calling output->assign_planes() when
output->disable_planes > 0. This brings a few complications to backends,
because they can't rely on the repaint loop starting from a certain
function: sometimes it starts from assign_planes(), others from
repaint().

Let's be more consistent: always call assign_planes() and let backends
handle output->disable_planes.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-07-18 17:58:45 +02:00
Leandro Ribeiro
3eed20254c backend-drm: add missing FAILURE_REASONS_FORCE_RENDERER
If we call drm_output_find_plane_for_view() with
DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR for a view that is not a
cursor view, it should fail to get a plane.

In such case, set the failure reason to FAILURE_REASONS_FORCE_RENDERER.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-07-18 17:58:45 +02:00
Leandro Ribeiro
2efc1838cb backend-drm: rename renderer-only to renderer-and-cursor mode
In the next commit we introduce a real "renderer-only" mode. So let's
rename DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY to
DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR, as it also assign views
to cursor planes.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-07-18 17:58:45 +02:00
Jeri Li (李杰)
44533f0ed6 ivi-shell: print surface id with decimalism
when use weston-debug to print view info, make sense if
use decimalism align with the configurable ivi surface id

Signed-off-by: Jeri Li <jeri.li>
2025-07-17 11:02:42 +00:00
Jeri Li
0f969fd6b0 ivi-shell: print available description of desktop surface
set label func for desktop surface, then it can
print available description of desktop surface

Signed-off-by: Jeri Li <jeri.li>
2025-07-17 11:02:42 +00:00
Deborah Brouwer
088c8ec21b gitlab-ci: Bump tag to rebuild containers
Bump the tag to trigger container rebuild to include new kernel and also
ci-templates updates.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Deborah Brouwer
5db61f07aa gitlab-ci: Bump kernel from 6.3 to 6.14
Update the kernel used in CI from version 6.3 to 6.14.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Deborah Brouwer
87dea962b8 tests: Use new buffer for second screenshot
When the same buffer is reused for both the first and second screenshot,
this can result in a deadlock. Avoid the issue by using a new buffer for
the second screenshot.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Deborah Brouwer
624d8b2d3d gitlab-ci: Format gitlab logs for build-and-test.sh
Use the FDO_CI_BASH_HELPERS functions from ci-templates to format the
gitlab ci logs for build-and-test.sh. This adds collapsible sections to make
the overall log easier to read.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Deborah Brouwer
675bb24a57 gitlab-ci: Move build-and-test script to separate file
Move the script from the build-and-test job to a separate bash file.
This makes it easier to read the .gitlab-ci.yml file and to edit the bash
script.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Deborah Brouwer
a1360d72f4 gitlab-ci: Format gitlab logs for build-deps.sh
Use the FDO_CI_BASH_HELPERS functions from ci-templates to format the
gitlab ci logs for build-deps.sh. This adds collapsible sections to make
the overall log easier to read.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Deborah Brouwer
86517d36d3 gitlab-ci: Update ci-templates
Update the ci-templates so that the ci tests can use new template
features such as gitlab log formatting.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Deborah Brouwer
28f1dfae95 gitlab-ci: Remove CONFIG_DRM_KMS_FB_HELPER config
CONFIG_DRM_KMS_FB_HELPER was removed in v5.14, it doesn't hurt to have
it here, but removing it makes the code clearer.

Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
2025-07-17 10:42:30 +03:00
Marius Vlad
8618a29649 shell.lua: Add output_resized callback handler
When resizing the outputs, re-create the background and relayout the
views according to the (newer) output dimensions.

This is a common feature amongs our shells, so do this for lua-shell as
well.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-07-08 22:48:19 +03:00
Marius Vlad
56b768d934 shell.lua: Add a helper to re-create background
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-07-08 22:47:46 +03:00
Derek Foreman
5a48cedc7b drm: Improve VRR timing at start of repaint loop
There was an old kernel bug where the drm driver could give us a stale
timestamp. We worked around this by performing a page flip at the
start of the repaint loop.

Now that we support VRR, when we don't render our refresh rate drops to the
display's lowest possible refresh rate. This leaves us with a race where
the repaint loop could be started between the mode's refresh rate and the
lowest possible VRR rate - which is indistinguishable from a stale
timestamp. In this case we'd perform a needless page flip and potentially
miss an opportunity to render.

The kernel bug was introduced in v3.16 in commit 844b03f27739135 and later
fixed in v4.1 in commit fdb68e09bbb1c98

Since the vrr_capable property was introduced in v4.20 in commit
ba1b0f6c73d4ea1, any kernel that supports VRR is new enough not to give us
stale timestamps, so we don't have to miss these opportunities.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-06-27 14:51:49 +01:00
Erico Nunes
2d34d32893 vulkan-renderer: support dmabuf renderbuffers
Initial support for dmabuf renderbuffers, based on the GL renderer
implementation.
This enables Vulkan renderer to use the pipewire backend with dmabuf.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-06-25 14:12:22 +00:00
Erico Nunes
33c418a85b vulkan-renderer: rework Vulkan dmabuf import
Rework the dmabuf import Vulkan code so that it is possible to reuse
a single routine across the DRM backend gbm import and dmabuf client
import.
This is will also make it possible to reuse it for dmabuf renderbuffers
as a follow-up.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-06-25 14:12:22 +00:00
Erico Nunes
4685cb1d1c vulkan-renderer: rework render_fence_fd
Decouple render_fence_fd from the DRM output, in particular so that
it is allowed in headless outputs (for upcoming dmabuf renderbuffers).
Also simplify the code to make it clear that it is handled per-output.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-06-25 14:12:22 +00:00
Erico Nunes
1a9d46e3bc vulkan-renderer: move render_done semaphore to image
For swapchain outputs, in some cases it is possible that a frame becomes
available by its fence but the last used swapchain image has still not
been returned to the swapchain. If the render_done semaphore is part of
the frame struct it will be reused and cause a validation error.
To prevent this from happening, move the render_done semaphore to the
image struct so that each of those semaphores is only used when the
associated image is safely acquired from the swapchain.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-06-25 14:12:22 +00:00
Erico Nunes
a79e7c3e8d clients/simple-vulkan: move render_done semaphore to image
In some cases it is possible that a frame becomes available by its
fence but the last used swapchain image has still not been returned to
the swapchain. If the render_done semaphore is part of the frame struct
it will be reused and cause a validation error.
To prevent this from happening, move the render_done semaphore to the
image struct so that each of those semaphores is only used when the
associated image is safely acquired from the swapchain.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-06-25 14:12:22 +00:00
Marius Vlad
feb4fd1386 compositor, frontend: Allow to configure placeholder-color
This is a trivial change to allow passing a user-defined color to
specify the color for the placeholder.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-24 16:00:05 +03:00
Pekka Paalanen
0a76b639fe backend-rdp: fix build with freerdp 3.15.0
Every .c file in RDP-backend hits this:

cc -Ilibweston/backend-rdp/rdp-backend.so.p -Ilibweston/backend-rdp
-I../../git/weston/libweston/backend-rdp -I. -I../../git/weston
-Iinclude -I../../git/weston/include -Ilibweston
-I../../git/weston/libweston -I/home/pq/local/include
-I/usr/include/pixman-1
-I/usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/freerdp3/
-I/usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/winpr3
-I/usr/include/libdrm -fdiagnostics-color=always
-fsanitize=address,undefined -fno-omit-frame-pointer
-D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Wpedantic -Werror
-std=gnu11 -O0 -g -Wmissing-prototypes -Wno-unused-parameter
-Wno-shift-negative-value -Wno-missing-field-initializers -Wno-pedantic
-Wundef -fvisibility=hidden -Wmissing-prototypes -Wno-unused-parameter
-Wno-shift-negative-value -Wno-missing-field-initializers -Wno-pedantic
-Wundef -fvisibility=hidden -fPIC -MD -MQ
libweston/backend-rdp/rdp-backend.so.p/rdp.c.o -MF
libweston/backend-rdp/rdp-backend.so.p/rdp.c.o.d -o
libweston/backend-rdp/rdp-backend.so.p/rdp.c.o -c
../../git/weston/libweston/backend-rdp/rdp.c

In file included from /usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/freerdp3/freerdp/client/rdpgfx.h:28,
                 from /usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/freerdp3/freerdp/gdi/gdi.h:34,
                 from /usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/freerdp3/freerdp/freerdp.h:35,
                 from ../../git/weston/libweston/backend-rdp/rdp.h:32,
                 from ../../git/weston/libweston/backend-rdp/rdp.c:37:
/usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/freerdp3/freerdp/codecs.h:93:9: error: ‘codecs_free’ is deprecated: [since 3.6.0] Use freerdp_client_codecs_free [-Werror=deprecated-declarations]
   93 |         WINPR_DEPRECATED_VAR("[since 3.6.0] Use freerdp_client_codecs_new",
      |         ^~~~~~~~~~~~~~~~~~~~
In file included from /usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/winpr3/winpr/winpr.h:22,
                 from /usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/winpr3/winpr/stream.h:26,
                 from /usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/freerdp3/freerdp/freerdp.h:25:
/usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/freerdp3/freerdp/codecs.h:91:47: note: declared here
   91 |                              FREERDP_API void codecs_free(rdpCodecs* codecs));
      |                                               ^~~~~~~~~~~
/usr/lib/x86_64-linux-gnu/pkgconfig/../../../include/winpr3/winpr/platform.h:497:41: note: in definition of macro ‘WINPR_DEPRECATED_VAR’
  497 | #define WINPR_DEPRECATED_VAR(text, obj) obj __attribute__((deprecated(text)))
      |                                         ^~~
cc1: all warnings being treated as errors

Looks like there is a magic define that fixes this, as we are not using
the deprecated things to begin with.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-23 13:19:40 +00:00
Robert Mader
c8f71ff503 pixel-formats: Move FOURCC defines to weston-drm-fourcc.h
Which is the correct place for them.

Currently they cause warnings like:
```
/usr/include/libdrm/drm_fourcc.h:389:9: warning: ‘DRM_FORMAT_S010’ redefined
```

with libdrm >= 2.4.125.

Fixes: 3dce9e8c2 (pixel-formats: Add Sx1x software decoder formats)
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-06-23 15:03:06 +02:00
Taehyeon Jeong
0add10986d input: improve keyboard keys array traversal in notify_key()
The loop in notify_key() that traverses the keyboard keys array has been
improved by adding a break statement after removing a key and simplifying
the loop structure. This eliminates unnecessary iterations and removes
ambiguity in the code flow, making it both more efficient and clearer.

Signed-off-by: Taehyeon Jeong wxogus25@gmail.com
2025-06-20 20:17:37 +00:00
Derek Foreman
37bf61c68c drm: Fix pageflip counter crash when using multiple backends
We need to skip non-drm backends in the output list to avoid a NULL pointer
dereference.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-06-20 14:05:08 -05:00
Robert Mader
3dce9e8c24 pixel-formats: Add Sx1x software decoder formats
Expected to land in Linux 6.17 and already pulled into a
libdrm release (2.4.125).

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-06-17 15:07:01 +02:00
Pekka Paalanen
275155812c color: fine-tune pipeline printing
Separate the parts a bit better.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
6b051ce76b color: print details of the color pipeline
Give a little more insight to the values in a pipeline.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
c533be60d6 color: fix count_parameters type
It's a count, so it's not a bool. Luckily the only counts ever assigned
to it so far were 0 and 1.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
4d6e690fd0 color: de-dup curve printing
Less repetition, easier to modify the format later.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
2fc5e8b2e9 color-lcms: fix lcms matrix printing
If the offset was negative, there would be no space between the columns:

    Matrix
       1.0025  0.0000  0.0000-0.0012

Add the space.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
fec6a3c51e color: print CIE xy with 4 decimals
Usually even three is enough, but D65 tends to be given with four.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
5f22ba7e2e color: refactor to weston_color_gamut_fprint()
Removes repetition and makes weston_color_profile_params_to_str() a
little more concise. Eases changing the xy number formatting next.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
acd3e557af color: shorten the named of primaries
These can be much more terse and still remain completely readable,
improving debug prints' readability.

Only one place needs to explicitly mention it's about primaries, the
rest are already evident.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-17 10:40:03 +03:00
Pekka Paalanen
16e958607a color-lcms: clarify ICC-to-ICC pipeline prints
In the future parametric<->ICC color transformations will be a thing.
Clarify that the printed pipeline is just the ICC-to-ICC part of it.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-16 17:01:17 +03:00
Pekka Paalanen
ddd03a3606 color: drop "transfer function" from TF descriptions
Several places that print this string already include "transfer
function", so there is no need to say it twice. The one place where it
is needed is fixed accordingly. Other places already imply it enough.

This shortens the prints without losing anything.

A few descriptions are improved to help understanding.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-16 17:01:17 +03:00
Marius Vlad
a4494f2ea3 backend-drm: Use a local variable to store output frame rate data
As otherwise we might trip because the output might be not available.

Fixes: cda8de1089 ("backend-drm: Count and display KMS page flips")

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-10 12:00:07 +00:00
Pablo Saavedra
c0dfeaf156 frontend: Assign output before registry shared output init
Set the shared output's Weston output reference before obtaining
the registry from the parent display. Ensures proper access to
output context during registry event handling.

Also prevent weston_seat_init when shared output lacks a compositor,
avoiding crashes on invalid initialization.

Signed-off-by: Pablo Saavedra <psaavedra@igalia.com>
2025-06-09 12:18:03 +00:00
zhou liang
fc3e3cf653 compositor: prevent weston_surface references a destroyed output
weston_surface retains a pointer to its associated output, but if the
output is destroyed, the pointer becomes invalid. In set_fullscreen(),
weston_shell_utils_get_focused_output may return this stale output via
weston_keyboard, leading to a use-after-free crash.

This change ensures the output reference is cleared when the output is
destroyed, preventing potential crashes.

Signed-off-by: zhou liang <liang.zhou@gehealthcare.com>
2025-06-09 11:23:37 +00:00
zhou liang
0286b37d76 xdg-shell: Reset configure_idle to NULL at first
To prevent configure_idle from being called again by wl_event_source_remove,
now set configure_idle to NULL inside its handler function. This ensures
the idle source won't be removed multiple times if the handler is called
again.

Signed-off-by: zhou liang <liang.zhou@gehealthcare.com>
2025-06-07 15:08:08 +08:00
Joshua Goins
dc33a296b8 doc: Update to the new --no-resizable RDP flag
This was changed in 75280d2e40 but only
updated in the weston CLI help. But there's still documentation leftover
in .ini files and manpages that refer to the older flag.

Signed-off-by: Joshua Goins <joshua.goins@kdab.com>
2025-06-04 15:38:05 -04:00
Marius Vlad
0600265c64 frontend: Make use of the advertised debug scopes
This patch introduces a new cmd line option, namely `--debug-scopes`
(or shorthand `-d`) to limit which debug scopes are being advertised
over the westond-debug protocol.

To avoid tedious work to make this work in the same time as `--debug`, a
boolean type of option which doesn't accept any other entries, I've
decided to have a dedicated string cmd line argument.

If passing `--debug` all debug scopes are advertised by default
(keep the same behaviour). If you'd like to limit which of those scopes are
advertised, use the -d and only that one those scopes be advertised.
Pass these as a command-separated list.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-04 17:43:47 +03:00
Marius Vlad
2dd870adac weston-log: Add a advertised list of debug scopes
This introduces a new list that is being checked up when advertising
or when the client attempts to bind a debug scope.

This would allow for a way in which the frontend can determine which
debug scopes the weston-debug protocol can advertise or the client
using the protocol can bind to.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-04 17:43:33 +03:00
Marius Vlad
762e286a44 cp: Correctly format debug scope for content protection
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-04 17:38:16 +03:00
Marius Vlad
a3ab74028a launcher-libseat: Don't hard-stop on libseat-debug
If not libseat-debug scope is not set we would hit an assert, and
we might have a legitimate case where we don't want to have it enabled.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-04 17:38:16 +03:00
Marius Vlad
1181d638ac timeline: Check for timelog scope being enabled
As further weston_log_subscription_iterate implicitly assumes we can
create one, and that might not be always the case.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-04 17:38:16 +03:00
Marius Vlad
413e471fb1 gl-renderer: Don't hard-stop if debugging scopes aren't enabled
We might not want to enable these scopes always so don't limit
the GL-renderer availability based if these are enabled or not.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-04 17:38:16 +03:00
Derek Foreman
e91eccd709 lua-shell: Add lua-shell
lua-shell is a new meta-shell for Weston. It does nothing in and of
itself, but is defined to be user-scriptable and configurable. A
supplied Lua script will be interpreted and executed by Weston, allowing
full control over window management in response to events.

This includes a shell.lua example script which behaves as a tiling WM.

Co-authored-by: Michael Tretter <m.tretter@pengutronix.de>
Co-authored-by: Marius Vlad <marius.vlad@collabora.com>
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-06-04 15:47:06 +03:00
Derek Foreman
cf44b691c6 compositor: Add weston_view_move_before_layer_entry
Add a function to move a view in front of a layer entry, so we can easily
add this functionality to lua-shell in a future commit.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-06-04 15:39:03 +03:00
Pekka Paalanen
c24685d14b tests/color-icc-output: reduce tolerance on BT2020 MAT
I don't know when this was improved, I just noticed that we can reduce
the tolerance here.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Pekka Paalanen
556272bae9 color-lcms: change stock sRGB to true power-2.2
The sRGB expected display behavior uses the pure power-law with exponent
2.2, not the two-piece sRGB transfer function.
cmsCreate_sRGBProfileTHR() used the two-piece TF, now we use the proper
display TF.

This is particularly meaningful when implicit sRGB content is converted
to HDR formats, in order to maintain the stimuli reproduction near zero.

cmlcms_send_image_desc_info() is already sending this, it doesn't need
fixing.

Changing the curve also changes the error tolerances. The change is
theoretically a no-op, but the curve and its inverse and temporary
rounding add error. The new curve is more prone to error, so it is not
surprising we need to raise the tolerance. The color transformation does
end up as power-2.2 analytical form and I do not think it is ever
lowered to a LUT in alpha-blending test, so there is no obvious fix
improving the accuracy. The worst case point in alpha-blending still
occurs at the very same point as before.

The test reference images are updated for the same reason, they would
fail otherwise.

Both alpha-blending and color-icc-output contain the same sRGB-optical
sub-test, hence the same error tolerance.

It is surprising to have to increase the ICC roundtrip error tolerance
in color-icc-output test, given that the curves are passed as parametric
to LittleCMS, and adobeRGB case works with the old tolerance even. I did
not investigate further.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Pekka Paalanen
718f7f56df tests/color_util: add power-2.2 transfer function
This is needed by the next commit.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Pekka Paalanen
8468289fa3 tests/color_util: move lcms2 data into struct tone_curve_info
Refactoring data about a thing into one place to simplify code.

Also this function is never expected to fail, so no need for the boolean
return.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Pekka Paalanen
015533bac5 tests/color_util: convert 4 switches into a table
Collect all information of an item into a table entry in one place. Will
be easier to add new items this way.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Pekka Paalanen
338d727d99 tests: drop EOTF from TRANSFER_FN_SRGB_EOTF
The sRGB display uses a power-2.2 transfer characteristic. These enum
values refer to the two-piece sRGB transfer function instead, so they
should not be named "EOTF".

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Pekka Paalanen
b2bc30034b color-lcms: do not smooth monotonic shapers
When I was changing the stock sRGB profile from the two-piece TF to the
power-2.2 TF, all CLUT tests in color-icc-output started failing. It
appeared that cmsSmoothToneCurve() caused an already monotonic curve to
become non-monotonic, and then failing its own monotonicity test. I can
only guess that it might have something to do with the power-2.2 curve
having nearly zero derivative near zero.

As a workaround, check if the curve is already monotonic and don't
bother smoothing in that case. This allows the tests to pass in the
future where the sRGB profile has been changed.

OTOH, increasing smoothing_param up to 10.0f still did not help.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Pekka Paalanen
bf1d8c458b color: check steps_valid in weston_color_transform_string()
Do not want to print the steps if they are not correct.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-06-03 15:47:20 +03:00
Marius Vlad
63264ae3f4 weston-drm-fourcc: Add fallback for P030
As DRM_FORMAT_P030 was introduced in some later libdrm (2.4.114)
version add a fallback for it to allow building on systems which do
not have that libdrm version.

Fixes 4f4011d79e ("pixel-formats: Add P030")

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-03 06:38:27 +01:00
Marius Vlad
b2c8f35c23 renderer-vulkan: Allow to compile without Vulkan renderer
As spotted in the wild, building without Vulkan still picks up
Vulkan headers. This drops the VkInstance alltogether as that's not
really used.

As this file appears to be pulling XCB headers guard them as well.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-06-02 14:37:59 +03:00
Pekka Paalanen
135b95808c shared: fix matrix type computations
When I changed the weston_matrix implementation to linalg-4.h, I broke
the type computations: they were getting reset instead of accumulated.
This manifested with the desktop-shell feature where one can arbitrarily
rotate the windows. A rotated window triggered an incorrect matrix type,
which then did not ignore the surface opaque region as it should have.
That caused rendering artifacts on all renderers.

Fixes: 3fefb5ba44
Fixes: https://gitlab.freedesktop.org/wayland/weston/-/issues/1031

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-05-30 11:45:08 +00:00
Derek Foreman
a124b19a01 compositor: Remove weston_view_damage_below()
It has no more callers, and hasn't done what its name implies for a very
long time.

Remove it.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-05-30 11:38:47 +00:00
Derek Foreman
cc0edfd13d compositor: Remove weston_view_damage_below from transform add/remove
weston_view_damage_below() does nothing but schedule a repaint, and a
repaint will be scheduled in weston_view_geometry_dirty_internal() anyway,
so remove the extra call.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-05-30 11:38:47 +00:00
Derek Foreman
1683d7a9d2 compositor: Schedule a repaint directly in weston_view_unmap
Instead of calling weston_view_damage_below(), which only schedules a
repaint, call weston_view_schedule_repaint() instead.

The result is the same, but the code is less confusing.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-05-30 11:38:47 +00:00
Derek Foreman
601a72dd8c compositor: Remove weston_view_damage_below calls from update_transform
Update transform only does something if we've called
weston_view_geometry_dirty_internal() previously to set the dirty flag.

weston_view_damage_below() just schedules a repaint, and
weston_view_geometry_dirty_internal() will already have done that.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-05-30 11:38:47 +00:00
Derek Foreman
7900235fee desktop-shell: Remove weston_view_damage_below from desktop_view_destroy
weston_view_damage_below() has done nothing but schedule a repaint for a
long time now.

weston_view_destroy() will trigger the repaint without forcing it here.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-05-30 11:38:47 +00:00
Marius Vlad
e70cfe319c fullscreen-shell: Deprecate fullscreen-shell and screenshare module
kiosk-shell/xdg-shell is the (more) modern approach, so let's inform
users that fullscreen-shell is going way.

This also adds an explicit dependency of shell-fullscreen for
screenshare. With this change, both screenshare and fullscreen-share
are disabled by default.

Fixes: #848

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-30 14:31:08 +03:00
Marius Vlad
b3480f5b30 backend-wayland: Remove zwp_fullscreen
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-30 14:31:07 +03:00
Daniel Stone
300d059044 libweston: Remove PAINT_NODE_CONTENT_DIRTY
This was only used by weston_surface_damage(), which we have just
gleefully deleted.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 16:46:05 +01:00
Daniel Stone
816e4180bc libweston: Remove weston_surface_damage()
There is no valid reason for anyone to call this.

True surface damage is already handled when surfaces are committed. View
damage is already handled through any per-view manipulation which would
generate damage. There is thus no reason for anyone to ever call this.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 16:45:43 +01:00
Daniel Stone
653182759f libweston: Damage outputs for content-protection changes
The content-protection state is a property of the output, as it affects
quite a bit of output state, as well as things like whether or not
recording is possible.

Instead of damaging surfaces for content-protection state changes,
damage each output for which the protected surface is relevant.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 16:45:31 +01:00
Daniel Stone
9a5b4087c8 libweston: Remove weston_surface_damage() from subsurface commit
When we change the subsurface order, the surface itself has not received
any damage: what's been damaged is the views. Place the damage where it
should be, as the act of moving the view within the view list is where
the damage originates from.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 16:45:10 +01:00
Daniel Stone
179aae34f7 desktop-shell: Remove damage for curtain
There is no need to damage a curtain. Adding or removing a view is what
causes the damage.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 15:47:30 +01:00
Daniel Stone
44c2c3ce72 desktop-shell: Remove weston_surface_damage() from rotate
This already calls either weston_view_add_transform() or
weston_view_remove_transform() followed by
weston_view_update_transform(), the combination of which will already
force a repaint for those views.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 15:47:30 +01:00
Daniel Stone
0aafc50419 libweston: Remove weston_surface_damage() from view-layer
This already calls weston_view_geometry_dirty_internal() and
weston_view_update_transform(), the combination of which will already
force a repaint for those views.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 15:47:30 +01:00
Daniel Stone
d90eed2b99 libweston: Remove weston_surface_damage() from view-alpha update
This already calls weston_view_geometry_dirty_internal() and
weston_view_update_transform(), the combination of which will already
force a repaint for those views.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 15:47:30 +01:00
Daniel Stone
c71ae0c89b libweston: Remove weston_surface_damage() from view-transform
These already call weston_view_geometry_dirty_internal() and
weston_view_update_transform(), the combination of which will already
force a repaint for those views.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-28 15:47:30 +01:00
Erico Nunes
8e7ca3a470 backend-pipewire: add Vulkan renderer support
Add the Vulkan renderer in the pipewire backend renderer switches.
For now this goes over the pipewire memfd path.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-27 17:13:15 +02:00
Erico Nunes
508d5f0bea backend-rdp: add Vulkan renderer support
Add the Vulkan renderer in the rdp backend renderer switches.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-27 17:13:15 +02:00
Erico Nunes
3c2ff4324b backend-vnc: add Vulkan renderer support
Add the Vulkan renderer in the vnc backend renderer switches.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-27 17:13:15 +02:00
Erico Nunes
30aacca3ff vulkan-renderer: add readback for renderbuffers
This will allow use of the vnc, rdp and pipewire (memfd) backends
with the Vulkan renderer.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-27 17:13:02 +02:00
Erico Nunes
f8af0dbf72 vulkan-renderer: fix read pixels for sub regions
The captured buffer cannot be just memcpy'ed to the destination as
it might overwrite existing pixels outside of the capture region.
For now switch it to a pixman composition.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-27 10:45:00 +02:00
liang zhou
4e4d7993ba xdg-shell: fix weston crash while send configuration
When xdg_toplevel_send_configure is executed, the xdg_toplevel resource
may have already been destroyed, causing Weston to crash.

Signed-off-by: liang zhou <liang.zhou@gehealthcare.com>
2025-05-25 03:04:40 +00:00
Erico Nunes
df8af39a2a gitlab-ci: Create some jobs for Vulkan build coverage
Adjust the no-GL jobs to also do no-Vulkan and only create a couple more
to cover disabling the individual renderers.
Copy the hack for obscure LLVM leak reports so that tests can pass in CI
with lavapipe for a Vulkan driver.
Disable vulkan-renderer build on debian lts for now as unsupported.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Erico Nunes
5536a98e97 clients/simple-dmabuf-vulkan: New Vulkan client example
Example to serve as a reference of a basic Wayland client using
Vulkan with dmabuf. This does not use a traditional Vulkan swapchain
but implements it using imported gbm buffers. Also features use of
linux-explicit-synchronization-unstable-v1 with Vulkan.
Based on weston-simple-dmabuf-egl.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Erico Nunes
75c37afa62 clients/simple-vulkan: New Vulkan client example
Example to serve as a reference of a basic Wayland client using
Vulkan, contained in a single source file and with a minimal set
of dependencies.
Features incremental present (similar to swap_buffers_with_damage
from EGL) which is not commonly used by other Vulkan demos and is
useful to test the compositor.
Based on weston-simple-egl.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Erico Nunes
ec52e0cdda tests: Add support for Vulkan renderer
Add support for Vulkan renderer in most places where there was
support for GL renderer.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Erico Nunes
8f56d03d4b libweston: Vulkan renderer
A Vulkan renderer for weston, based on the GL renderer.
The goal is to impose the least requirements as possible on Vulkan
implementations, as to allow even Vulkan 1.0 (or early development)
drivers to run a Wayland compositor. Any additional features or
extensions are made optional if possible.
Currently supports drm, wayland, x11 and headless backends.
As of this implementation, this is still considered an experimental
renderer.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Erico Nunes
60f7b59d8f gitlab-ci: Prepare base CI images for Vulkan build and tests
Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Erico Nunes
76431a952f clients/simple-dmabuf-egl: Add missing destructors
Destructors for zwp_linux_explicit_synchronization_v1 and
weston_direct_display_v1 were missing.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Erico Nunes
ad4746101a tests: Remove gl_ suffix from force_full_upload
This will also be used for Vulkan-renderer tests.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-23 20:36:05 +01:00
Rémi Bernon
2f35f84d8e
xwayland: Activate no_focus_window when a Wayland window is activated
None active window might be interpreted from an X point of view as a
transient focus state, and is used by multiple X window managers when
a temporary focus change is in progress, or simply when grabbing the
keyboard.

From Wine side, we translate any active window change to the Win32
application, and handling None active window as an actual window
deactivation and focus loss creates spurious events and an undesired
feedback loop, as apps might react to it.

We still want to be able to detect actual focus loss under an XWayland
session, and having XWayland window manager focus an actual X window
instead will make the distinction possible.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
2025-05-23 18:07:02 +02:00
Rémi Bernon
87ae07b63f
xwayland: Create a dummy no_focus_window to use for non-X window focus
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
2025-05-23 18:07:02 +02:00
Erico Nunes
4ab8d6d2c4 libweston: move gl-borders up to weston_renderer
This just moves gl-borders up to libweston weston_renderer as-is,
with no change in functionality.
This is a preparation step so that other renderers can use the
same interface.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-18 18:00:08 +02:00
Pekka Paalanen
f71db77341 tests/client-buffer: reduce the scope of #if
Containining the pre-compiler conditionals inside tiny functions makes
the code easier to read.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-05-15 16:24:53 +03:00
Pekka Paalanen
381bc2761f tests/client-buffer: annotate unintended test cases
These cases were never meant to exist, but because the harness assumes
all tests must run on all fixtures, we have to return something.

This is a temporary measure to improve readability. Eventually this test
program should be split:

- shm RGB + YUV
- dmabuf RGB without force-yuv-fallback
- dmabuf YUV with and without force-yuv-fallback

or

- shm RGB + YUV
- dmabuf RGB + YUV without force-yuv-fallback
- dmabuf YUV with force-yuv-fallback

or

- shm + dmabuf; RGB + YUV without force-yuv-fallback
- dmabuf YUV with force-yuv-fallback

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-05-15 16:24:53 +03:00
Pekka Paalanen
33d82b6b79 tests/client-buffer: handle no-list in format_must_pass()
Make the callers simpler and easier to read.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-05-15 15:49:23 +03:00
Robert Mader
55a85e8e16 pixel-formats: Remove unimplemented header
The implementation got removed already and we can just check
the color_model now.

Fixes: 51ed256d (libweston: Replace pixel format's sampler_type with color_model enum)

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-05-15 15:08:18 +03:00
Robert Mader
fe5a846512 tests: client-buffer: Use gl_force_import_yuv_fallback quirk
Ensure we test our internal YUV->RGB shader and multiplane paths.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-05-15 15:08:18 +03:00
Robert Mader
d24caf5f32 gl-renderer: Add gl_force_import_yuv_fallback test quirk
Forcing the fallback paths for YUV formats. This will allow us
to test these paths on CI now that llvmpipe supports all tested
formats natively.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-05-15 15:08:18 +03:00
Robert Mader
65e3a7324a tests: client-buffer: Return RESULT_SKIP where appropriate
Split up the test to run it for SHM and DRM individually so we
get fine-grained results.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-05-15 15:08:18 +03:00
Robert Mader
68aed0775e tests: client-buffer: Remove llvmpipe workarounds
The issue were fixed in
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34775

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-05-15 15:08:18 +03:00
Robert Mader
e476276bf6 gitlab-ci: Bump wayland-protocols to 1.44
Which we'll need soon, so reuse the image bump in the previous
commit.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-05-15 15:08:18 +03:00
Robert Mader
244f930365 gitlab-ci: Build with llvmpipe multiplanar YCbCr support
As well as fixes for broken packed YUYV variants.

Latest Mesa requires Meson >= 1.3.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-05-15 15:08:18 +03:00
Leandro Ribeiro
e6289aee68 color-lcms: rewrite misleading comment
Update a comment explaining what we may do in the future when
cmsSmoothToneCurve() fails.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-15 14:42:45 +03:00
Daniel Stone
4393bec40a core: Short-circuit assign_outputs() during shutdown
If we're shutting down, moving surfaces to a different output will not
be profitable. Just clear out the output mask entirely and return early.

This specifically avoids the following issue seen with the Wayland
backend when shutting down:
  - outputs destroyed
  - colour manager destroyed
  - seats destroyed
  - pointer destroyed
  - sprite view destroyed
  - find new output for the sprite view
  - update colour profile for the sprite view
  - neither the view nor the compositor has any outputs left
  - try to use the stock sRGB transfer
  - oops, no colour manager

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-05-14 17:24:43 +00:00
Leandro Ribeiro
8ef3423bf7 color: remove unused WESTON_COLOR_MAPPING_TYPE_3D_LUT
Since "color: do not use color steps for non-optimized pipelines",
WESTON_COLOR_MAPPING_TYPE_3D_LUT became unused. So drop it from our
code.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
df07af056d color: do not use color steps for non-optimized pipelines
For non-optimized pipelines, stop using the color steps (pre curve,
color mapping and post curve). Instead, make use of the
xform->to_shaper_plus_3dlut() vfunc.

In this patch we add a bool to signalize that the steps are valid (for
optimized pipelines) or not. If not (non-optimized ones), the vfunc must
be used.

This brings flexibility for the renderer/backend implementing the xform.
For now we only implement xform's in the GL-renderer, and this has no
behavior changes. It should be relevant when we implement the xform in
our DRM-backend, see commit "color: add to_shaper_plus_3dlut() vfunc to
struct weston_color_transform".

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
3187999208 tests: add color-math-test
This tests a few mathematical operations that are common to color work.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
0945ac3fa8 color: add to_shaper_plus_3dlut() vfunc to struct weston_color_transform
This function allow us to get a shaper (3x1D LUT) + 3D LUT that is
equivalent to a certain xform.

With that, we allow backend/renderer that are not capable of handling
the color steps of the xform to fallback to something else.

E.g. when we introduce the code to offload color xform to KMS using the
DRM-backend, we'll depend on the driver/hardware implementing the color
steps. With this patch, DRM-backend should be able to fallback to a
shaper (3x1D LUT) + 3DLUT, color operations that should be commonly
supported by drivers/hardwares.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
9f1cf0db24 color-lcms: keep fallback LCMS xform even when pipeline is optimized
Up to now, when we were able to optimize a color pipeline, we'd delete
xform->cmap_3dlut. In such cases, we'd have a pre curve, color mapping
and post curve that Weston recognizes and implements in the shaders. So
there was no need to use xform->cmap_3dlut.

But at some point we'll try to offload such color transformations to our
DRM-backend, and we are not in control of what color operations the
hardware/driver are capable of. In such case, we may want to use the
fallback LCMS xform (xform->cmap_3dlut) and decompose it into a shaper
(3x1D LUT) + 3D LUT, as such operations should be commonly supported
by hardwares/drivers.

This shows that using the optimized pipeline or not should be a
renderer/backend decision. So do not delete xform->cmap_3dlut even when
we optimize the pipeline.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
b3fae5ae6b gl-renderer: split gl_color_curve_lut_3x1d()
For now this is useless, but in the next commits this split will be
pretty useful.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
4fe16c1bec gl-renderer: split gl_color_mapping_lut_3d()
For now this is useless, but in the next commits this split will be
pretty useful.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
334ae04614 gl-renderer: cosmetic improvement to gl_color_mapping_lut_3d()
Change this function signature to look similar to
gl_color_curve_lut_3x1d(), as they do similar things.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Leandro Ribeiro
209a5b8400 gl-renderer: rename gl_3d_lut() to gl_color_mapping_lut_3d()
We are filling a struct gl_renderer_color_mapping in this function,
so rename to better reflect that.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-05-13 17:36:52 +03:00
Erico Nunes
14d95cd6ce tests: client-buffer: Support must pass list per renderer
This test has only supported the GL renderer, with a must pass list of
formats which matches what the GL renderer advertises and supports.
This commit prepares the test to support other renderers by moving the
must pass list to the test setup declaration, so that it can be defined
per renderer. This is in preparation to add more renderers here as a
followup.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-13 17:08:52 +03:00
Erico Nunes
6f6576dec2 tests: client-buffer: Add arguments to fixture setup
Prepare to add more multiple renderer options.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-13 17:08:52 +03:00
Erico Nunes
0c84f990d6 tests: output-decorations: Add arguments to fixture setup
Prepare to add more multiple renderer options.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-05-13 17:08:52 +03:00
Marius Vlad
d76a89c9d8 debug-flight-recorder.rst: Describe how to grab flight recorder
As I found myself writing these for a MR think it would better
to have to easily available to point people to.

Another small change is that since c706e1f8c8 we no longer
default subscribe to drm-backend for the flight recorder so update docs
as well. Combined with this new file should actually explain better how
to make use of it.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-13 10:10:23 +03:00
Marius Vlad
a40c638003 doc/sphinx/conf.py.in: Change sphinx.ext.intersphinx
To latest change.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-12 20:29:01 +03:00
Marius Vlad
ac2bbe24cb doc/sphinx/doxygen.ini.in: Removed deprecated HTML timestampt option
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-12 15:15:01 +03:00
Marius Vlad
35da5ca5a6 xdg-client-helper: Use a default WINDOW size value
If the shell doesn't provide a configure size, use a default one.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-06 15:30:37 +03:00
Marius Vlad
7bb9fc5b62 weston-test-client-helper: Move helpers into weston-test-client-helper
As we can re-use this for other tests make them available.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-06 15:27:58 +03:00
Marius Vlad
1296690ede weston-test-client-helper: Use the helper already avaible
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-06 15:27:58 +03:00
Marius Vlad
3b7d29f871 tests: Add xdg-client-helper library
And make use of it in kiosk-shell-test. There's no functional change,
this is for other shells to re-use the code here.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-05-06 15:27:58 +03:00
Pekka Paalanen
5ca78cdf05 color-lcms: accept matrices with offset
Now that color mapping matrix in GL-renderer supports an offset, allow
merging and translating matrix stages with offsets.

color-icc-output test is already hitting these new paths with the
sRGB->sRGB CLUT fixture (number 6), hence new tests are not needed.
Previously, after optimization the pipeline still contained 3
consecutive matrix stages. Now, those three are combined into one.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-05-05 11:26:24 +03:00
Pekka Paalanen
b15dcfe790 gl-renderer: add offset to the color mapping matrix
The offset will be useful for black point handling.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-05-05 11:26:24 +03:00
Pekka Paalanen
42059ce258 libweston: move stuff into colorimetry.h
Add a new header for colorimetry stuff. Adding more things in
libweston.h doesn't feel good, they drown in the sea of everything.

Pure refactoring, no changes.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-30 16:11:58 +03:00
Pekka Paalanen
eadc3d32ce libweston: add C++ braces to linalg headers
Forgot to add these. Looks like all public headers should have them.

Fixes: e8b7ade58b

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-30 16:11:58 +03:00
Pekka Paalanen
e837179f14 build: install linalg-3.h
Forgot.

Fixes: e8b7ade58b

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-30 16:11:58 +03:00
Pekka Paalanen
e57eb5b15d tests: return status from each test definition
Add a status return value to every test definition. There are no
behavioral changes, previously the RESULT_OK was simply assumed.

The benefit of this is that in the future individual tests can also
return RESULT_SKIP, so that we can keep statistics of skipped tests.

ivi-layout-internal-test.c has the only case where a test function may
return early. That one is set to return RESULT_HARD_ERROR to match the
compositor exit code already there.

Also documentation is updated.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-30 15:07:35 +03:00
Robert Mader
303d88448a tests: client-buffer: Add dmabuf support
Using the udmabuf allocator which is usually available these days,
both on CI runners and dev mashines. The buffers have the the same
content are tested against the same reference images as in the shm
case.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-30 11:39:25 +02:00
Robert Mader
33db73f134 tests: client-helper: Add dmabuf protocol support
Allow querying supported formats and modifiers.
We use version 3 as it is easier to implement and also works
if no main device is present - such as when using llvmpipe.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-30 11:13:06 +02:00
Robert Mader
cd35c6c780 gl-renderer: Add YUV422 and YVU422 to yuv_formats
So we can test them on CI. For completeness and because they
are commonly used by SW decoders.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-30 11:13:06 +02:00
Robert Mader
d6f1b2a6a4 tests: client-buffer: Preparations for dmabuf support
Add stride alignment support make various cleanups in
order to support both shm and dmabufs. No changes in
test results intended.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-30 11:13:06 +02:00
Robert Mader
9f0ac15ce6 tests: Rename shm-buffer to client-buffer
In preparation to also test dmabufs.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-30 11:12:38 +02:00
Marius Vlad
6f94022e8c ivi-shell/layout: Create a temporary background curtain
Similar to 0ff5ac0f7b, "desktop-shell: Add a placeholder curtain on
new outputs", to address the 68761d3f11, "compositor: Ensure the
scene graph isn't empty at repaint".

This is needed to allow ivi-shell to start-up otherwise we hit the
assertion introduced with 68761d3f11.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-04-29 17:41:07 +03:00
Pekka Paalanen
edd00d9652 CI: restore junit results in Gitlab
Fix a typo that caused test results to not be found. This adds them back
to the MR and pipeline Gitlab pages.

Fixes: 68fd41a719

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-29 10:27:34 +03:00
Pekka Paalanen
294d4cabd4 gl-renderer: unpack linpow/powlin parameters differently
This consolidates the parameter unpacking for the two types of
parametric curves. The goal is code that reads better.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-28 16:46:43 +03:00
Pekka Paalanen
107e9ed69c gl-renderer use struct to de-dup curves in fragment.glsl
Using more structured types allows removing one of color_pre_curve() and
color_post_curve() completely, reducing code duplication.

Ideally I would have wanted to use a single type for a curve, having
both lut and par in it, but I am not sure the unused half would still be
eliminated during compilation.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-28 16:46:34 +03:00
Pekka Paalanen
dcb4a1012d gl-renderer: de-dup getting curve uniform locations
Reduce pasta, reads better.

Shame that the string manipulation is so cumbersome. All strings are
hardcoded literals though, so the assert is good enough.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-28 16:42:46 +03:00
Derek Foreman
52204f55ea frontend: Fix crash in output resize handler
The output resized signal sends a struct weston_output as the data, not
a struct weston_head.

Fixes 197c5e0084

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-04-24 12:20:53 -05:00
Vlad Zahorodnii
09c8902225 desktop-shell: Fix leaking weston_desktop_surface
If the view has become unmapped, the weston_desktop_surface should still
be unreferenced, otherwise it'll be leaked until the client disconnects.

Signed-off-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
2025-04-16 11:19:59 +00:00
Derek Foreman
4e1e922a28 kiosk-shell: Fix fullscreen_requests
In my haste to fix a crash in kiosk-shell, I made it potentially put
surfaces on wrong outputs instead.

Fixes e1ac6139ca
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-04-16 11:04:36 +00:00
Pekka Paalanen
007a1e1def gl-renderer: assert lut_3x1d scale and offset
Add asserts the same as what the color mapping 3D LUT uses, for
consistency since both implement a LUT with the same principles.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 14:07:05 +03:00
Pekka Paalanen
95cb915d32 gl-renderer: move color mapping asserts to load config
The frequency of checking remaing the same, but we can use an already
needed switch statement and do not need one just for the asserts. This
makes gl_shader_config_set_color_transform() nice and short.

The MAPPING_MATRIX assert was useless, the variable is set right above.

Asserting the mapping type is valid happens already in
gl_shader_load_config_mapping().

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 12:07:45 +03:00
Pekka Paalanen
cf6735a761 gl-renderer: refactor into gl_shader_load_config_mapping()
The new function parameters acts as shorthands, making the moved code a
little more concise. It also gains an assert for an invalid mapping
type, which previously would have been awkward to code.
gl_shader_load_config() becomes easier to read.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 11:57:32 +03:00
Pekka Paalanen
9ce3ce4250 gl-renderer: share color mapping union for gl_shader_config
Reduce divergence between the structs to maybe allow more consolidation
in the future.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 11:38:23 +03:00
Pekka Paalanen
77015ae226 gl-renderer: name the anonymous union in gl_renderer_color_mapping
This is both more consistent with other embedded unions, and it allows
to pull the union out into its own named type in the following patch.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 11:38:23 +03:00
Pekka Paalanen
d1e4ae5e1d gl-renderer: refactor into gl_shader_load_config_curve()
De-duplicate code.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 11:38:19 +03:00
Pekka Paalanen
05f5e400e9 gl-renderer: union gl_shader_color_curve_uniforms
This type name allows for code de-duplication.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 11:35:41 +03:00
Pekka Paalanen
a47fabeaa4 gl-renderer: share curve union for gl_shader_config
This will help reducing the duplicate open-coding of pre- and
post-curves in the following commits. This is also a step towards
eliminating the duplication between struct gl_shader_config and
gl_renderer_color_transform.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-15 11:34:38 +03:00
Pekka Paalanen
70b5ec5bfe color: use weston_mat3f for mapping step
Replace a plain array with a type-safe documented structure.
This will get more wide use later.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-14 17:11:43 +03:00
Pekka Paalanen
98ec0d9b6c color: structurize parametric curve data
Rather than using a two-dimensional array, provide names to the fields.
The fields are primarily used by their names, but we also need the data
as a flat array of floats, so use unions to achieve that: two different
views into the same data.

This makes the code more self-explanatory. In color-operations.c it
removes a handful of temporaries. Comparison in color-properties.c is
simplified. ARRAY_COPY() turns into an assignment.

MAX_PARAMS_PARAM_CURVE is eliminated. Instead of having to maintain a
copy in fragment.glsl, the definition there is automated.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-14 11:00:21 +00:00
Pekka Paalanen
f7bf732004 gl-renderer: make gl-renderer-internal.h selfcontained
This helps me with VScode when clangd doesn't claim this header to be
full of unknown stuff.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-14 11:00:21 +00:00
Derek Foreman
e1ac6139ca kiosk-shell: Fix fullscreen_requests
The output can be NULL, so that must be tested before looking up the
shell_output from the output.

Fixes 77dcbe381f

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-04-11 14:00:32 -05:00
xufeng wang
5eb316d77c libweston: fix crash when getting connector's property failed
When weston tries to update drm head info, if the connector is disconnected, it cannot get the connector's property.

If get connector's property failed, drm_connector_assign_connector_info returns -1 and head->connector->conn, head->connector->props_drm remain to be nullptr, but they are used in update_head_from_connector, so the crash occurs.

So just return ret when drm_connector_assign_connector_info returns -1, and head->connector, head->connector will not be used later.

Signed-off-by: xufeng wang <550002860@gehealthcare.com>
2025-04-11 15:58:22 +08:00
Leandro Ribeiro
8762c3bab5 color: implement perceptual quantizer transfer function
This implements WESTON_TF_ST2084_PQ.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
0af48f0415 color: add function to create 3x1D LUT from color curve
Some external API's (e.g. DRM/KMS) are not capable of dealing with
enumerated color curves. In such cases, we may need to create LUT's that
correspond to such curves and give them to such API's

So add function weston_color_curve_to_3x1D_LUT() to craft 3x1D LUT from
a color curve.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
2ac863397c color: add function to create color curve from tf
When we create a parametric color profile (we still do not fully
support, but plan to), a struct weston_color_tf_info is created.

So add a new function weston_color_curve_from_tf_info() to create a
color curve given a transfer function.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
0ebd2b5e0e color-lcms: rename a few functions
Since "color-lcms: recognize LCMS curves that matches transfer
functions", a few function names became slightly outdated. Rename them.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
ccf6db49b7 color-lcms: recognize LCMS curves that matches transfer functions
LittleCMS curves contain curves that are parametric. They may be
well-known curves, and we are not checking that. If that's the case,
we should create enumerated color curves, instead of parametric.

This can be helpful for renderers and/or backends that want to implement
the curve, as they may have access to an API that accept enumerated
curves.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
209882c7d4 color: add curve type enumerated
Not all color curves comes from parameters. For instance, with the
CM&HDR protocol users can set color curves from tf_info.

So let's add a new curve type to accommodate that.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
0fe575b4a9 color: move LINPOW/POWLIN to new enum weston_color_curve_parametric_type
This just makes the code more readable and should help us to avoid
mistakes in the future. No behavior changes.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
46920d8a61 color-lcms: define max number of params for LittleCMS curves
Follow-up of "color: define max number of params for parametric curves
and tf's". Let's do the same for LittleCMS parametric curves.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
037f2dbff1 color: define max number of params for parametric curves and tf's
Up to now we were using 10 as the max number of params for color curves
and transfer functions. But this came from LittleCMS, whose parametric
curves may contain up to 10 params.

But out color curves and tf's are not tied to LittleCMS, so let's define
constants to help avoid confusion.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Leandro Ribeiro
52262cb06c shared: add weston_assert_uint32_lt_or_eq()
This will be useful in the next commits.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-10 12:43:00 +00:00
Derek Foreman
d9893c6af2 compositor: Fix a potential crash at shutdown
weston_global_destroy_save() can directly destroy a global if the
compositor state is WESTON_COMPOSITOR_OFFSCREEN.

Make sure we don't try to set_user_data after this has happened.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-04-10 12:02:26 +00:00
Robert Mader
81800294a9 gitlab-ci: Bump image
Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-08 21:53:45 +00:00
Robert Mader
682d420b50 gitlab-ci: Build kernel with udmabuf support
With udmabuf we can write test for dmabuf paths in a similar
manner to shm. It's available by default in most recent distros
and thus works OOTB on developer setups.

Drop vgem as it isn't needed any more and makes the CI use
kms_swrast (instead swrast), which isn't compatible with the
llvmpipe dmabuf implementation yet.
Using swrast also streamlines CI with running tests locally,
making debugging easier.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-08 21:53:45 +00:00
Robert Mader
57f48ab91c gitlab-ci: Update Mesa for llvmpipe dmabuf support
llvmpipe now supports EGL_EXT_image_dma_buf_import, allowing
us to test zwp_linux_dmabuf_v1 on CI.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-08 21:53:45 +00:00
Robert Mader
9675ef49f2 gitlab-ci: Update Meson
And clean up accordingly. This is required for the following commit.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-04-08 21:53:45 +00:00
Leandro Ribeiro
cb43a086b5 frontend: improve error message
We have the following error message in parse_color_characteristics():

name=%s: reserved name. Do not use ':' character in the name.

It gets confusing when "name" ends with ':'. So rephrase it to clarify
the error message in such case.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-03 17:50:02 +03:00
Leandro Ribeiro
d3ef4f9576 color: improve code that validates color gamut
First of all, we make it work for NaN CIE xy values.

We also improve the error message a bit. It was only printing that the
color gamut was invalid, but it didn't explain why. This adds the
explanation (out of valid range).

And finally, we make the code a bit shorter.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-03 17:49:53 +03:00
Leandro Ribeiro
25a10fa2cd color: add WL_EXPORT to param builder functions
The internal API to create parametric color profiles should be available
not only to libweston, but also to frontend. WL_EXPORT was missing from
the functions, so add that.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-04-03 17:49:40 +03:00
Pekka Paalanen
98becedfcd libweston: publish eotf and colorimetry mode to string
Frontend wants to print these sometimes.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-03 17:49:20 +03:00
Pekka Paalanen
d26ab4360d color-lcms: transform_search_param well-formedness
Assert that the search param structure is well-formed, so that there
won't be cache misses due inconsistent fields.

Anything called from inside cmlcms_color_transform_get() can skip
asserting these.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-03 17:49:03 +03:00
Pekka Paalanen
ce80a059f1 color-lcms: use alloc/register in profile_from_params
This is a nice clean-up.

The parameter-based color profile is actually fully formed. The problem
of using it is dealt in the next patch.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-03 17:48:08 +03:00
Pekka Paalanen
5ef1432195 color-lcms: cmlcms_color_profile_alloc/register()
Split the create function into two parts, allocation and finalization.
All ICC-specific code is moved into callers, so that the parameter-based
profile creation can start using alloc/register too.

cmlcms_color_profile 120 bytes, so it's unlikely we could ever deal with
that allocation failing - don't even try.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-03 17:47:32 +03:00
Pekka Paalanen
385334b77a color-noop: improve profile error messages
While no-op does not support these, other color managers might. Change
the wording so that the user does not think that Weston does not support
these at all.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-03 17:46:45 +03:00
Marius Vlad
1030268c6d gitlab-ci.yml: Limit gcov and perfetto to just x86 build
This should speed up considerably the other builds / tests.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-04-03 07:58:05 +00:00
Michael Olbrich
83053f0ce4 backend-drm: make sure outputs are enabled during plane assignment
drm_output_propose_state() is called during from drm_assign_planes(). At this
point, the output is enabled, but it may be disabled in the current state, that
is copied.

So explicitly enable the output by setting dpms to WESTON_DPMS_ON.
The same thing is already done in drm_output_repaint() but that's to late for
drm_output_propose_state(). Move that to the fallback path when planes are
disabled. It's no longer needed in general and changing the state between the
atomic test and commit is not a good idea anyways.

Without this, the atomic commit may fail, even though the corresponding test was
successful.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-04-02 18:02:45 +00:00
Marius Vlad
9aa910c4d4 backend-drm: Fix count page flips on invalid outputs
Slight oversight of counting page flips from within the atomic commit
handler when we don't really have an output. Do that after *after*
checking for a valid output.

Fixes: cda8de1089, ("backend-drm: Count and display KMS page flips")

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-04-02 13:09:45 +00:00
Erico Nunes
ae47d27f06 clients/simple-egl: destroy tearing_manager on exit
Add missing tearing_manager destructor call.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-04-02 06:34:13 +00:00
Erico Nunes
4fa4665d7a clients/simple-egl: remove duplicated shader program link
This is unnecessary as the program is already linked at this point.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-04-02 06:34:13 +00:00
Loïc Molinari
5a56856866 gl-renderer: Init output borders with transparent pixels
When the 1st frame of the X11 backend is rendered by the GL renderer,
an invalid call to glBindTexture() with a target of 0 is emitted. This
is because the border status of the window renderbuffers are flagged
dirty while the border status of the output state is not. This commit
ensures that the output state and the renderbuffers border status are
dirty by default. It also enforces the creation of output border
textures even though no valid data have (yet) been passed, in which
case the textures are filled with transparent pixels.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-04-01 13:55:06 +00:00
Pekka Paalanen
b872c71820 color-lcms: use weston_mat4f for matrix stages
This makes multiply_matrix_stages() handle offset vectors correctly, but
they will not apprear here yet, because
is_matrix_stage_with_zero_offset() forbids merging such matrices.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:54 +03:00
Pekka Paalanen
d3561621e3 tests: change BPC to weston_mat4f
Stop using weston_matrix.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:54 +03:00
Pekka Paalanen
adfe772db2 tests: replace lcmsMAT3 with weston_mat3f
Replace an ad hoc 3x3 matrix, that was supposed to match LittleCMS matrix
but did not, with our new consistent weston_mat3f API.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:54 +03:00
Pekka Paalanen
3fefb5ba44 libweston, clients, tests: implement weston_matrix in terms of weston_mat4f
This converts weston_matrix and weston_vector to use linalg-types
internally. All direct accesses to members had to be converted
everywhere, mostly in the simplest form possible which leaves some
trivially reducable code around.

The intention is that we can now gradually migrate away from
weston_matrix in the future.

Look like one trailing space got accidentally annihilated in
compositor.c.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:54 +03:00
Pekka Paalanen
92d7caa767 tests: add linalg-3 test cases
These are the same as linalg-4 cases, except the matrices have been
generated anew, and checked with Octave that the condition numbers and
determinant values hold.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:54 +03:00
Pekka Paalanen
e8b7ade58b libweston: add linalg-3.h
3x3 matrices, a straight-forward copy of libalg-4.h.

Useful for color computations and 2-D geometry.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:54 +03:00
Pekka Paalanen
2bbd2e4364 tests: add linalg-4 tests
Ensure our basic computations are correct.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:53 +03:00
Pekka Paalanen
f0567654d6 libweston: introduce linalg.h
linalg-types.h can be used from e.g. libweston.h so that structures can
embed linalg types but without forcing every user of libweston.h to
compile all the inline functions.

weston_mat4f implements most of weston_matrix, and some more. This is
just for starters. Implementing weston_mat3fwill be essentially a copy
of all this.

The matrix inversion is a copy from weston_matrix with a little bit of
clean-up.

The goal is to create a more intuitive libear algebra API, that is easy
to extend to 3x3 matrices and 3-vectors, eventually superseding all
existing matrix code: weston_matrix, calls to LittleCMS matrix
routines (plugin API), and ad hoc matrix code in tests/.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-04-01 15:59:53 +03:00
Loïc Molinari
6bbc6c1256 gl-renderer: Fix SHM RGB888 and BGR888 endianness
The 24 bpp RGB and BGR SHM formats are meant to be stored little
endian, not big endian.

Fixes a regression in commit 815ccaff.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-04-01 12:31:51 +02:00
Marius Vlad
9d841e39e8 compositor: Mark pnode accordingly when buffer type is direct
As we exit early we never have the chance to mark it as is_direct when
the buffer type is direct_display.

This is required as is_direct is never checked in GL attach part we
end up tripping on invalid renderer_private causing it to assert.

Fixes 2db4f17244f, "compositor: re-order paint node placeholder checks"

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-25 16:16:04 +00:00
Pekka Paalanen
fbf026653b color-lcms: cmsMAT3 is row-major after all
Found out in https://github.com/mm2/Little-CMS/issues/483

This should be a complete no-op change, but there is one difference.
Previously matrix_inf_norm() summed over rows. Now it sums over columns
as it should be. This shouldn't hurt because it is only used to identify
identity matrices. The bug was actually in is_identity_matrix_stage()
because it deliberately passed what was assumed to be a transpose of the
matrix.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-03-25 08:40:32 +00:00
Marius Vlad
f0ee8be804 terminal: Restore SIGPIPE signal handler to oldact (SIG_DFL)
Prior to executing a new command restore the parent process to the
default SIG_DLF handler as we normally use SIG_IGN it to avoid
crashing on pasted input.

As we seem to be hitting a Broken Pipe message when running
certain scripts, it seem we need to restore back the
default handler.

This is similar to what other folks have been doing in
https://github.com/labwc/labwc/issues/1209.

Fixes: #994

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-13 10:37:08 +02:00
Marius Vlad
46f25304c1 meson.build: Bump libweston to 15
As we had changes like 9ae0a7ec and adeb634c which require a libweston major bump
uprev.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-07 14:30:20 +00:00
Marius Vlad
1a2c25116b libweston: Rename LED_* to WESTON_LED*
This is required to avoid a namespace collision for LED_COMPOSE key
code and was introduced with c112760368, "input: Add support for
LED_COMPOSE and LED_KANA".

If not already done this requires a libweston major version bump.

Fixes: #997
Fixes: c112760368, "input: Add support for LED_COMPOSE and LED_KANA
USB HID LEDs"

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-07 14:30:20 +00:00
Robert Mader
82c5b386d8 meson: require libdisplay-info >= 0.2.0
We get rid of a little bit of fallback code, but the real reason is that
in the future the frontend will start using libdisplay-info as well, and
this lets us avoid adding fallback code there too.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-03-06 18:34:57 +00:00
Robert Mader
9f21128d78 gitlab-ci: Rebuild image with libdisplay-info to 0.2.0
Next we are going to make libdisplay-info 0.2.0 a hard requirement.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-03-06 18:34:57 +00:00
Pekka Paalanen
76e659f45e build: make libdisplay-info mandatory
Frontend will be needing it, too, so move it up. In doing so, we make it
a mandatory dependency of Weston. This should be fine, because it was
required by DRM-backend which is the foremost.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-03-06 18:34:57 +00:00
Marius Vlad
c706e1f8c8 flightrecorder: Don't subscribe by default to the drm-backend
As the flight recorder subscribed by default to the drm-backend will
implicily arm the KMS page flip counter. Just use the "log", log scope.

To make this more obvious, with this change we also print the
subscriptions, when we detect that the flight recorder is enabled.

Users can use the provided cmd line args (-f/--flight-rec-scopes) to
adjust those.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-06 16:09:42 +02:00
Marius Vlad
5beca735b0 backend-drm: Explicitly arm/disarm the page flip timer counter
when drm-backend debug scope is set.

This follows-up with the surface counter timer but because this is
buried in the drm-backend we make use the drm-backend scope if there's a
subscription to it and enable and arm the counter as well when that
happens.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-06 16:09:42 +02:00
Marius Vlad
cda8de1089 backend-drm: Count and display KMS page flips
This patch counts the page flips (either in atomic or legacy page flips)
for DRM outputs and prints them using the drm-backend scope.

Similar to the frame callback timer counter this installs a counter that
periodically computes page flips per a pre-defined interval.

This also includes a perfetto counter to display these in perfetto.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-06 16:09:42 +02:00
Marius Vlad
5f1c43de29 fontend: Arm the surface counter timer only when using debug
Rather than having this timer always fire up & running, do it when we actually
enable debug, with the `--debug` cmd line argument.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-06 16:09:42 +02:00
Marius Vlad
bbe0b74ebd libweston: Add also painted frame rate counters
Rather than using wl_surface::commit to count the frame rate, use the
painted frames for each paint node, and implictly the surface.

This happens in the output repaint paint node list parsing, and includes
also a perfetto counter to display it.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-06 16:09:39 +02:00
Marius Vlad
e850e97ab7 libweston: Add frame commit frame rate counting
This is a continuation of work from
https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/24

This patch adds a surface callback frame rate counter to the scene-graph
debug scope.

The timer interval is set by default to 1 second. This use a timer to
periodically compute the current frame callback commits in that interval
as the surface frame rate per timer interval.  Note that is solely based on
wl_surface::commit call.

Together with this, this patch also adds perfetto counter that stores
the same computed frame rate. This means the counter will be updated on
the next interval timer when the timer is armed/fired such that that
perfetto drawings will show up in a window period of time (interval).

Helpful to identify what frame rates clients achieve to debug
performance issues as to provide an objective common group. Using the
debug-scope aggregates all surfaces at the same place. This is not based
on the GPU whatsoever so it can also work on SHM type of buffers.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Signed-off-by: Changwoo Cho <changwoo.cho@lge.com>
2025-03-06 15:14:12 +02:00
Marius Vlad
ad3957ddf8 timeline-perfetto: Store disambiguator globally
This way we can use the same ID when for perfetto counters to allow
to identify clients much easier.

Also, renamed "surface" with "unlabelled surface" when get_label function
is not set.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-03-06 15:14:12 +02:00
Erico Nunes
af95899121 gl-renderer: close gbm device fd on destroy
Trivial fix to get a clean valgrind fd report with gl-renderer.

Signed-off-by: Erico Nunes <nunes.erico@gmail.com>
2025-03-04 14:18:27 +00:00
Derek Foreman
9660a4f315 desktop-shell: Use output shell_private data
Replace find_shell_output_from_weston_output with private data.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-03-04 12:30:51 +00:00
Derek Foreman
013c21ec38 desktop-shell: Store struct shell_output in internal structs
Similar to what's just been done to kiosk-shell, use our internal
shell_output instead of directly using weston_output in our internal
structures.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-03-04 12:30:51 +00:00
Derek Foreman
77dcbe381f libweston: Add shell_private data
Shells need to find their own internal structures for weston_outputs.
Let's make that process trivial instead of a list walk.

Add a getter and setter for this private data and use it from the kiosk
shell.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-03-04 12:30:51 +00:00
Derek Foreman
5ab5582981 kiosk-shell: Store kiosk_shell_output in kiosk_shell_surface
We end up doing some extra list walks and mildly awkward contortions to
find the kiosk_shell_output from the weston_output.

Store the kiosk_shell_output instead - it's always trivial to find the
weston_output from that, and it just seems a bit cleaner conceptually for
kiosk shell abstractions to point to other kiosk shell abstractions when
available.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-03-04 12:30:51 +00:00
Pekka Paalanen
a97ccc4a1a tests: add idalloc
Get the realloc() code path executed.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-03-03 15:05:30 +02:00
Pekka Paalanen
6773ffa758 libweston: fix bitshift in weston_idalloc_get_id()
Fixes the following UBSan error:

../../git/weston/libweston/id-number-allocator.c:140:16: runtime error:
left shift of 1 by 31 places cannot be represented in type 'int'

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-03-03 14:40:21 +02:00
Pekka Paalanen
ed51e9ae43 libweston: fix realloc in weston_idalloc
realloc() does not initialize the added memory, it needs to be zeroed
explicitly.

Not zeroing this memory had one severe consequence: if the new
lowest_free_bucket was 0xffffffff, weston_idalloc_get_id() would fail an
assertion.

Otherwise non-zero bits in the added memory would just cause id numbers
to be skipped unnecessarily, which does no harm.

Fixes: https://gitlab.freedesktop.org/wayland/weston/-/issues/1000

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-03-03 13:51:25 +02:00
Pekka Paalanen
2733a95962 libweston: refactor update_lowest_free_bucket()
No functional change here other than asserting that next_num didn't wrap
around. This reorganization helps adding the code
needed to clear the memory added by xrealloc() in the next patch.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-03-03 13:51:05 +02:00
Loïc Molinari
1b7655636d tests: Don't abort on failure
Setup a custom assertion handler that increases an assertion counter
instead of aborting on failure. This allows to run all the sub tests
defined for a test and to correctly report which sub test failed.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 23:50:45 +01:00
Loïc Molinari
4134685257 tests: Remove NDEBUG catcher
NDEBUG doesn't need to be catched anymore now that the test suite
don't use libc's abort() anymore.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 23:50:45 +01:00
Loïc Molinari
fbe2f27915 tests: Remove zunitc testing framework
This framework isn't used anymore.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 23:50:45 +01:00
Loïc Molinari
9373e76655 shared: Rename NULL and not NULL pointer assertions
Make the NULL assertions more explicit.

weston_assert_ptr_is_null() -> weston_assert_ptr_null()
weston_assert_ptr()         -> weston_assert_ptr_not_null()

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 23:50:45 +01:00
Loïc Molinari
c855bc7af0 tests: Port all test clients to the new test asserts
This commit gets rid of libc's abort() usage in the test suite using
test asserts instead.

Asserts run in the server as plugins aren't converted because they are
shared between server and client.

Co-authored-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 23:50:41 +01:00
Loïc Molinari
d92560a0e4 tests: Port config-parser test to Weston testing framework
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 22:50:51 +01:00
Loïc Molinari
1f169c044c tests: Port timespec test to Weston testing framework
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 22:50:51 +01:00
Loïc Molinari
12819c4151 shared: Let bit asserts take a bit instead of a position
It's much more common to have bits defined as enums than having a
position, so let's just directly take a bit as argument to the bit
asserts. For the few cases where only the position is available, it's
easy to get the right bit using a shift.

The is_pow2_64() helper functions have been added in order to validate
the bit passed as argument and prevent programming errors.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 22:50:51 +01:00
Loïc Molinari
57c3cee7ed tests: Add test asserts based on new Weston assert system
This commit introduces various Weston based asserts for the testing
framework. The goal is to ease test writing and improve readability.

Using custom asserts instead of relying on libc's assert() will also
help providing NDEBUG builds. This is currently not possible because
setting NDEBUG would disable all the asserts in the tests.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-26 22:50:51 +01:00
Robert Mader
9124a98aec color: update color-management protocol to wp-v1
For a list of changes that got squashed into this commit see
https://gitlab.freedesktop.org/rmader/weston/-/commits/color-management-protocol-wp-v1-bkp

Co-authored-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
Signed-off-by: Robert Mader <robert.mader@collabora.com>
Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-02-26 10:09:43 -03:00
LI Qingwu
6d9c42a7d2 ivi-shell: re-align ivi_layout_interface structure
re-aligned the ivi_layout_interface structure in ivi-layout.c.
purely a formatting update, no functional changes were made.

Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
2025-02-21 09:25:11 +00:00
LI Qingwu
7e941cf6f1 ivi-shell: Add desktop surface ping timeout notification
Implement new ivi_layout_interface method and signal to forward
desktop client ping timeout events for unresponsive client handling.

Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
2025-02-21 09:25:11 +00:00
Théo Maillart
2b69bc0811 gl-renderer: clip subimage dimensions to its buffer ones
A window freeze can occur in specific use cases like when using a kiosk
shell. It scales surfaces to fit the compositor size and the transformation
to buffer space can, in some cases, round the size one pixel higher than
the texture size, making glTexSubImage2D() refuse the size argument and
generate a GL_INVALID_VALUE without updating the texture.
This commit ensures the GL renderer doesn't exceed the texture size.

Here is how the issue was reproduced:
	$ weston --renderer=gl --backend=wayland --width=1920 --height=1080 --shell=kiosk
	$ gst-launch-1.0 videotestsrc ! video/x-raw,height=590,width=500 ! waylandsink display=wayland-1

Signed-off-by: Théo Maillart <tmaillart@freebox.fr>
2025-02-21 07:03:56 +00:00
Derek Foreman
bfb2dfae63 compositor: Try an immediate repaint if VRR enabled
When in VRR mode, repainting without a wait might happen instantly,
so do it.

This is likely not the best long term solution, but is ok for now
while weston's vrr support is experimental.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-02-21 06:49:42 +00:00
Derek Foreman
c7cf87fe85 frontend: Enable VRR from the config file
Allow weston.ini to enable game VRR.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-02-21 06:49:42 +00:00
Derek Foreman
8e26bf1ce9 libweston: Add VRR capabilities
Add functions to query output VRR capabilities and set the current VRR
mode.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-02-21 06:49:42 +00:00
Derek Foreman
85d1ca7fab drm-backend: Set VRR_ENABLED property based on output configuration
Set up the VRR_ENABLED instead of always clearing it to 0.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-02-21 06:49:42 +00:00
Derek Foreman
c321cc3020 drm-backend: Add Variable Refresh Rate modes
Query the vrr_capable property for heads, and expose it to frontends.

Currently we only support game mode VRR, but expose VRR capabilities as
an enum in anticipation of supporting QMS VRR in the future.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-02-21 06:49:42 +00:00
Robert Mader
de6f0b870a gitlab-ci: Bump wayland-protocols to 1.41
Disable tests as they require wayland-scanner 1.23.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-02-17 17:42:13 +00:00
Loïc Molinari
e72839f52c gl-renderer: Make YUV formats table static
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
62c25e8ca0 gl-renderer: Add macro to improve YUV formats table readability
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
7974f8f46e gl-renderer: Use .r to access red component in samplers
This is for consistency reasons too.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
0ca40593dc gl-renderer: Sample XYUV shader variant using .rgb
This is mostly to improve consistency.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
b947955499 gl-renderer: Replace Y_XUXV variant by Y_UV with texture swizzles
Formats using SHADER_VARIANT_Y_XUXV can now use SHADER_VARIANT_Y_UV
instead with swizzle variations in order to simplify the fragment
shader.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
51ed256d26 libweston: Replace pixel format's sampler_type with color_model enum
The sampler type, which was initially meant for the GL renderer, is
currently used to derive the color model of pixel formats. This commit
gets rid of this legacy field and replaces it with an explicit one
indicating the color model.

Note that it also fixes the issue that formats wouldn't be considered
YUV if ENABLE_EGL isn't defined because the sampler type field in that
particular case would always be 0.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
24b5d91316 gl-renderer: Get legacy EGL buffers info from YUV formats table
Automatise variant and planes selection for legacy EGL buffers support
by using the global information from the YUV formats table and setup
texture swizzles for legacy EGL buffers and dma-buf.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
de2a4ebc3c clients: Let simple-shm create buffers of requested RGB format
This is a temporary solution to easily test wl_shm support for
different RGB formats. I think it would be better to have a dedicated
client to test all the supported RGB and YUV formats for the wl_shm,
dma-buf import and legacy EGL protocols.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
dd66debd46 tests: Add tests for RGB wl_shm format variants
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
d254cb14fc tests: Rename yuv-buffer test to shm-buffer
Next commit will add tests for RGB formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
89e20bcda6 tests: Add support and tests for 16-bit YUV wl_shm format variants
Fixes the offset issue in gl_renderer_attach_shm().

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
73d6c2cc85 tests: Add tests for swizzled YUV wl_shm format variants
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
ad85a4a2d1 tests: Ensure wl_shm format support before testing
Tests shouldn't fail on platforms lacking support for a particular
format.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
b9ae1eb4a9 gl-renderer: Extend YUV formats
Add new formats to the YUV formats table: YVYU, UYVY, VYUY, NV21,
NV61, NV42, YVU420 and YVU4444.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
20f246eaef gl-renderer: Add wl_shm support to all declared YUV pixel formats
Support more YUV formats using texture swizzles. Automatise wl_shm
format addition based on the format table using the new texture format
utility gl_texture_is_format_supported().

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
cf43e7da9f libweston: Extend RGB formats
Add new formats supported by OpenGL to the pixel formats table: R16,
RG88, GR1616, RG1616, XRGB16161616 and ARGB16161616.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
5e267afa6d gl-renderer: Add wl_shm support to all declared RGB pixel formats
Support more RGB formats using texture swizzles. Automatise wl_shm
format addition based on the format table using the new texture format
utility gl_texture_is_format_supported().

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
da393fd468 gl-renderer: Cache and defer blend state update to draw call
This slightly minimises state changes.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
e18e3b6c4a gl-renderer: Replace RGBX shader variant with texture swizzles
Simplify fragment shader logic by getting rid of the RGBX variant
which can be implemented using texture swizzles instead.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
e8160e059d gl-renderer: Relax EXT_texture_format_BGRA8888 requirement
This can now be removed thanks to texture swizzles.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
be5c662bae gl-renderer: Add OpenGL ES 2 support to texture swizzles
Fallback to shader based swizzling when OpenGL ES 3 isn't available.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
a990e8ceda gl-renderer: Prefer GL_RGBA8 with swizzles over GL_BGRA8_EXT
All the formats are declared as RGBA swizzled variations. Make the
BGRA8888 format do the same for consistency reasons as there shouldn't
be any performance impact for it.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
815ccaff92 gl-renderer: Replace channel ordering with texture swizzles
The channel ordering system currently proposes to swizzle components
in the fragment shader for a few combinations. This commit replaces
this system with texture swizzling parameters in order to support all
the possible combinations in a more efficient way.

This will allow to easily add a lot more formats and as a nice side
effect to force components to 0 or 1, which is useful for opaque
formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
891736793a gl-renderer: Add swizzles to texture parameters utilities
OpenGL ES 3 adds support for texture swizzling parameters in order to
let graphics drivers efficiently swizzle R, G, B and A components at
texture look-up, with the nice feature of allowing 0 and 1 as
supported values.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
5342945bb8 gl-renderer: Add texture parameters utilities
Cache and update texture parameters only when changed by storing
minification/magnification filters, wrap modes and their target into a
dedicated gl_texture_parameters structure and by calling new utility
functions to create and flush parameters.

This structure is itself stored into the buffer state for each texture
of a surface and into the output state for border and shadow textures.

The shader config filled before emitting a draw call now just takes a
pointer to the array of texture ids, a pointer to the array of
parameters and the number of textures.

This allows to simplify the logic in gl-renderer.c, to minimise GL
state changes and to let the utility wrapper validate the parameters.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Loïc Molinari
acc40ce2bb gl-renderer: Add EXT_EGL_image_storage support
EXT_EGL_image_storage provides a mechanism for creating texture
objects that are both EGL image targets and immutable. When available,
this makes the texture object target immutable, preventing
respecifications.

While adding support for that extension, it appeared that the
compositor calls attach_buffer() at every buffer updates and that the
texture object is each time respecified to the same EGL image. This
commit additionally prevents any respecification when
EXT_EGL_image_storage isn't available.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-17 15:54:52 +00:00
Martin Rys
c112760368 input: Add support for LED_COMPOSE and LED_KANA USB HID LEDs
Also bump up the xkbcommon dependency to a newer, 10 year old version,
to be able to remove very old ifdefs.

Signed-off-by: Martin Rys <martin@rys.rs>
2025-02-12 17:04:06 +02:00
gpotter2
59c6015c52 Move shell structures of desktop-shell to the header
Signed-off-by: gpotter2 <10530980+gpotter2@users.noreply.github.com>
2025-02-12 14:13:53 +00:00
Michael Olbrich
6e88a851a4 libweston-desktop: don't try to move child surfaces to not existing layer
The parent surface may not be on a layer. In that case, remove all child
surfaces from their current layer as well.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-02-12 13:51:11 +00:00
Marius Vlad
94dd926b99 backend-drm: Clear out the the fb handles
This is purely cosmetic but we do this in other parts as well, when
releasing the GEM handles. Use the macro for no of planes as well when
going over them.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-02-07 23:44:18 +02:00
Marius Vlad
3d5772fb06 backend-drm: Abide by the weston-direct-display specification
Turns out it seems we have a missed some spots when using the
weston-direct-display protocol.

Specifically we still seem to be attempting a dma buffer import which
ultimately can reach the GPU. This patch rectifies that in such a way
that we can actually provide a full scanout path for client's (dma)
buffers as to avoid hitting the GPU entirely.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-02-07 23:44:15 +02:00
Derek Foreman
8993f5eabb compositor: Drop flow id from weston_view_update_transform
This can end up being the first function to touch a surface in a flow,
which leads to confusing traces.

Just trace the function without a flow instead.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-02-06 13:26:11 +00:00
Michael Olbrich
f36a0c2cb8 backend-headless: use weston_output_arm_frame_timer()
headless_output_repaint() is not actually called immediately after
weston_output_finish_frame(): Weston waits for "frame-duration - repaint-window"
but at least one millisecond.
And renderning can also take an arbitrary amount of time.

So use weston_output_arm_frame_timer() like all other timer based backends. It
takes all of this into account and calculates the delay relative to the next
expected vblank time.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2025-02-06 11:20:14 +00:00
Marius Vlad
c335ec70af gitlab-ci: Expand CI job for building with a C++ compiler
This tests out if libweston can be built with a C++ compiler and catch
potential issues which we don't normally see.

We re-use one of the builds, the full-x86-64 one, and build this new
front-end alongside it.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-02-06 10:21:22 +00:00
Loïc Molinari
10f8b4ba81 gl-renderer: Adapt gl_fbo_texture_init() to new texture utilities
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
b3f6491b3a gl-renderer: Extend accepted renderbuffer formats
Use the new FBO utilities to extend the list of supported FBO formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
3d8edc15ce gl-renderer: Port wl_shm code to new texture utilities
A new gl_format_info structure is added to the pixel_format_info
structure in order to store new GL format information (compatible with
Table 1 in gl-utils.c) for each supported format. There will be a
temporary duplication of GL format info in order to keep other parts
of the code not yet ported working. That will be removed later.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
672178dc24 gl-renderer: Port color transformation to new texture utilities
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
ccf3fda334 gl-renderer: Port border images to new texture utilities
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
ca7e21bb94 gl-renderer: Port wireframe code to new texture utilities
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
0c8b6ce945 gl-renderer: Add 3D support to texture utilities
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
7e73234313 gl-renderer: Add ARM_rgba8 support to utilities
ARM_rgba8 allows OpenGL ES 2 implementations to support GL_RGBA8 FBO
format.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
85dd477466 gl-renderer: Add EXT_texture_format_BGRA8888 support to utilities
EXT_texture_format_BGRA8888 allows OpenGL ES implementations to
support GL_BGRA8_EXT FBO and texture format.

OpenGL implementations handle the spec differently regarding the use
of GL_BGRA8_EXT or GL_BGRA_EXT with TexStorage*D(), TexImage*D() and
RenderbufferStorage(). A recent revision of the spec (and Mesa)
clarifies all that, but in order to support most drivers we simply
check which method is supported by order of preference.

Co-authored-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
dcee21f02f gl-renderer: Add OES_required_internalformat support to utilities
Before the creation of the EXT_texture_storage extension,
OES_required_internalformat used to guarantee minimal FBO and texture
precisions to OpenGL ES 1 and 2 implementations using sized internal
formats.

Note that new external format and type combinations (like for instance
GL_RGB and GL_UNSIGNED_BYTE for the GL_RGB565 sized internal format)
should be available when OES_required_internalformat is supported.
This isn't supported by this wrapper for now because of the implicit
conversion in gl_texture_2d_init() that forces a specific type when
EXT_texture_storage isn't available.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
43bbd15437 gl-renderer: Add EXT_texture_type_2_10_10_10_REV support
EXT_texture_type_2_10_10_10_REV allows OpenGL ES 2 implementations to
support GL_RGB10_A2 texture format.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
db25130e15 gl-renderer: Add EXT_texture_norm16 support to utilities
EXT_texture_norm16 allows OpenGL ES 3 implementations to support
GL_R16_EXT, GL_R16_SNORM_EXT, GL_RG16_EXT, GL_RG16_SNORM_EXT,
GL_RGB16_EXT, GL_RGB16_SNORM_EXT, GL_RGBA16_EXT and
GL_RGBA16_SNORM_EXT 16-bit fixed-point texture and FBO formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
46603446d7 gl-renderer: Add QCOM_render_sRGB_R8_RG8 support to utilities
QCOM_render_sRGB_R8_RG8 allows OpenGL ES 3 implementations to support
GL_SR8_EXT and GL_SRG8_EXT FBO formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
e505bbe017 gl-renderer: Add EXT_texture_sRGB_RG8 support to utilities
EXT_texture_sRGB_RG8 allows OpenGL ES 3 implementations to support
GL_SRG8_EXT texture format.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
b2d737f1f0 gl-renderer: Add EXT_texture_sRGB_R8 support to utilities
EXT_texture_sRGB_R8 allows OpenGL ES 3 implementations to support
GL_SR8_EXT texture format.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
e72d7d963d gl-renderer: Add APPLE_texture_packed_float support to utilities
APPLE_texture_packed_float allows OpenGL ES 2 implementations to
support GL_R11F_G11F_B10F and GL_RGB9_A5 texture formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
58494e5ba2 gl-renderer: Add NV_packed_float support to utilities
NV_packed_float allows OpenGL ES 2 implementations to support
GL_R11F_G11F_B10F FBO and texture format.

Note that GL_HALF_FLOAT should be available (the spec is a bit
confusing) as type combination with the GL_RGB external format when
both NV_packed_float and OES_texture_half_float are supported on
OpenGL ES 2. This isn't supported by this wrapper for now because of
the implicit conversion in gl_texture_2d_init() that forces a specific
type when EXT_texture_storage isn't available.

NV_packed_float_linear would require a new utility function to
retrieve whether a texture can be linearly interpolated by the texture
samplers or not. This hasn't been added for the other formats because
there's no users for now but this might be added later.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
8162058c8d gl-renderer: Add EXT_color_buffer_float support to utilities
EXT_color_buffer_float allows OpenGL ES implementations to support
GL_R16F, GL_RG16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_RGBA32F and
GL_R11F_G11F_B10F FBO formats. All of these are supported by default
from OpenGL ES 3.2.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
2fc9a47e09 gl-renderer: Add EXT_color_buffer_half_float support to utilities
EXT_color_buffer_half_float allows OpenGL ES implementations to
support GL_R16F, GL_RG16F, GL_RGB16F and GL_RGBA16F FBO formats.
GL_R16F, GL_RG16F and GL_RGBA16F are supported by default from OpenGL
ES 3.2.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
37a5c249e5 gl-renderer: Add OES_texture_float support to utilities
OES_texture_float allows OpenGL ES 2 implementations to support
GL_R32F, GL_RG32F, GL_RGB32F and GL_RGBA32F texture formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
9048d752c5 gl-renderer: Add OES_texture_half_float support to utilities
OES_texture_half_float allows OpenGL ES 2 implementations to support
GL_R16F, GL_RG16F, GL_RGB16F and GL_RGBA16F texture formats.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
eaf2ec3888 gl-renderer: Add EXT_texture_rg support to utilities
EXT_texture_rg adds support for GL_R8 and GL_RG8 FBOs and textures.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
177efc7a59 gl-renderer: Add EXT_texture_storage support to utilities
OpenGL ES 2 implementations support texture immutability and sized
internal formats using the GL_EXT_texture_storage extension.

Co-authored-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
0cede83390 gl-renderer: Add OpenGL ES 2 support to texture utilities
Use glTexImage2D() instead of glTexStorage2D() and convert coloured
sized internal formats to base formats in order to support OpenGL ES
2.

Co-authored-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
a7611efce9 gl-renderer: Add texture utilities
Add gl_texture_is_format_supported(), gl_texture_2d_init(),
gl_texture_2d_upload() and gl_texture_fini() utilities. The creation
function accepts all the coloured sized internal format from OpenGL ES
3 using glTexStorage2D() to create immutable textures and reduce API
overhead.

Co-authored-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
8c74b48493 gl-renderer: Check for OES_EGL_image to create FBOs from EGLImages
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
dc7299d69c gl-renderer: Check supported FBO formats
Validate the colour-renderable sized internal formats passed to
gl_fbo_init() using a new gl_fbo_is_format_supported() utility. Sized
internal formats are now required. More formats will progressively be
added depending on the OpenGL ES version and the supported extensions.

Support for RGBA8 FBOs is now required by the GL renderer.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
1dc6868947 gl-renderer: Add OpenGL ES 3 sized internal format table
This table will be used as a reference by GL utilities.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
c39799b684 gl-renderer: Move GLES headers inclusion to common header
Avoid duplicating the inclusion of the GLES headers by including them
once in gl-renderer-internal.h.

Upgrade GLES3 header to gl32.h.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
7f3969c823 gl-renderer: Move utilities to new file gl-utils.c
These utility functions are used (or will be used) in different source
files. This prevents gl-renderer.c from growing too much (the coming
texture utilities are quite verbose) by moving generic functions out.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Loïc Molinari
e3a5589975 gl-renderer: Make space for upcoming extension flags
Next commits will add support for a bunch of extensions. The extension
flag enumeration is sorted alhpabetically. This commit makes some
space for the coming flags and presets the current values in order to
avoid useless diff lines and ease code review.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-02-06 08:42:56 +00:00
Robert Mader
6394f7d1ca Set default YUV color coefficients and range to BT.709/limited
As most SDR video content uses that instead of BT.601. Crucially, most
KMS drivers use BT.709 as the default for the COLOR_ENCODING value,
making it the effective default for hardware planes we used before we
started setting an explicit value.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-02-04 12:36:12 +00:00
Robert Mader
1b7462011d gl-render: Set default color hints for EGL images
In order to be consistent with our internal YUV shader and KMS plane
output. Note that the extension requires the hints to be ignored for
RGB formats.

Note that the attribs array previously was slightly larger than the
maximum number of attributes required.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-02-04 12:36:12 +00:00
Robert Mader
ce79976dfc backend-drm: Set default plane color space and range hints
Upstream KMS drivers currently default to either ITU-R BT.601 YCbCr or
ITU-R BT.709 YCbCr. Ensure consistent behavior by setting a default.
We use BT.601 as that is what our fallback shader uses at the moment.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-02-04 12:36:12 +00:00
Robert Mader
5fae3a5141 pixel-formats: Add is_yuv helper
Which will be used in later commits. For now using the sampler_type
works for all existing formats, however should we ever want to use
it for RGB formats this functions needs to get adopted.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-02-04 12:36:12 +00:00
Derek Foreman
e22a11513d doc: Add some very sparse perfetto documentation
Just tell people that timeline points are in perfetto, and how to
add a function trace.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
0be4403f65 timeline: Add flow ids for surfaces
We add a flow_id when we touch a surface that has no flow id, and clear
it when we flush damage, so a flow line will be drawn connecting any
operations on a surface and terminating in its damage clear.

This is less useful for surfaces that never receive explicit damage after
they're set up, such as background images and the panel, as they might
never show up as a damage track, and have an unterminated flow line.

For surfaces that do show up on a damage track, we can follow them back to
the commit that caused them to update.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
313aa041e4 timeline: Post core_flush_damage after clearing damage
This shouldn't cause any problems with WESGR output, since the timing
will still be very close to what it was previously.

With perfetto tracing, this helps with event ordering. The final flush
event will now come after the damage accumulation function calls instead
of before. This is better when we add flow lines in a following commit.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
485cb4ab12 timeline: Add the TL_POINTs into perfetto data
Try to roughly achieve feature parity with WESGR by processing the same
timepoint data and feeding it into perfetto, with output and surface
specific tracks.

We can't match the way WESGR draws this information, because perfetto has
a different display paradigm, but we can try to at least make sure all the
same information is visible in an understandable way.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
b3635c17f4 timeline: Add weston_timeline_profiling() and use it
When we use perfetto, we'll want to enable the renderer timepoints, which
are currently gated behind weston_log_scope_is_enabled(). So let's make a
function that checks if either the timeline scope or perfetto is enabled.

We do not yet process these timepoints, that comes in a future commit.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
da1dca9d77 compositor: Add a bunch of arbitrary perfetto trace points
Just pepper some perfetto tracing about.

These functions are picked mostly to provide some visibility into repaint,
but in the future we might want to add more sites, such as input
processing.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
bdfe7a3e58 libweston: Add support for perfetto profiling
This borrows heavily from the Mesa project's perfetto instrumentation, and
for now just adds perfetto to the build and a collection of useful macros
for adding trace points.

The atomics have been cargo culted in - Weston currently has no need of
such things, but I guess they're harmless for now and could be useful if
we consider threads in the future.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
738d4b9509 compositor: Refactor assign planes into its own function
This is just so we can have nicer profiling output later.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Derek Foreman
5d51042e6b timeline: Make an enum for the timepoint strings
I'll be adding perfetto instrumentation, which will want to know the
timepoint name without having to parse it.

For now, just pass an enum and add a helper function to convert to strings.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-01-24 12:22:13 +00:00
Daniel Stone
0c31f7dfd2 drm: Remove workaround for ancient Mesa GBM issue
This issue was fixed several years ago; we don't need to carry the
workaround anymore.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-01-23 11:57:42 +00:00
Marius Vlad
cfbf49d7e0 meson.build: Bump to C11 with GNU extensions
Weston seems quite ready for that so let us do it!

This makes the winpr3 Static assert warning message go away, allowing us
to perform a build (as we fail with any type of warnings).

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-01-21 19:20:06 +00:00
Marius Vlad
d17e61546e gitlab-ci.yml: Bump CI templates and use FDO_DISTRIBUTION_PLATFORM
This is required to get proper ach image from docker.io (for armv7 builds).

Similar to https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/449

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-01-21 19:20:06 +00:00
Loïc Molinari
7f87268474 libweston: Fix doc string
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
e8dae983b7 renderers: Catch backend programming errors with asserts
Add asserts ensuring that outputs aren't created or destroyed twice
and that a valid pair of output/renderbuffer is passed to
repaint_output().

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
1656158d6d gl-renderer: Update renderbuffers in dedicated function
Accumulate renderbuffer damages and select a GL renderbuffer for
repaint in a dedicated function.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
4ee40b653f gl-renderer: Coalesce renderbuffer window retrieval functions
Coalesce gl_renderer_create_renderbuffer_window() and
output_get_window_renderbuffer() into a single
gl_renderer_get_renderbuffer_window() function.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
8567b960fd gl-renderer: Rename dummy renderbuffers to window renderbuffers
Use the term window instead of dummy to make it clear we're dealing
with buffers allocated by the window-system.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
1d167d883f pixman-renderer: Remove renderbuffer_get_image() function
renderbuffer_get_image() is only used by the X11 backend to retrieve
the size of the renderbuffer. The previous commit assumes that
renderbuffers are created at the size of the associated output so the
renderbuffer size can now be retrieved from the output.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
96c49d91a5 libweston: Enforce renderbuffer size
Although backends can create renderbuffers of any size, they always
request the output's current mode size (including decorations).
Letting backends ask for a different size than the output has a few
read-back related design issues like for instance weston_renderer's
read_pixels() API users, currently assuming the output size and
without knowledge of renderbuffers, can retrieve cropped images if a
backend asks for a smaller size. Same issue for the output capture
subsystem.

This commit proposes to fix these issues by simply, albeit perhaps
radically, removing the width and height parameters from
create_renderbuffer(), enforcing the current mode's size of the
associated output.

The VNC and PipeWire backends now also access the output size via the
current mode, not through the width and height variables. This has the
benefit of unifying the backends, as well as the renderers, in their
use of output sizes.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
4eddce5557 libweston: Unify renderbuffer creation API
The Pixman renderer creates renderbuffers with the create_image() and
create_image_from_ptr() functions. The recent addition of the GL
renderer's create_fbo() function, which is pretty similar to the
Pixman ones, brings the opportunity to unify Pixman and GL renderers.

This commit proposes a common renderer function create_renderbuffer()
to create a renderbuffer of the specified format with an optional user
provided destination buffer.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
91da8560eb gl-renderer: Leave FBOs bound in init utilities on success
This avoids having to re-bind them in functions that reuse them
immediately afterwards and does not affect any other parts of code.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
1f1c219d5c gl-renderer: Don't set min/mag filters in gl_fbo_texture_init()
This is most often set again at render time.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
51d217a9b4 gl-renderer: Adapt gl_fbo_texture_*() to new FBO utilities
This commit makes gl_fbo_texture_init() and gl_fbo_texture_fini()
consistent with the new FBO handling utilities by using the same
conventions: output parameters, variable names, descriptions.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
1f4d291850 gl-renderer: Remove glGetError() check from gl_fbo_image_init()
Remove the glGetError() check from gl_fbo_image_init() after the call
to glEGLImageTargetRenderbufferStorageOES(). It would probably just
return a previous error queued by an unrelated GL call because the
error flags aren't cleared. So instead of obfuscating the code, this
commit removes that check and relies instead on the framebuffer
completeness check which will better report issues.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
0688343dec gl-renderer: Add FBO handling utilities
Add generic gl_fbo_init(), gl_fbo_image_init() and gl_fbo_fini()
utilities to the GL renderer and make use of these in the renderbuffer
creation functions.

This also fixes a framebuffer object leak on dma-buf renderbuffer
creation when the EGLImageTargetRenderbufferStorageOES() call fails.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
1c7274deed gl-renderer: Make surface_copy_content() render to a GL renderbuffer
There's no need to render the surface content to a GL texture so make
it render to a GL renderbuffer instead.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:31 +01:00
Loïc Molinari
092076f6f5 gl-renderer: Regroup renderbuffer creation functions
Move gl_renderer_create_renderuffer_dmabuf() along with the other
renderbuffer creation functions, using a common naming pattern.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:34:27 +01:00
Loïc Molinari
c5e6fa7103 gl-renderer: Move common renderbuffer init to dedicated func
Avoid code duplication in renderbuffer creation functions.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
83a1a0293a gl-renderer: Use a union to store type specific renderbuffer data
This makes type specific accesses more explicit and less verbose than
the container_of/base alternative which was needed when the base
renderbuffer type was exposed in libweston-internal.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
2bfaac0f5c gl-renderer: Skip non-dummy rbs in get_dummy_renderbuffer()
No backends currently create FBO or dma-buf renderbuffers on outputs
associated to a window. This is theoretically possible though and
should be allowed by the GL renderer. This commit prevents
output_get_dummy_renderbuffer() from mixing up renderbuffer types.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
47035a776c gl-renderer: Don't accumulate damages on stale renderbuffers
Stale renderbuffers are kept in the renderbuffer list until they're
destroyed by the backend. In the meantime, they shouldn't accumulate
damages since they won't be used anymore.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
e3878c8214 backend-drm: Add renderbuffer's discarded event support
The output doesn't get finalised and initialised again on resizes
anymore with the Pixman renderer. Only the current dumb and render
buffers get reallocated.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
f6bc92571e backend-x11: Add renderbuffer's discarded event support
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
c7ec967d12 backend-wayland: Add renderbuffer's discarded event support
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
a2e6086bc6 backend-rdp: Add renderbuffer's discarded event support
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
f2fc277fb2 backend-vnc: Add renderbuffer's discarded event support
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
a49b2e5a0d libweston: Deal with renderbuffer discards using an event handler
It's currently assumed by backends that renderers discard
renderbuffers on resize. This commit introduces a new
weston_renderbuffer_discarded_func callback that must be passed at
renderbuffer creation in order to be notified of discarded events from
the renderer. This discarded event could potentially be reused later
by renderers on other occasions without having to change backends once
they get proper support for that.

On output resize, once a discarded event handler fails (returns false)
on a renderbuffer, all the remaining renderbuffers in the output list
go stale and weston_renderer_resize_output() ultimately returns false
for backends to be notified of the failure.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
b9e199b47d libweston: Use explicit renderbuffer destruction
Renderbuffers currently have a libweston-internal base data structure
with a ref-counting system to handle their lifetime. The problem is
that renderers keep a ref to all renderbuffers in a list per output
(to deal with damages) and that it prevents backends from releasing
renderbuffer resources when not needed anymore. Renderbuffers are then
only released (last ref removed) when the output is destroyed or
resized. dma-buf renderbuffers even expose a dedicated function
remove_renderbuffer_dmabuf() to explictly request the release of their
resources.

This commit proposes to get rid of the ref-counting system by exposing
a single entry point to explicitly destroy all types of renderbuffers
from the renderer.

Instead of removing a renderbuffer from its output list and dropping
its ref when the output is resized, this commit also introduces the
concept of stale renderbuffers which consists in releasing the
resources of a renderbuffer when it's discarded by the renderer while
keeping it in the output list, with a stale state, until it's
explicitly destroyed.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Loïc Molinari
1619a4a1e5 libweston: Let renderers manage renderbuffers' damage
Move the responsibility for damaging the entire area of new
renderbuffers from backends to renderers.

There's one little drawback: VNC damage logging can't log the
accumulated renderbuffer damage anymore, but I guess this should
somehow be done as an option in the renderers.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-21 14:21:40 +01:00
Leandro Ribeiro
c01a1f7c64 tests: add color-management tests for the parametric interface
This adds tests to create image descriptions through color parameters
using the CM&HDR protocol extension.

The code for that was added in commit "color: allow clients to create
image description from parameters".

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
70ad4cd901 color-lcms: print params from parametric color profiles
Start to print the parameters from struct cmlcms_color_profile::params
in cmlcms_color_profile_print(). This will be useful for the next
commit, in which we add tests that craft parametric color profiles.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
277082dbd9 color: change has_parameters to count_parameters
A counter instead of a boolean should be useful when we add code
printing the parameters. This should help us to avoid printing unused
parameters.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
5d7e2710a2 color: cosmetic changes to the CM&HDR protocol implementation
No behavior changes. Adjust a few comments, error messages, variable
names, etc.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
06e1241948 color: allow clients to create image description from parameters
Commit "color: add support to the color-management protocol" added
support for the majority of the interfaces from the color-management
protocol.

The missing part was the interface that allows clients to create image
descriptions from parameters. In this patch we do that.

For now this just exercises the mechanical aspects of the protocol, we
still need to write the code to create proper color profiles from that
and make use of them in our codebase.

In the next commits we add a new test file with lots of tests exercising
the creation of image descriptions through parameters.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
9dcc5f20f8 color: adjust a few error codes in our parametric creator API
If a certain feature is unsupported, return UNSUPPORTED instead of
BAD_TF, BAD_PRIMARIES, etc.

Also, up to now cm->get_color_profile_from_params() would return
UNSUPPORTED. But this is different from the other UNSUPPORTED usages, so
return a new error.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
b852744977 color: prioritize protocol error instead of graceful failure
In the parametric builder API, which is used by our color management
protocol implementation, we have errors that may be translated to
protocol errors or graceful failures. As we return a single err code
to the protocol implementation, let's prioritize the protocol error.

We do that by inverting the order of checks, as the first error code
caught is the one prioritized.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
0ed8294881 color: add weston_color_profile_param_builder_set_primary_luminance()
This follows a recent change in the CM&HDR protocol (more specifically,
v4 of the experimental version). Now users of the API can set luminance
parameters for the primary color volume.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
9db8ad6ad1 color: add WESTON_COLOR_FEATURE_SET_LUMINANCES
This follows a recent change in the CM&HDR protocol (more specifically,
v4 of the experimental version). Now clients can use the protocol to set
luminance parameters for the primary color volume.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
9ae0a7ec05 color: accept max_fall and max_cll even for tf different from PQ
The CM&HDR protocol extension spec relaxed the requirements for the
max_fall and max_cll setters. Now we accept such values even when the
transfer function is not PQ.

This also fixes an issue in which we'd not accept target_luminance
for transfer function different from PQ, which was not on the spec.

INCONSISTENT_SET is not being used in any other errors, so remove that
from enum weston_color_profile_param_builder_error.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
1082ef328a color: rename luminance to target luminance
In the experimental color-management protocol v3
(xx-color-management-v3), we had only the luminance parameters that were
defining the luminance range targeted by the image description. But in
v4 a way to specify luminance parameters for the primary color volume
has been added.

In order to avoid confusion, rename existent luminance variables to
target luminance.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
3f0de3bdf4 color: rename COLOR_CHARACTERISTICS_H to COLOR_PROPERTIES_H
While choosing a name for file color-properties.h, I've had originally
opted for color-characteristics.h. But we already have some other stuff
named color characteristics in the code, so I've changed that to
color-properties.h.

This fixes a leftover from that. Rename WESTON_COLOR_CHARACTERISTICS_H
to WESTON_COLOR_PROPERTIES_H.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Leandro Ribeiro
432b9af0cd color: add getters to primaries_info and tf_info from protocol enum
This will be necessary in the next commit, so add that.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-20 09:30:46 +00:00
Marius Vlad
43f7b7b3bb windowed-output-api.h: Provide ARRAY_LENGH() for windowed-output-api
We need this common helper as we don't have access to shared helper, so
just define one in-situ.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-01-17 10:18:28 +02:00
Marius Vlad
207fed2710 Revert "shared/helpers.h: Migrate helpers.h to libweston"
This is problematic as we don't have namespacing for these and some of
the macros can interfere with other defines.

This reverts commit 8634c7e349.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-01-17 10:18:26 +02:00
kang-sooyeon
c77a5d386a libweston/input.c: Fix weston crash with the mouse event
Fix weston crash when user click the mouse continuosly while
the video is playing.
Call weston_view_update_transform before calling
weston_coord_global_to_surface to update view->transform.dirty to 0.

Fixes #985

Tested-by: Sooyeon Kang sooyeon8979@gmail.com
Signed-off-by: Sooyeon Kang sooyeon8979@gmail.com
2025-01-17 07:54:59 +00:00
Leandro Ribeiro
eabc19bc3b drm: log more try_view_on_plane_failure_reasons
Up to now, we've been logging only the failures that we get from
drm_fb_get_from_paint_node(). So let's start logging the other failures
we get in drm_output_find_plane_for_view() as well.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:03:22 -03:00
Leandro Ribeiro
5c3067ad54 drm: print why dma-buf feedback is being updated
This may be helpful for debugging.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:03:22 -03:00
Leandro Ribeiro
306033616b drm: print try_view_on_plane_failure_reasons bitmask as string
This should help people to debug. Instead of printing an hex value,
print each enum value present in the bitmask as a string (comma
separated).

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:03:22 -03:00
Leandro Ribeiro
4cc489c6af shared: move bits_to_str() to string-helpers.h
This function is useful across multiple components of the project, so
move it to a helper header.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:03:20 -03:00
Leandro Ribeiro
5fcedcf5ef drm: remove scanout tranche if we detect INADEQUATE_CONTENT_PROTECTION
Client won't be able to do direct-scanout with this surface, and the
format/modifier doesn't matter in this case. So let's remove the scanout
tranche from dma-buf feedback in such case.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:01:13 -03:00
Leandro Ribeiro
d3ead778de drm: avoid dma-buf feedback endless loop
Currently we have the following situation: we add a scanout tranche
because if the client re-allocates with another format/modifier, the
chances of being placed in a DRM/KMS plane is higher.

But then we run out of overlay planes. So we remove the scanout tranche,
because the format/modifier available in the renderer tranche are
optimal for rendering.

Now Weston detects again that the format/modifier is what may be
avoiding the view being place in a plane, re-adding the scanout tranche.
And we have an endless loop.

To avoid this, let's accumulate the reasons why placing the view in a
place failed. So if we detect that we don't have planes available, no
matter the format/modifier, we won't add the scanout tranche.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:01:13 -03:00
Leandro Ribeiro
8b83bb5ceb drm: fix issue with enum being wrongly used
FAILURE_REASONS_ADD_FB_FAILED is defined as (1 << 3), so when we are
accumulating "failure reasons" in a variable we don't need to do the bit
shift again.

This results in an issue, because (1 << FAILURE_REASONS_ADD_FB_FAILED)
results in (1 << (1 << 3)) == (1 << 8).

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:01:13 -03:00
Leandro Ribeiro
3210cec531 drm: fix a few dma-buf feedback failure reasons
There are a few points in the code where we are wrongly using
FAILURE_REASONS_ADD_FB_FAILED, probably because we didn't have so many
"failure reasons" previously. This update such cases to use enum's that
make sense.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:01:13 -03:00
Leandro Ribeiro
b347af2ce0 drm: try other planes that may support fences
Do not skip all the planes if a single one of them do not support
fences. The other may do.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2025-01-16 10:01:13 -03:00
Loïc Molinari
a2dba7ff00 gl-renderer: Add extensions and features section to guidelines
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
4be294bd69 gl-renderer: Move list init after feature flags setup
Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
8d21829f49 gl-renderer: Add GPU timeline feature flag
This flag ensures support for both the GL_ANDROID_native_fence_sync
and the GL_EXT_disjoint_timer_query extensions at run-time. The GL
features log now reports that flag so the warning log has been
removed.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
169bb00bbd gl-renderer: Add color transforms feature flag
Replace gl_supports_color_transforms with a feature flag.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
7f01f9e18e gl-renderer: Add async read-back feature flag
Replace has_pbo with a feature flag.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
090c01da87 gl-renderer: Load GL function pointers with GET_PROC_ADDRESS()
Use the same macro than for the EGL function pointers.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
68a70bf9c4 gl-renderer: Order GL function pointers by extensions
Storing GL function pointers along with their associated extension
name allows to better track the function pointers declared.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
d7dcc2eaa7 gl-renderer: Remove GL extension booleans
Now that the GL extensions are stored in the gl_extensions bitfield,
there's no need to use booleans anymore.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
0026986cce gl-renderer: Check for GL_OES_EGL_image support
This commit ensures GL_OES_EGL_image is available before setting up
dma-buf renderer functions because it's not implied by the presence of
the EGL_EXT_image_dma_buf_import extension.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
aaf968bf58 gl-renderer: Slightly improve color transforms check
GL_OES_texture_3D isn't used because of the complexity implied for
correct OpenGL ES 2 support (see commit 734c2278), so there's no need
to check for it. The check also now avoids checking for
GL_EXT_color_buffer_half_float on OpenGL ES 3.2 which includes support
for 16-bit FP renderbuffers by default.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
02b4eccd05 gl-renderer: Add EGL_KHR_get_all_proc_addresses checks
The GL renderer supports OpenGL ES from version 2.0 to 3.2. It's meant
to correctly link on systems with only OpenGL ES 2, so OpenGL ES 3
symbols can't be used directly. eglGetProcAddress() is currently
defined to not support the querying of non-extension OpenGL ES
functions. Support for that is exposed by the
KHR_get_all_proc_addresses extension. This commit ensures OpenGL ES 3
function addresses can be retrieved by eglGetProcAddress() by checking
for that extension at run-time.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
4ae493ff25 gl-renderer: Store GL extensions as flags
A new gl_extensions bitfield is added to the renderer to store the
flags supported by the GL implementation. This allows the GL renderer
to easily check for extension support whenever needed.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
db5c06bd16 gl-renderer: Remove branch never taken
Don't flag EGL_PBUFFER_BIT to get the EGL config if the
EGL_KHR_surfaceless_context extension isn't available. The branch is
never taken because the extension is required and if it isn't
available, the function would have already returned.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
4f7f888d6c gl-renderer: Improve EGL_WL_bind_wayland_display extension handling
Get the EGL_WL_bind_wayland_display extension function addresses after
checking for extension availability.

Let the EGL display setup end before trying to bind the Wayland
display in gl-renderer.c. The EGL features log will now report the
extension as supported even if the bind subsequently fails, in which
case a warning is logged.

This commit also avoids calling query_buffer() if the display isn't
bound in fill_buffer_info(), it would otherwise fail or even segfault
if the EGL_WL_bind_wayland_display extension isn't available.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
0361ddf13e gl-renderer: Require EGL version >= 1.2
OpenGL ES 2 and some attributes like EGL_RENDERABLE_TYPE are supported
by EGL from version 1.2.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
94ca770c2a gl-renderer: Add explicit sync feature flag
This feature flag is for explicit sync support.

We replace the explicit sync warning by logging supported fence syncs
along with the report EGL features report.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
c29e2a7928 gl-renderer: Get function pointer addresses after extension check
Trying to follow the principle presented previously, this commit
ensures extension function addresses are retrieved once their
associated extension has been checked for availability.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
d38f45c6b6 gl-renderer: check for EGL_KHR_image_base extension
Get eglCreateImageKHR() and eglDestroyImageKHR() function addresses
depending on EGL_KHR_image_base availability.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
3d0d850980 gl-renderer: Add swap buffers with damage feature flag
This second feature flag ensures that either the
EGL_EXT_swap_buffers_with_damage or EGL_EXT_swap_buffers_with_damage
extension is available.

Some function pointer addresses are currently retrieved depending on
the availabilty of their associated extension and some others are
retrieved unconditionally. For consistency reasons, we'll try from now
on in this commit set to first load function pointers depending on the
associated extension availability and then flag features once all the
addresses are retrieved.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
4a4a9b94d6 gl-renderer: Add no config context feature flag
This commit introduces feature flags. While an extension flag only
ensures the availability of an extension at run-time, a feature flag
ensures the availability of a minimal OpenGL ES version and/or
extensions in order to easily check for the availability of a specific
feature at run-time.

This first feature ensures the availability of either the
EGL_KHR_no_config_context or EGL_MESA_configless_context extensions.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
9d9d09a04d gl-renderer: Load EGL function pointers with a new macro
A new GET_PROC_ADDRESS() macro is added to get a function address at
run-time using eglGetProcAddress() and to assert() the address isn't
NULL at once.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
2852c92d89 gl-renderer: Order EGL function pointers by extensions
Storing EGL function pointers along with their associated extension
name allows to better track the function pointers declared.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
c56c104f7a gl-renderer: Remove EGL extension booleans
Now that the EGL extensions are stored in the egl_*_extensions
bitfields, there's no need to use booleans anymore.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
54dfa0743e gl-renderer: Store EGL display extensions as flags
The egl_display_extensions bitfield is added to store the display
extensions supported by the EGL implementation.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
12b9c65011 gl-renderer: Store EGL device extensions as flags
The egl_device_extensions bitfield is added to store the device
extensions supported by the EGL implementation.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
14d5406a90 gl-renderer: Store EGL client extensions as flags
A new egl_client_extensions bitfield is added to the renderer to store
the client flags supported by the EGL implementation. This allows the
GL renderer to easily check for extension support whenever needed.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
00f7bf91d8 gl-renderer: Add extension flag parser
This new utility parses extension strings and fills a bitfield of
matched flags. This will be used to store EGL and GL extension flags.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Loïc Molinari
39a199293e gl-renderer: Move versioning utils to internal header
Next commits will need this outside of gl-renderer.c.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
2025-01-14 13:24:39 +00:00
Paul Pu
ddb6225338 desktop-shell: support disallow-output-changed-move
With this, when unplugging an extended display, the view displayed on
the extended display won't be re-positioned to other displays.

On some embedded devices, the views are often fullscreen displayed, even
on the extended displays. When disconnecting the extended displays, the
views are not desired to be moved onto the existing displays. Without
this change, we can see the view flash across the existing displays
even though the UI program hides the view as soon as it can, which is
unexpected.

Signed-off-by: Paul Pu <hui.pu@gehealthcare.com>
2025-01-14 08:05:14 +00:00
Leo Li
89f77176b6 backend-drm: Rename mm_has_underlay to mm_underlay_only
Now that secondary planes can be both underlay and overlay, this flag's
meaning also changed. Update it for correctness.

Signed-off-by: Leo Li <sunpeng.li@amd.com>
2025-01-13 16:05:31 +00:00
Leo Li
ca894ab44f backend-drm: Use plane's zpos_min to check for underlay ability
Previously, whether a KMS plane is underlay-able is determined by
whether it's zpos_max is < the primary plane's zpos_min. In other words,
a plane will only be considered underlay-able if its entire valid zpos
range is under the primary plane's lowest zpos.

This is too restrictive - it's possible for planes to have a valid zpos
range that spans below and above the primary's zpos range.

Therefore, allow planes to be used as underlays if their zpos_min is <
the primary plane's zpos_min.

In addition, force rendering on a view if it contains alpha, and is
occluded by a rendered view. If such a view is overlaid, it would render
with incorrect zorder. If it's underlaid, it would render with incorrect
alpha-blending due to hole-punching. Therefore, it must be rendered.

Force rendering prevents the view from going into
`drm_output_find_plane_for_view()`, which serves as an optimization, but
is also observed to prevent dmabuf feedback (derived from
`try_view_on_plane_failure_reasons`) from ping-ponging between two
values, causing some apps (like weston-simple-egl) to constantly
reallocate its buffers.

Because a plane can now - if supported - be used as an underlay, an
overlay, or both, add a `enum drm_plane_subtype` to differentiate
between them. Then, print it's subtype and underlay/overlay assignment
once a decision is made.

v2:
* Squash w/ patch to force rendering on alpha view occluded by rendered
  view
* Bring back plane subtype enum to be more expressive about plane
  capabilities
* Correct need_hole != false when a view's assignment changes from
  underlay to overlay

Signed-off-by: Leo Li <sunpeng.li@amd.com>
2025-01-13 16:05:31 +00:00
Colin Kinloch
5aae333bbb clients/window: Save pending allocation if mapping fullscreen
This means the window will appear at the set size when unsetting
fullscreen.

Signed-off-by: Colin Kinloch <colin.kinloch@collabora.com>
2025-01-13 17:03:48 +02:00
Colin Kinloch
0aeb8e5910 clients/fullscreen: Add option to map window fullscreen
Signed-off-by: Colin Kinloch <colin.kinloch@collabora.com>
2025-01-06 12:17:40 +00:00
Paul Pu
b2b8dd6215 libweston: fix crash when a client binds to a destroyed output
When the head is already destroyed, its global resource still can be
accessible by the client, which leads to a UAF crash.

This sets the head's global resource's user data to null before the
head is destroyed, and when the `bind` request is being handled but the
object's user data is null, do what we do when the the head's output is
null.

Signed-off-by: Paul Pu <hui.pu@gehealthcare.com>
2024-12-18 16:22:35 +08:00
Derek Foreman
5b35631545 desktop-shell: Fix background image
Commit 264c205add ignored the fact that a
background color of 0 should fall back to the background image, and
broke that case.

Fixes 264c205add
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-12-17 09:36:45 -06:00
Robert Mader
16e5406877 backend-drm: Add support for YUV plane color properties
The drm_color_encoding and drm_color_range enums are used for
YUV->RGB conversion and mirror what EGL_YUV_COLOR_SPACE_HINT_EXT
and EGL_SAMPLE_RANGE_HINT_EXT as well as our `yuva2rgba()`
shader func do. Add the necessary boiler plate for them.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2024-12-16 15:33:20 +00:00
Derek Foreman
264c205add desktop-shell: Make backgrounds fully opaque
Non-opaque backgrounds don't make sense, and cause rendering
problems.

Silently set backgrounds fully opaque, and remove any mention of
alpha from the man page.

Kiosk-shell already implicitly forces opaque backgrounds.

Old weston.ini with FF for alpha will always continue to work.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-12-11 10:03:37 -06:00
Derek Foreman
68761d3f11 compositor: Ensure the scene graph isn't empty at repaint
If the scene graph is empty at repaint the renderer will do nothing to the
buffer. On some platforms this results in displaying garbage, and on
platforms where we use frame buffer compression we can cause longer
lasting visual problems.

Make sure we never get here with an empty scene graph.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-12-04 14:52:34 +00:00
Derek Foreman
0ff5ac0f7b desktop-shell: Add a placeholder curtain on new outputs
Desktop-shell currently waits for the desktop-shell client to set up a
background image. But the outputs are enabled before this happens, which
forces a repaint.

If the fade animation is enabled, there's a fade curtain in place, but if
it's disabled the scene graph is empty at the repaint.

This repaint with an empty scene graph can have very nasty consequences,
especially if frame buffer compression is in use, as the buffer isn't
rendered into and can be in an undefined state that confuses whatever
video hardware is trying to decode the buffer.

Add a temporary black curtain placeholder that ensures the scene graph has
something in it before the client gets a chance to commit the real
background.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-12-04 14:52:34 +00:00
Gyeyoung Baek
483a5a73cb clients/ivi-shell-user-interface.c: Add 'command' config
Previously, commands could only be specified by their path,
so it was not possible to pass arguments.
Use the 'command' config first,
and if it is NULL, fall back to the existing 'path' config.

Signed-off-by: Gyeyoung Baek <gyeyoung976@gmail.com>

Co-authored-by: Michael Olbrich <m.olbrich@pengutronix.de>
2024-12-04 12:36:20 +00:00
Michael Olbrich
3866ecc5d3 libweston: fix crash when a client queries a destroyed output
A client can call get_xdg_output() at any time. If the output was destroyed,
then all output resources are orphaned. This includes clearing the user data of
the resource.
This can happen, for example, when a monitor or HDMI switch quickly toggles the
HDMI hotplug pin.

So check if a head is associated with the resource. If not, just create the
resource and then return immediately.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
2024-12-04 11:02:36 +00:00
Tomek Bury
67253b30e8 tests: fix test build error on older Linux
The linux/input-even-codes.h was split from linux/input.h but it's still
included from linux/input.h

Signed-off-by: Tomek Bury <tomek.bury@gmail.com>
2024-12-03 21:50:33 +00:00
Derek Foreman
53189ebb89 compositor: re-order paint node placeholder checks
Doing these in the wrong order breaks content protection, and breaks
placing direct-display paint nodes on underlays.

Fixes: 827e2276 ("gl-renderer: Draw holes on primary plane for the view on underlay")
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-12-03 21:33:41 +00:00
Derek Foreman
8dbb3e17d0 drm: Fix underlay test
We need to reset the underlay check inside the view evaluation loop,
otherwise once we need an underlay we'll treat every following view as
needing an underlay.

Fixes: 1065d23406 ("backend-drm: Improve plane assignment for underlay platform")
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-12-03 11:33:05 -06:00
Tomek Bury
b14461b13b gl-renderer: make DMABUF allocator optional
The dmabuf allocator pulls in libgbm which lives inside Mesa and is built
as a non-standalone part Mesa. This makes gl-renderer hard-wired to Mesa.

The allocator is only used by an optional pipewire backend so make
the allocator optional too.

Signed-off-by: Tomek Bury <tomek.bury@gmail.com>
2024-12-03 13:41:50 +00:00
Marius Vlad
bf7b2311e7 gl-renderer: Take direct-display into consideration
The buffer_init function added with commit 83b37c0ac4, "renderers: pull
dmabuf initial setup out of attach", doesn't take into consideration the
the buffer's direct-display property.

Previously, gl_renderer_attach_dmabuf, wasn't being called when dmabuf's
direct-display  was turned on, but with commit 83b37c0ac4 this has been changed.

So with commit 83b37c0ac4, linux_dmabuf_buffer_get_user_data will never
return a valid gb (gl buffer state), causing a crash using
direct-display extension. This adds an explicit check to return early
when this happens.

Fixes: 83b37c0ac4, "renderers: pull dmabuf initial setup out of attach"
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-12-01 23:17:50 +02:00
Marius Vlad
dae61f3321 windowed-output-api.h: Do an explicit cast to avoid C++ build failure
Address the following build issue:

error: invalid conversion from ‘const void*’ to ‘const
weston_windowed_output_api*’ [-fpermissive] return
weston_plugin_api_get(compositor, api_names[type],
~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
const void* sizeof(struct weston_windowed_output_api));

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-11-25 11:26:35 +00:00
Marius Vlad
8634c7e349 shared/helpers.h: Migrate helpers.h to libweston
As weston_windowed_output_get_api needs ARRAY_LENGTH() move helpers to a
libweston/ so other users can re-use that instead of re-defining these
all over. Easier for other front-ends to make use of them.

With this change windowed-output-api.h also includes the helpers header.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-11-25 11:26:35 +00:00
Ian Ray
fc278fb3cc shared: fix binding-modifier none
Fix binding-modifier "none" which was defaulting to Super.

Commit [1] introduced the original support for "none" but the logic was
subsequently lost in f7ba35f5.

[1] 553d1248 ("desktop-shell: Allow binding-modifier weston.ini option to be none")

Fixes: #976

Fixes: f7ba35f5 ("kiosk-shell: Enable debug keybindings")
Signed-off-by: Ian Ray <ian.ray@gehealthcare.com>
2024-11-20 22:16:59 +02:00
Tomek Bury
c313543364 tests: fix build warnings when backend-drm is not enabled
Signed-off-by: Tomek Bury <tomek.bury@gmail.com>
2024-11-20 12:10:57 +00:00
Derek Foreman
4f2cc67fde compositor: Prevent startup crash when hdcp mode is set on display
We can startup with the display already in type1 content protection mode.
When this happens, we call weston_output_dirty_paint_nodes() on a display
that hasn't yet been enabled. The paint node list isn't initialized yet,
so we crash.

We don't actually need to touch the paint nodes here anyway, as
weston_output_damage() ensures a repaint if the ourput is enabled, and
weston_output_dirty_paint_nodes() just forces calculation of things
unrelated to protection, and we'll override most of that in
maybe_replace_paint_node() if necessary when we get there.

Just drop the weston_output_dirty_paint_nodes() call to stop the
crash.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-11-20 09:23:08 +00:00
Philipp Zabel
b4386289d6 vnc: Allow neatvnc in version 0.9.0
Neat VNC 0.9.0 is backwards compatible.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
2024-11-20 08:54:10 +00:00
Robert Mader
4f4011d79e pixel-formats: Add P030
Which is used on the RPi4/5 by the HEVC HW decoder for 10bit content.

Note that this is not enough to make KMS offloading work as the
decoder uses the BROADCOM_SAND128 modifier which - for now - requires
manual/unusual handling (i.e. this requires going through GL).

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2024-11-11 12:17:36 +01:00
Jonas Ådahl
10ecf60848 xdg-shell: Allow poup grab on non-grabbing popup
Grabbing requires a single chain of grabbing popups, but it doesn't require
grabbing to start with a toplevel, it could just as well start with a
non-grabbing popup.

Avoid seding an error when a client attempts to do this.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
2024-11-06 10:43:27 +02:00
Alexey Yerin
d30683341c clients: don't redraw on xdg_toplevel.configure
Signed-off-by: Alexey Yerin <yyp@disroot.org>
Signed-off-by: Kirill Primak <vyivel@eclair.cafe>
2024-11-06 10:12:51 +02:00
Derek Foreman
1ee1b93bac desktop-shell: Don't crash if the output is removed in startup
If the output is destroyed between setting the panel and committing the
panel, or between setting the background and committing the background,
we have a use after free crash.

Handle this by clearing the surface private pointers on output destroy
so we can skip the useless commits.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-11-05 11:29:39 -06:00
Marius Vlad
fe35be5013 gitlab-ci: Bump libdrm to 2.4.118 to add NV{15,20,30} fmts
And add ifndef guards for cases were do have support for it.

While at it I need to change how we build it due to:

'meson.build:21:0: ERROR: Value "false" (of type "string") for combo
option "Enable support for vc4's KMS API." is not one of the choices.
Possible choices are (as string): "enabled", "disabled", "auto".'

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-11-04 16:40:46 +02:00
Leandro Ribeiro
a3fd8f3c97 color-lcms: accept ICC profiles of device class ColorSpace
From "color: update color-management protocol to xx-v4" onwards, we
should accept ICC profiles of device class ColorSpace, as the CM&HDR
protocol says. So do that.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
2024-11-04 13:13:22 +00:00
Daniel Stone
8fdc55c03f pixel-formats: Add NV15/20/30 YUV 10bpc formats
NV15/20/30 are a family of 10bpc YUV formats which have 4
horizontally-adjacent samples packed into a 40-bit cluster. The
difference between 15/20/30 is in the subsampling.

No fallbacks are provided, as there is no format pairing which would
allow us to sensibly unpack the clusters.

Signed-off-by: Daniel Stone <daniels@collabora.com>
2024-11-01 15:05:28 +00:00
Derek Foreman
16dc3b2b7f clients/simple-egl: simplify wait for configure loop
Just move the init function outside of the loop and we can drop the
if/continue.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-10-21 10:46:27 +00:00
Marius Vlad
80e47a7161 libweston/desktop: Avoid a potential crash on invalid resource
This checks for a valid resource when getting a xdg_popup. Similar to
the check in get_toplevel.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-10-21 11:14:48 +03:00
Marius Vlad
8b5bb588df libweston/desktop: Don't destroy the xdg_surface
Upon xdg_toplevel::destroy we seem to be calling xdg_surface::destroy
destroy handler. Protocol states that we should umap the surface with
client having the posibility to getting another toplevel role for the
same xdg_surface and re-map the window.

This also adds a guard for an unlikely invalid resource.

Fixes: #774

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-10-21 11:14:46 +03:00
Marius Vlad
a501acd291 libweston/matrix: Fix narrow conversion with C++
Fixes the following C++ narrow conversion:

/include/libweston-14/libweston/matrix.h: In function ‘weston_coord
weston_coord_truncate(weston_coord)’:
/include/libweston-14/libweston/matrix.h:212:39: error: narrowing
conversion of ‘(int)in.weston_coord::x’ from ‘int’ to ‘double’
[-Werror=narrowing] 212 |         return (struct weston_coord){
	(int)in.x, (int)in.y };
      |                                       ^~~~~~~~~
/home/mvlad/install-new/include/libweston-14/libweston/matrix.h:212:50:
error: narrowing conversion of ‘(int)in.weston_coord::y’ from ‘int’ to
‘double’ [-Werror=narrowing] 212 |         return (struct weston_coord){
	(int)in.x, (int)in.y };

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-10-18 20:40:56 +03:00
James Le Cuirot
9a536962a5
tests: Make some tests dependent on the shell-desktop option
The internal-screenshot and text tests are dependent on the feature and
fail with it disabled.

Signed-off-by: James Le Cuirot <chewi@gentoo.org>
2024-10-14 22:47:13 +01:00
James Le Cuirot
486d96a162
tests: Make the kiosk test dependent on the shell-kiosk option
The test is dependent on the feature and fails with it disabled.

Signed-off-by: James Le Cuirot <chewi@gentoo.org>
2024-10-14 22:46:34 +01:00
Marius Vlad
217fb30847 desktop-shell: Don't attempt to re-add the view to panel layer
This change fixes a side-effect of weston_view_move_to_layer helper
which would basically unmap the view because the layer entry list is no
longer visible. Only add the view to panel layer the first time.

Fixes: #956

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-10-11 11:36:03 +03:00
Jeri Li
04f27f1be2 libweston/desktop: avoid weston crash while xdg_surface ack_configure
checks the resource and sends a protocol error if the client tries to
send a request to an inert object then returns out of the request
handler

Signed-off-by: Jeri Li <jeri.li@mediatek.com>
2024-10-11 11:22:21 +03:00
Marius Vlad
68bbc4cf51 libweston: Move weston_get_backend_type after enum declaration
Fix: #951

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-10-10 07:56:59 +00:00
Jan Engelhardt
f86ff8c07d build: insert missing wayland-server-protocol dependency
A new build error sprung up in weston-14 compared to 13.0.0.
Fix it.

FAILED: tests/liblib_lcms_util.a.p/lcms_util.c.o
cc -Itests/liblib_lcms_util.a.p -Itests -I../tests -I. -I.. -Iinclude
-I../include -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall
-Winvalid-pch -Wextra -Wpedantic -std=gnu99 -Wmissing-prototypes
-Wno-unused-parameter -Wno-shift-negative-value
-Wno-missing-field-initializers -Wno-pedantic -Wundef
-fvisibility=hidden -O2 -Wall -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3
-fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables
-fstack-clash-protection -Werror=return-type -flto=auto -g -fPIC -MD
-MQ tests/liblib_lcms_util.a.p/lcms_util.c.o -MF
tests/liblib_lcms_util.a.p/lcms_util.c.o.d -o
tests/liblib_lcms_util.a.p/lcms_util.c.o -c ../tests/lcms_util.c
In file included from ../tests/lcms_util.c:35:
../include/libweston/matrix.h:33:10: fatal error:
wayland-server-protocol.h: No such file or directory

   33 | #include <wayland-server-protocol.h>

Signed-off-by: Jan Engelhardt <jengelh@inai.de>
2024-10-08 19:36:09 +02:00
David Edmundson
fe64eee3ae libweston: Send seat name before announcing devices
Clients need to know the seat name at the time they create mouse and
keyboard objects. This brings Weston in line with other compositors.

The documentation upstream currently is not super clear. It states name
is explicitly sent on bind, capabilities don't mention being sent on
bind in any way.

Signed-off-by: David Edmundson <davidedmundson@kde.org>
2024-09-26 13:28:30 +00:00
EatingSumo
312c8bea66 libweston/screenshooter: Fix build when __builtin_clz is not available
Fix compilation error when `__builtin_clz` is not available by renaming variable 'u' to 'run'

Signed-off-by: Junyu Long <877730493@qq.com>
2024-09-26 13:17:27 +00:00
Derek Foreman
067e977fe1 desktop-shell: Don't try to move parented views on output removal
These should be repositioned relative to their parents, attempting to
move them independently not only doesn't make sense, but violates
weston_coord sanity checks.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-09-18 09:13:19 -05:00
Jan Alexander Steffens (heftig)
0e451e8dc3
libweston/noop-renderer: Check shm_buffer for NULL
Copy the check from the pixman renderer.

Fixes: https://gitlab.freedesktop.org/wayland/weston/-/issues/953
Signed-off-by: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
2024-09-14 06:38:47 +02:00
Derek Foreman
2e51def212 libdisplay-info: Bump wrap version
We need libdisplay-info 0.2.0 for some features, but our wrapper
currently builds 0.1.1, leading to some surprising errors when
trying to use those features.

Bump the wrap version so if we're pulling this in from a wrap
we get the latest features.

We leave the hard dependency alone for now, as it's still not
widely deployed.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2024-09-13 09:43:04 -05:00
Joan Torres
a266c5fff5 clients: Add color
Add a client that creates a surface with one color using single pixel buffer.

Set to that surface an image_description created with the parametric creator of
the color management protocol.

This client can get as params:
  1. Width and height
  2. Color channels R, G, B, A
  3. The name of primaries
  4. The name of a transfer function
  5. The min, max, ref luminance levels

Signed-off-by: Joan Torres <joan.torres@suse.com>
2024-09-09 13:51:51 +00:00
Joan Torres
53419eb991 clients/window: Allow rendering frame wihout shadow
Rendering the shadow currently renders some dark color near the border inside
the inner content.

Altough the content is on top of it, if the content has some transparency,
that dark color appears and this might be unwanted.

Add an option to not render the shadow to avoid that problem.

Signed-off-by: Joan Torres <joan.torres@suse.com>
2024-09-09 13:51:51 +00:00
Marius Vlad
e026fd6540 meson.build: reopen main for regular development
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-09-04 12:12:34 +03:00
Marius Vlad
60981998b2 build: bump to version 14.0.0 for the official release
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-09-04 11:53:50 +03:00
341 changed files with 52385 additions and 16597 deletions

View file

@ -1,6 +1,6 @@
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0:
.templates_sha: &template_sha 184ca628f89f3193c249b4e34e45afee2773a833 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
.templates_sha: &template_sha 32afe5644697e503af18a736587c8619fa036a72 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
# This file uses the freedesktop ci-templates to build Weston and run our
# tests in CI.
#
@ -43,7 +43,7 @@
variables:
FDO_UPSTREAM_REPO: wayland/weston
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
FDO_DISTRIBUTION_TAG: '2024-08-14-00-freerdp3.x'
FDO_DISTRIBUTION_TAG: '2025-12-19-mesa-25.3.2'
include:
@ -66,6 +66,11 @@ include:
# we need a default case though, so all the rest still run
- when: on_success
default:
retry:
max: 2
when: runner_system_failure
.merge-rules:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
@ -79,7 +84,7 @@ stages:
- "Pre Base container"
- "Base container"
- "Full build and test"
- "No-GL build and test"
- "No-GL/Vulkan build and test"
- "Other builds"
- pages
@ -88,20 +93,23 @@ stages:
.os-debian-lts:
variables:
BUILD_OS: debian
LLVM_VERSION: 11
LLVM_VERSION: 15
USE_DEBIAN_BACKPORTS: y
PACKAGES_SPECIFIC: vulkan-validationlayers-dev
FREERDP_VERSION: 2
FDO_DISTRIBUTION_VERSION: bullseye
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
FDO_DISTRIBUTION_VERSION: bookworm
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
.os-debian:
variables:
BUILD_OS: debian
LLVM_VERSION: 15
LLVM_VERSION: 19
FREERDP_VERSION: 3
USE_BOOKWORM_BACKPORTS: y
# If you upgrade from bookworm, see the use_tls=0 notes in tests/meson.build.
FDO_DISTRIBUTION_VERSION: bookworm
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
USE_DEBIAN_BACKPORTS: y
PACKAGES_SPECIFIC: vulkan-utility-libraries-dev libpolly-19-dev libclang-rt-19-dev python3-standard-imghdr
# If you upgrade from trixie, see the use_tls=0 notes in tests/meson.build.
FDO_DISTRIBUTION_VERSION: trixie
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
# Does not inherit .default-rules as we only want it to run in MR context.
check-commit:
@ -111,7 +119,6 @@ check-commit:
stage: "Merge request checks"
script:
- ci-fairy check-commits --signed-off-by --junit-xml=results.xml
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
variables:
GIT_DEPTH: 100
artifacts:
@ -139,12 +146,14 @@ check-commit:
- .os-debian-lts
variables:
BUILD_ARCH: "armv7"
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
.debian-armv7:
extends:
- .os-debian
variables:
BUILD_ARCH: "armv7"
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
# Inhibit installation of freerdp-dev
@ -211,8 +220,6 @@ armv7-debian-lts-container_prep:
- .fdo.container-build@debian
tags:
- aarch64
variables:
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
needs:
- job: base-container-pre
timeout: 30m
@ -225,8 +232,6 @@ armv7-debian-container_prep:
- .fdo.container-build@debian
tags:
- aarch64
variables:
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
needs:
- job: base-container-pre
timeout: 30m
@ -262,17 +267,23 @@ aarch64-debian-container_prep:
timeout: 15m
variables:
BUILDDIR: $CI_PROJECT_DIR/build-weston-$CI_JOB_NAME
BUILDDIR_WESTINY: $CI_PROJECT_DIR/build-westiny-$CI_JOB_NAME
PREFIX: $CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
PREFIX_WESTINY: $CI_PROJECT_DIR/prefix-westiny-$CI_JOB_NAME
before_script:
- export PATH=~/.local/bin:$PATH
- export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
- export TESTS_RES_PATH="$BUILDDIR/tests-res.txt"
- export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
- mkdir "$BUILDDIR" "$PREFIX"
- mkdir "$BUILDDIR_WESTINY" "$PREFIX_WESTINY"
.build-with-clang:
variables:
CC: clang-$LLVM_VERSION
CC_LD: lld-$LLVM_VERSION
CXX: clang++-$LLVM_VERSION
CXX_LD: lld-$LLVM_VERSION
MESON_TOOLCHAIN_OPTIONS: "$MESON_OPTIONS -Db_lundef=false" # clang+ASan+undef=boom
# Extends the core build templates to also provide for running our testing. We
@ -282,17 +293,8 @@ aarch64-debian-container_prep:
extends:
- .default-rules
script:
- cd "$BUILDDIR"
- meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
- ninja install
- test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
- virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
- TEST_RES=$(cat $TESTS_RES_PATH)
- rm $TESTS_RES_PATH
- cp -R /weston-virtme ./
- rm weston-virtme/${KERNEL_IMAGE}
- exit $TEST_RES
"${CI_PROJECT_DIR}/.gitlab-ci/build-and-test.sh"
artifacts:
name: weston-$CI_COMMIT_SHA
when: always
@ -303,7 +305,7 @@ aarch64-debian-container_prep:
- $BUILDDIR/weston-virtme
- $PREFIX
reports:
junit: $BUILDDIR/meson-logs/testlog-junit.xml
junit: $BUILDDIR/meson-logs/testlog.junit.xml
# Same as above, but without running any tests.
.build-no-test:
@ -425,67 +427,79 @@ aarch64-debian-container_prep:
- job: aarch64-debian-container_prep
artifacts: false
# Full build, used for testing under KVM.
# Full build (gcov + perfetto) used for testing under KVM.
.build-options-full:
stage: "Full build and test"
variables:
MESON_OPTIONS: >
-Doptimization=0
-Db_coverage=true
--force-fallback-for=perfetto
-Dperfetto=true
-Dperfetto:werror=false
-Dwerror=true
-Dtest-skip-is-failure=true
after_script:
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
- ninja -C "$BUILDDIR" coverage-xml
# Full build, (without gcov and perfetto)
.build-options-full-v2:
stage: "Full build and test"
variables:
MESON_OPTIONS: >
-Doptimization=0
-Dwerror=true
-Dtest-skip-is-failure=true
x86_64-debian-lts-full-build:
extends:
- .test-env-debian-lts-x86_64
- .build-options-full
x86_64-debian-full-build:
extends:
- .test-env-debian-x86_64
- .build-options-full
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: $BUILDDIR/meson-logs/coverage.xml
x86_64-debian-full-build:
extends:
- .test-env-debian-x86_64
- .build-options-full-v2
aarch64-debian-lts-full-build:
extends:
- .test-env-debian-lts-aarch64
- .build-options-full
- .build-options-full-v2
aarch64-debian-full-build:
extends:
- .test-env-debian-aarch64
- .build-options-full
- .build-options-full-v2
x86_64-clang-debian-lts-full-build:
extends:
- .test-env-debian-lts-x86_64
- .build-with-clang
- .build-options-full
- .build-options-full-v2
x86_64-clang-debian-full-build:
extends:
- .test-env-debian-x86_64
- .build-with-clang
- .build-options-full
- .build-options-full-v2
aarch64-clang-debian-lts-full-build:
extends:
- .test-env-debian-lts-aarch64
- .build-with-clang
- .build-options-full
- .build-options-full-v2
aarch64-clang-debian-full-build:
extends:
- .test-env-debian-aarch64
- .build-with-clang
- .build-options-full
- .build-options-full-v2
# Docs should be invariant on all architectures, so we only do it on Debian
# x86-64.
@ -499,9 +513,20 @@ docs-build:
- .build-env-debian-x86_64
- .build-no-test
# Building without gl-renderer, to make sure this keeps working.
# Building without gl-renderer and/or vulkan-renderer, to make sure this keeps working.
.build-options-no-gl-no-vulkan:
stage: "No-GL/Vulkan build and test"
variables:
MESON_OPTIONS: >
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
-Drenderer-gl=false
-Drenderer-vulkan=false
-Dremoting=false
-Dpipewire=false
-Dwerror=true
.build-options-no-gl:
stage: "No-GL build and test"
stage: "No-GL/Vulkan build and test"
variables:
MESON_OPTIONS: >
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
@ -510,51 +535,72 @@ docs-build:
-Dpipewire=false
-Dwerror=true
x86_64-debian-lts-no-gl-build:
.build-options-no-vulkan:
stage: "No-GL/Vulkan build and test"
variables:
MESON_OPTIONS: >
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
-Drenderer-vulkan=false
-Dremoting=false
-Dpipewire=false
-Dwerror=true
x86_64-debian-lts-no-gl-no-vulkan-build:
extends:
- .test-env-debian-lts-x86_64
- .build-options-no-gl
- .build-options-no-gl-no-vulkan
x86_64-debian-no-gl-no-vulkan-build:
extends:
- .test-env-debian-x86_64
- .build-options-no-gl-no-vulkan
armv7-debian-lts-no-gl-no-vulkan-build:
extends:
- .build-env-debian-lts-armv7
- .build-no-test
- .build-options-no-gl-no-vulkan
armv7-debian-no-gl-no-vulkan-build:
extends:
- .build-env-debian-armv7
- .build-no-test
- .build-options-no-gl-no-vulkan
armv7-clang-debian-lts-no-gl-no-vulkan-build:
extends:
- .build-env-debian-lts-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl-no-vulkan
armv7-clang-debian-no-gl-no-vulkan-build:
extends:
- .build-env-debian-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl-no-vulkan
aarch64-debian-lts-no-gl-no-vulkan-build:
extends:
- .test-env-debian-lts-aarch64
- .build-options-no-gl-no-vulkan
aarch64-debian-no-gl-no-vulkan-build:
extends:
- .test-env-debian-aarch64
- .build-options-no-gl-no-vulkan
x86_64-debian-no-gl-build:
extends:
- .test-env-debian-x86_64
- .build-options-no-gl
armv7-debian-lts-no-gl-build:
x86_64-debian-no-vulkan-build:
extends:
- .build-env-debian-lts-armv7
- .build-no-test
- .build-options-no-gl
- .test-env-debian-x86_64
- .build-options-no-vulkan
armv7-debian-no-gl-build:
extends:
- .build-env-debian-armv7
- .build-no-test
- .build-options-no-gl
armv7-clang-debian-lts-no-gl-build:
extends:
- .build-env-debian-lts-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl
armv7-clang-debian-no-gl-build:
extends:
- .build-env-debian-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl
aarch64-debian-lts-no-gl-build:
extends:
- .test-env-debian-lts-aarch64
- .build-options-no-gl
aarch64-debian-no-gl-build:
extends:
- .test-env-debian-aarch64
- .build-options-no-gl
# Expose docs and coverage reports, so we can show users any changes to these
# inside their merge requests, letting us check them before merge.
@ -566,18 +612,18 @@ aarch64-debian-no-gl-build:
docs-and-coverage:
extends:
- .default-rules
- .debian-x86_64
- .debian-lts-x86_64
- .fdo.suffixed-image@debian
stage: pages
needs:
- job: docs-build
artifacts: true
- job: x86_64-debian-full-build
- job: x86_64-debian-lts-full-build
artifacts: true
timeout: 5m
script:
- mv prefix-weston-docs-build/share/doc/weston Documentation
- mv build-weston-x86_64-debian-full-build/meson-logs/coveragereport Test_Coverage
- mv build-weston-x86_64-debian-lts-full-build/meson-logs/coveragereport Test_Coverage
- rm Test_Coverage/gcov.css
- cp doc/style/lcov-style.css Test_Coverage/gcov.css
- cp doc/style/*.png Test_Coverage/

29
.gitlab-ci/build-and-test.sh Executable file
View file

@ -0,0 +1,29 @@
#!/bin/bash
source "${FDO_CI_BASH_HELPERS}"
fdo_log_section_start_collapsed build_weston "build_weston"
cd "$BUILDDIR"
meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
ninja install
if [ "$CI_JOB_NAME" == "x86_64-debian-full-build" ]; then
cd "$BUILDDIR_WESTINY"
export NPREFIX=$CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
export PKG_CONFIG_PATH=$NPREFIX/lib/pkgconfig/:$NPREFIX/share/pkgconfig/:$NPREFIX/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
meson setup --prefix="$PREFIX_WESTINY" --wrap-mode=nofallback ../westinyplus/
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
ninja install
ninja clean
cd -
fi
fdo_log_section_end build_weston
test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
TEST_RES=$(cat $TESTS_RES_PATH)
rm $TESTS_RES_PATH
cp -R /weston-virtme ./
rm weston-virtme/${KERNEL_IMAGE}
exit $TEST_RES

View file

@ -4,6 +4,8 @@
# .gitlab-ci.yml for more information. This script is called from an
# OS-specific build scripts like debian-install.sh.
source "${FDO_CI_BASH_HELPERS}"
set -o xtrace -o errexit
# Set concurrency to an appropriate level for our shared runners, falling back
@ -25,7 +27,8 @@ esac
# Build and install Meson. Generally we want to keep this in sync with what
# we require inside meson.build.
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.0.0
fdo_log_section_start_collapsed install_meson "install_meson"
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.4.2
export PATH=$HOME/.local/bin:$PATH
# Our docs are built using Sphinx (top-level organisation and final HTML/CSS
@ -41,31 +44,22 @@ pip3 install $PIP_ARGS sphinxcontrib-qthelp==1.0.3
pip3 install $PIP_ARGS sphinxcontrib-serializinghtml==1.1.5
pip3 install $PIP_ARGS breathe==4.31.0
pip3 install $PIP_ARGS sphinx_rtd_theme==1.0.0
fdo_log_section_end install_meson
# Build a Linux kernel for use in testing. We enable the VKMS module so we can
# predictably test the DRM backend in the absence of real hardware. We lock the
# version here so we see predictable results.
#
# To run this we use virtme, a QEMU wrapper: https://github.com/amluto/virtme
# To run this we use virtme-ng, a QEMU wrapper. It is a fork from virtme, whose
# development stalled.
#
# virtme makes our lives easier by abstracting handling of the console,
# virtme-ng makes our lives easier by abstracting handling of the console,
# filesystem, etc, so we can pretend that the VM we execute in is actually
# just a regular container.
#
# The reason why we are using a fork here is that it adds a patch to have the
# --script-dir command line option. With that we can run scripts that are in a
# certain folder when virtme starts, which is necessary in our use case.
#
# The upstream also has some commands that could help us to reach the same
# results: --script-sh and --script-exec. Unfornutately they are not completely
# implemented yet, so we had some trouble to use them and it was becoming
# hackery.
#
# The fork pulls in this support from the original GitHub PR, rebased on top of
# a newer upstream version which fixes AArch64 support.
fdo_log_section_start_collapsed install_kernel "install_kernel"
if [[ -n "$KERNEL_DEFCONFIG" ]]; then
# 6.3 is (still) used as >= 6.5 drm-writeback test will timeout
git clone --depth=1 --branch=v6.3 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
git clone --depth=1 --branch=v6.18 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
cd linux
if [[ "${BUILD_ARCH}" = "x86-64" ]]; then
@ -91,9 +85,8 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
./scripts/config \
--enable CONFIG_DRM \
--enable CONFIG_DRM_KMS_HELPER \
--enable CONFIG_DRM_KMS_FB_HELPER \
--enable CONFIG_DRM_VKMS \
--enable CONFIG_DRM_VGEM
--enable CONFIG_UDMABUF
make ARCH=${LINUX_ARCH} oldconfig
make ARCH=${LINUX_ARCH}
@ -108,14 +101,15 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
./setup.py install
cd ..
fi
fdo_log_section_end install_kernel
# Build and install Wayland; keep this version in sync with our dependency
# in meson.build.
fdo_log_section_start_collapsed install_wayland "install_wayland"
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
cd wayland
git show -s HEAD
mkdir build
meson build --wrap-mode=nofallback -Ddocumentation=false
meson setup build --wrap-mode=nofallback -Ddocumentation=false
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf wayland
@ -123,24 +117,39 @@ rm -rf wayland
# Keep this version in sync with our dependency in meson.build. If you wish to
# raise a MR against custom protocol, please change this reference to clone
# your relevant tree, and make sure you bump $FDO_DISTRIBUTION_TAG.
git clone --branch 1.33 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
git clone --branch 1.46 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
cd wayland-protocols
git show -s HEAD
meson build --wrap-mode=nofallback
meson setup build --wrap-mode=nofallback -Dtests=false
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf wayland-protocols
fdo_log_section_end install_wayland
# Build and install our own version of libdrm. Debian 11 (bullseye) provides
# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api, and Mesa
# depends on 2.4.109 as well.
git clone --branch libdrm-2.4.109 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
# Bump to 2.4.118 to include DRM_FORMAT_NV{15,20,30}
fdo_log_section_start_collapsed install_libdrm "install_libdrm"
git clone --branch libdrm-2.4.118 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
cd drm
meson build --wrap-mode=nofallback -Dauto_features=disabled \
-Dvc4=false -Dfreedreno=false -Detnaviv=false
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
-Dvc4=disabled -Dfreedreno=disabled -Detnaviv=disabled
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf drm
fdo_log_section_end install_libdrm
# Build and install Vulkan-Headers with a defined version, mostly because
# the version in Debian 11 (bullseye) is too old to build vulkan-renderer.
fdo_log_section_start_collapsed install_vulkan_headers "install_vulkan_headers"
git clone --branch sdk-1.3.239.0 --depth=1 https://github.com/KhronosGroup/Vulkan-Headers
cd Vulkan-Headers
cmake -G Ninja -B build
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf Vulkan-Headers
fdo_log_section_end install_vulkan_headers
# Build and install our own version of Mesa. Debian provides a perfectly usable
# Mesa, however llvmpipe's rendering behaviour can change subtly over time.
@ -149,64 +158,89 @@ rm -rf drm
# features from Mesa then bump this version and $FDO_DISTRIBUTION_TAG, however
# please be prepared for some of the tests to change output, which will need to
# be manually inspected for correctness.
git clone --branch 23.0 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
fdo_log_section_start_collapsed install_mesa "install_mesa"
# Needed for Mesa >= 25.3
git clone --branch 12.2.0 --depth=1 https://github.com/KhronosGroup/glslang
cd glslang
cmake -G Ninja -B build
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf glslang
# The 25.3 was the first stable release where the Vulkan backend works with
# vkms+lavapipe.
git clone --branch mesa-25.3.2 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
cd mesa
meson build --wrap-mode=nofallback -Dauto_features=disabled \
-Dgallium-drivers=swrast -Dvulkan-drivers= -Ddri-drivers=
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
-Dgallium-drivers=llvmpipe -Dvulkan-drivers=swrast -Dvideo-codecs= \
-Degl=enabled -Dgbm=enabled -Dgles2=enabled -Dllvm=enabled \
-Dshared-glapi=enabled -Dglx=disabled
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf mesa
fdo_log_section_end install_mesa
# PipeWire is used for remoting support. Unlike our other dependencies its
# behaviour will be stable, however as a pre-1.0 project its API is not yet
# stable, so again we lock it to a fixed version.
#
# ... the version chosen is 0.3.32 with a small Clang-specific build fix.
fdo_log_section_start_collapsed install_pipewire "install_pipewire"
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire-src
cd pipewire-src
git checkout -b snapshot bf112940d0bf8f526dd6229a619c1283835b49c2
meson build --wrap-mode=nofallback
meson setup build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf pipewire-src
fdo_log_section_end install_pipewire
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
# We use this for our tests using the DRM backend.
fdo_log_section_start_collapsed install_seatd "install_seatd"
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
cd seatd
meson build --wrap-mode=nofallback -Dauto_features=disabled \
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
-Dlibseat-seatd=enabled -Dlibseat-logind=systemd -Dserver=enabled
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf seatd
fdo_log_section_end install_seatd
# Build and install aml and neatvnc, which are required for the VNC backend
fdo_log_section_start_collapsed install_aml_neatvnc "install_aml_neatvnc"
git clone --branch v0.3.0 --depth=1 https://github.com/any1/aml.git
cd aml
meson build --wrap-mode=nofallback
meson setup build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf aml
git clone --branch v0.7.0 --depth=1 https://github.com/any1/neatvnc.git
cd neatvnc
meson build --wrap-mode=nofallback -Dauto_features=disabled
meson setup build --wrap-mode=nofallback -Dauto_features=disabled
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf neatvnc
fdo_log_section_end install_aml_neatvnc
# Build and install libdisplay-info, used by drm-backend
git clone --branch 0.1.1 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
fdo_log_section_start_collapsed install_libdisplay-info "install_libdisplay-info"
git clone --branch 0.2.0 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
cd libdisplay-info
meson build --wrap-mode=nofallback
meson setup build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf libdisplay-info
fdo_log_section_end install_libdisplay-info
# Build and install lcms2, which we use to support color-management.
fdo_log_section_start_collapsed install_lcms2 "install_lcms2"
git clone --branch master https://github.com/mm2/Little-CMS.git lcms2
cd lcms2
git checkout -b snapshot lcms2.16
meson build --wrap-mode=nofallback
meson setup build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf lcms2
fdo_log_section_end install_lcms2

View file

@ -26,14 +26,22 @@ MESA_DEV_PKGS="
python3-mako
"
# These get temporarily installed for other build dependencies and then
# force-removed.
# cmake is used by Vulkan-Headers
BUILD_DEV_PKGS="
cmake
"
# Needed for running the custom-built mesa
MESA_RUNTIME_PKGS="
libllvm${LLVM_VERSION}
"
if [ x"$USE_BOOKWORM_BACKPORTS" = "xy" ] ; then
echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
if [ x"$USE_DEBIAN_BACKPORTS" = "xy" ] ; then
echo 'deb http://deb.debian.org/debian '${FDO_DISTRIBUTION_VERSION}'-backports main' >> /etc/apt/sources.list
fi
apt-get update
apt-get -y --no-install-recommends install \
autoconf \
@ -45,6 +53,7 @@ apt-get -y --no-install-recommends install \
graphviz \
gcovr \
git \
glslang-tools \
hwdata \
lcov \
libasound2-dev \
@ -59,7 +68,7 @@ apt-get -y --no-install-recommends install \
libexpat1-dev \
libffi-dev \
libgbm-dev \
libgdk-pixbuf2.0-dev \
libgdk-pixbuf-xlib-2.0-dev \
libgles2-mesa-dev \
libglu1-mesa-dev \
libgstreamer1.0-dev \
@ -68,6 +77,7 @@ apt-get -y --no-install-recommends install \
libjack-jackd2-dev \
libjpeg-dev \
libjpeg-dev \
liblua5.4-dev \
libmtdev-dev \
libpam0g-dev \
libpango1.0-dev \
@ -122,7 +132,9 @@ apt-get -y --no-install-recommends install \
cargo rustc \
iproute2 udev \
$MESA_DEV_PKGS \
$BUILD_DEV_PKGS \
$MESA_RUNTIME_PKGS \
$PACKAGES_SPECIFIC \
$LINUX_DEV_PKGS \
if [ "$FREERDP_VERSION" -ne 0 ] ; then
@ -135,4 +147,4 @@ fi
# And remove packages which are only required for our build dependencies,
# which we don't need bloating the image whilst we build and run Weston.
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS $BUILD_DEV_PKGS

View file

@ -11,3 +11,16 @@ leak:wl_shm_buffer_begin_access
leak:g_malloc0
leak:sysprof_collector_get
leak:/ld-*.so*
# Add all of perfetto, since it's not easy to clean up after it
leak:perfetto
# lavapipe inexplicably leaks when Vulkan physical devices are enumerated,
# despite us a) not using that device and b) freeing the instance. This is
# apparently a known issue. (Also when ASan creates threads ...)
leak:vkEnumeratePhysicalDevices
leak:asan_thread_start
# glib/pangoft for Trixie update
leak:libpangoft2
leak:libglib

View file

@ -12,10 +12,7 @@ export LIBSEAT_BACKEND=seatd
# devices are loaded is not predictable, so the DRM node that VKMS takes can
# change across each boot. That's why we have this one-liner shell script to get
# the appropriate node for VKMS.
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/devices/platform/vkms/drm/card*)
# To run tests in the CI that exercise the zwp_linux_dmabuf_v1 implementation in
# Weston, we use VGEM to allocate buffers.
export WESTON_TEST_SUITE_ALLOC_DEVICE=$(basename /sys/devices/platform/vgem/drm/card*)
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/bus/faux/devices/vkms/drm/card*)
# ninja test depends on meson, and meson itself looks for its modules on folder
# $HOME/.local/lib/pythonX.Y/site-packages (the Python version may differ).
@ -26,11 +23,11 @@ export HOME=/root
export PATH=$HOME/.local/bin:$PATH
export PATH=/usr/local/bin:$PATH
export SEATD_LOGLEVEL=debug
# Terrible hack, per comment in weston-test-runner.c's main(): find Mesa's
# llvmpipe driver module location
export WESTON_CI_LEAK_DL_HANDLE=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true)
# llvmpipe/lavapipe driver module location
export WESTON_CI_LEAK_DL_HANDLES=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true):
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libvulkan_lvp.so -print 2>/dev/null || true)
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libgallium\*.so -print 2>/dev/null || true)
# run the tests and save the exit status
# we give ourselves a very generous timeout multiplier due to ASan overhead

View file

@ -117,11 +117,11 @@ finish_calibration (struct calibrator *calibrator)
*/
memset(&m, 0, sizeof(m));
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
m.d[i] = calibrator->tests[i].clicked_x;
m.d[i + 4] = calibrator->tests[i].clicked_y;
m.d[i + 8] = 1;
m.M.col[0].el[i] = calibrator->tests[i].clicked_x;
m.M.col[1].el[i] = calibrator->tests[i].clicked_y;
m.M.col[2].el[i] = 1;
}
m.d[15] = 1;
m.M.col[3].el[3] = 1;
weston_matrix_invert(&inverse, &m);
@ -129,8 +129,8 @@ finish_calibration (struct calibrator *calibrator)
memset(&y_calib, 0, sizeof(y_calib));
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
x_calib.f[i] = calibrator->tests[i].drawn_x;
y_calib.f[i] = calibrator->tests[i].drawn_y;
x_calib.v.el[i] = calibrator->tests[i].drawn_x;
y_calib.v.el[i] = calibrator->tests[i].drawn_y;
}
/* Multiples into the vector */
@ -138,8 +138,8 @@ finish_calibration (struct calibrator *calibrator)
weston_matrix_transform(&inverse, &y_calib);
printf ("Calibration values: %f %f %f %f %f %f\n",
x_calib.f[0], x_calib.f[1], x_calib.f[2],
y_calib.f[0], y_calib.f[1], y_calib.f[2]);
x_calib.v.el[0], x_calib.v.el[1], x_calib.v.el[2],
y_calib.v.el[0], y_calib.v.el[1], y_calib.v.el[2]);
exit(0);
}

584
clients/color.c Normal file
View file

@ -0,0 +1,584 @@
/*
* Copyright (C) 2024 SUSE Software Solutions Germany GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <assert.h>
#include <errno.h>
#include "color-management-v1-client-protocol.h"
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "window.h"
enum image_description_status {
IMAGE_DESCRIPTION_NOT_CREATED = 0,
IMAGE_DESCRIPTION_READY,
IMAGE_DESCRIPTION_FAILED,
};
struct pixel_color {
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
};
struct color {
struct display *display;
struct window *window;
struct widget *parent_widget;
struct widget *widget;
struct wp_color_manager_v1 *color_manager;
struct wp_color_management_surface_v1 *color_surface;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
struct wp_viewporter *viewporter;
struct wp_viewport *viewport;
struct pixel_color pixel_color;
enum wp_color_manager_v1_primaries primaries;
enum wp_color_manager_v1_transfer_function transfer_function;
float min_lum;
float max_lum;
float ref_lum;
uint32_t supported_color_features;
uint32_t supported_rendering_intents;
uint32_t supported_primaries_named;
uint32_t supported_tf_named;
};
struct valid_enum {
const char *name;
uint32_t value;
};
static bool opt_help = false;
static uint32_t opt_width = 250;
static uint32_t opt_height = 250;
static const char *opt_r = NULL;
static const char *opt_g = NULL;
static const char *opt_b = NULL;
static const char *opt_a = NULL;
static const char *opt_primaries = NULL;
static const char *opt_transfer_function = NULL;
static const char *opt_min_lum = NULL;
static const char *opt_max_lum = NULL;
static const char *opt_ref_lum = NULL;
static const struct weston_option cli_options[] = {
{ WESTON_OPTION_BOOLEAN, "help", 0, &opt_help },
{ WESTON_OPTION_UNSIGNED_INTEGER, "width", 'w', &opt_width },
{ WESTON_OPTION_UNSIGNED_INTEGER, "height", 'h', &opt_height },
{ WESTON_OPTION_STRING, 0, 'R', &opt_r },
{ WESTON_OPTION_STRING, 0, 'G', &opt_g },
{ WESTON_OPTION_STRING, 0, 'B', &opt_b },
{ WESTON_OPTION_STRING, 0, 'A', &opt_a },
{ WESTON_OPTION_STRING, "primaries", 'p', &opt_primaries },
{ WESTON_OPTION_STRING, "transfer-function", 't', &opt_transfer_function },
{ WESTON_OPTION_STRING, "min-lum", 'm', &opt_min_lum },
{ WESTON_OPTION_STRING, "max-lum", 'M', &opt_max_lum },
{ WESTON_OPTION_STRING, "ref-lum", 'r', &opt_ref_lum },
};
static const struct valid_enum valid_primaries[] = {
{ "srgb", WP_COLOR_MANAGER_V1_PRIMARIES_SRGB },
{ "bt2020", WP_COLOR_MANAGER_V1_PRIMARIES_BT2020 },
};
static const struct valid_enum valid_transfer_functions[] = {
{ "srgb", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB },
{ "pq", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ },
{ "linear", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR },
};
static bool
validate_color(const char *c, uint32_t *dest, uint32_t fallback)
{
char *end;
double value;
if (!c) {
*dest = fallback;
return true;
}
value = strtod(c, &end);
if (value < 0.0 || value > 1.0 || *end != '\0') {
fprintf(stderr, "Validating color failed, it should be between 0.0 and 1.0\n");
return false;
}
*dest = value * UINT32_MAX;
return true;
}
static bool
validate_option(const char *option, uint32_t *dest,
const struct valid_enum *valid_options,
int count, uint32_t fallback)
{
int i;
if (!option) {
*dest = fallback;
return true;
}
for (i = 0; i < count; i++) {
if (strcmp(valid_options[i].name, option) == 0) {
*dest = valid_options[i].value;
return true;
}
}
fprintf(stderr, "Validating option '%s' failed, valid options:\n", option);
for (i = 0; i < count; i++)
fprintf(stderr, "'%s' ", valid_options[i].name);
fprintf(stderr, "\n");
return false;
}
static bool
validate_luminance(const char *c, float *dest, float fallback)
{
char *end;
float value;
if (!c) {
*dest = fallback;
return true;
}
value = strtof(c, &end);
if (value < 0.f || value > 10000.f || *end != '\0') {
fprintf(stderr, "Validating luminance failed, it should be between 0 and 10,000\n");
return false;
}
*dest = value;
return true;
}
static bool
validate_options(struct color *color)
{
return validate_color(opt_r, &color->pixel_color.r, 0) &&
validate_color(opt_g, &color->pixel_color.g, 0) &&
validate_color(opt_b, &color->pixel_color.b, 0) &&
validate_color(opt_a, &color->pixel_color.a, UINT32_MAX) &&
validate_option(opt_primaries, &color->primaries,
valid_primaries,
ARRAY_LENGTH(valid_primaries),
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB) &&
validate_option(opt_transfer_function, &color->transfer_function,
valid_transfer_functions,
ARRAY_LENGTH(valid_transfer_functions),
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) &&
validate_luminance(opt_min_lum, &color->min_lum, -1.f) &&
validate_luminance(opt_max_lum, &color->max_lum, -1.f) &&
validate_luminance(opt_ref_lum, &color->ref_lum, -1.f);
}
static void
usage(const char *program_name, int exit_code)
{
unsigned int i;
fprintf(stderr, "Usage: %s [OPTIONS]\n", program_name);
fprintf(stderr, " --help\n");
fprintf(stderr, " --width or -w\n");
fprintf(stderr, " --height or -h\n");
fprintf(stderr, " -R (0.0 to 1.0)\n");
fprintf(stderr, " -G (0.0 to 1.0)\n");
fprintf(stderr, " -B (0.0 to 1.0)\n");
fprintf(stderr, " -A (0.0 to 1.0)\n");
fprintf(stderr, " --primaries or -p:");
fprintf(stderr, "\n ");
for (i = 0; i < ARRAY_LENGTH(valid_primaries); i++)
fprintf(stderr, " '%s'", valid_primaries[i].name);
fprintf(stderr, "\n");
fprintf(stderr, " --transfer-function or -t:");
fprintf(stderr, "\n ");
for (i = 0; i < ARRAY_LENGTH(valid_transfer_functions); i++)
fprintf(stderr, " '%s'", valid_transfer_functions[i].name);
fprintf(stderr, "\n");
fprintf(stderr, " --min-lum or -m (0.0 to 10000.0)\n");
fprintf(stderr, " --max-lum or -M (0.0 to 10000.0)\n");
fprintf(stderr, " --ref-lum or -r (0.0 to 10000.0)\n");
exit(exit_code);
}
static void
supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t render_intent)
{
struct color *color = data;
color->supported_rendering_intents |= 1 << render_intent;
}
static void
supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t feature)
{
struct color *color = data;
color->supported_color_features |= 1 << feature;
}
static void
supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t tf)
{
struct color *color = data;
color->supported_tf_named |= 1 << tf;
}
static void
supported_primaries_named(void *data,
struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t primaries)
{
struct color *color = data;
color->supported_primaries_named |= 1 << primaries;
}
static void
done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
{
}
static const struct wp_color_manager_v1_listener color_manager_listener = {
supported_intent,
supported_feature,
supported_tf_named,
supported_primaries_named,
done,
};
static void
global_handler(struct display *display, uint32_t name,
const char *interface, uint32_t version, void *data)
{
struct color *color = data;
struct wl_surface *surface = widget_get_wl_surface(color->widget);
if (strcmp(interface, wp_color_manager_v1_interface.name) == 0) {
color->color_manager = display_bind(display, name,
&wp_color_manager_v1_interface, 1);
color->color_surface = wp_color_manager_v1_get_surface(color->color_manager,
surface);
wp_color_manager_v1_add_listener(color->color_manager,
&color_manager_listener, color);
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
color->single_pixel_manager =
display_bind(display, name,
&wp_single_pixel_buffer_manager_v1_interface, 1);
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
color->viewporter = display_bind(display, name,
&wp_viewporter_interface, 1);
color->viewport = wp_viewporter_get_viewport(color->viewporter, surface);
}
}
static bool
check_color_requirements(struct color *color)
{
if (!color->color_manager) {
fprintf(stderr, "The compositor doesn't expose %s\n",
wp_color_manager_v1_interface.name);
return false;
}
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC))) {
fprintf(stderr, "The color manager doesn't support the parametric creator\n");
return false;
}
if (!(color->supported_primaries_named & (1 << color->primaries))) {
fprintf(stderr, "The color manager doesn't support the primaries name\n");
return false;
}
if (!(color->supported_tf_named & (1 << color->transfer_function))) {
fprintf(stderr, "The color manager doesn't support the transfer function\n");
return false;
}
if (!(color->supported_rendering_intents & (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL))) {
fprintf(stderr, "The color manager doesn't support perceptual render intent\n");
return false;
}
if (color->min_lum != -1.f || color->max_lum != -1.f || color->ref_lum != -1.f) {
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES))) {
fprintf(stderr, "The color manager doesn't support setting luminances\n");
return false;
}
if (color->min_lum == -1.f || color->max_lum == -1.f || color->ref_lum == -1.f) {
fprintf(stderr, "To set the luminances it is required min-lum, max-lum and ref-lum\n");
return false;
}
}
return true;
}
static void
color_destroy(struct color *color)
{
if (color->color_surface)
wp_color_management_surface_v1_destroy(color->color_surface);
if (color->color_manager)
wp_color_manager_v1_destroy(color->color_manager);
if (color->single_pixel_manager)
wp_single_pixel_buffer_manager_v1_destroy(color->single_pixel_manager);
if (color->viewport)
wp_viewport_destroy(color->viewport);
if (color->viewporter)
wp_viewporter_destroy(color->viewporter);
if (color->widget)
widget_destroy(color->widget);
if (color->parent_widget)
widget_destroy(color->parent_widget);
if (color->window)
window_destroy(color->window);
if (color->display)
display_destroy(color->display);
free(color);
}
static void
resize_handler(struct widget *parent_widget, int32_t width, int32_t height, void *data)
{
struct color *color = data;
struct rectangle allocation;
struct wl_surface *surface = widget_get_wl_surface(color->widget);
struct wl_subsurface *subsurface = widget_get_wl_subsurface(color->widget);
widget_get_allocation(parent_widget, &allocation);
wl_subsurface_set_position(subsurface, allocation.x, allocation.y);
wp_viewport_set_destination(color->viewport, width, height);
wl_surface_commit(surface);
}
static void
set_empty_input_region(struct color *color, struct widget *widget)
{
struct wl_region *region;
struct wl_compositor *compositor;
struct wl_surface *surface = widget_get_wl_surface(widget);
compositor = display_get_compositor(color->display);
region = wl_compositor_create_region(compositor);
wl_surface_set_input_region(surface, region);
wl_region_destroy(region);
}
static void
buffer_release(void *data, struct wl_buffer *buffer)
{
wl_buffer_destroy(buffer);
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
static void
set_single_pixel(struct color *color, struct widget *widget)
{
struct wl_surface *surface = widget_get_wl_surface(widget);
struct wl_buffer *buffer =
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(color->single_pixel_manager,
color->pixel_color.r,
color->pixel_color.g,
color->pixel_color.b,
color->pixel_color.a);
wl_buffer_add_listener(buffer, &buffer_listener, NULL);
wl_surface_attach(surface, buffer, 0, 0);
}
static void
image_description_failed(void *data,
struct wp_image_description_v1 *wp_image_description_v1,
uint32_t cause, const char *msg)
{
enum image_description_status *image_desc_status = data;
fprintf(stderr, "Failed to create image description: %u - %s\n",
cause, msg);
*image_desc_status = IMAGE_DESCRIPTION_FAILED;
}
static void
image_description_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
uint32_t identity)
{
enum image_description_status *image_desc_status = data;
*image_desc_status = IMAGE_DESCRIPTION_READY;
}
static const struct wp_image_description_v1_listener image_description_listener = {
image_description_failed,
image_description_ready,
};
static struct wp_image_description_v1 *
create_image_description(struct color *color, uint32_t primaries_named, uint32_t tf_named)
{
struct wp_image_description_creator_params_v1 *params_creator;
struct wp_image_description_v1 *image_description;
enum image_description_status image_desc_status = IMAGE_DESCRIPTION_NOT_CREATED;
int ret = 0;
params_creator = wp_color_manager_v1_create_parametric_creator(color->color_manager);
wp_image_description_creator_params_v1_set_primaries_named(params_creator, primaries_named);
wp_image_description_creator_params_v1_set_tf_named(params_creator, tf_named);
if (color->min_lum != -1 && color->max_lum != -1 && color->ref_lum != -1)
wp_image_description_creator_params_v1_set_luminances(params_creator,
color->min_lum * 10000,
color->max_lum,
color->ref_lum);
image_description = wp_image_description_creator_params_v1_create(params_creator);
wp_image_description_v1_add_listener(image_description,
&image_description_listener,
&image_desc_status);
while (ret != -1 && image_desc_status == IMAGE_DESCRIPTION_NOT_CREATED)
ret = wl_display_dispatch(display_get_display(color->display));
if (ret == -1) {
wp_image_description_v1_destroy(image_description);
fprintf(stderr, "Error when creating the image description: %s\n", strerror(errno));
return NULL;
}
if (image_desc_status == IMAGE_DESCRIPTION_FAILED) {
wp_image_description_v1_destroy(image_description);
return NULL;
}
assert(image_desc_status == IMAGE_DESCRIPTION_READY);
return image_description;
}
static bool
set_image_description(struct color *color, struct widget *widget)
{
struct wp_image_description_v1 *image_description;
image_description =
create_image_description(color,
color->primaries,
color->transfer_function);
if (!image_description)
return false;
wp_color_management_surface_v1_set_image_description(
color->color_surface,
image_description,
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
wp_image_description_v1_destroy(image_description);
return true;
}
int
main(int argc, char *argv[])
{
struct color *color;
if (parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv) > 1)
usage(argv[0], EXIT_FAILURE);
if (opt_help)
usage(argv[0], EXIT_SUCCESS);
color = xzalloc(sizeof *color);
if (!validate_options(color)) {
color_destroy(color);
exit(EXIT_FAILURE);
}
color->display = display_create(&argc, argv);
if (!color->display) {
color_destroy(color);
exit(EXIT_FAILURE);
}
color->window = window_create(color->display);
color->parent_widget = window_frame_create(color->window, color);
color->widget = window_add_subsurface(color->window, color, SUBSURFACE_SYNCHRONIZED);
display_set_user_data(color->display, color);
display_set_global_handler(color->display, global_handler);
wl_display_roundtrip(display_get_display(color->display));
if (!check_color_requirements(color)) {
color_destroy(color);
exit(EXIT_SUCCESS);
}
window_unset_shadow(color->window);
window_set_title(color->window, "Color");
window_set_appid(color->window, "org.freedesktop.weston.color");
/* The first resize call sets the min size,
* setting 0, 0 sets a default size */
window_schedule_resize(color->window, 0, 0);
window_schedule_resize(color->window, opt_width, opt_height);
widget_set_resize_handler(color->parent_widget, resize_handler);
widget_set_use_cairo(color->widget, 0);
set_empty_input_region(color, color->widget);
set_single_pixel(color, color->widget);
if (set_image_description(color, color->widget))
display_run(color->display);
color_destroy(color);
return 0;
}

View file

@ -53,6 +53,7 @@
#include "window.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "tablet-unstable-v2-client-protocol.h"
#include "weston-desktop-shell-client-protocol.h"
@ -777,14 +778,62 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path, cons
enum {
BACKGROUND_SCALE,
BACKGROUND_SCALE_CROP,
BACKGROUND_SCALE_FIT,
BACKGROUND_TILE,
BACKGROUND_CENTERED
};
static void
buffer_release(void *data, struct wl_buffer *buffer)
{
wl_buffer_destroy(buffer);
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
static void
background_draw(struct widget *widget, void *data)
{
struct background *background = data;
if (!background->image && background->color) {
struct display *display = window_get_display(background->window);
struct wp_single_pixel_buffer_manager_v1 *sp_manager;
struct wl_surface *wl_surface;
struct wl_buffer *wl_buffer;
uint32_t r8, g8, b8;
uint32_t r32, g32, b32;
/* Single pixel buffer must use scale 1 */
window_set_buffer_scale(background->window, 1);
sp_manager = display_get_single_pixel_buffer_manager(display);
assert(sp_manager);
wl_surface = widget_get_wl_surface(background->widget);
assert(wl_surface);
r8 = (background->color >> 16) & 0xff;
g8 = (background->color >> 8) & 0xff;
b8 = (background->color >> 0) & 0xff;
r32 = r8 << 24 | r8 << 16 | r8 << 8 | r8;
g32 = g8 << 24 | g8 << 16 | g8 << 8 | g8;
b32 = b8 << 24 | b8 << 16 | b8 << 8 | b8;
wl_buffer =
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(sp_manager,
r32,
g32,
b32,
0xffffffff);
assert(wl_buffer);
wl_surface_attach(wl_surface, wl_buffer, 0, 0);
wl_buffer_add_listener(wl_buffer, &buffer_listener, NULL);
widget_surface_flush(widget);
} else {
cairo_surface_t *surface, *image;
cairo_pattern_t *pattern;
cairo_matrix_t matrix;
@ -830,7 +879,11 @@ background_draw(struct widget *widget, void *data)
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
break;
case BACKGROUND_SCALE_CROP:
case BACKGROUND_SCALE_FIT:
if (background->type == BACKGROUND_SCALE_CROP)
s = (sx < sy) ? sx : sy;
else
s = (sx > sy) ? sx : sy;
/* align center */
tx = (im_w - s * allocation.width) * 0.5;
ty = (im_h - s * allocation.height) * 0.5;
@ -865,6 +918,7 @@ background_draw(struct widget *widget, void *data)
cairo_destroy(cr);
cairo_surface_destroy(surface);
}
background->painted = 1;
check_desktop_ready(background->window);
@ -892,6 +946,7 @@ background_configure(void *data,
}
if (!background->image && background->color) {
widget_set_use_cairo(background->widget, 0);
widget_set_viewport_destination(background->widget, width, height);
width = 1;
height = 1;
@ -1191,6 +1246,10 @@ background_create(struct desktop *desktop, struct output *output)
weston_config_section_get_color(s, "background-color",
&background->color, 0x00000000);
/* Backgrounds must be fully opaque. */
if (background->color != 0)
background->color |= 0xFF000000;
weston_config_section_get_string(s, "background-type",
&type, "tile");
if (type == NULL) {
@ -1202,6 +1261,8 @@ background_create(struct desktop *desktop, struct output *output)
background->type = BACKGROUND_SCALE;
} else if (strcmp(type, "scale-crop") == 0) {
background->type = BACKGROUND_SCALE_CROP;
} else if (strcmp(type, "scale-fit") == 0) {
background->type = BACKGROUND_SCALE_FIT;
} else if (strcmp(type, "tile") == 0) {
background->type = BACKGROUND_TILE;
} else if (strcmp(type, "centered") == 0) {
@ -1321,10 +1382,11 @@ output_handle_scale(void *data,
int32_t scale)
{
struct output *output = data;
struct background *background = output->background;
if (output->panel)
window_set_buffer_scale(output->panel->window, scale);
if (output->background)
if (background && !background->color)
window_set_buffer_scale(output->background->window, scale);
}

View file

@ -515,7 +515,7 @@ create_drag_source(struct dnd *dnd,
dnd_drag->drag_surface =
wl_compositor_create_surface(compositor);
if (display_get_data_device_manager_version(display) <
if (dnd->self_only || display_get_data_device_manager_version(display) <
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
/* Data sources version < 3 will not get action
* nor dnd_finished events, as we can't honor
@ -546,12 +546,12 @@ create_drag_source(struct dnd *dnd,
flower_mime_type);
wl_data_source_offer(dnd_drag->data_source,
text_mime_type);
}
if (display_get_data_device_manager_version(display) >=
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
wl_data_source_set_actions(dnd_drag->data_source, actions);
}
}
wl_data_device_start_drag(input_get_data_device(input),
dnd_drag->data_source,

View file

@ -346,6 +346,7 @@ usage(int error_code)
fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
" -w <width>\tSet window width to <width>\n"
" -h <height>\tSet window height to <height>\n"
" -f\t\tMap window as fullscreen\n"
" --help\tShow this help text\n\n");
exit(error_code);
@ -394,6 +395,8 @@ int main(int argc, char *argv[])
usage(EXIT_FAILURE);
fullscreen.height = atol(argv[i]);
} else if (strcmp(argv[i], "-f") == 0) {
fullscreen.fullscreen = 1;
} else if (strcmp(argv[i], "--help") == 0)
usage(EXIT_SUCCESS);
else
@ -434,6 +437,8 @@ int main(int argc, char *argv[])
window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
window_set_user_data(fullscreen.window, &fullscreen);
if (fullscreen.fullscreen)
window_set_fullscreen(fullscreen.window, fullscreen.fullscreen);
/* Hack to set minimum allocation so we can shrink later */
window_schedule_resize(fullscreen.window,
1, 1);

View file

@ -143,6 +143,8 @@ hmi_homescreen_launcher {
uint32_t workspace_id;
char *icon;
char *path;
char **argv;
struct wl_list link;
};
@ -308,12 +310,10 @@ launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
struct hmi_homescreen_launcher *launcher = NULL;
wl_list_for_each(launcher, launcher_list, link) {
char *argv[] = { NULL };
if (surfaceId != launcher->icon_surface_id)
continue;
execute_process(launcher->path, argv);
execute_process(launcher->path, launcher->argv);
return 1;
}
@ -1065,6 +1065,32 @@ create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
free(launchers);
}
static char **
parse_command(char *str)
{
char **argv;
char *saveptr;
char *token;
int i;
int count = 1;
for (i = 1; str[i]; i++)
if (str[i] == ' ' && str[i-1] != ' ')
count++;
argv = xcalloc(count + 1, sizeof(char*));
i = 0;
token = strtok_r(str, " ", &saveptr);
while (token != NULL) {
argv[i++] = token;
token = strtok_r(NULL, " ", &saveptr);
}
return argv;
}
/**
* Internal method to read out weston.ini to get configuration
*/
@ -1177,6 +1203,7 @@ hmi_homescreen_setting_create(void)
while (weston_config_next_section(config, &section, &name)) {
struct hmi_homescreen_launcher *launcher;
char *command;
if (strcmp(name, "ivi-launcher") != 0)
continue;
@ -1186,8 +1213,18 @@ hmi_homescreen_setting_create(void)
weston_config_section_get_string(section, "icon",
&launcher->icon, NULL);
weston_config_section_get_string(section, "command",
&command, NULL);
if (command == NULL) {
weston_config_section_get_string(section, "path",
&launcher->path, NULL);
launcher->argv = NULL;
} else {
launcher->argv = parse_command(command);
launcher->path = launcher->argv[0];
}
weston_config_section_get_uint(section, "workspace-id",
&launcher->workspace_id, 0);
weston_config_section_get_uint(section, "icon-id",

View file

@ -14,6 +14,8 @@ srcs_toytoolkit = [
relative_pointer_unstable_v1_protocol_c,
pointer_constraints_unstable_v1_client_protocol_h,
pointer_constraints_unstable_v1_protocol_c,
single_pixel_buffer_v1_client_protocol_h,
single_pixel_buffer_v1_protocol_c,
tablet_unstable_v2_client_protocol_h,
tablet_unstable_v2_protocol_c,
ivi_application_client_protocol_h,
@ -161,6 +163,21 @@ simple_clients = [
],
'dep_objs': [ dep_wayland_client, dep_libshared ]
},
{
'name': 'timing',
'sources': [
'simple-timing.c',
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
commit_timing_v1_client_protocol_h,
commit_timing_v1_protocol_c,
fifo_v1_client_protocol_h,
fifo_v1_protocol_c,
presentation_time_client_protocol_h,
presentation_time_protocol_c,
],
'dep_objs': [ dep_wayland_client, dep_libshared ]
},
{
'name': 'touch',
'sources': [
@ -172,6 +189,89 @@ simple_clients = [
},
]
if dep_vulkan.found() and prog_glslang.found()
srcs_simple_vulkan_shaders = [
'simple_vulkan_vertex_shader.vert',
'simple_vulkan_fragment_shader.frag',
]
simple_vulkan_shaders = []
foreach s : srcs_simple_vulkan_shaders
simple_vulkan_shaders += custom_target(s + '.spv.h',
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
input: s,
output: '@BASENAME@.spv.h',
)
endforeach
simple_clients += {
'name': 'vulkan',
'sources': [
'simple-vulkan.c',
simple_vulkan_shaders,
fractional_scale_v1_client_protocol_h,
fractional_scale_v1_protocol_c,
tearing_control_v1_client_protocol_h,
tearing_control_v1_protocol_c,
viewporter_client_protocol_h,
viewporter_protocol_c,
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
],
'dep_objs': [
dep_vulkan,
dep_libm,
dep_libshared,
dep_matrix_c,
dep_wayland_client,
],
'deps': [ 'vulkan', 'wayland-cursor' ],
'options': [ 'renderer-gl' ]
}
srcs_simple_dmabuf_vulkan_shaders = [
'simple_dmabuf_vulkan_vertex_shader.vert',
'simple_dmabuf_vulkan_fragment_shader.frag',
]
simple_dmabuf_vulkan_shaders = []
foreach s : srcs_simple_dmabuf_vulkan_shaders
simple_dmabuf_vulkan_shaders += custom_target(s + '.spv.h',
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
input: s,
output: '@BASENAME@.spv.h',
)
endforeach
simple_clients += {
'name': 'dmabuf-vulkan',
'sources': [
'simple-dmabuf-vulkan.c',
simple_dmabuf_vulkan_shaders,
linux_dmabuf_unstable_v1_client_protocol_h,
linux_dmabuf_unstable_v1_protocol_c,
linux_explicit_synchronization_unstable_v1_client_protocol_h,
linux_explicit_synchronization_unstable_v1_protocol_c,
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
weston_direct_display_client_protocol_h,
weston_direct_display_protocol_c,
],
'dep_objs': [
dep_vulkan,
dep_libdrm_headers,
dep_libm,
dep_libdrm,
dep_libshared,
dep_matrix_c,
dep_wayland_client,
dep_libweston_private, # for pixel-formats.h
],
'deps': [ 'vulkan', 'wayland-cursor', 'gbm' ],
'options': [ 'renderer-gl' ]
}
endif
foreach t : simple_clients
if simple_build_all or simple_clients_enabled.contains(t.get('name'))
t_name = 'weston-simple-' + t.get('name')
@ -269,6 +369,15 @@ demo_clients = [
'basename': 'cliptest',
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
},
{
'basename': 'color',
'add_sources': [
color_management_v1_client_protocol_h,
color_management_v1_protocol_c,
single_pixel_buffer_v1_client_protocol_h,
single_pixel_buffer_v1_protocol_c,
],
},
{
'basename': 'constraints',
'add_sources': [
@ -391,7 +500,7 @@ if get_option('shell-desktop')
env_modmap += 'weston-desktop-shell=@0@;'.format(exe_shell_desktop.full_path())
endif
if get_option('shell-desktop') or get_option('shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
if get_option('shell-desktop') or get_option('deprecated-shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
exe_shooter = executable(
'weston-screenshooter',
'screenshot.c',
@ -399,6 +508,7 @@ if get_option('shell-desktop') or get_option('shell-fullscreen') or get_option('
weston_output_capture_protocol_c,
include_directories: common_inc,
dependencies: [
dep_client_buffer,
dep_toytoolkit,
dep_libweston_private, # for pixel-formats.h
dep_pixman,

View file

@ -775,7 +775,7 @@ registry_handle_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
d->presentation =
wl_registry_bind(registry,
name, &wp_presentation_interface, 1);
name, &wp_presentation_interface, 2);
wp_presentation_add_listener(d->presentation,
&presentation_listener, d);
}

View file

@ -24,33 +24,44 @@
#include "config.h"
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <pixman.h>
#include <cairo.h>
#include <assert.h>
#include <cairo.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <pixman.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <unistd.h>
#include <wayland-client.h>
#include "weston-output-capture-client-protocol.h"
#include "shared/os-compatibility.h"
#include "shared/xalloc.h"
#include "shared/file-util.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "pixel-formats.h"
#include "shared/client-buffer-util.h"
#include "shared/file-util.h"
#include "shared/os-compatibility.h"
#include "shared/string-helpers.h"
#include "shared/xalloc.h"
#include "weston-output-capture-client-protocol.h"
struct screenshooter_app {
struct wl_display *display;
struct wl_registry *registry;
struct wl_shm *shm;
struct zwp_linux_dmabuf_v1 *dmabuf;
struct weston_capture_v1 *capture_factory;
bool verbose;
const struct pixel_format_info *requested_format;
enum weston_capture_v1_source src_type;
enum client_buffer_type buffer_type;
struct wl_list output_list; /* struct screenshooter_output::link */
bool retry;
@ -59,14 +70,14 @@ struct screenshooter_app {
};
struct screenshooter_buffer {
size_t len;
void *data;
struct wl_buffer *wl_buffer;
struct client_buffer *buf;
pixman_image_t *image;
enum weston_capture_v1_source src_type;
};
struct screenshooter_output {
struct screenshooter_app *app;
uint32_t name;
struct wl_list link; /* struct screenshooter_app::output_list */
struct wl_output *wl_output;
@ -76,7 +87,8 @@ struct screenshooter_output {
int buffer_width;
int buffer_height;
const struct pixel_format_info *fmt;
struct wl_array formats;
bool formats_done;
struct screenshooter_buffer *buffer;
};
@ -93,10 +105,6 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
const struct pixel_format_info *fmt)
{
struct screenshooter_buffer *buffer;
struct wl_shm_pool *pool;
int fd;
size_t bytes_pp;
size_t stride;
assert(width > 0);
assert(height > 0);
@ -105,54 +113,60 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
buffer = xzalloc(sizeof *buffer);
bytes_pp = fmt->bpp / 8;
stride = width * bytes_pp;
buffer->len = stride * height;
assert(width == stride / bytes_pp);
assert(height == buffer->len / stride);
fd = os_create_anonymous_file(buffer->len);
if (fd < 0) {
fprintf(stderr, "creating a buffer file for %zd B failed: %s\n",
buffer->len, strerror(errno));
free(buffer);
return NULL;
}
buffer->data = mmap(NULL, buffer->len, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (buffer->data == MAP_FAILED) {
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
close(fd);
free(buffer);
return NULL;
}
pool = wl_shm_create_pool(app->shm, fd, buffer->len);
close(fd);
buffer->wl_buffer =
wl_shm_pool_create_buffer(pool, 0, width, height, stride,
pixel_format_get_shm_format(fmt));
wl_shm_pool_destroy(pool);
buffer->buf = client_buffer_util_create_shm_buffer(app->shm,
fmt,
width,
height);
buffer->image = pixman_image_create_bits(fmt->pixman_format,
width, height,
buffer->data, stride);
buffer->buf->data,
buffer->buf->strides[0]);
abort_oom_if_null(buffer->image);
return buffer;
}
static struct screenshooter_buffer *
screenshot_create_udmabuf(struct screenshooter_app *app,
int width, int height,
const struct pixel_format_info *fmt)
{
struct screenshooter_buffer* buffer = NULL;
assert(width > 0);
assert(height > 0);
assert(fmt);
buffer = xzalloc(sizeof *buffer);
buffer->buf = client_buffer_util_create_dmabuf_buffer(app->display,
app->dmabuf,
fmt,
width,
height);
if (fmt->pixman_format) {
buffer->image = pixman_image_create_bits(fmt->pixman_format,
width, height,
buffer->buf->data,
buffer->buf->strides[0]);
abort_oom_if_null(buffer->image);
}
return buffer;
}
static void
screenshooter_buffer_destroy(struct screenshooter_buffer *buffer)
{
if (!buffer)
return;
if (buffer->image)
pixman_image_unref(buffer->image);
munmap(buffer->data, buffer->len);
wl_buffer_destroy(buffer->wl_buffer);
client_buffer_util_destroy_buffer(buffer->buf);
free(buffer);
}
@ -162,10 +176,37 @@ capture_source_handle_format(void *data,
uint32_t drm_format)
{
struct screenshooter_output *output = data;
uint32_t *fmt;
assert(output->source == proxy);
output->fmt = pixel_format_get_info(drm_format);
if (output->formats_done) {
wl_array_release(&output->formats);
wl_array_init(&output->formats);
output->formats_done = false;
}
fmt = wl_array_add(&output->formats, sizeof(uint32_t));
assert(fmt);
*fmt = drm_format;
if (output->app->verbose) {
const struct pixel_format_info *fmt_info;
fmt_info = pixel_format_get_info(drm_format);
assert(fmt_info);
printf("Got format %s / 0x%x\n", fmt_info->drm_format_name,
drm_format);
}
}
static void
capture_source_handle_formats_done(void *data,
struct weston_capture_source_v1 *proxy)
{
struct screenshooter_output *output = data;
output->formats_done = true;
}
static void
@ -180,6 +221,9 @@ capture_source_handle_size(void *data,
output->buffer_width = width;
output->buffer_height = height;
if (output->app->verbose)
printf("Got size %dx%d\n", width, height);
}
static void
@ -209,7 +253,9 @@ capture_source_handle_failed(void *data,
struct screenshooter_output *output = data;
output->app->waitcount--;
output->app->failed = true;
/* We don't set app.failed here because there could be other
* outputs we still want to capture!
*/
if (msg)
fprintf(stderr, "Output capture error: %s\n", msg);
@ -217,6 +263,7 @@ capture_source_handle_failed(void *data,
static const struct weston_capture_source_v1_listener capture_source_handlers = {
.format = capture_source_handle_format,
.formats_done = capture_source_handle_formats_done,
.size = capture_source_handle_size,
.complete = capture_source_handle_complete,
.retry = capture_source_handle_retry,
@ -231,17 +278,20 @@ create_output(struct screenshooter_app *app, uint32_t output_name, uint32_t vers
version = MIN(version, 4);
output = xzalloc(sizeof *output);
output->app = app;
output->name = output_name;
output->wl_output = wl_registry_bind(app->registry, output_name,
&wl_output_interface, version);
abort_oom_if_null(output->wl_output);
output->source = weston_capture_v1_create(app->capture_factory,
output->wl_output,
WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER);
app->src_type);
abort_oom_if_null(output->source);
weston_capture_source_v1_add_listener(output->source,
&capture_source_handlers, output);
wl_array_init(&output->formats);
wl_list_insert(&app->output_list, &output->link);
}
@ -250,6 +300,8 @@ destroy_output(struct screenshooter_output *output)
{
weston_capture_source_v1_destroy(output->source);
wl_array_release(&output->formats);
if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
wl_output_release(output->wl_output);
else
@ -277,7 +329,13 @@ handle_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, weston_capture_v1_interface.name) == 0) {
app->capture_factory = wl_registry_bind(registry, name,
&weston_capture_v1_interface,
1);
2);
} else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) {
if (version < 3)
return;
app->dmabuf = wl_registry_bind(registry, name,
&zwp_linux_dmabuf_v1_interface,
3);
}
}
@ -295,15 +353,46 @@ static const struct wl_registry_listener registry_listener = {
static void
screenshooter_output_capture(struct screenshooter_output *output)
{
const struct pixel_format_info *fmt_info = NULL;
uint32_t *fmt;
screenshooter_buffer_destroy(output->buffer);
wl_array_for_each(fmt, &output->formats) {
fmt_info = pixel_format_get_info(*fmt);
assert(fmt_info);
if (fmt_info == output->app->requested_format ||
output->app->requested_format == NULL)
break;
fmt_info = NULL;
}
if (!fmt_info) {
fprintf(stderr, "No supported format found\n");
exit(1);
}
if (output->app->verbose)
printf("Creating buffer with format %s / 0x%x and size %ux%u\n",
fmt_info->drm_format_name, fmt_info->format,
output->buffer_width, output->buffer_height);
if (output->app->buffer_type == CLIENT_BUFFER_TYPE_SHM) {
output->buffer = screenshot_create_shm_buffer(output->app,
output->buffer_width,
output->buffer_height,
output->fmt);
fmt_info);
} else if (output->app->buffer_type == CLIENT_BUFFER_TYPE_DMABUF) {
output->buffer = screenshot_create_udmabuf(output->app,
output->buffer_width,
output->buffer_height,
fmt_info);
}
abort_oom_if_null(output->buffer);
weston_capture_source_v1_capture(output->source,
output->buffer->wl_buffer);
output->buffer->buf->wl_buffer);
output->app->waitcount++;
}
@ -323,6 +412,8 @@ screenshot_write_png(const struct buffer_size *buff_size,
abort_oom_if_null(shot);
wl_list_for_each(output, output_list, link) {
client_buffer_util_maybe_sync_dmabuf_start(output->buffer->buf);
pixman_image_composite32(PIXMAN_OP_SRC,
output->buffer->image, /* src */
NULL, /* mask */
@ -331,6 +422,8 @@ screenshot_write_png(const struct buffer_size *buff_size,
0, 0, /* mask x,y */
output->offset_x, output->offset_y, /* dst x,y */
output->buffer_width, output->buffer_height);
client_buffer_util_maybe_sync_dmabuf_end(output->buffer->buf);
}
surface = cairo_image_surface_create_for_data((void *)pixman_image_get_data(shot),
@ -349,6 +442,59 @@ screenshot_write_png(const struct buffer_size *buff_size,
pixman_image_unref(shot);
}
static void
screenshot_write_yuv(const struct buffer_size *buff_size,
struct wl_list *output_list)
{
struct screenshooter_output *output;
int i = 0;
wl_list_for_each(output, output_list, link) {
struct screenshooter_buffer *buffer = output->buffer;
char filepath[PATH_MAX];
char filepath_prefix[100];
int write_offset = 0;
FILE *fp;
sprintf(filepath_prefix, "wayland-screenshot-output-%d-", i++);
fp = file_create_dated(getenv("XDG_PICTURES_DIR"),
filepath_prefix, ".yuv", filepath,
sizeof(filepath));
if (!fp) {
fprintf(stderr, "Writing yuv file for output %d failed\n", i);
return;
}
client_buffer_util_maybe_sync_dmabuf_start(buffer->buf);
for (unsigned int j = 0; j < pixel_format_get_plane_count(buffer->buf->fmt); j++) {
int plane_height =
buffer->buf->height / pixel_format_hsub(buffer->buf->fmt, j);
for (int k = 0; k < plane_height; k++) {
size_t lines_written;
lines_written = fwrite(buffer->buf->data + write_offset,
buffer->buf->bytes_per_line[j],
1, fp);
if (lines_written != 1) {
fprintf(stderr,
"Writing yuv file for output %d " \
"failed during write(): %s\n",
i, strerror(errno));
return;
}
write_offset += buffer->buf->strides[j];
}
}
fclose (fp);
client_buffer_util_maybe_sync_dmabuf_end(buffer->buf);
}
}
static int
screenshot_set_buffer_size(struct buffer_size *buff_size,
struct wl_list *output_list)
@ -382,41 +528,182 @@ screenshot_set_buffer_size(struct buffer_size *buff_size,
return 0;
}
static bool
received_formats_for_all_outputs(struct screenshooter_app *app)
{
struct screenshooter_output *output;
wl_list_for_each(output, &app->output_list, link) {
if (!output->formats_done)
return false;
}
return true;
}
static bool
all_output_formats_are_yuv(struct wl_list *output_list)
{
struct screenshooter_output *output;
int color_model = -1;
wl_list_for_each(output, output_list, link) {
if (color_model == -1) {
color_model = output->buffer->buf->fmt->color_model;
continue;
}
if ((int)output->buffer->buf->fmt->color_model != color_model) {
fprintf(stderr, "Mixing of RGB and YUV output formats not supported\n");
exit(1);
}
}
assert(color_model == (int)COLOR_MODEL_RGB ||
color_model == (int)COLOR_MODEL_YUV);
return color_model == COLOR_MODEL_YUV;
}
static void
print_usage_and_exit(void)
{
printf("usage flags:\n"
"\t'-h,--help'"
"\n\t\tprint this help output\n"
"\t'-v,--verbose'"
"\n\t\tprint additional output\n"
"\t'-f,--format=<>'"
"\n\t\tthe DRM format name to use without the DRM_FORMAT_ prefix, e.g. RGBA8888 or NV12\n"
"\n\t\tIn case of YCbCr formats like NV12, instead of a single .png, the output will consist of raw .yuv files for each output."
"\n\t\tThese files do not contain any metadata, however that can be added by converting to .y4m with a command like:"
"\n\t\tffmpeg -s 1024x768 -r 1 -pix_fmt yuv420p -i ~/wayland-screenshot-output-0-2025-08-01_15-58-24.yuv -c:v copy screenshot.y4m\n"
"\n\t\tNote that this may not work for all YCbCr pixel formats.\n"
"\t'-s,--source-type=<>'"
"\n\t\tframebuffer to use framebuffer source (default), "
"\n\t\twriteback to use writeback source\n"
"\t'-b,--buffer-type=<>'"
"\n\t\tshm to use a SHM buffer (default), "
"\n\t\tdmabuf to use a DMA buffer\n");
exit(0);
}
static const struct weston_enum_map source_types [] = {
{ "framebuffer", WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER },
{ "writeback", WESTON_CAPTURE_V1_SOURCE_WRITEBACK },
};
static const struct weston_enum_map buffer_types [] = {
{ "shm", CLIENT_BUFFER_TYPE_SHM },
{ "dmabuf", CLIENT_BUFFER_TYPE_DMABUF },
};
int
main(int argc, char *argv[])
{
struct wl_display *display;
struct screenshooter_output *output;
struct screenshooter_output *tmp_output;
struct buffer_size buff_size = {};
struct screenshooter_app app = {};
int c, option_index;
app.src_type = WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER;
app.buffer_type = CLIENT_BUFFER_TYPE_SHM;
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'},
{"format", required_argument, NULL, 'f'},
{"source-type", required_argument, NULL, 's'},
{"buffer-type", required_argument, NULL, 'b'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "hvf:s:b:",
long_options, &option_index)) != -1) {
const struct weston_enum_map *entry;
switch(c) {
case 'v':
app.verbose = true;
break;
case 'f':
app.requested_format = pixel_format_get_info_by_drm_name(optarg);
if (!app.requested_format) {
fprintf(stderr, "Unknown format %s\n", optarg);
return -1;
}
break;
case 's':
entry = weston_enum_map_find_name(source_types,
optarg);
if (!entry)
print_usage_and_exit();
app.src_type = entry->value;
break;
case 'b':
entry = weston_enum_map_find_name(buffer_types,
optarg);
if (!entry)
print_usage_and_exit();
app.buffer_type = entry->value;
break;
default:
print_usage_and_exit();
}
}
wl_list_init(&app.output_list);
display = wl_display_connect(NULL);
if (display == NULL) {
app.display = wl_display_connect(NULL);
if (app.display == NULL) {
fprintf(stderr, "failed to create display: %s\n",
strerror(errno));
return -1;
}
app.registry = wl_display_get_registry(display);
app.registry = wl_display_get_registry(app.display);
wl_registry_add_listener(app.registry, &registry_listener, &app);
/* Process wl_registry advertisements */
wl_display_roundtrip(display);
wl_display_roundtrip(app.display);
if (!app.shm) {
fprintf(stderr, "Error: display does not support wl_shm\n");
return -1;
}
if (!app.capture_factory) {
fprintf(stderr, "Error: display does not support weston_capture_v1\n");
return -1;
}
if (app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER &&
app.buffer_type != CLIENT_BUFFER_TYPE_SHM) {
fprintf(stderr, "Error: Only support shm buffer with framebuffer source\n");
return -1;
}
if(app.buffer_type == CLIENT_BUFFER_TYPE_SHM && !app.shm) {
fprintf(stderr, "Error: display does not support wl_shm\n");
return -1;
}
if (app.buffer_type == CLIENT_BUFFER_TYPE_DMABUF && !app.dmabuf) {
fprintf(stderr, "Error: Compositor does not support zwp_linux_dmabuf_v1\n");
return -1;
}
if (app.verbose) {
printf("Taking screenshot with %s source %s buffer\n",
(app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER) ? "framebuffer" : "writeback",
(app.buffer_type == CLIENT_BUFFER_TYPE_SHM) ? "shm" : "dma");
}
/* Process initial events for wl_output and weston_capture_source_v1 */
wl_display_roundtrip(display);
wl_display_roundtrip(app.display);
while (!received_formats_for_all_outputs(&app)) {
if (app.verbose)
printf("Waiting for compositor to send capture source data\n");
if (wl_display_dispatch(app.display) < 0) {
fprintf(stderr, "Error: connection terminated\n");
return -1;
}
}
do {
app.retry = false;
@ -425,7 +712,7 @@ main(int argc, char *argv[])
screenshooter_output_capture(output);
while (app.waitcount > 0 && !app.failed) {
if (wl_display_dispatch(display) < 0)
if (wl_display_dispatch(app.display) < 0)
app.failed = true;
assert(app.waitcount >= 0);
}
@ -434,6 +721,10 @@ main(int argc, char *argv[])
if (!app.failed) {
if (screenshot_set_buffer_size(&buff_size, &app.output_list) < 0)
return -1;
if (all_output_formats_are_yuv(&app.output_list))
screenshot_write_yuv(&buff_size, &app.output_list);
else
screenshot_write_png(&buff_size, &app.output_list);
} else {
fprintf(stderr, "Error: screenshot or protocol failure\n");
@ -444,8 +735,10 @@ main(int argc, char *argv[])
weston_capture_v1_destroy(app.capture_factory);
wl_shm_destroy(app.shm);
if (app.dmabuf)
zwp_linux_dmabuf_v1_destroy(app.dmabuf);
wl_registry_destroy(app.registry);
wl_display_disconnect(display);
wl_display_disconnect(app.display);
return 0;
}

View file

@ -815,7 +815,7 @@ render(struct window *window, struct buffer *buffer)
glUniform1f(window->gl.offset_uniform, offset);
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
(GLfloat *) reflection.d);
(GLfloat *) reflection.M.colmaj);
glClearColor(0.0,0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
@ -864,7 +864,7 @@ render_mandelbrot(struct window *window, struct buffer *buffer)
glUniform1f(window->gl.offset_uniform, offset);
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
(GLfloat *) reflection.d);
(GLfloat *) reflection.M.colmaj);
glClearColor(0.6, 0.6, 0.6, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
@ -1110,6 +1110,12 @@ destroy_display(struct display *display)
free(display->modifiers);
if (display->direct_display)
weston_direct_display_v1_destroy(display->direct_display);
if (display->explicit_sync)
zwp_linux_explicit_synchronization_v1_destroy(display->explicit_sync);
if (display->dmabuf)
zwp_linux_dmabuf_v1_destroy(display->dmabuf);

File diff suppressed because it is too large Load diff

View file

@ -564,7 +564,6 @@ init_gl(struct window *window)
glBindAttribLocation(program, window->gl.pos, "pos");
glBindAttribLocation(program, window->gl.col, "color");
glLinkProgram(program);
window->gl.rotation_uniform =
glGetUniformLocation(program, "rotation");
@ -940,10 +939,10 @@ redraw(struct window *window)
angle = ((time - window->initial_frame_time) / speed_div)
% 360 * M_PI / 180.0;
}
rotation.d[0] = cos(angle);
rotation.d[2] = sin(angle);
rotation.d[8] = -sin(angle);
rotation.d[10] = cos(angle);
rotation.M.col[0].el[0] = cos(angle);
rotation.M.col[0].el[2] = sin(angle);
rotation.M.col[2].el[0] = -sin(angle);
rotation.M.col[2].el[2] = cos(angle);
switch (window->buffer_transform) {
case WL_OUTPUT_TRANSFORM_FLIPPED:
@ -982,7 +981,7 @@ redraw(struct window *window)
glViewport(0, 0, window->buffer_size.width, window->buffer_size.height);
glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
(GLfloat *) rotation.d);
(GLfloat *) rotation.M.colmaj);
if (window->opaque || window->fullscreen)
glClearColor(0.0, 0.0, 0.0, 1);
@ -1474,15 +1473,10 @@ main(int argc, char **argv)
create_surface(&window);
/* we already have wait_for_configure set after create_surface() */
while (running && ret != -1 && window.wait_for_configure) {
while (running && ret != -1 && window.wait_for_configure)
ret = wl_display_dispatch(display.display);
/* wait until xdg_surface::configure acks the new dimensions */
if (window.wait_for_configure)
continue;
init_gl(&window);
}
display.cursor_surface =
wl_compositor_create_surface(display.compositor);
@ -1530,6 +1524,9 @@ out_no_xdg_shell:
if (display.compositor)
wl_compositor_destroy(display.compositor);
if (display.tearing_manager)
wp_tearing_control_manager_v1_destroy(display.tearing_manager);
if (display.viewporter)
wp_viewporter_destroy(display.viewporter);

View file

@ -34,6 +34,7 @@
#include <sys/mman.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#include <linux/input.h>
@ -42,8 +43,20 @@
#include <libweston/zalloc.h>
#include "xdg-shell-client-protocol.h"
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#define FMT(fmt, bpp, r, g, b, a) { WL_SHM_FORMAT_ ## fmt, #fmt, bpp, { r, g, b, a } }
#define MAX_BUFFER_ALLOC 2
struct window;
struct format {
uint32_t code;
const char *string;
int bpp;
uint64_t color[4];
};
struct display {
struct wl_display *display;
struct wl_registry *registry;
@ -52,7 +65,10 @@ struct display {
struct wl_seat *seat;
struct wl_keyboard *keyboard;
struct wl_shm *shm;
bool has_xrgb;
const struct format *format;
bool paint_format;
bool has_format;
struct window *window;
};
struct buffer {
@ -81,6 +97,68 @@ struct window {
bool needs_update_buffer;
};
static const struct format shm_formats[] = {
/* 8 bpp formats */
FMT(R8, 8, 0x00, 0x55, 0xaa, 0xff ),
/* 16 bpp formats */
FMT(R16, 16, 0x0000, 0x5555, 0xaaaa, 0xffff ),
FMT(GR88, 16, 0x00ff, 0xff00, 0x0000, 0xffff ),
FMT(RG88, 16, 0xff00, 0x00ff, 0x0000, 0xffff ),
FMT(RGB565, 16, 0xf800, 0x07e0, 0x001f, 0xffff ),
FMT(BGR565, 16, 0x001f, 0x07e0, 0xf800, 0xffff ),
FMT(XRGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
FMT(ARGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
FMT(XBGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
FMT(ABGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
FMT(RGBX4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
FMT(RGBA4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
FMT(BGRX4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
FMT(BGRA4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
FMT(XRGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
FMT(ARGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
FMT(XBGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
FMT(ABGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
FMT(RGBX5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
FMT(RGBA5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
FMT(BGRX5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
FMT(BGRA5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
/* 24 bpp formats */
FMT(RGB888, 24, 0xff0000, 0x00ff00, 0x0000ff, 0xffffff ),
FMT(BGR888, 24, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff ),
/* 32 bpp formats */
FMT(GR1616, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff ),
FMT(RG1616, 32, 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff ),
FMT(XRGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
FMT(ARGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
FMT(XBGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
FMT(ABGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
FMT(RGBX8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
FMT(RGBA8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
FMT(BGRX8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
FMT(BGRA8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
FMT(XRGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
FMT(ARGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
FMT(XBGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
FMT(ABGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
FMT(RGBX1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
FMT(RGBA1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
FMT(BGRX1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
FMT(BGRA1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
/* 64 bpp formats */
FMT(XRGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
FMT(ARGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
FMT(XBGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
FMT(ABGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
FMT(XRGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
FMT(ARGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
FMT(XBGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
FMT(ABGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
};
static int running = 1;
static void
@ -151,7 +229,8 @@ static const struct wl_buffer_listener buffer_listener = {
};
static int
create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
create_shm_buffer(struct window *window, struct buffer *buffer,
const struct format *format)
{
struct wl_shm_pool *pool;
int fd, size, stride;
@ -161,7 +240,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
width = window->width;
height = window->height;
stride = width * 4;
stride = width * (format->bpp / 8);
size = stride * height;
display = window->display;
@ -182,7 +261,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
pool = wl_shm_create_pool(display->shm, fd, size);
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
width, height,
stride, format);
stride, format->code);
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
wl_shm_pool_destroy(pool);
close(fd);
@ -219,8 +298,16 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t time, uint32_t key,
uint32_t state)
{
if (key == KEY_ESC && state)
struct display *d = data;
if (key == KEY_F11 && state) {
if (d->window->fullscreen)
xdg_toplevel_unset_fullscreen(d->window->xdg_toplevel);
else
xdg_toplevel_set_fullscreen(d->window->xdg_toplevel, NULL);
} else if (key == KEY_ESC && state) {
running = 0;
}
}
static void
@ -416,14 +503,16 @@ window_next_buffer(struct window *window)
return NULL;
if (!buffer->buffer) {
ret = create_shm_buffer(window, buffer, WL_SHM_FORMAT_XRGB8888);
ret = create_shm_buffer(window, buffer,
window->display->format);
if (ret < 0)
return NULL;
/* paint the padding */
memset(buffer->shm_data, 0xff,
window->width * window->height * 4);
window->width * window->height *
(window->display->format->bpp / 8));
}
return buffer;
@ -475,6 +564,122 @@ paint_pixels(void *image, int padding, int width, int height, uint32_t time)
}
}
static void
paint_format(void *image, const struct format *format, int width, int height)
{
uint64_t *img64 = (uint64_t*) image;
uint32_t *img32 = (uint32_t*) image;
uint16_t *img16 = (uint16_t*) image;
uint8_t *img8 = (uint8_t*) image;
uint64_t color;
int i, j;
#define GET_COLOR(y) \
(y < (1 * (height / 4))) ? format->color[0] : \
(y < (2 * (height / 4))) ? format->color[1] : \
(y < (3 * (height / 4))) ? format->color[2] : \
format->color[3]
switch (format->code) {
case WL_SHM_FORMAT_R8:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img8[i * width + j] = color;
}
break;
case WL_SHM_FORMAT_R16:
case WL_SHM_FORMAT_GR88:
case WL_SHM_FORMAT_RG88:
case WL_SHM_FORMAT_RGB565:
case WL_SHM_FORMAT_BGR565:
case WL_SHM_FORMAT_XRGB4444:
case WL_SHM_FORMAT_ARGB4444:
case WL_SHM_FORMAT_XBGR4444:
case WL_SHM_FORMAT_ABGR4444:
case WL_SHM_FORMAT_RGBX4444:
case WL_SHM_FORMAT_RGBA4444:
case WL_SHM_FORMAT_BGRX4444:
case WL_SHM_FORMAT_BGRA4444:
case WL_SHM_FORMAT_XRGB1555:
case WL_SHM_FORMAT_ARGB1555:
case WL_SHM_FORMAT_XBGR1555:
case WL_SHM_FORMAT_ABGR1555:
case WL_SHM_FORMAT_RGBX5551:
case WL_SHM_FORMAT_RGBA5551:
case WL_SHM_FORMAT_BGRX5551:
case WL_SHM_FORMAT_BGRA5551:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img16[i * width + j] = color;
}
break;
case WL_SHM_FORMAT_RGB888:
case WL_SHM_FORMAT_BGR888:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++) {
img8[(i * width + j) * 3 + 0] =
(color >> 0) & 0xff;
img8[(i * width + j) * 3 + 1] =
(color >> 8) & 0xff;
img8[(i * width + j) * 3 + 2] =
(color >> 16) & 0xff;
}
}
break;
case WL_SHM_FORMAT_GR1616:
case WL_SHM_FORMAT_RG1616:
case WL_SHM_FORMAT_XRGB8888:
case WL_SHM_FORMAT_ARGB8888:
case WL_SHM_FORMAT_XBGR8888:
case WL_SHM_FORMAT_ABGR8888:
case WL_SHM_FORMAT_RGBX8888:
case WL_SHM_FORMAT_RGBA8888:
case WL_SHM_FORMAT_BGRX8888:
case WL_SHM_FORMAT_BGRA8888:
case WL_SHM_FORMAT_XRGB2101010:
case WL_SHM_FORMAT_ARGB2101010:
case WL_SHM_FORMAT_XBGR2101010:
case WL_SHM_FORMAT_ABGR2101010:
case WL_SHM_FORMAT_RGBX1010102:
case WL_SHM_FORMAT_RGBA1010102:
case WL_SHM_FORMAT_BGRX1010102:
case WL_SHM_FORMAT_BGRA1010102:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img32[i * width + j] = color;
}
break;
case WL_SHM_FORMAT_XRGB16161616:
case WL_SHM_FORMAT_ARGB16161616:
case WL_SHM_FORMAT_XBGR16161616:
case WL_SHM_FORMAT_ABGR16161616:
case WL_SHM_FORMAT_XRGB16161616F:
case WL_SHM_FORMAT_ARGB16161616F:
case WL_SHM_FORMAT_XBGR16161616F:
case WL_SHM_FORMAT_ABGR16161616F:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img64[i * width + j] = color;
}
break;
default:
assert(0);
break;
};
#undef GET_COLOR
}
static const struct wl_callback_listener frame_listener;
static void
@ -493,7 +698,12 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
abort();
}
paint_pixels(buffer->shm_data, 20, window->width, window->height, time);
if (window->display->paint_format)
paint_format(buffer->shm_data, window->display->format,
window->width, window->height);
else
paint_pixels(buffer->shm_data, 20, window->width,
window->height, time);
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
wl_surface_damage(window->surface,
@ -517,8 +727,8 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
struct display *d = data;
if (format == WL_SHM_FORMAT_XRGB8888)
d->has_xrgb = true;
if (format == d->format->code)
d->has_format = true;
}
struct wl_shm_listener shm_listener = {
@ -572,7 +782,7 @@ static const struct wl_registry_listener registry_listener = {
};
static struct display *
create_display(void)
create_display(const struct format *format, bool paint_format)
{
struct display *display;
@ -584,7 +794,9 @@ create_display(void)
display->display = wl_display_connect(NULL);
assert(display->display);
display->has_xrgb = false;
display->format = format;
display->paint_format = paint_format;
display->has_format= false;
display->registry = wl_display_get_registry(display->display);
wl_registry_add_listener(display->registry,
&registry_listener, display);
@ -636,8 +848,9 @@ create_display(void)
* technique.
*/
if (!display->has_xrgb) {
fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
if (!display->has_format) {
fprintf(stderr, "Format '%s' not supported by compositor.\n",
format->string);
exit(1);
}
@ -668,19 +881,86 @@ signal_int(int signum)
running = 0;
}
static void
usage(const char *program)
{
fprintf(stdout,
"Usage: %s [OPTIONS]\n"
"\n"
"Draw pixels into shared memory buffers using wl_shm\n"
"\n"
"Options:\n"
" -h, --help Show this help\n"
" -F, --format <format> Test format (see list below)\n"
"\n"
"RGB formats:\n"
" - 8 bpp: r8.\n"
"\n"
" - 16 bpp: r16, gr88, rg88, rgb565, bgr565, xrgb4444, argb4444, xbgr4444,\n"
" abgr4444, rgbx4444, rgba4444, bgrx4444, bgra4444, xrgb1555,\n"
" argb1555, xbgr1555, abgr1555, rgbx5551, rgba5551, bgrx5551,\n"
" bgra5551.\n"
"\n"
" - 24 bpp: rgb888, bgr888.\n"
"\n"
" - 32 bpp: gr1616, rg1616, xrgb8888, argb8888, xbgr8888, abgr8888, rgbx8888,\n"
" rgba8888, bgrx8888, bgra8888, xrgb2101010, argb2101010, xbgr2101010,\n"
" abgr2101010, rgbx1010102, rgba1010102, bgrx1010102, bgra1010102.\n"
"\n"
" - 64 bpp: xrgb16161616, argb16161616, xbgr16161616, abgr16161616,\n"
" xrgb16161616f, argb16161616f, xbgr16161616f, abgr16161616f.\n",
program);
}
int
main(int argc, char **argv)
{
struct sigaction sigint;
struct display *display;
struct window *window;
int ret = 0;
const struct format *format = NULL;
bool paint_format = false;
const char *value;
int ret = 0, i, j;
display = create_display();
window = create_window(display, 250, 250);
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h") ||
!strcmp(argv[i], "--help")) {
usage(argv[0]);
return 0;
} else if (!strcmp(argv[i], "-F") ||
!strcmp(argv[i], "--format")) {
value = ++i == argc ? "" : argv[i];
for (j = 0; j < (int) ARRAY_SIZE(shm_formats); j++) {
if (!strcasecmp(shm_formats[j].string, value)) {
format = &shm_formats[j];
paint_format = true;
break;
}
}
if (!format) {
fprintf(stderr, "Format '%s' not supported by "
"client.\n", value);
return 1;
}
} else {
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
return 1;
}
}
if (!format)
for (i = 0; i < (int) ARRAY_SIZE(shm_formats); i++)
if (shm_formats[i].code == WL_SHM_FORMAT_XRGB8888)
format = &shm_formats[i];
assert(format);
display = create_display(format, paint_format);
window = create_window(display, 256, 256);
if (!window)
return 1;
display->window = window;
sigint.sa_handler = signal_int;
sigemptyset(&sigint.sa_mask);
sigint.sa_flags = SA_RESETHAND;

885
clients/simple-timing.c Normal file
View file

@ -0,0 +1,885 @@
/*
* Copyright © 2011 Benjamin Franzke
* Copyright © 2010 Intel Corporation
* Copyright © 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#include <linux/input.h>
#include <wayland-client.h>
#include "shared/os-compatibility.h"
#include "shared/timespec-util.h"
#include "shared/xalloc.h"
#include <libweston/zalloc.h>
#include "xdg-shell-client-protocol.h"
#include "commit-timing-v1-client-protocol.h"
#include "fifo-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#define MAX_BUFFER_ALLOC 1000
struct display {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
struct xdg_wm_base *wm_base;
struct wl_seat *seat;
struct wl_keyboard *keyboard;
struct wl_shm *shm;
struct wp_commit_timing_manager_v1 *commit_timing_manager;
struct wp_fifo_manager_v1 *fifo_manager;
struct wp_presentation *presentation;
bool have_clock_id;
clockid_t presentation_clock_id;
int64_t first_frame_time;
int64_t refresh_nsec;
};
struct buffer {
struct window *window;
struct wl_buffer *buffer;
void *shm_data;
int busy;
int width, height;
size_t size; /* width * 4 * height */
struct wl_list buffer_link; /** window::buffer_list */
};
struct window {
struct display *display;
int width, height;
int init_width, init_height;
struct wl_surface *surface;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
struct wl_list buffer_list;
struct wl_callback *callback;
struct wp_fifo_v1 *fifo;
struct wp_commit_timer_v1 *commit_timer;
bool wait_for_configure;
bool maximized;
bool fullscreen;
bool needs_update_buffer;
};
struct feedback {
struct wp_presentation_feedback *fb;
struct window *window;
int64_t target_time;
bool final;
};
static int running = 1;
static void
draw_for_time(void *data, int64_t time, bool wait_fifo);
static void
finish_run(struct window *window);
static struct buffer *
alloc_buffer(struct window *window, int width, int height)
{
struct buffer *buffer = calloc(1, sizeof(*buffer));
buffer->width = width;
buffer->height = height;
wl_list_insert(&window->buffer_list, &buffer->buffer_link);
return buffer;
}
static void
destroy_buffer(struct buffer *buffer)
{
if (buffer->buffer)
wl_buffer_destroy(buffer->buffer);
munmap(buffer->shm_data, buffer->size);
wl_list_remove(&buffer->buffer_link);
free(buffer);
}
static struct buffer *
pick_free_buffer(struct window *window)
{
struct buffer *b;
struct buffer *buffer = NULL;
wl_list_for_each(b, &window->buffer_list, buffer_link) {
if (!b->busy) {
buffer = b;
break;
}
}
return buffer;
}
static void
prune_old_released_buffers(struct window *window)
{
struct buffer *b, *b_next;
wl_list_for_each_safe(b, b_next,
&window->buffer_list, buffer_link) {
if (!b->busy && (b->width != window->width ||
b->height != window->height))
destroy_buffer(b);
}
}
static void
buffer_release(void *data, struct wl_buffer *buffer)
{
struct buffer *mybuf = data;
mybuf->busy = 0;
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
static int
create_shm_buffer(struct window *window, struct buffer *buffer)
{
struct wl_shm_pool *pool;
int fd, size, stride;
void *data;
int width, height;
struct display *display;
width = window->width;
height = window->height;
stride = width * 4;
size = stride * height;
display = window->display;
fd = os_create_anonymous_file(size);
if (fd < 0) {
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
size, strerror(errno));
return -1;
}
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) {
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
close(fd);
return -1;
}
pool = wl_shm_create_pool(display->shm, fd, size);
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
width, height,
stride,
WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
wl_shm_pool_destroy(pool);
close(fd);
buffer->size = size;
buffer->shm_data = data;
return 0;
}
static void
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
uint32_t format, int fd, uint32_t size)
{
/* Just so we dont leak the keymap fd */
close(fd);
}
static void
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface,
struct wl_array *keys)
{
}
static void
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface)
{
}
static void
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t time, uint32_t key,
uint32_t state)
{
if (key == KEY_ESC && state)
running = 0;
}
static void
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t mods_depressed,
uint32_t mods_latched, uint32_t mods_locked,
uint32_t group)
{
}
static const struct wl_keyboard_listener keyboard_listener = {
keyboard_handle_keymap,
keyboard_handle_enter,
keyboard_handle_leave,
keyboard_handle_key,
keyboard_handle_modifiers,
};
static void
seat_handle_capabilities(void *data, struct wl_seat *seat,
enum wl_seat_capability caps)
{
struct display *d = data;
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
d->keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
wl_keyboard_destroy(d->keyboard);
d->keyboard = NULL;
}
}
static const struct wl_seat_listener seat_listener = {
seat_handle_capabilities,
};
static void
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
uint32_t serial)
{
struct window *window = data;
xdg_surface_ack_configure(surface, serial);
if (window->wait_for_configure) {
draw_for_time(window, 0, false);
window->wait_for_configure = false;
}
}
static const struct xdg_surface_listener xdg_surface_listener = {
handle_xdg_surface_configure,
};
static void
handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
int32_t width, int32_t height,
struct wl_array *states)
{
struct window *window = data;
uint32_t *p;
window->fullscreen = false;
window->maximized = false;
wl_array_for_each(p, states) {
uint32_t state = *p;
switch (state) {
case XDG_TOPLEVEL_STATE_FULLSCREEN:
window->fullscreen = true;
break;
case XDG_TOPLEVEL_STATE_MAXIMIZED:
window->maximized = true;
break;
}
}
if (width > 0 && height > 0) {
if (!window->fullscreen && !window->maximized) {
window->init_width = width;
window->init_height = height;
}
window->width = width;
window->height = height;
} else if (!window->fullscreen && !window->maximized) {
window->width = window->init_width;
window->height = window->init_height;
}
window->needs_update_buffer = true;
}
static void
handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
{
running = 0;
}
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
handle_xdg_toplevel_configure,
handle_xdg_toplevel_close,
};
static struct window *
create_window(struct display *display, int width, int height)
{
struct window *window;
int i;
window = zalloc(sizeof *window);
if (!window)
return NULL;
window->callback = NULL;
window->display = display;
window->width = width;
window->height = height;
window->init_width = width;
window->init_height = height;
window->surface = wl_compositor_create_surface(display->compositor);
window->fifo = wp_fifo_manager_v1_get_fifo(display->fifo_manager,
window->surface);
window->commit_timer = wp_commit_timing_manager_v1_get_timer(display->commit_timing_manager,
window->surface);
window->needs_update_buffer = false;
wl_list_init(&window->buffer_list);
assert(display->wm_base);
window->xdg_surface =
xdg_wm_base_get_xdg_surface(display->wm_base,
window->surface);
assert(window->xdg_surface);
xdg_surface_add_listener(window->xdg_surface,
&xdg_surface_listener, window);
window->xdg_toplevel =
xdg_surface_get_toplevel(window->xdg_surface);
assert(window->xdg_toplevel);
xdg_toplevel_add_listener(window->xdg_toplevel,
&xdg_toplevel_listener, window);
xdg_toplevel_set_title(window->xdg_toplevel, "simple-shm");
xdg_toplevel_set_app_id(window->xdg_toplevel,
"org.freedesktop.weston.simple-shm");
wl_surface_commit(window->surface);
window->wait_for_configure = true;
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
alloc_buffer(window, window->width, window->height);
return window;
}
static void
destroy_window(struct window *window)
{
struct buffer *buffer, *buffer_next;
if (window->callback)
wl_callback_destroy(window->callback);
wl_list_for_each_safe(buffer, buffer_next,
&window->buffer_list, buffer_link)
destroy_buffer(buffer);
if (window->xdg_toplevel)
xdg_toplevel_destroy(window->xdg_toplevel);
if (window->xdg_surface)
xdg_surface_destroy(window->xdg_surface);
wl_surface_destroy(window->surface);
if (window->fifo)
wp_fifo_v1_destroy(window->fifo);
if (window->commit_timer)
wp_commit_timer_v1_destroy(window->commit_timer);
free(window);
}
static struct buffer *
window_next_buffer(struct window *window)
{
struct buffer *buffer = NULL;
int ret = 0;
if (window->needs_update_buffer) {
int i;
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
alloc_buffer(window, window->width, window->height);
window->needs_update_buffer = false;
}
buffer = pick_free_buffer(window);
if (!buffer)
return NULL;
if (!buffer->buffer) {
ret = create_shm_buffer(window, buffer);
if (ret < 0)
return NULL;
/* paint the padding */
memset(buffer->shm_data, 0xff,
window->width * window->height * 4);
}
return buffer;
}
static void
paint_pixels(void *image, int width, int height, uint32_t time)
{
const int halfh = height / 2;
const int halfw = width / 2;
int ir, or;
uint32_t *pixel = image;
int y;
/* squared radii thresholds */
or = (halfw < halfh ? halfw : halfh) - 8;
ir = or - 32;
or *= or;
ir *= ir;
for (y = 0; y < height; y++) {
int x;
int y2 = (y - halfh) * (y - halfh);
for (x = 0; x < width; x++) {
uint32_t v;
/* squared distance from center */
int r2 = (x - halfw) * (x - halfw) + y2;
if (r2 < ir)
v = (r2 / 32 + time / 64) * 0x0080401;
else if (r2 < or)
v = (y + time / 32) * 0x0080401;
else
v = (x + time / 16) * 0x0080401;
v &= 0x00ffffff;
/* cross if compositor uses X from XRGB as alpha */
if (abs(x - y) > 6 && abs(x + y - height) > 6)
v |= 0xff000000;
*pixel++ = v;
}
}
}
static void
queue_some_frames(struct window *window)
{
struct display *display = window->display;
int64_t target_nsec;
int i;
assert(display->first_frame_time);
/* Round off error will cause us problems if we don't
* reduce this a bit, because we could end up rounding
* to either side of a refresh.
*/
target_nsec = display->first_frame_time - 100000;
for (i = 0; i < 60; i++) {
target_nsec += display->refresh_nsec * 2;
draw_for_time(window, target_nsec, false);
}
for (i = 0; i < 30; i++) {
target_nsec += display->refresh_nsec * 4;
draw_for_time(window, target_nsec, false);
}
for (i = 0; i < 10; i++) {
target_nsec += display->refresh_nsec * 10;
draw_for_time(window, target_nsec, false);
}
for (i = 0; i < 10; i++) {
target_nsec += display->refresh_nsec * 100;
draw_for_time(window, target_nsec, false);
}
finish_run(window);
}
static void
feedback_sync_output(void *data,
struct wp_presentation_feedback *presentation_feedback,
struct wl_output *output)
{
/* Just don't care */
}
static void
feedback_presented(void *data,
struct wp_presentation_feedback *presentation_feedback,
uint32_t tv_sec_hi,
uint32_t tv_sec_lo,
uint32_t tv_nsec,
uint32_t refresh_nsec,
uint32_t seq_hi,
uint32_t seq_lo,
uint32_t flags)
{
struct feedback *feedback = data;
struct window *window = feedback->window;
struct display *display = window->display;
struct timespec pres_ts = {
.tv_sec = ((int64_t)tv_sec_hi << 32) + tv_sec_lo,
.tv_nsec = tv_nsec,
};
int64_t ntime = timespec_to_nsec(&pres_ts);
double delay;
if (feedback->final) {
running = 0;
goto out;
}
if (!feedback->target_time) {
display->first_frame_time = ntime;
display->refresh_nsec = refresh_nsec;
queue_some_frames(window);
goto out;
}
delay = (ntime - feedback->target_time) / 1000000.0;
printf("%fms away from intended time\n", delay);
if (fabs(delay) > display->refresh_nsec / 1000000)
printf("Warning: we missed the intended target display cycle.\n");
out:
wp_presentation_feedback_destroy(feedback->fb);
free(feedback);
}
static void
feedback_discarded(void *data,
struct wp_presentation_feedback *presentation_feedback)
{
struct feedback *feedback = data;
printf("Warning: a frame was discarded\n");
if (feedback->final)
running = 0;
wp_presentation_feedback_destroy(feedback->fb);
free(feedback);
}
static const struct wp_presentation_feedback_listener feedback_listener = {
feedback_sync_output,
feedback_presented,
feedback_discarded,
};
static void
finish_run(struct window *window)
{
struct display *display = window->display;
struct feedback *feedback;
struct buffer *buffer;
feedback = xzalloc(sizeof *feedback);
feedback->window = window;
feedback->final = true;
feedback->target_time = 0;
buffer = window_next_buffer(window);
assert(buffer);
paint_pixels(buffer->shm_data, window->width,
window->height, 1);
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
feedback->fb = wp_presentation_feedback(display->presentation,
window->surface);
wp_presentation_feedback_add_listener(feedback->fb,
&feedback_listener, feedback);
wp_fifo_v1_wait_barrier(window->fifo);
wl_surface_commit(window->surface);
}
static void
draw_for_time(void *data, int64_t time, bool wait_fifo)
{
struct window *window = data;
struct display *display = window->display;
struct buffer *buffer;
struct feedback *feedback;
assert(display->have_clock_id);
prune_old_released_buffers(window);
buffer = window_next_buffer(window);
assert(buffer);
paint_pixels(buffer->shm_data, window->width,
window->height, time / 1000000);
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
feedback = xzalloc(sizeof *feedback);
feedback->window = window;
feedback->fb = wp_presentation_feedback(display->presentation,
window->surface);
wp_presentation_feedback_add_listener(feedback->fb,
&feedback_listener, feedback);
feedback->target_time = time;
if (time) {
struct timespec target;
timespec_from_nsec(&target, time);
wp_commit_timer_v1_set_timestamp(window->commit_timer,
(int64_t)target.tv_sec >> 32,
target.tv_sec,
target.tv_nsec);
}
wp_fifo_v1_set_barrier(window->fifo);
wl_surface_commit(window->surface);
buffer->busy = 1;
}
static void
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
{
xdg_wm_base_pong(shell, serial);
}
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
xdg_wm_base_ping,
};
static void
presentation_handle_clock_id(void *data,
struct wp_presentation *wp_presentation,
uint32_t clock_id)
{
struct display *display = data;
display->presentation_clock_id = clock_id;
display->have_clock_id = true;
}
static const struct wp_presentation_listener presentation_listener = {
presentation_handle_clock_id,
};
static void
registry_handle_global(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
struct display *d = data;
if (strcmp(interface, "wl_compositor") == 0) {
d->compositor =
wl_registry_bind(registry,
id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "xdg_wm_base") == 0) {
d->wm_base = wl_registry_bind(registry,
id, &xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
} else if (strcmp(interface, "wl_seat") == 0) {
d->seat = wl_registry_bind(registry, id,
&wl_seat_interface, 1);
wl_seat_add_listener(d->seat, &seat_listener, d);
} else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry,
id, &wl_shm_interface, 1);
} else if (strcmp(interface, wp_commit_timing_manager_v1_interface.name) == 0) {
d->commit_timing_manager = wl_registry_bind(registry, id,
&wp_commit_timing_manager_v1_interface,
1);
} else if (strcmp(interface, wp_fifo_manager_v1_interface.name) == 0) {
d->fifo_manager = wl_registry_bind(registry, id,
&wp_fifo_manager_v1_interface,
1);
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
d->presentation = wl_registry_bind(registry, id,
&wp_presentation_interface,
2);
wp_presentation_add_listener(d->presentation,
&presentation_listener, d);
}
}
static void
registry_handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name)
{
}
static const struct wl_registry_listener registry_listener = {
registry_handle_global,
registry_handle_global_remove
};
static struct display *
create_display(void)
{
struct display *display;
display = xzalloc(sizeof *display);
display->display = wl_display_connect(NULL);
assert(display->display);
display->registry = wl_display_get_registry(display->display);
wl_registry_add_listener(display->registry,
&registry_listener, display);
wl_display_roundtrip(display->display);
if (display->shm == NULL) {
fprintf(stderr, "No wl_shm global\n");
exit(1);
}
wl_display_roundtrip(display->display);
return display;
}
static void
destroy_display(struct display *display)
{
if (display->shm)
wl_shm_destroy(display->shm);
if (display->wm_base)
xdg_wm_base_destroy(display->wm_base);
if (display->compositor)
wl_compositor_destroy(display->compositor);
if (display->presentation)
wp_presentation_destroy(display->presentation);
if (display->fifo_manager)
wp_fifo_manager_v1_destroy(display->fifo_manager);
if (display->commit_timing_manager)
wp_commit_timing_manager_v1_destroy(display->commit_timing_manager);
if (display->keyboard)
wl_keyboard_destroy(display->keyboard);
if (display->seat)
wl_seat_destroy(display->seat);
wl_registry_destroy(display->registry);
wl_display_flush(display->display);
wl_display_disconnect(display->display);
free(display);
}
static void
signal_int(int signum)
{
running = 0;
}
static void
usage(const char *program)
{
fprintf(stdout,
"Usage: %s [OPTIONS]\n"
"\n"
"Schedule frames in the future with commit-timing\n"
"\n"
"Options:\n"
" -h, --help Show this help\n"
"\n",
program);
}
int
main(int argc, char **argv)
{
struct sigaction sigint;
struct display *display;
struct window *window;
int ret = 0, i;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h") ||
!strcmp(argv[i], "--help")) {
usage(argv[0]);
return 0;
} else {
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
return 1;
}
}
display = create_display();
window = create_window(display, 256, 256);
if (!window)
return 1;
sigint.sa_handler = signal_int;
sigemptyset(&sigint.sa_mask);
sigint.sa_flags = SA_RESETHAND;
sigaction(SIGINT, &sigint, NULL);
while (running && ret != -1)
ret = wl_display_dispatch(display->display);
fprintf(stderr, "simple-timing exiting\n");
destroy_window(window);
destroy_display(display);
return 0;
}

2171
clients/simple-vulkan.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
#version 450 core
layout(location = 0) in vec4 v_color;
layout(location = 0) out vec4 f_color;
void main() {
f_color = v_color;
}

View file

@ -0,0 +1,17 @@
#version 450 core
layout(std140, set = 0, binding = 0) uniform block {
uniform mat4 reflection;
uniform float offset;
};
layout(location = 0) in vec4 pos;
layout(location = 1) in vec4 color;
layout(location = 0) out vec4 v_color;
void main()
{
gl_Position = reflection * (pos + vec4(offset, offset, 0.0, 0.0));
v_color = color;
}

View file

@ -0,0 +1,9 @@
#version 450 core
layout(location = 0) in vec4 vVaryingColor;
layout(location = 0) out vec4 f_color;
void main()
{
f_color = vVaryingColor;
}

View file

@ -0,0 +1,16 @@
#version 450 core
layout(std140, set = 0, binding = 0) uniform block {
uniform mat4 rotation;
};
layout(location = 0) in vec4 in_position;
layout(location = 1) in vec4 in_color;
layout(location = 0) out vec4 vVaryingColor;
void main()
{
gl_Position = rotation * in_position;
vVaryingColor = vec4(in_color.rgba);
}

View file

@ -58,6 +58,7 @@ static char *option_term;
static char *option_shell;
static struct wl_list terminal_list;
struct sigaction oldact;
static struct terminal *
terminal_create(struct display *display);
@ -3100,6 +3101,9 @@ terminal_run(struct terminal *terminal, const char *path)
close(pipes[0]);
setenv("TERM", option_term, 1);
setenv("COLORTERM", option_term, 1);
sigaction(SIGPIPE, &oldact, NULL);
if (execl(path, path, NULL)) {
printf("exec failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
@ -3177,8 +3181,10 @@ int main(int argc, char *argv[])
* socket whose reading end has been closed */
sigpipe.sa_handler = SIG_IGN;
sigemptyset(&sigpipe.sa_mask);
sigemptyset(&oldact.sa_mask);
sigpipe.sa_flags = 0;
sigaction(SIGPIPE, &sigpipe, NULL);
sigaction(SIGPIPE, &sigpipe, &oldact);
d = display_create(&argc, argv);
if (d == NULL) {

View file

@ -330,9 +330,9 @@ compute_calibration(struct calibrator *cal, float *result)
*/
weston_matrix_init(&m);
for (i = 0; i < 3; i++) {
m.d[i + 0] = cal->samples[i].touched.x;
m.d[i + 4] = cal->samples[i].touched.y;
m.d[i + 8] = 1.0f;
m.M.col[0].el[i] = cal->samples[i].touched.x;
m.M.col[1].el[i] = cal->samples[i].touched.y;
m.M.col[2].el[i] = 1.0f;
}
m.type = WESTON_MATRIX_TRANSFORM_OTHER;
@ -342,20 +342,20 @@ compute_calibration(struct calibrator *cal, float *result)
}
for (i = 0; i < 3; i++) {
x_calib.f[i] = cal->samples[i].drawn_cal.x;
y_calib.f[i] = cal->samples[i].drawn_cal.y;
x_calib.v.el[i] = cal->samples[i].drawn_cal.x;
y_calib.v.el[i] = cal->samples[i].drawn_cal.y;
}
x_calib.f[3] = 0.0f;
y_calib.f[3] = 0.0f;
x_calib.v.el[3] = 0.0f;
y_calib.v.el[3] = 0.0f;
/* Multiples into the vector */
weston_matrix_transform(&inverse, &x_calib);
weston_matrix_transform(&inverse, &y_calib);
for (i = 0; i < 3; i++)
result[i] = x_calib.f[i];
result[i] = x_calib.v.el[i];
for (i = 0; i < 3; i++)
result[i + 3] = y_calib.f[i];
result[i + 3] = y_calib.v.el[i];
return 0;
}

View file

@ -44,9 +44,7 @@
#include <xkbcommon/xkbcommon.h>
#ifdef HAVE_XKBCOMMON_COMPOSE
#include <xkbcommon/xkbcommon-compose.h>
#endif
#include <wayland-cursor.h>
#include <linux/input.h>
@ -57,6 +55,7 @@
#include <libweston/zalloc.h>
#include "xdg-shell-client-protocol.h"
#include "color-management-v1-client-protocol.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "text-cursor-position-client-protocol.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "relative-pointer-unstable-v1-client-protocol.h"
@ -91,10 +90,11 @@ struct display {
struct wl_data_device_manager *data_device_manager;
struct text_cursor_position *text_cursor_position;
struct xdg_wm_base *xdg_shell;
struct xx_color_manager_v4 *color_manager;
struct wp_color_manager_v1 *color_manager;
struct zwp_tablet_manager_v2 *tablet_manager;
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer_manager;
uint32_t serial;
uint32_t color_manager_features;
@ -217,7 +217,7 @@ struct surface {
struct wl_callback *frame_cb;
uint32_t last_time;
struct xx_color_management_surface_v4 *cm_surface;
struct wp_color_management_surface_v1 *cm_surface;
struct rectangle allocation;
struct rectangle server_allocation;
@ -400,10 +400,8 @@ struct input {
struct {
struct xkb_keymap *keymap;
struct xkb_state *state;
#ifdef HAVE_XKBCOMMON_COMPOSE
struct xkb_compose_table *compose_table;
struct xkb_compose_state *compose_state;
#endif
xkb_mod_mask_t control_mask;
xkb_mod_mask_t alt_mask;
xkb_mod_mask_t shift_mask;
@ -480,7 +478,7 @@ struct shm_pool {
};
struct cm_image_description {
struct xx_image_description_v4 *image_desc;
struct wp_image_description_v1 *image_desc;
enum cm_image_desc_status {
CM_IMAGE_DESC_NOT_CREATED = 0,
CM_IMAGE_DESC_READY,
@ -493,27 +491,27 @@ render_intent_info_table[] = {
{
.intent = RENDER_INTENT_PERCEPTUAL,
.desc = "Perceptual",
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL,
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL,
},
{
.intent = RENDER_INTENT_RELATIVE,
.desc = "Media-relative colorimetric",
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE,
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE,
},
{
.intent = RENDER_INTENT_RELATIVE_BPC,
.desc = "Media-relative colorimetric + black point compensation",
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC,
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE_BPC,
},
{
.intent = RENDER_INTENT_SATURATION,
.desc = "Saturation",
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_SATURATION,
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION,
},
{
.intent = RENDER_INTENT_ABSOLUTE,
.desc = "ICC-absolute colorimetric",
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE,
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_ABSOLUTE,
},
};
@ -568,7 +566,7 @@ debug_print(void *proxy, int line, const char *func, const char *fmt, ...)
#endif
static void
cm_image_desc_ready(void *data, struct xx_image_description_v4 *xx_image_description_v4,
cm_image_desc_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
uint32_t identity)
{
struct cm_image_description *cm_image_desc = data;
@ -577,7 +575,7 @@ cm_image_desc_ready(void *data, struct xx_image_description_v4 *xx_image_descrip
}
static void
cm_image_desc_failed(void *data, struct xx_image_description_v4 *xx_image_description_v4,
cm_image_desc_failed(void *data, struct wp_image_description_v1 *wp_image_description_v1,
uint32_t cause, const char *msg)
{
struct cm_image_description *cm_image_desc = data;
@ -588,7 +586,7 @@ cm_image_desc_failed(void *data, struct xx_image_description_v4 *xx_image_descri
cm_image_desc->status = CM_IMAGE_DESC_FAILED;
}
static const struct xx_image_description_v4_listener cm_image_desc_listener = {
static const struct wp_image_description_v1_listener cm_image_desc_listener = {
.ready = cm_image_desc_ready,
.failed = cm_image_desc_failed,
};
@ -610,10 +608,10 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
uint32_t length, uint32_t offset,
enum render_intent intent, char **err_msg)
{
struct xx_image_description_creator_icc_v4 *icc_creator;
struct wp_image_description_creator_icc_v1 *icc_creator;
struct display *display = widget->window->display;
struct surface *surface = widget->surface;
struct xx_color_manager_v4 *color_manager_wrapper;
struct wp_color_manager_v1 *color_manager_wrapper;
struct wl_event_queue *queue;
struct cm_image_description cm_image_desc;
const struct render_intent_info *intent_info;
@ -623,11 +621,11 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
str_printf(err_msg,
"%s extension not supported by the Wayland " \
"compositor, ignoring image color profile.",
xx_color_manager_v4_interface.name);
wp_color_manager_v1_interface.name);
return false;
}
if (!((display->color_manager_features >> XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4) & 1)) {
if (!((display->color_manager_features >> WP_COLOR_MANAGER_V1_FEATURE_ICC_V2_V4) & 1)) {
str_printf(err_msg,
"Wayland compositor does not support creating image " \
"descriptions from ICC files, ignoring color profile.");
@ -650,15 +648,15 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
wl_proxy_set_queue((struct wl_proxy *)color_manager_wrapper, queue);
/* Create ICC image description creator and set the ICC file. */
icc_creator = xx_color_manager_v4_new_icc_creator(color_manager_wrapper);
icc_creator = wp_color_manager_v1_create_icc_creator(color_manager_wrapper);
wl_proxy_wrapper_destroy(color_manager_wrapper);
xx_image_description_creator_icc_v4_set_icc_file(icc_creator,
wp_image_description_creator_icc_v1_set_icc_file(icc_creator,
icc_fd, offset, length);
/* Create the image description. It will also destroy the ICC creator. */
cm_image_desc.status = CM_IMAGE_DESC_NOT_CREATED;
cm_image_desc.image_desc = xx_image_description_creator_icc_v4_create(icc_creator);
xx_image_description_v4_add_listener(cm_image_desc.image_desc,
cm_image_desc.image_desc = wp_image_description_creator_icc_v1_create(icc_creator);
wp_image_description_v1_add_listener(cm_image_desc.image_desc,
&cm_image_desc_listener, &cm_image_desc);
/* Wait until compositor creates the image description or gracefully
@ -666,7 +664,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
while (ret != -1 && cm_image_desc.status == CM_IMAGE_DESC_NOT_CREATED)
ret = wl_display_dispatch_queue(display->display, queue);
if (ret == -1) {
xx_image_description_v4_destroy(cm_image_desc.image_desc);
wp_image_description_v1_destroy(cm_image_desc.image_desc);
wl_event_queue_destroy(queue);
str_printf(err_msg,
"Disconnected from the Wayland compositor, " \
@ -677,7 +675,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
/* Gracefully failed to create image description. Error already printed
* in the handler. */
if (cm_image_desc.status == CM_IMAGE_DESC_FAILED) {
xx_image_description_v4_destroy(cm_image_desc.image_desc);
wp_image_description_v1_destroy(cm_image_desc.image_desc);
wl_event_queue_destroy(queue);
str_printf(err_msg,
"Image description creation gracefully failed.");
@ -687,14 +685,14 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
if (!surface->cm_surface)
surface->cm_surface =
xx_color_manager_v4_get_surface(display->color_manager,
wp_color_manager_v1_get_surface(display->color_manager,
surface->surface);
xx_color_management_surface_v4_set_image_description(surface->cm_surface,
wp_color_management_surface_v1_set_image_description(surface->cm_surface,
cm_image_desc.image_desc,
intent_info->protocol_intent);
xx_image_description_v4_destroy(cm_image_desc.image_desc);
wp_image_description_v1_destroy(cm_image_desc.image_desc);
wl_event_queue_destroy(queue);
return true;
@ -1451,6 +1449,35 @@ surface_flush(struct surface *surface)
surface->cairo_surface = NULL;
}
void
widget_surface_flush(struct widget *widget)
{
struct surface *surface = widget->surface;
if (surface->opaque_region) {
wl_surface_set_opaque_region(surface->surface,
surface->opaque_region);
wl_region_destroy(surface->opaque_region);
surface->opaque_region = NULL;
}
if (surface->input_region) {
wl_surface_set_input_region(surface->surface,
surface->input_region);
wl_region_destroy(surface->input_region);
surface->input_region = NULL;
}
if (surface->viewport) {
wp_viewport_set_destination(surface->viewport,
widget->viewport_dest_width,
widget->viewport_dest_height);
}
wl_surface_damage(surface->surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(surface->surface);
}
int
window_has_focus(struct window *window)
{
@ -1578,7 +1605,7 @@ surface_destroy(struct surface *surface)
wp_viewport_destroy(surface->viewport);
if (surface->cm_surface)
xx_color_management_surface_v4_destroy(surface->cm_surface);
wp_color_management_surface_v1_destroy(surface->cm_surface);
wl_surface_destroy(surface->surface);
@ -1846,8 +1873,9 @@ widget_cairo_update_transform(struct widget *widget, cairo_t *cr)
surface->allocation.width,
surface->allocation.height,
surface->buffer_scale);
cairo_matrix_init(&m, matrix.d[0], matrix.d[1], matrix.d[4],
matrix.d[5], matrix.d[12], matrix.d[13]);
cairo_matrix_init(&m, matrix.M.col[0].x, matrix.M.col[0].y,
matrix.M.col[1].x, matrix.M.col[1].y,
matrix.M.col[3].x, matrix.M.col[3].y);
cairo_transform(cr, &m);
}
@ -3102,10 +3130,8 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
struct input *input = data;
struct xkb_keymap *keymap;
struct xkb_state *state;
#ifdef HAVE_XKBCOMMON_COMPOSE
struct xkb_compose_table *compose_table;
struct xkb_compose_state *compose_state;
#endif
char *locale;
char *map_str;
@ -3153,7 +3179,6 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
locale = "C";
/* Set up XKB compose table */
#ifdef HAVE_XKBCOMMON_COMPOSE
compose_table =
xkb_compose_table_new_from_locale(input->display->xkb_context,
locale,
@ -3177,7 +3202,6 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
fprintf(stderr, "could not create XKB compose table for locale '%s'. "
"Disabiling compose\n", locale);
}
#endif
xkb_keymap_unref(input->xkb.keymap);
xkb_state_unref(input->xkb.state);
@ -3228,7 +3252,6 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
static xkb_keysym_t
process_key_press(xkb_keysym_t sym, struct input *input)
{
#ifdef HAVE_XKBCOMMON_COMPOSE
if (!input->xkb.compose_state)
return sym;
if (sym == XKB_KEY_NoSymbol)
@ -3249,9 +3272,6 @@ process_key_press(xkb_keysym_t sym, struct input *input)
default:
return sym;
}
#else
return sym;
#endif
}
static void
@ -4372,8 +4392,8 @@ undo_resize(struct window *window)
}
}
void
window_schedule_resize(struct window *window, int width, int height)
static void
window_configure_resize(struct window *window, int width, int height)
{
/* We should probably get these numbers from the theme. */
const int min_width = 200, min_height = 200;
@ -4400,6 +4420,12 @@ window_schedule_resize(struct window *window, int width, int height)
window->pending_allocation.height = window->min_allocation.height;
window->resize_needed = 1;
}
void
window_schedule_resize(struct window *window, int width, int height)
{
window_configure_resize(window, width, height);
window_schedule_redraw(window);
}
@ -4488,6 +4514,14 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
}
}
/* If the window is being mapped fullscreen,
* save the last pending allocation */
if (window->fullscreen &&
(window->saved_allocation.width == 0 ||
window->saved_allocation.height == 0)) {
window->saved_allocation = window->pending_allocation;
}
if (window->frame) {
if (window->maximized) {
frame_set_flag(window->frame->frame, FRAME_FLAG_MAXIMIZED);
@ -4508,12 +4542,12 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
* on the shadow margin to get the difference. */
int margin = window_get_shadow_margin(window);
window_schedule_resize(window,
window_configure_resize(window,
width + margin * 2,
height + margin * 2);
} else if (window->saved_allocation.width > 0 &&
window->saved_allocation.height > 0) {
window_schedule_resize(window,
window_configure_resize(window,
window->saved_allocation.width,
window->saved_allocation.height);
}
@ -4937,6 +4971,20 @@ window_set_locked_pointer_motion_handler(struct window *window,
window->locked_pointer_motion_handler = handler;
}
void
window_set_shadow(struct window *window)
{
if (window->frame)
frame_unset_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
}
void
window_unset_shadow(struct window *window)
{
if (window->frame)
frame_set_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
}
void
window_set_title(struct window *window, const char *title)
{
@ -6671,7 +6719,7 @@ display_bind_tablets(struct display *d, uint32_t id)
}
static void
cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t render_intent)
{
struct display *d = data;
@ -6680,7 +6728,7 @@ cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
}
static void
cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t feature)
{
struct display *d = data;
@ -6689,24 +6737,31 @@ cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4
}
static void
cm_supported_tf_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
cm_supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t tf_code)
{
/* unused in this file */
}
static void
cm_supported_primaries_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
cm_supported_primaries_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t primaries_code)
{
/* unused in this file */
}
static const struct xx_color_manager_v4_listener cm_listener = {
static void
cm_done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
{
/* unused in this file */
}
static const struct wp_color_manager_v1_listener cm_listener = {
.supported_intent = cm_supported_intent,
.supported_feature = cm_supported_feature,
.supported_tf_named = cm_supported_tf_named,
.supported_primaries_named = cm_supported_primaries_named,
.done = cm_done,
};
static void
@ -6777,12 +6832,17 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
&wp_viewporter_interface, 1);
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
display_bind_tablets(d, id);
} else if (strcmp(interface, "xx_color_manager_v4") == 0) {
} else if (strcmp(interface, "wp_color_manager_v1") == 0) {
d->color_manager =
wl_registry_bind(registry, id,
&xx_color_manager_v4_interface, 1);
xx_color_manager_v4_add_listener(d->color_manager,
&wp_color_manager_v1_interface, 1);
wp_color_manager_v1_add_listener(d->color_manager,
&cm_listener, d);
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
d->single_pixel_buffer_manager =
wl_registry_bind(registry, id,
&wp_single_pixel_buffer_manager_v1_interface,
1);
}
if (d->global_handler)
@ -7005,7 +7065,7 @@ display_destroy(struct display *display)
xdg_wm_base_destroy(display->xdg_shell);
if (display->color_manager)
xx_color_manager_v4_destroy(display->color_manager);
wp_color_manager_v1_destroy(display->color_manager);
if (display->shm)
wl_shm_destroy(display->shm);
@ -7071,6 +7131,12 @@ display_get_compositor(struct display *display)
return display->compositor;
}
struct wp_single_pixel_buffer_manager_v1 *
display_get_single_pixel_buffer_manager(struct display *display)
{
return display->single_pixel_buffer_manager;
}
uint32_t
display_get_serial(struct display *display)
{

View file

@ -76,6 +76,9 @@ display_has_subcompositor(struct display *display);
struct wl_compositor *
display_get_compositor(struct display *display);
struct wp_single_pixel_buffer_manager_v1 *
display_get_single_pixel_buffer_manager(struct display *display);
struct output *
display_get_output(struct display *display);
@ -530,6 +533,12 @@ void
window_set_locked_pointer_motion_handler(
struct window *window, window_locked_pointer_motion_handler_t handler);
void
window_set_shadow(struct window *window);
void
window_unset_shadow(struct window *window);
void
window_set_title(struct window *window, const char *title);
@ -604,6 +613,9 @@ widget_cairo_create(struct widget *widget);
struct wl_surface *
widget_get_wl_surface(struct widget *widget);
void
widget_surface_flush(struct widget *widget);
uint32_t
widget_get_last_time(struct widget *widget);

View file

@ -33,6 +33,7 @@ home.png
icon_ivi_clickdot.png
icon_ivi_flower.png
icon_ivi_simple-egl.png
icon_ivi_simple-egl-vertical.png
icon_ivi_simple-shm.png
icon_ivi_smoke.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -9,6 +9,7 @@ install_data(
'icon_ivi_clickdot.png',
'icon_ivi_flower.png',
'icon_ivi_simple-egl.png',
'icon_ivi_simple-egl-vertical.png',
'icon_ivi_simple-shm.png',
'icon_ivi_smoke.png',
'icon_terminal.png',

View file

@ -48,168 +48,6 @@
#define DEFAULT_NUM_WORKSPACES 1
#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
struct focus_state {
struct desktop_shell *shell;
struct weston_seat *seat;
struct workspace *ws;
struct weston_surface *keyboard_focus;
struct wl_list link;
struct wl_listener seat_destroy_listener;
struct wl_listener surface_destroy_listener;
};
/*
* Surface stacking and ordering.
*
* This is handled using several linked lists of surfaces, organised into
* layers. The layers are ordered, and each of the surfaces in one layer are
* above all of the surfaces in the layer below. The set of layers is static and
* in the following order (top-most first):
* Lock layer (only ever displayed on its own)
* Cursor layer
* Input panel layer
* Fullscreen layer
* Panel layer
* Workspace layers
* Background layer
*
* The list of layers may be manipulated to remove whole layers of surfaces from
* display. For example, when locking the screen, all layers except the lock
* layer are removed.
*
* A surfaces layer is modified on configuring the surface, in
* set_surface_type() (which is only called when the surfaces type change is
* _committed_). If a surfaces type changes (e.g. when making a window
* fullscreen) its layer changes too.
*
* In order to allow popup and transient surfaces to be correctly stacked above
* their parent surfaces, each surface tracks both its parent surface, and a
* linked list of its children. When a surfaces layer is updated, so are the
* layers of its children. Note that child surfaces are *not* the same as
* subsurfaces child/parent surfaces are purely for maintaining stacking
* order.
*
* The children_link list of siblings of a surface (i.e. those surfaces which
* have the same parent) only contains weston_surfaces which have a
* shell_surface. Stacking is not implemented for non-shell_surface
* weston_surfaces. This means that the following implication does *not* hold:
* (shsurf->parent != NULL) !wl_list_is_empty(shsurf->children_link)
*/
struct shell_surface {
struct wl_signal destroy_signal;
struct weston_desktop_surface *desktop_surface;
struct weston_view *view;
struct weston_surface *wsurface_anim_fade;
struct weston_view *wview_anim_fade;
int32_t last_width, last_height;
struct desktop_shell *shell;
struct wl_list children_list;
struct wl_list children_link;
struct weston_coord_global saved_pos;
bool saved_position_valid;
bool saved_rotation_valid;
int unresponsive, grabbed;
uint32_t resize_edges;
uint32_t orientation;
struct {
struct weston_transform transform;
struct weston_matrix rotation;
} rotation;
struct {
struct weston_curtain *black_view;
} fullscreen;
struct weston_output *fullscreen_output;
struct weston_output *output;
struct wl_listener output_destroy_listener;
struct surface_state {
bool fullscreen;
bool maximized;
bool lowered;
} state;
struct {
bool is_set;
struct weston_coord_global pos;
} xwayland;
int focus_count;
bool destroying;
struct wl_list link; /** desktop_shell::shsurf_list */
};
struct shell_grab {
struct weston_pointer_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
};
struct shell_touch_grab {
struct weston_touch_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_touch *touch;
};
struct shell_tablet_tool_grab {
struct weston_tablet_tool_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_tablet_tool *tool;
};
struct weston_move_grab {
struct shell_grab base;
struct weston_coord_global delta;
bool client_initiated;
};
struct weston_touch_move_grab {
struct shell_touch_grab base;
int active;
struct weston_coord_global delta;
};
struct weston_tablet_tool_move_grab {
struct shell_tablet_tool_grab base;
wl_fixed_t dx, dy;
};
struct rotate_grab {
struct shell_grab base;
struct weston_matrix rotation;
struct {
float x;
float y;
} center;
};
struct shell_seat {
struct weston_seat *seat;
struct wl_listener seat_destroy_listener;
struct weston_surface *focused_surface;
struct wl_listener caps_changed_listener;
struct wl_listener pointer_focus_listener;
struct wl_listener keyboard_focus_listener;
struct wl_listener tablet_tool_added_listener;
struct wl_list link; /** shell::seat_list */
};
struct tablet_tool_listener {
struct wl_listener base;
struct wl_listener removed_listener;
};
static struct desktop_shell *
shell_surface_get_shell(struct shell_surface *shsurf);
@ -235,20 +73,6 @@ shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
static void
get_maximized_size(struct shell_surface *shsurf, int32_t *width, int32_t *height);
static struct shell_output *
find_shell_output_from_weston_output(struct desktop_shell *shell,
struct weston_output *output)
{
struct shell_output *shell_output;
wl_list_for_each(shell_output, &shell->output_list, link) {
if (shell_output->output == output)
return shell_output;
}
return NULL;
}
static bool
shsurf_is_max_or_fullscreen(struct shell_surface *shsurf)
{
@ -269,8 +93,8 @@ set_shsurf_size_maximized_or_fullscreen(struct shell_surface *shsurf,
if (fullscreen_requested) {
if (shsurf->output) {
width = shsurf->output->width;
height = shsurf->output->height;
width = shsurf->output->output->width;
height = shsurf->output->output->height;
}
} else if (max_requested) {
/* take the panels into considerations */
@ -369,21 +193,18 @@ shell_grab_start(struct shell_grab *grab,
void
get_output_work_area(struct desktop_shell *shell,
struct weston_output *output,
struct shell_output *sh_output,
pixman_rectangle32_t *area)
{
struct shell_output *sh_output;
struct weston_output *output;
area->x = 0;
area->y = 0;
area->width = 0;
area->height = 0;
if (!output)
if (!sh_output)
return;
sh_output = find_shell_output_from_weston_output(shell, output);
assert(sh_output);
output = sh_output->output;
area->x = output->pos.c.x;
area->y = output->pos.c.y;
@ -523,6 +344,7 @@ shell_configuration(struct desktop_shell *shell)
struct weston_config *config;
char *s, *client;
bool allow_zap;
bool disallow_output_changed_move;
config = wet_get_config(shell->compositor);
section = weston_config_get_section(config, "shell", NULL, NULL);
@ -535,6 +357,11 @@ shell_configuration(struct desktop_shell *shell)
"allow-zap", &allow_zap, true);
shell->allow_zap = allow_zap;
weston_config_section_get_bool(section,
"disallow-output-changed-move",
&disallow_output_changed_move, false);
shell->disallow_output_changed_move = disallow_output_changed_move;
shell->binding_modifier = weston_config_get_binding_modifier(config, MODIFIER_SUPER);
weston_config_section_get_string(section, "animation", &s, "none");
@ -1061,7 +888,12 @@ constrain_position(struct weston_move_grab *move)
if (shsurf->shell->panel_position ==
WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
get_output_work_area(shsurf->shell, surface->output, &area);
struct shell_output *shoutput = NULL;
if (surface->output)
shoutput = weston_output_get_shell_private(surface->output);
get_output_work_area(shsurf->shell, shoutput, &area);
geometry =
weston_desktop_surface_get_geometry(shsurf->desktop_surface);
@ -1702,15 +1534,26 @@ shell_surface_set_output(struct shell_surface *shsurf,
{
struct weston_surface *es =
weston_desktop_surface_get_surface(shsurf->desktop_surface);
struct shell_output *shoutput = NULL;
if (output)
shoutput = weston_output_get_shell_private(output);
/* get the default output, if the client set it as NULL
check whether the output is available */
if (output)
shsurf->output = output;
if (shoutput)
shsurf->output = shoutput;
else if (es->output)
shsurf->output = es->output;
else
shsurf->output = weston_shell_utils_get_default_output(es->compositor);
shsurf->output = weston_output_get_shell_private(es->output);
else {
struct shell_output *shoutput = NULL;
struct weston_output *w_output;
w_output = weston_shell_utils_get_default_output(es->compositor);
if (w_output)
shoutput = weston_output_get_shell_private(w_output);
shsurf->output = shoutput;
}
if (shsurf->output_destroy_listener.notify) {
wl_list_remove(&shsurf->output_destroy_listener.link);
@ -1721,7 +1564,7 @@ shell_surface_set_output(struct shell_surface *shsurf,
return;
shsurf->output_destroy_listener.notify = notify_output_destroy;
wl_signal_add(&shsurf->output->destroy_signal,
wl_signal_add(&shsurf->output->output->destroy_signal,
&shsurf->output_destroy_listener);
}
@ -1867,7 +1710,13 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
struct weston_surface *surface =
weston_desktop_surface_get_surface(shsurf->desktop_surface);
struct weston_compositor *ec = surface->compositor;
struct weston_output *output = shsurf->fullscreen_output;
struct weston_output *output = NULL;
if (!shsurf->fullscreen_output)
return;
output = shsurf->fullscreen_output->output;
struct weston_curtain_params curtain_params = {
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
.pos = output->pos,
@ -1882,14 +1731,14 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
weston_view_move_to_layer(shsurf->view,
&shsurf->shell->fullscreen_layer.view_list);
weston_shell_utils_center_on_output(shsurf->view, shsurf->fullscreen_output);
weston_shell_utils_center_on_output(shsurf->view, output);
if (!shsurf->fullscreen.black_view) {
shsurf->fullscreen.black_view =
weston_shell_utils_curtain_create(ec, &curtain_params);
}
weston_view_set_output(shsurf->fullscreen.black_view->view,
shsurf->fullscreen_output);
output);
weston_view_move_to_layer(shsurf->fullscreen.black_view->view,
&shsurf->view->layer_link);
@ -2055,8 +1904,8 @@ fade_out_done(struct weston_view_animation *animation, void *data)
if (weston_view_is_mapped(shsurf->wview_anim_fade)) {
weston_view_move_to_layer(shsurf->wview_anim_fade, NULL);
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
}
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
}
struct shell_surface *
@ -2269,8 +2118,13 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf)
shell_surface_update_layer(shsurf);
if (shsurf->state.maximized) {
surface->output = shsurf->output;
weston_view_set_output(shsurf->view, shsurf->output);
struct weston_output *w_output = NULL;
if (shsurf->output)
w_output = shsurf->output->output;
surface->output = w_output;
weston_view_set_output(shsurf->view, w_output);
}
if (!shell->locked) {
@ -2376,8 +2230,12 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
WESTON_ACTIVATE_FLAG_FULLSCREEN);
}
} else if (shsurf->state.maximized) {
struct weston_output *w_output = NULL;
set_maximized_position(shell, shsurf);
surface->output = shsurf->output;
if (surface->output)
w_output = shsurf->output->output;
surface->output = w_output;
} else {
struct weston_coord_surface offset = buf_offset;
struct weston_coord_global pos;
@ -2777,7 +2635,13 @@ background_committed(struct weston_surface *es,
struct weston_coord_surface new_origin)
{
struct shell_output *sh_output = es->committed_private;
struct desktop_shell *shell = sh_output->shell;
struct desktop_shell *shell;
/* The output was destroyed before the background was committed */
if (!sh_output)
return;
shell = sh_output->shell;
if (!weston_surface_has_content(es))
return;
@ -2793,6 +2657,7 @@ background_committed(struct weston_surface *es,
sh_output->output->pos);
weston_view_move_to_layer(sh_output->background_view,
&shell->background_layer.view_list);
weston_output_set_ready(sh_output->output);
}
static void
@ -2812,7 +2677,6 @@ desktop_shell_set_background(struct wl_client *client,
struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
struct desktop_shell *shell = wl_resource_get_user_data(resource);
struct weston_surface *surface =
wl_resource_get_user_data(surface_resource);
struct shell_output *sh_output;
@ -2829,7 +2693,7 @@ desktop_shell_set_background(struct wl_client *client,
return;
surface->output = head->output;
sh_output = find_shell_output_from_weston_output(shell, surface->output);
sh_output = weston_output_get_shell_private(surface->output);
if (sh_output->background_surface) {
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -2866,9 +2730,17 @@ panel_committed(struct weston_surface *es,
struct weston_coord_surface new_origin)
{
struct shell_output *sh_output = es->committed_private;
struct weston_output *output = sh_output->output;
struct weston_coord_global pos = output->pos;
struct desktop_shell *shell = sh_output->shell;
struct weston_output *output;
struct weston_coord_global pos;
struct desktop_shell *shell;
/* The output was destroyed before the panel was committed */
if (!sh_output)
return;
output = sh_output->output;
pos = output->pos;
shell = sh_output->shell;
if (!weston_surface_has_content(es))
return;
@ -2895,13 +2767,14 @@ panel_committed(struct weston_surface *es,
weston_surface_map(es);
assert(wl_list_empty(&es->views));
sh_output->panel_view = weston_view_create(es);
weston_view_move_to_layer(sh_output->panel_view,
&shell->panel_layer.view_list);
}
assert(sh_output->panel_view);
pos = weston_coord_global_add(output->pos, sh_output->panel_offset);
weston_view_set_position(sh_output->panel_view, pos);
weston_view_move_to_layer(sh_output->panel_view,
&shell->panel_layer.view_list);
}
static void
@ -2922,7 +2795,6 @@ desktop_shell_set_panel(struct wl_client *client,
struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
struct desktop_shell *shell = wl_resource_get_user_data(resource);
struct weston_surface *surface =
wl_resource_get_user_data(surface_resource);
struct shell_output *sh_output;
@ -2939,7 +2811,7 @@ desktop_shell_set_panel(struct wl_client *client,
return;
surface->output = head->output;
sh_output = find_shell_output_from_weston_output(shell, surface->output);
sh_output = weston_output_get_shell_private(surface->output);
if (sh_output->panel_surface) {
wl_resource_post_error(surface_resource,
@ -3431,7 +3303,6 @@ rotate_grab_motion(struct weston_pointer_grab *grab,
}
weston_view_update_transform(shsurf->view);
weston_surface_damage(shsurf->view->surface);
}
static void
@ -3555,7 +3426,7 @@ rotate_binding(struct weston_pointer *pointer, const struct timespec *time,
* the alt-tab switcher, which need to de-promote fullscreen layers. */
void
lower_fullscreen_layer(struct desktop_shell *shell,
struct weston_output *lowering_output)
struct shell_output *lowering_output)
{
struct workspace *ws;
struct weston_view *view, *prev;
@ -3975,9 +3846,6 @@ shell_fade_init(struct desktop_shell *shell)
if (!shell->fade.curtain)
return;
weston_view_update_transform(shell->fade.curtain->view);
weston_surface_damage(shell->fade.curtain->view->surface);
loop = wl_display_get_event_loop(shell->compositor->wl_display);
shell->fade.startup_timer =
wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
@ -4047,6 +3915,7 @@ weston_view_set_initial_position(struct weston_view *view,
int32_t range_x, range_y;
int32_t x, y;
struct weston_output *output, *target_output = NULL;
struct shell_output *shoutput;
struct weston_seat *seat;
pixman_rectangle32_t area;
struct weston_coord_global pos;
@ -4084,7 +3953,9 @@ weston_view_set_initial_position(struct weston_view *view,
* If this is negative it means that the surface is bigger than
* output.
*/
get_output_work_area(shell, target_output, &area);
assert(target_output);
shoutput = weston_output_get_shell_private(target_output);
get_output_work_area(shell, shoutput, &area);
x = area.x;
y = area.y;
@ -4466,6 +4337,12 @@ shell_reposition_view_on_output_change(struct weston_view *view)
struct shell_surface *shsurf;
int visible;
/* We can't simply reposition popups and such, they must move with
* the parent.
*/
if (view->geometry.parent)
return;
if (wl_list_empty(&ec->output_list))
return;
@ -4541,12 +4418,18 @@ shell_output_destroy(struct shell_output *shell_output)
{
struct desktop_shell *shell = shell_output->shell;
if (!shell->disallow_output_changed_move) {
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
}
if (shell_output->panel_surface)
if (shell_output->panel_surface) {
wl_list_remove(&shell_output->panel_surface_listener.link);
if (shell_output->background_surface)
shell_output->panel_surface->committed_private = NULL;
}
if (shell_output->background_surface) {
wl_list_remove(&shell_output->background_surface_listener.link);
shell_output->background_surface->committed_private = NULL;
}
wl_list_remove(&shell_output->destroy_listener.link);
wl_list_remove(&shell_output->link);
free(shell_output);
@ -4606,7 +4489,7 @@ handle_output_resized(struct wl_listener *listener, void *data)
struct desktop_shell *shell =
container_of(listener, struct desktop_shell, resized_listener);
struct weston_output *output = (struct weston_output *)data;
struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
struct shell_output *sh_output = weston_output_get_shell_private(output);
handle_output_resized_shsurfs(shell);
@ -4624,6 +4507,8 @@ create_shell_output(struct desktop_shell *shell,
if (shell_output == NULL)
return;
weston_output_set_shell_private(output, shell_output);
shell_output->output = output;
shell_output->shell = shell;
shell_output->destroy_listener.notify = handle_output_destroy;
@ -4631,7 +4516,7 @@ create_shell_output(struct desktop_shell *shell,
&shell_output->destroy_listener);
wl_list_insert(shell->output_list.prev, &shell_output->link);
if (wl_list_length(&shell->output_list) == 1)
if (!shell->disallow_output_changed_move && wl_list_length(&shell->output_list) == 1)
shell_for_each_layer(shell,
shell_output_changed_move_layer, NULL);
}
@ -4658,6 +4543,12 @@ handle_output_move_layer(struct desktop_shell *shell,
if (view->output != output)
continue;
/* We can't simply reposition popups and such, they must move with
* the parent.
*/
if (view->geometry.parent)
continue;
pos = weston_coord_global_add(
weston_view_get_pos_offset_global(view),
output->move);

View file

@ -23,6 +23,9 @@
* DEALINGS IN THE SOFTWARE.
*/
#ifndef WESTON_DESKTOP_SHELL_H
#define WESTON_DESKTOP_SHELL_H
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
@ -32,6 +35,169 @@
#include "weston-desktop-shell-server-protocol.h"
struct focus_state {
struct desktop_shell *shell;
struct weston_seat *seat;
struct workspace *ws;
struct weston_surface *keyboard_focus;
struct wl_list link;
struct wl_listener seat_destroy_listener;
struct wl_listener surface_destroy_listener;
};
/*
* Surface stacking and ordering.
*
* This is handled using several linked lists of surfaces, organised into
* layers. The layers are ordered, and each of the surfaces in one layer are
* above all of the surfaces in the layer below. The set of layers is static and
* in the following order (top-most first):
* Lock layer (only ever displayed on its own)
* Cursor layer
* Input panel layer
* Fullscreen layer
* Panel layer
* Workspace layers
* Background layer
*
* The list of layers may be manipulated to remove whole layers of surfaces from
* display. For example, when locking the screen, all layers except the lock
* layer are removed.
*
* A surfaces layer is modified on configuring the surface, in
* set_surface_type() (which is only called when the surfaces type change is
* _committed_). If a surfaces type changes (e.g. when making a window
* fullscreen) its layer changes too.
*
* In order to allow popup and transient surfaces to be correctly stacked above
* their parent surfaces, each surface tracks both its parent surface, and a
* linked list of its children. When a surfaces layer is updated, so are the
* layers of its children. Note that child surfaces are *not* the same as
* subsurfaces child/parent surfaces are purely for maintaining stacking
* order.
*
* The children_link list of siblings of a surface (i.e. those surfaces which
* have the same parent) only contains weston_surfaces which have a
* shell_surface. Stacking is not implemented for non-shell_surface
* weston_surfaces. This means that the following implication does *not* hold:
* (shsurf->parent != NULL) !wl_list_is_empty(shsurf->children_link)
*/
struct shell_surface {
struct wl_signal destroy_signal;
struct weston_desktop_surface *desktop_surface;
struct weston_view *view;
struct weston_surface *wsurface_anim_fade;
struct weston_view *wview_anim_fade;
int32_t last_width, last_height;
struct desktop_shell *shell;
struct wl_list children_list;
struct wl_list children_link;
struct weston_coord_global saved_pos;
bool saved_position_valid;
bool saved_rotation_valid;
int unresponsive, grabbed;
uint32_t resize_edges;
uint32_t orientation;
struct {
struct weston_transform transform;
struct weston_matrix rotation;
} rotation;
struct {
struct weston_curtain *black_view;
} fullscreen;
struct shell_output *fullscreen_output;
struct shell_output *output;
struct wl_listener output_destroy_listener;
struct surface_state {
bool fullscreen;
bool maximized;
bool lowered;
} state;
struct {
bool is_set;
struct weston_coord_global pos;
} xwayland;
int focus_count;
bool destroying;
struct wl_list link; /** desktop_shell::shsurf_list */
};
struct shell_grab {
struct weston_pointer_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
};
struct shell_touch_grab {
struct weston_touch_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_touch *touch;
};
struct shell_tablet_tool_grab {
struct weston_tablet_tool_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_tablet_tool *tool;
};
struct weston_move_grab {
struct shell_grab base;
struct weston_coord_global delta;
bool client_initiated;
};
struct weston_touch_move_grab {
struct shell_touch_grab base;
int active;
struct weston_coord_global delta;
};
struct weston_tablet_tool_move_grab {
struct shell_tablet_tool_grab base;
wl_fixed_t dx, dy;
};
struct rotate_grab {
struct shell_grab base;
struct weston_matrix rotation;
struct {
float x;
float y;
} center;
};
struct shell_seat {
struct weston_seat *seat;
struct wl_listener seat_destroy_listener;
struct weston_surface *focused_surface;
struct wl_listener caps_changed_listener;
struct wl_listener pointer_focus_listener;
struct wl_listener keyboard_focus_listener;
struct wl_listener tablet_tool_added_listener;
struct wl_list link; /** shell::seat_list */
};
struct tablet_tool_listener {
struct wl_listener base;
struct wl_listener removed_listener;
};
enum animation_type {
ANIMATION_NONE,
@ -140,6 +306,7 @@ struct desktop_shell {
} fade;
bool allow_zap;
bool disallow_output_changed_move;
uint32_t binding_modifier;
enum animation_type win_animation_type;
enum animation_type win_close_animation_type;
@ -176,12 +343,12 @@ get_current_workspace(struct desktop_shell *shell);
void
get_output_work_area(struct desktop_shell *shell,
struct weston_output *output,
struct shell_output *output,
pixman_rectangle32_t *area);
void
lower_fullscreen_layer(struct desktop_shell *shell,
struct weston_output *lowering_output);
struct shell_output *lowering_output);
void
activate(struct desktop_shell *shell, struct weston_view *view,
@ -199,3 +366,5 @@ void
shell_for_each_layer(struct desktop_shell *shell,
shell_for_each_layer_func_t func,
void *data);
#endif /* WESTON_DESKTOP_SHELL_H */

View file

@ -196,7 +196,8 @@ epub_exclude_files = ['search.html']
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/3': None}
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
# -- Options for todo extension ----------------------------------------------

View file

@ -1208,15 +1208,6 @@ HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.

View file

@ -48,7 +48,7 @@ doxygen_conf_weston = configure_file(
script_data = configuration_data()
script_data.set('SRCDIR', meson.current_build_dir())
script_data.set('OUTDIR', meson.current_build_dir() + '/doc')
script_data.set('OUTDIR', meson.current_build_dir() / 'weston')
# Set a different directory for doctrees to avoid installing them
script_data.set('DOCTREES_DIR', meson.current_build_dir() + '/doctrees')
@ -82,9 +82,11 @@ endif
sphinx_doc = custom_target(
'weston-doc-breathe',
command: script_doxy_sphinx,
output: 'doc',
output: 'weston',
build_by_default: true,
env: sphinx_env,
install: true,
install_dir: dir_data / 'doc',
)
# we need this because we will have a stale 'doc' directory
@ -93,10 +95,3 @@ docs = run_target(
'docs',
command: script_doxy_sphinx,
)
install_subdir(
sphinx_doc.full_path(),
install_dir: dir_data / 'doc' / 'weston',
exclude_files: '.buildinfo',
strip_directory: true,
)

View file

@ -6,4 +6,15 @@ else
SPHINX_WERROR=""
fi
@DOXYGEN_CMD@ @DOXYGEN_CONF@ && @SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@
set -e
BUILDINFO_ORIG="@OUTDIR@/.buildinfo"
BUILDINFO_SAVE="@SRCDIR@/buildinfo.save"
[ -f "$BUILDINFO_SAVE" ] && mv -f "$BUILDINFO_SAVE" "$BUILDINFO_ORIG"
@DOXYGEN_CMD@ @DOXYGEN_CONF@
@SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@
mv -f "$BUILDINFO_ORIG" "$BUILDINFO_SAVE"

View file

@ -86,7 +86,8 @@ the surface was added to. However, the views are not provided to the IVI
controller.
After configuring all expected changes, the controller must call the
``commit_changes`` to atomically update the display layout.
``commit_changes`` to atomically update the display layout and call
``screen_ready`` to inform the compositor that it can start issueing repaints.
IVI-shell example implementation
--------------------------------

View file

@ -10,6 +10,7 @@ Libweston
libweston/shell-utils.rst
libweston/output-management.rst
libweston/log.rst
libweston/debug-flight-recorder.rst
`Libweston` is an effort to separate the re-usable parts of Weston into a
library. `Libweston` provides most of the boring and tedious bits of correctly

View file

@ -0,0 +1,51 @@
.. _debugging flight recorder:
Debugging with Flight Recorder
==============================
Weston can write debug scopes data to a circular ring buffer. This ring
buffer can be accessed through a debug key, assuming you have a keyboard
attached, or in case Weston dies, through a coredump. This document describes
how to access that data in the later case.
The ring buffer data can be accessed with a gdb python script that searches
the coredump file for the that ring buffer address in order to retrieve
data from it.
Prior to setting this up make sure that flight recorder is configured
accordingly. Make sure that Weston is started with the debug scopes that
you're interested into. For instance if you'd like to get the :samp:`drm-backend` one
Weston should show when starting up:
::
Flight recorder: enabled, scopes subscribed: drm-backend
For that Weston needs to be started with :samp:`--debug -f drm-backend`.
Also, make sure that the system is configured to generate a core dump. Refer
to :samp:`man core(5)` for how to do that.
Next you'll need the `gdb python
script <https://gitlab.freedesktop.org/wayland/weston/-/blob/main/doc/scripts/gdb/flight_rec.py>`_,
as that will be needed to search for the ring buffer within the coredump.
Finally, to make this easier and push everything from the ring buffer to a
file, we would need to create a batch gdb file script to invoke the commands
for us.
As an example name that file :file:`test.gdb` and add the following to entries
to it, making sure to adjust the path for the python script.
::
source /path/to/flight_rec.py
display_flight_rec
Then run the following commands to dump the contents of the ring buffer
straight to a file:
::
$ gdb --batch --command=/path/to/test.gdb -q /path/to/test/weston/binary --core /path/to/coredump &> dump.log.txt

View file

@ -141,8 +141,9 @@ force the contents to be printed on :samp:`stdout` file-descriptor.
The user has first to specify which log scope to subscribe to.
Specifying which scopes to subscribe for the flight-recorder can be done using
:samp:`--flight-rec-scopes`. By default, the 'log' scope and 'drm-backend' are
the scopes subscribed to.
:samp:`-f|--flight-rec-scopes`. By default, only the 'log' scope is subscribed
to. See :ref:`debugging flight recorder` on how retrieve the contents of the
flight recorder in case Weston dies/crashes unexpectedly.
weston-debug protocol
~~~~~~~~~~~~~~~~~~~~~
@ -178,6 +179,13 @@ The following illustrates how to use it:
./weston-debug timeline > log.json
./wesgr -i log.json -o log.svg
Weston has experimental support for `Perfetto <https://perfetto.dev>`_ for
performance profiling. It can be enabled by using `-Dperfetto=true` during
the meson invocation to configure the build.
If Perfetto support is built in, timeline points are added to Perfetto tracks
when Perfetto is running, even when the 'timeline' scope is not enabled.
Inserting timeline points
~~~~~~~~~~~~~~~~~~~~~~~~~
@ -186,6 +194,13 @@ take the :type:`weston_compositor` instance, followed by the name of the
timeline point. What follows next is a variable number of arguments, which
**must** end with the macro :c:macro:`TLP_END`.
Adding Perfetto trace points
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In addition to timeline points, Perfetto can also display timing information
for individual functions. The easiest way to add profiling data for a function
is to insert the :c:macro:`WESTON_TRACE_FUNC` at the top of the function.
Debug protocol API
------------------

View file

@ -2,6 +2,7 @@
files = [
'compositor.rst',
'head.rst',
'debug-flight-recorder.rst',
'log.rst',
'output.rst',
'output-management.rst',

View file

@ -35,12 +35,15 @@ stitching them together is performed by a *renderer*. By doing so, it is
compositing all surfaces into a single image, which is being handed out to a
back-end, and finally, displayed on the screen.
libweston provides two useful renderers. One uses
`OpenGL ES <https://www.khronos.org/opengles/>`_, which will often be accelerated
by your GPU when suitable drivers are installed. The other uses the
`Pixman <http://www.pixman.org>`_ library which is entirely CPU (software)
rendered. You can select between these with the ``--renderer=gl`` and
``--renderer=pixman`` arguments when starting Weston.
libweston provides multiple useful renderers. There are
`OpenGL ES <https://www.khronos.org/opengles/>`_ and
`Vulkan <https://www.vulkan.org/>`_ renderers, which will often be accelerated
by your GPU when suitable drivers are installed.
Another uses the `Pixman <http://www.pixman.org>`_ library which is entirely
CPU (software) rendered.
You can select between these with the ``--renderer=gl``, ``--renderer=vulkan``
and ``--renderer=pixman`` arguments when starting Weston.
Multi-back-end support
----------------------

View file

@ -90,7 +90,8 @@ Standalone tests
Standalone tests do not have a fixture setup function defined in the test
program or the fixture setup function calls
:func:`weston_test_harness_execute_standalone` explicitly. All test cases must
be defined with :c:func:`TEST` or :c:func:`TEST_P`.
be defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
return a value from :type:`test_result_code`.
This is the simplest possible test example:
@ -98,7 +99,7 @@ This is the simplest possible test example:
TEST(always_success)
{
/* true */
return RESULT_OK;
}
@ -110,7 +111,8 @@ Plugin tests
Plugin tests must have a fixture setup function that calls
:func:`weston_test_harness_execute_as_plugin`. All test cases must be defined
with :c:func:`PLUGIN_TEST` which declares an implicit function argument
:type:`weston_compositor` ``*compositor``.
:type:`weston_compositor` ``*compositor``. Each such function must
return a value from :type:`test_result_code`.
The compositor fixture manufactures the necessary environment variables and the
command line argument array to launch Weston, and calls :func:`wet_main`
@ -137,6 +139,7 @@ This is an example of a plugin test that just logs a line:
{
/* struct weston_compositor *compositor; */
testlog("Got compositor %p\n", compositor);
return RESULT_OK;
}
@ -147,7 +150,8 @@ Client tests
Plugin tests must have a fixture setup function that calls
:func:`weston_test_harness_execute_as_client`. All test cases must be
defined with :c:func:`TEST` or :c:func:`TEST_P`.
defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
return a value from :type:`test_result_code`.
The compositor fixture manufactures the necessary environment variables and the
command line argument array to launch Weston, and calls :func:`wet_main`
@ -202,6 +206,7 @@ clients:
expect_protocol_error(client, &wp_viewport_interface,
WP_VIEWPORT_ERROR_BAD_VALUE);
return RESULT_OK;
}
TEST(test_roundtrip)
@ -210,6 +215,7 @@ clients:
client = create_client_and_test_surface(100, 50, 123, 77);
client_roundtrip(client);
return RESULT_OK;
}
@ -257,15 +263,6 @@ type of tests to keep the fixture setup simple. See
:ref:`test-suite-standalone`, :ref:`test-suite-plugin` and
:ref:`test-suite-client` how to set up each type in a test program.
.. note::
**TODO:** Currently it is not possible to gracefully skip or fail a test.
You can skip with ``exit(RESULT_SKIP)`` but that will quit the whole test
program and all defined tests that were not ran yet will be counted as
failed. You can fail a test by any means, e.g. ``exit(RESULT_FAIL)``, but
the same caveat applies. Succeeded tests must simply return and not call any
exit function.
.. toctree::
:hidden:

View file

@ -31,6 +31,7 @@
#include <libweston/config-parser.h>
#include "shared/helpers.h"
#include "shared/string-helpers.h"
#include "weston-private.h"
struct {
@ -64,12 +65,10 @@ get_backend_from_string(const char *name,
return false;
}
struct {
char *name;
enum weston_renderer_type renderer;
} renderer_name_map[] = {
static const struct weston_enum_map renderer_name_map[] = {
{ "auto", WESTON_RENDERER_AUTO },
{ "gl", WESTON_RENDERER_GL },
{ "vulkan", WESTON_RENDERER_VULKAN },
{ "noop", WESTON_RENDERER_NOOP },
{ "pixman", WESTON_RENDERER_PIXMAN },
};
@ -78,17 +77,16 @@ bool
get_renderer_from_string(const char *name,
enum weston_renderer_type *renderer)
{
size_t i;
const struct weston_enum_map *entry;
if (!name)
name = "auto";
for (i = 0; i < ARRAY_LENGTH(renderer_name_map); i++) {
if (strcmp(name, renderer_name_map[i].name) == 0) {
*renderer = renderer_name_map[i].renderer;
entry = weston_enum_map_find_name(renderer_name_map, name);
if (entry) {
*renderer = entry->value;
return true;
}
}
return false;
}

File diff suppressed because it is too large Load diff

View file

@ -16,6 +16,7 @@ deps_weston = [
dep_libevdev,
dep_libdl,
dep_threads,
dep_libdisplay_info,
]
if get_option('xwayland')
@ -67,7 +68,8 @@ install_data(
install_dir: dir_data / 'wayland-sessions'
)
if get_option('screenshare')
if get_option('deprecated-screenshare') and get_option('deprecated-shell-fullscreen')
warning('deprecated-screenshare. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848. Consider using mirroring (see man page) for same functionality and better performance.')
srcs_screenshare = [
'screen-share.c',
fullscreen_shell_unstable_v1_client_protocol_h,

View file

@ -371,7 +371,13 @@ ss_seat_create(struct shared_output *so, uint32_t id)
if (seat == NULL)
return NULL;
if (so->output) {
weston_seat_init(&seat->base, so->output->compositor, "screen-share");
} else {
weston_log("Skip seat creation the screen share output has not an output compositor\n");
return NULL;
}
seat->output = so;
seat->id = id;
seat->parent.seat = wl_registry_bind(so->parent.registry, id,
@ -970,6 +976,8 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
if (!so->parent.display)
goto err_alloc;
/* Set Weston output reference in the shared output before registry */
so->output = output;
so->parent.registry = wl_display_get_registry(so->parent.display);
if (!so->parent.registry)
goto err_display;
@ -1033,7 +1041,6 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
wl_list_init(&so->shm.buffers);
wl_list_init(&so->shm.free_buffers);
so->output = output;
so->output_destroyed.notify = output_destroyed;
wl_signal_add(&so->output->destroy_signal, &so->output_destroyed);
@ -1079,6 +1086,7 @@ shared_output_destroy(struct shared_output *so)
wl_list_remove(&so->output_destroyed.link);
wl_list_remove(&so->frame_listener.link);
if (so->cache_image)
pixman_image_unref(so->cache_image);
free(so->tmp_data);

View file

@ -53,3 +53,8 @@ wet_output_set_colorimetry_mode(struct weston_output *output,
typedef void (*wet_head_additional_setup)(struct weston_head *head,
struct weston_head *head_to_mirror);
struct weston_color_profile *
wet_create_output_color_profile(struct weston_output *output,
struct weston_config *wc,
const char *prof_name);

View file

@ -260,8 +260,10 @@ wet_load_xwayland(struct weston_compositor *comp)
wxw->compositor = comp;
wxw->api = api;
wxw->xwayland = xwayland;
if (api->listen(xwayland, wxw, spawn_xserver) < 0)
if (api->listen(xwayland, wxw, spawn_xserver) < 0) {
free(wxw);
return NULL;
}
return wxw;
}

View file

@ -353,6 +353,8 @@ fs_output_create(struct fullscreen_shell *shell, struct weston_output *output)
}
}
weston_output_set_ready(output);
return fsout;
}

View file

@ -1,4 +1,6 @@
if get_option('shell-fullscreen')
if get_option('deprecated-shell-fullscreen')
warning('deprecated-shell-fullscreen enabled. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848')
srcs_shell_fullscreen = [
'fullscreen-shell.c',
fullscreen_shell_unstable_v1_server_protocol_h,

View file

@ -258,6 +258,14 @@ struct weston_drm_backend_config {
* rendering device.
*/
char *additional_devices;
/** Try to offload blend-to-output color transformation
*
* As KMS currently only supports to offload the transformation in a
* LUT, this may result in precision issues. Also, this requires
* "color-management" to be enabled.
*/
bool offload_blend_to_output;
};
#ifdef __cplusplus

View file

@ -49,6 +49,11 @@ struct weston_headless_backend_config {
* mHz to 1,000,000 mHz. 0 is a special value that triggers repaints
* only on capture requests, not on damages. */
int refresh;
/** Create a fake seat, some clients may complain without a wl_seat.
* The default is not to create a wl_seat.
*/
bool fake_seat;
};
#ifdef __cplusplus

View file

@ -54,19 +54,20 @@ struct weston_pipewire_output_api {
const char *name,
const struct pipewire_config *config);
/** Set the size of a PipeWire output to the specified width and height.
/** Set the size and frame rate of a PipeWire output to the specified value.
*
* If the width or height are set to -1, the size of the underlying
* PipeWire head will be used.
* If the width or height or framerate are set to -1, the size or frame rate
* of the underlying PipeWire head will be used.
*
* \param output The weston output for which the size shall be set
* \param width Desired width of the output
* \param height Desired height of the output
* \param framerate Desired frame rate of the output
*
* Returns 0 on success, -1 on failure.
*/
int (*output_set_size)(struct weston_output *output,
int width, int height);
int width, int height, int framerate);
/** The pixel format to be used by the output.
*

View file

@ -0,0 +1,358 @@
/*
* Copyright © 2008-2011 Kristian Høgsberg
* Copyright © 2012-2025 Collabora, Ltd.
* Copyright © 2017, 2018 General Electric Company
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <libweston/linalg-3.h>
struct weston_compositor;
struct weston_color_profile_param_builder;
struct weston_color_profile;
struct weston_color_transform;
/** Colorimetry mode for outputs and heads
*
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* Default (RGB) colorimetry differs from all the others in that the signal
* colorimetry is not defined here. It is defined by the video sink, and it
* may be described in e.g. EDID.
*/
enum weston_colorimetry_mode {
/** Invalid colorimetry mode, or none supported. */
WESTON_COLORIMETRY_MODE_NONE = 0,
/** Default (RGB) colorimetry, video sink dependant */
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
/** Rec. ITU-R BT.2020 RGB */
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
/** SMPTE ST 2113 DCI-P3 RGB D65 */
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
/** SMPTE ST 2113 DCI-P3 RGB Theater */
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
};
/** Bitmask of all defined colorimetry modes */
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
WESTON_COLORIMETRY_MODE_P3D65 | \
WESTON_COLORIMETRY_MODE_P3DCI | \
WESTON_COLORIMETRY_MODE_ICTCP))
const char *
weston_colorimetry_mode_to_str(enum weston_colorimetry_mode c);
/** EOTF mode for outputs and heads
*
* A list of EOTF modes for driving displays, defined by CTA-861-G for
* Dynamic Range and Mastering InfoFrame.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
*/
enum weston_eotf_mode {
/** Invalid EOTF mode, or none supported. */
WESTON_EOTF_MODE_NONE = 0,
/** Traditional gamma, SDR luminance range */
WESTON_EOTF_MODE_SDR = 0x01,
/** Traditional gamma, HDR luminance range */
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
/** Preceptual quantizer, SMPTE ST 2084 */
WESTON_EOTF_MODE_ST2084 = 0x04,
/** Hybrid log-gamma, ITU-R BT.2100 */
WESTON_EOTF_MODE_HLG = 0x08,
};
/** Bitmask of all defined EOTF modes */
#define WESTON_EOTF_MODE_ALL_MASK \
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
const char *
weston_eotf_mode_to_str(enum weston_eotf_mode e);
/** CIE 1931 xy chromaticity coordinates */
struct weston_CIExy {
float x;
float y;
};
/** Chromaticity coordinates and white point that defines the color gamut */
struct weston_color_gamut {
struct weston_CIExy primary[3]; /* RGB order */
struct weston_CIExy white_point;
};
enum weston_npm_direction {
WESTON_NPM_FORWARD,
WESTON_NPM_INVERSE
};
bool
weston_normalized_primary_matrix_init(struct weston_mat3f *npm,
const struct weston_color_gamut *gamut,
enum weston_npm_direction dir);
struct weston_mat3f
weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to);
/** Color primaries known by libweston */
enum weston_color_primaries {
WESTON_PRIMARIES_CICP_SRGB = 0,
WESTON_PRIMARIES_CICP_PAL_M,
WESTON_PRIMARIES_CICP_PAL,
WESTON_PRIMARIES_CICP_NTSC,
WESTON_PRIMARIES_CICP_GENERIC_FILM,
WESTON_PRIMARIES_CICP_BT2020,
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
WESTON_PRIMARIES_CICP_DCI_P3,
WESTON_PRIMARIES_CICP_DISPLAY_P3,
WESTON_PRIMARIES_ADOBE_RGB,
};
/** Transfer functions known by libweston */
enum weston_transfer_function {
WESTON_TF_BT1886 = 0,
WESTON_TF_GAMMA22,
WESTON_TF_GAMMA28,
WESTON_TF_SRGB,
WESTON_TF_EXT_SRGB,
WESTON_TF_ST240,
WESTON_TF_ST428,
WESTON_TF_ST2084_PQ,
WESTON_TF_EXT_LINEAR,
WESTON_TF_LOG_100,
WESTON_TF_LOG_316,
WESTON_TF_XVYCC,
WESTON_TF_HLG,
WESTON_TF_POWER,
};
enum weston_alpha_mode {
WESTON_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL = 0,
WESTON_ALPHA_MODE_PREMULTIPLIED_OPTICAL,
WESTON_ALPHA_MODE_STRAIGHT,
};
enum weston_color_matrix_coef {
WESTON_COLOR_MATRIX_COEF_UNSET = 0,
WESTON_COLOR_MATRIX_COEF_IDENTITY,
WESTON_COLOR_MATRIX_COEF_BT601,
WESTON_COLOR_MATRIX_COEF_BT709,
WESTON_COLOR_MATRIX_COEF_BT2020,
};
enum weston_color_quant_range {
WESTON_COLOR_QUANT_RANGE_UNSET = 0,
WESTON_COLOR_QUANT_RANGE_FULL,
WESTON_COLOR_QUANT_RANGE_LIMITED,
};
enum weston_ycbcr_chroma_location {
WESTON_YCBCR_CHROMA_LOCATION_UNSET = 0,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_0,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_1,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_2,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_3,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_4,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_5,
};
/** Error codes that the color profile parameters functions may return. */
enum weston_color_profile_param_builder_error {
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES_NAMED,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CREATE_FAILED,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
};
struct weston_color_profile_param_builder *
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
void
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
bool
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
bool
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *primaries);
bool
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
enum weston_color_primaries primaries);
bool
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
enum weston_transfer_function tf);
bool
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
float power_exponent);
bool
weston_color_profile_param_builder_set_primary_luminance(struct weston_color_profile_param_builder *builder,
float ref_lum, float min_lum, float max_lum);
bool
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *target_primaries);
bool
weston_color_profile_param_builder_set_target_primaries_named(struct weston_color_profile_param_builder *builder,
enum weston_color_primaries target_primaries);
bool
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
float min_lum, float max_lum);
bool
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
float maxFALL);
bool
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
float maxCLL);
struct weston_color_profile *
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
const char *name_part,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
enum weston_color_characteristics_groups {
/** weston_color_characteristics::primary is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
/** weston_color_characteristics::white is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
/** weston_color_characteristics::max_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
/** weston_color_characteristics::min_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
/** weston_color_characteristics::maxFALL is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
/** all valid bits */
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
};
/** Basic display color characteristics
*
* This is a simple description of a display or output (monitor) color
* characteristics. The parameters can be found in EDID, with caveats. They
* are particularly useful with HDR monitors.
*/
struct weston_color_characteristics {
/** Which fields are valid
*
* A bitmask of values from enum weston_color_characteristics_groups.
*/
uint32_t group_mask;
/* EOTF is tracked externally with enum weston_eotf_mode */
/** Chromaticities of the primaries */
struct weston_CIExy primary[3];
/** White point chromaticity */
struct weston_CIExy white;
/** Display's desired maximum content peak luminance, cd/m² */
float max_luminance;
/** Display's desired minimum content luminance, cd/m² */
float min_luminance;
/** Display's desired maximum frame-average light level, cd/m² */
float maxFALL;
};
struct weston_color_profile *
weston_color_profile_ref(struct weston_color_profile *cprof);
void
weston_color_profile_unref(struct weston_color_profile *cprof);
const char *
weston_color_profile_get_description(struct weston_color_profile *cprof);
char *
weston_color_profile_get_details(struct weston_color_profile *cprof);
struct weston_color_profile *
weston_compositor_load_icc_file(struct weston_compositor *compositor,
const char *path);
#ifdef __cplusplus
}
#endif

View file

@ -32,6 +32,7 @@ extern "C" {
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#define WESTON_CONFIG_FILE_ENV_VAR "WESTON_CONFIG_FILE"
@ -107,6 +108,20 @@ int weston_config_next_section(struct weston_config *config,
uint32_t
weston_config_get_binding_modifier(struct weston_config *config, uint32_t default_mod);
/** Container for an array of strings. */
struct weston_string_array {
/** Length of \c array. */
size_t len;
/** Pointer to an array of strings. */
char **array;
};
void
weston_string_array_fini(struct weston_string_array *strarr);
struct weston_string_array
weston_parse_space_separated_list(const char *str);
#ifdef __cplusplus
}
#endif

View file

@ -43,6 +43,7 @@ extern "C" {
#include <libweston/matrix.h>
#include <libweston/zalloc.h>
#include <libweston/colorimetry.h>
struct weston_log_pacer {
/** This must be set to zero before first use */
@ -73,6 +74,12 @@ struct weston_point2d_device_normalized {
double y;
};
struct weston_commit_timing_target {
bool valid;
bool satisfied;
struct timespec time;
};
struct weston_compositor;
struct weston_surface;
struct weston_buffer;
@ -85,9 +92,6 @@ struct linux_dmabuf_buffer;
struct weston_recorder;
struct weston_pointer_constraint;
struct ro_anonymous_file;
struct weston_color_profile_param_builder;
struct weston_color_profile;
struct weston_color_transform;
struct pixel_format_info;
struct weston_output_capture_info;
struct weston_output_color_outcome;
@ -107,9 +111,13 @@ enum weston_keyboard_locks {
};
enum weston_led {
LED_NUM_LOCK = (1 << 0),
LED_CAPS_LOCK = (1 << 1),
LED_SCROLL_LOCK = (1 << 2),
WESTON_LED_NUM_LOCK = (1 << 0),
WESTON_LED_CAPS_LOCK = (1 << 1),
WESTON_LED_SCROLL_LOCK = (1 << 2),
#ifdef HAVE_COMPOSE_AND_KANA
WESTON_LED_COMPOSE = (1 << 3),
WESTON_LED_KANA = (1 << 4),
#endif
};
enum weston_mode_aspect_ratio {
@ -129,6 +137,17 @@ enum weston_surface_protection_mode {
WESTON_SURFACE_PROTECTION_MODE_ENFORCED
};
enum weston_output_color_effect_type {
WESTON_OUTPUT_COLOR_EFFECT_TYPE_INVERSION = 0,
WESTON_OUTPUT_COLOR_EFFECT_TYPE_CVD_CORRECTION,
};
enum weston_cvd_correction_type {
WESTON_CVD_CORRECTION_TYPE_DEUTERANOPIA = 0,
WESTON_CVD_CORRECTION_TYPE_PROTANOPIA,
WESTON_CVD_CORRECTION_TYPE_TRITANOPIA,
};
/** Possible mode of an output
*
* \ingroup output
@ -147,7 +166,6 @@ struct weston_animation {
void (*frame)(struct weston_animation *animation,
struct weston_output *output,
const struct timespec *time);
int frame_counter;
struct wl_list link;
};
@ -199,10 +217,12 @@ enum weston_hdcp_protection {
* \ingroup testharness
*/
struct weston_testsuite_quirks {
/** Force GL-renderer to do a full upload of wl_shm buffers. */
bool gl_force_full_upload;
/** Force GL/Vulkan-renderer to do a full upload of wl_shm buffers. */
bool force_full_upload;
/** Ensure GL shadow fb is used, and always repaint it fully. */
bool gl_force_full_redraw_of_shadow_fb;
/** Force GL-renderer to use the internal YUV->RGB shader */
bool gl_force_import_yuv_fallback;
/** Required enum weston_capability bit mask, otherwise skip run. */
uint32_t required_capabilities;
};
@ -225,248 +245,6 @@ struct weston_testsuite_data {
void *test_private_data;
};
/** Colorimetry mode for outputs and heads
*
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* Default (RGB) colorimetry differs from all the others in that the signal
* colorimetry is not defined here. It is defined by the video sink, and it
* may be described in e.g. EDID.
*/
enum weston_colorimetry_mode {
/** Invalid colorimetry mode, or none supported. */
WESTON_COLORIMETRY_MODE_NONE = 0,
/** Default (RGB) colorimetry, video sink dependant */
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
/** Rec. ITU-R BT.2020 RGB */
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
/** SMPTE ST 2113 DCI-P3 RGB D65 */
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
/** SMPTE ST 2113 DCI-P3 RGB Theater */
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
};
/** Bitmask of all defined colorimetry modes */
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
WESTON_COLORIMETRY_MODE_P3D65 | \
WESTON_COLORIMETRY_MODE_P3DCI | \
WESTON_COLORIMETRY_MODE_ICTCP))
/** EOTF mode for outputs and heads
*
* A list of EOTF modes for driving displays, defined by CTA-861-G for
* Dynamic Range and Mastering InfoFrame.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
*/
enum weston_eotf_mode {
/** Invalid EOTF mode, or none supported. */
WESTON_EOTF_MODE_NONE = 0,
/** Traditional gamma, SDR luminance range */
WESTON_EOTF_MODE_SDR = 0x01,
/** Traditional gamma, HDR luminance range */
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
/** Preceptual quantizer, SMPTE ST 2084 */
WESTON_EOTF_MODE_ST2084 = 0x04,
/** Hybrid log-gamma, ITU-R BT.2100 */
WESTON_EOTF_MODE_HLG = 0x08,
};
/** Bitmask of all defined EOTF modes */
#define WESTON_EOTF_MODE_ALL_MASK \
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
/** CIE 1931 xy chromaticity coordinates */
struct weston_CIExy {
float x;
float y;
};
/** Chromaticity coordinates and white point that defines the color gamut */
struct weston_color_gamut {
struct weston_CIExy primary[3]; /* RGB order */
struct weston_CIExy white_point;
};
/** Color primaries known by libweston */
enum weston_color_primaries {
WESTON_PRIMARIES_CICP_SRGB = 0,
WESTON_PRIMARIES_CICP_PAL_M,
WESTON_PRIMARIES_CICP_PAL,
WESTON_PRIMARIES_CICP_NTSC,
WESTON_PRIMARIES_CICP_GENERIC_FILM,
WESTON_PRIMARIES_CICP_BT2020,
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
WESTON_PRIMARIES_CICP_DCI_P3,
WESTON_PRIMARIES_CICP_DISPLAY_P3,
WESTON_PRIMARIES_ADOBE_RGB,
};
/** Transfer functions known by libweston */
enum weston_transfer_function {
WESTON_TF_LINEAR = 0,
WESTON_TF_GAMMA22,
WESTON_TF_GAMMA28,
WESTON_TF_SRGB,
WESTON_TF_EXT_SRGB,
WESTON_TF_BT709,
WESTON_TF_BT1361,
WESTON_TF_ST240,
WESTON_TF_ST428,
WESTON_TF_ST2084_PQ,
WESTON_TF_LOG_100,
WESTON_TF_LOG_316,
WESTON_TF_XVYCC,
WESTON_TF_HLG,
WESTON_TF_POWER,
};
/** Error codes that the color profile parameters functions may return. */
enum weston_color_profile_param_builder_error {
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TARGET_PRIMARIES,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
};
struct weston_color_profile_param_builder *
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
void
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
bool
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
bool
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *primaries);
bool
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
enum weston_color_primaries primaries);
bool
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
enum weston_transfer_function tf);
bool
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
float power_exponent);
bool
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *target_primaries);
bool
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
float min_luminance, float max_luminance);
bool
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
float maxFALL);
bool
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
float maxCLL);
struct weston_color_profile *
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
const char *name_part,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
enum weston_color_characteristics_groups {
/** weston_color_characteristics::primary is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
/** weston_color_characteristics::white is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
/** weston_color_characteristics::max_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
/** weston_color_characteristics::min_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
/** weston_color_characteristics::maxFALL is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
/** all valid bits */
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
};
/** Basic display color characteristics
*
* This is a simple description of a display or output (monitor) color
* characteristics. The parameters can be found in EDID, with caveats. They
* are particularly useful with HDR monitors.
*/
struct weston_color_characteristics {
/** Which fields are valid
*
* A bitmask of values from enum weston_color_characteristics_groups.
*/
uint32_t group_mask;
/* EOTF is tracked externally with enum weston_eotf_mode */
/** Chromaticities of the primaries */
struct weston_CIExy primary[3];
/** White point chromaticity */
struct weston_CIExy white;
/** Display's desired maximum content peak luminance, cd/m² */
float max_luminance;
/** Display's desired minimum content luminance, cd/m² */
float min_luminance;
/** Display's desired maximum frame-average light level, cd/m² */
float maxFALL;
};
/** Represents a head, usually a display connector
*
* \rst
@ -516,6 +294,10 @@ struct weston_head {
* When a client uses this request, we add the wl_resource we create to
* this list. */
struct wl_list cm_output_resource_list;
uint32_t supported_vrr_mode_mask;
uint32_t supported_color_format_mask;
};
enum weston_output_power_state {
@ -525,12 +307,63 @@ enum weston_output_power_state {
WESTON_OUTPUT_POWER_NORMAL
};
enum weston_paint_node_status {
WESTON_PAINT_NODE_CLEAN = 0,
WESTON_PAINT_NODE_OUTPUT_DIRTY = 1 << 0,
WESTON_PAINT_NODE_VIEW_DIRTY = 1 << 1,
WESTON_PAINT_NODE_VISIBILITY_DIRTY = 1 << 2,
WESTON_PAINT_NODE_PLANE_DIRTY = 1 << 3,
WESTON_PAINT_NODE_BUFFER_DIRTY = 1 << 4,
WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY = 1 << 5,
WESTON_PAINT_NODE_ALL_DIRTY = (1 << 6) - 1,
};
enum weston_vrr_mode {
/** No VRR */
WESTON_VRR_MODE_NONE = 0,
/** Game mode VRR */
WESTON_VRR_MODE_GAME = 1 << 0,
};
#define WESTON_VRR_MODE_ALL_MASK \
((uint32_t)(WESTON_VRR_MODE_GAME))
enum weston_color_format {
/** Driver assigned color format automatically */
WESTON_COLOR_FORMAT_AUTO = (1 << 0),
/** Force RGB color format */
WESTON_COLOR_FORMAT_RGB = (1 << 1),
/** Force YUV color format with 4:2:2 susampling */
WESTON_COLOR_FORMAT_YUV422 = (1 << 2),
/** Force YUV color format with no subsampling */
WESTON_COLOR_FORMAT_YUV444 = (1 << 3),
/** Force YUV color format with 4:2:0 subsampling */
WESTON_COLOR_FORMAT_YUV420 = (1 << 4),
};
/** Bitmask of all defined color formats */
#define WESTON_COLOR_FORMAT_ALL_MASK \
((uint32_t)(WESTON_COLOR_FORMAT_AUTO | WESTON_COLOR_FORMAT_RGB | \
WESTON_COLOR_FORMAT_YUV444 | WESTON_COLOR_FORMAT_YUV422 | \
WESTON_COLOR_FORMAT_YUV420))
struct weston_plane {
struct weston_compositor *compositor;
int32_t x, y;
struct wl_list link;
};
/** State of the repaint loop
*
* \ingroup output
*/
enum weston_repaint_status {
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
};
/** Content producer for heads
*
* \rst
@ -542,6 +375,8 @@ struct weston_output {
uint32_t id;
char *name;
void *shell_private;
struct weston_backend *backend;
/** Matches the lifetime from the user perspective */
@ -556,6 +391,9 @@ struct weston_output {
/* struct weston_paint_node::output_link */
struct wl_list paint_node_list;
/** Only valid during repaint: changes for this repaint */
enum weston_paint_node_status paint_node_changes;
/** From global to output buffer coordinates. */
struct weston_matrix matrix;
/** From output buffer to global coordinates. */
@ -565,6 +403,10 @@ struct weston_output {
struct weston_coord_global pos;
int32_t width, height;
uint64_t gpu_track_id;
uint64_t paint_track_id;
uint64_t presentation_track_id;
/** List of paint nodes in z-order, from top to bottom, maybe pruned
*
* struct weston_paint_node::z_order_link
@ -592,24 +434,34 @@ struct weston_output {
bool repaint_only_on_capture;
/** State of the repaint loop */
enum {
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
} repaint_status;
enum weston_repaint_status repaint_status;
/** If repaint_status is REPAINT_SCHEDULED, contains the time the
* next repaint should be run */
struct timespec next_repaint;
/** If repaint_statue is REPAINT_SCHEDULED, contains the time the
* next repaint should be displayed */
struct timespec next_present;
/** commit-timing protocol will set this for the closest requested
* presentation time from a surface on this output. It's only
* valid during weston_repaint_timer_arm. */
struct weston_commit_timing_target requested_present;
/** commit-timing protocol will set this when state containing
* a target time is applied. Weston will try to hit this time if
* VRR is in use.
*/
struct weston_commit_timing_target forced_present;
/** For cancelling the idle_repaint callback on output destruction. */
struct wl_event_source *idle_repaint_source;
struct wl_signal frame_signal;
struct wl_signal post_latch_signal;
struct wl_signal destroy_signal; /**< sent when disabled */
struct weston_coord_global move;
struct timespec frame_time; /* presentation timestamp */
uint32_t frame_flags; /* presentation flags */
uint64_t msc; /* media stream counter */
int disable_planes;
int destroying;
@ -658,13 +510,6 @@ struct weston_output {
void (*set_backlight)(struct weston_output *output, uint32_t value);
void (*set_dpms)(struct weston_output *output, enum dpms_enum level);
uint16_t gamma_size;
void (*set_gamma)(struct weston_output *output,
uint16_t size,
uint16_t *r,
uint16_t *g,
uint16_t *b);
bool enabled; /**< is in the output_list, not pending list */
struct weston_color_profile *color_profile;
@ -676,6 +521,8 @@ struct weston_output {
struct weston_output_color_outcome *color_outcome;
uint64_t color_outcome_serial;
struct weston_output_color_effect *color_effect;
int (*enable)(struct weston_output *output);
int (*disable)(struct weston_output *output);
@ -706,11 +553,32 @@ struct weston_output {
void (*detach_head)(struct weston_output *output,
struct weston_head *head);
/**
* Get the DRM formats supported by a compatible writeback connector.
*/
const struct weston_drm_format_array *(*get_writeback_formats)(struct weston_output *output);
/**
* When set, this output is a mirror-of another output. See
* mirror-of key in [output] section.
*/
struct weston_output *mirror_of;
enum weston_vrr_mode vrr_mode;
enum weston_color_format color_format;
/**
* Set by the shell to indicate there's some content for this
* output to display.
*/
bool ready;
/** Needs to rebuild the paint node z ordered list */
bool paint_node_list_needs_rebuild;
/** fifo_v1 - list of surfaces to clear next repaint */
struct wl_list fifo_barrier_surfaces;
};
enum weston_pointer_motion_mask {
@ -1053,6 +921,18 @@ struct weston_tablet {
const char *path;
};
struct weston_color_representation {
enum weston_alpha_mode alpha_mode;
enum weston_color_matrix_coef matrix_coefficients;
enum weston_color_quant_range quant_range;
enum weston_ycbcr_chroma_location chroma_location;
};
struct weston_color_representation_matrix {
struct weston_mat3f matrix;
struct weston_vec3f offset;
};
struct weston_coord_global
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
struct weston_pointer_motion_event *event);
@ -1223,6 +1103,10 @@ struct weston_xkb_info {
xkb_led_index_t num_led;
xkb_led_index_t caps_led;
xkb_led_index_t scroll_led;
#ifdef HAVE_COMPOSE_AND_KANA
xkb_led_index_t compose_led;
xkb_led_index_t kana_led;
#endif
};
struct weston_keyboard {
@ -1406,6 +1290,9 @@ enum weston_capability {
/* renderer supports color management operations */
WESTON_CAP_COLOR_OPS = 0x0040,
/* renderer supports color representation operations */
WESTON_CAP_COLOR_REP = 0x0080,
};
/* Configuration struct for a backend.
@ -1472,6 +1359,7 @@ struct weston_color_manager;
struct weston_dmabuf_feedback;
struct weston_dmabuf_feedback_format_table;
struct weston_renderer;
struct weston_content_update;
/** Main object, container-like structure which aggregates all other objects.
*
@ -1531,12 +1419,14 @@ struct weston_compositor {
struct wl_list debug_binding_list;
bool view_list_needs_rebuild;
int global_weston_surface_disambiguator; /* surface ids to avoid using PID-reuse */
uint32_t state;
struct wl_event_source *idle_source;
uint32_t idle_inhibit;
int idle_time; /* timeout, s */
struct wl_event_source *repaint_timer;
int repaint_timer_fd;
struct wl_event_source *repaint_timer_source;
const struct weston_pointer_grab_interface *default_pointer_grab;
@ -1592,6 +1482,9 @@ struct weston_compositor {
/* Whether to let the compositor run without any input device. */
bool require_input;
/* Ignore all libinput-based input devices */
bool disable_input;
/* Whether to load multiple backends. */
bool multi_backend;
@ -1615,6 +1508,7 @@ struct weston_compositor {
struct weston_log_scope *debug_scene;
struct weston_log_scope *timeline;
struct weston_log_scope *libseat_debug;
struct weston_log_filtered *advertised_log_scopes;
struct content_protection *content_protection;
@ -1626,6 +1520,34 @@ struct weston_compositor {
struct wl_global *weston_capture_v1;
struct wl_signal ask_auth;
} output_capture;
struct {
/** interval which we divide the amount of frames */
unsigned int frame_counter_interval;
/** fires with frame_counter_interval rate */
struct wl_event_source *frame_counter_timer;
} perf_surface_stats;
/* if set use this placeholder-color to use instead of the default
* grenadier one */
uint32_t placeholder_color;
bool no_xwm_decorations;
/**
* When set the compositor has latched content updates for the
* upcoming repaint, and no more updates may be applied until after
* that repaint occurs.
*/
bool latched;
struct wl_list transaction_queue_list; /* weston_transaction_queue::link */
/** commit_timing_v1 - target repaint time for content updates for
* surfaces with no output
*/
struct weston_commit_timing_target requested_repaint_fallback;
};
struct weston_solid_buffer_values {
@ -1774,7 +1696,6 @@ struct weston_view {
unsigned int click_to_activate_serial;
pixman_region32_t visible; /* Unoccluded region in global space */
float alpha; /* part of geometry, see below */
/* Surface geometry state, mutable.
@ -1838,11 +1759,16 @@ struct weston_view {
struct wl_listener output_destroy_listener;
/*
* A more complete representation of all outputs this surface is
* displayed on.
* A bitfield of outputs this view intersects - though it may not be
* visible on them.
*/
uint32_t output_mask;
/*
* A bitfield of outputs this view is visible (has unoccluded pixels) on.
*/
uint32_t output_visibility_mask;
bool is_mapped;
struct weston_log_pacer subsurface_parent_log_pacer;
};
@ -1867,11 +1793,11 @@ enum weston_surface_status {
};
struct weston_surface_state {
uint64_t flow_id;
enum weston_surface_status status;
/* wl_surface.attach */
struct weston_buffer *buffer;
struct wl_listener buffer_destroy_listener;
struct weston_buffer_reference buffer_ref;
struct weston_coord_surface buf_offset;
@ -1914,6 +1840,18 @@ struct weston_surface_state {
* color_management_surface_v1_interface.unset_image_description */
struct weston_color_profile *color_profile;
const struct weston_render_intent_info *render_intent;
/* wp_color_representation_surface_v1.set_alpha_mode */
/* wp_color_representation_surface_v1.set_coefficients_and_range */
/* wp_color_representation_surface_v1.set_chroma_location */
struct weston_color_representation color_representation;
/* wp_fifo_v1 */
bool fifo_barrier;
bool fifo_wait;
/* commit_timing_v1 */
struct weston_commit_timing_target update_time;
};
struct weston_surface_activation_data {
@ -2043,6 +1981,7 @@ struct weston_surface {
bool is_mapped, is_unmapping, is_mapping;
bool is_opaque;
uint32_t s_id;
/* An list of per seat pointer constraints. */
struct wl_list pointer_constraints;
@ -2068,8 +2007,41 @@ struct weston_surface {
*
* When a client uses this request, we add the wl_resource we create to
* this list. */
struct wl_list cm_feedback_surface_resource_list;
struct wl_list cm_surface_feedback_resource_list;
struct wl_resource *cm_surface;
struct wl_resource *color_representation_resource;
struct weston_color_representation color_representation;
uint64_t damage_track_id;
uint64_t flow_id;
/** increments for each wl_surface::commit,
* reset after each frame counter interval */
unsigned int frame_commit_counter;
/** increments after an output repaint when parsing paint node list;
* reset as frame_commit_counter */
unsigned int painted_frame_counter;
/** computed after each frame_counter_interval */
float frame_commit_fps_counter;
float painted_frame_fps_counter;
/** Visibility won't be calculated until repaint, but we use this to
* track whether we can safely use the last repaint's visibility
* calculations when considering this surface's visibility.
*/
uint32_t output_visibility_dirty_mask;
/** fifo_v1 */
struct weston_fifo *fifo;
bool fifo_barrier; /* Cleared after display */
struct wl_list fifo_barrier_link; /* output::fifo_barrier_surfaces */
/** commit_timing_v1 */
struct weston_commit_timer *commit_timer;
};
struct weston_subsurface {
@ -2090,14 +2062,10 @@ struct weston_subsurface {
bool changed;
} position;
int has_cached_data;
struct weston_surface_state cached;
struct weston_buffer_reference cached_buffer_ref;
/* Sub-surface has been reordered; need to apply damage. */
bool reordered;
int synchronized;
bool synchronized;
bool effectively_synchronized;
/* Used for constructing the view tree */
struct wl_list unused_views;
@ -2186,6 +2154,10 @@ void
weston_view_move_to_layer(struct weston_view *view,
struct weston_layer_entry *layer);
void
weston_view_move_before_layer_entry(struct weston_view *view,
struct weston_layer_entry *layer);
void
weston_layer_init(struct weston_layer *layer,
struct weston_compositor *compositor);
@ -2217,8 +2189,6 @@ void
weston_output_schedule_repaint_reset(struct weston_output *output);
void
weston_output_schedule_repaint_restart(struct weston_output *output);
enum weston_compositor_backend
weston_get_backend_type(struct weston_backend *backend);
void
weston_compositor_schedule_repaint(struct weston_compositor *compositor);
void
@ -2387,12 +2357,6 @@ void
weston_surface_set_size(struct weston_surface *surface,
int32_t width, int32_t height);
void
weston_surface_damage(struct weston_surface *surface);
void
weston_view_damage_below(struct weston_view *view);
void
weston_view_unmap(struct weston_view *view);
@ -2469,12 +2433,15 @@ enum weston_renderer_type {
WESTON_RENDERER_NOOP = 1,
WESTON_RENDERER_PIXMAN = 2,
WESTON_RENDERER_GL = 3,
WESTON_RENDERER_VULKAN = 4,
};
struct weston_backend *
weston_compositor_load_backend(struct weston_compositor *compositor,
enum weston_compositor_backend backend,
struct weston_backend_config *config_base);
enum weston_compositor_backend
weston_get_backend_type(struct weston_backend *backend);
void
weston_compositor_exit(struct weston_compositor *ec);
void *
@ -2699,6 +2666,13 @@ void
weston_output_set_transform(struct weston_output *output,
uint32_t transform);
void
weston_output_color_effect_inversion(struct weston_output *output);
void
weston_output_color_effect_cvd_correction(struct weston_output *output,
enum weston_cvd_correction_type type);
bool
weston_output_set_color_profile(struct weston_output *output,
struct weston_color_profile *cprof);
@ -2785,19 +2759,6 @@ void
weston_timeline_refresh_subscription_objects(struct weston_compositor *wc,
void *object);
struct weston_color_profile *
weston_color_profile_ref(struct weston_color_profile *cprof);
void
weston_color_profile_unref(struct weston_color_profile *cprof);
const char *
weston_color_profile_get_description(struct weston_color_profile *cprof);
struct weston_color_profile *
weston_compositor_load_icc_file(struct weston_compositor *compositor,
const char *path);
/** Describes who is trying to capture and which output */
struct weston_output_capture_client {
struct wl_client *client;
@ -2834,6 +2795,33 @@ int
weston_output_mode_set_native(struct weston_output *output,
struct weston_mode *mode,
int32_t scale);
int
weston_output_set_vrr_mode(struct weston_output *output,
enum weston_vrr_mode vrr_mode);
uint32_t
weston_output_get_supported_vrr_modes(struct weston_output *output);
const struct weston_drm_format_array *
weston_output_get_writeback_formats(struct weston_output *output);
void
weston_compositor_arm_surface_counter_fps(struct weston_compositor *ec);
void
weston_compositor_disarm_surface_counter_fps(struct weston_compositor *ec);
void
weston_output_set_color_format(struct weston_output *output,
enum weston_color_format color_format);
uint32_t
weston_output_get_supported_color_formats(struct weston_output *output);
void
weston_output_set_ready(struct weston_output *output);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,228 @@
/*
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <math.h>
#include <libweston/linalg-types.h>
/* ================= 3-vectors and 3x3 matrices ============== */
/** Construct a column vector from elements */
#define WESTON_VEC3F(x, y, z) ((struct weston_vec3f){ .el = { (x), (y), (z) }})
/** Construct the [0, 0, 0]^T vector */
#define WESTON_VEC3F_ZERO ((struct weston_vec3f){ .el = {}})
/** Construct matrix from elements a{row}{column} */
#define WESTON_MAT3F(a00, a01, a02, \
a10, a11, a12, \
a20, a21, a22) \
((struct weston_mat3f){ .colmaj = { \
a00, a10, a20, \
a01, a11, a21, \
a02, a12, a22, \
}})
/** Construct the identity 3x3 matrix */
#define WESTON_MAT3F_IDENTITY \
((struct weston_mat3f){ .colmaj = { \
1.0f, 0.0f, 0.0f, \
0.0f, 1.0f, 0.0f, \
0.0f, 0.0f, 1.0f, \
}})
/** Construct a diagonal matrix */
static inline struct weston_mat3f
weston_m3f_diag(struct weston_vec3f d)
{
return WESTON_MAT3F(
d.x, 0.0f, 0.0f,
0.0f, d.y, 0.0f,
0.0f, 0.0f, d.z);
}
/** Copy the top-left 3x3 from 4x4 */
static inline struct weston_mat3f
weston_m3f_from_m4f_xyz(struct weston_mat4f M)
{
return WESTON_MAT3F(
M.col[0].el[0], M.col[1].el[0], M.col[2].el[0],
M.col[0].el[1], M.col[1].el[1], M.col[2].el[1],
M.col[0].el[2], M.col[1].el[2], M.col[2].el[2]
);
}
/** Drop w from vec4f */
static inline struct weston_vec3f
weston_v3f_from_v4f_xyz(struct weston_vec4f v)
{
return WESTON_VEC3F(v.x, v.y, v.z);
}
/** 3-vector dot product */
static inline float
weston_v3f_dot_v3f(struct weston_vec3f a, struct weston_vec3f b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
/**
* Convert an array of vec3f into planar format
*
* Takes an array of RGB triplets and converts it into a planar format where all R
* values come first, then all G values, then all B values.
*
* \param planar The destination array for planar data, must have space for 3 * len floats
* \param arr Array of RGB triplets as vec3f structs
* \param len Number of RGB triplets in the array
*/
static inline void
weston_v3f_array_to_planar(float *planar, const struct weston_vec3f *arr, size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
planar[i ] = arr[i].r;
planar[i + len] = arr[i].g;
planar[i + 2 * len] = arr[i].b;
}
}
/** Clamp each element to the range [a, b], replacing NaN with a. */
static inline struct weston_vec3f
weston_v3f_clamp(struct weston_vec3f v, float a, float b)
{
return WESTON_VEC3F(v.x >= a ? (v.x <= b ? v.x : b) : a,
v.y >= a ? (v.y <= b ? v.y : b) : a,
v.z >= a ? (v.z <= b ? v.z : b) : a);
}
/**
* Matrix infinity-norm
*
* http://www.netlib.org/lapack/lug/node75.html
*/
static inline float
weston_m3f_inf_norm(struct weston_mat3f M)
{
unsigned row;
double infnorm = -1.0;
for (row = 0; row < 3; row++) {
unsigned col;
double sum = 0.0;
for (col = 0; col < 3; col++)
sum += fabsf(M.col[col].el[row]);
if (infnorm < sum)
infnorm = sum;
}
return infnorm;
}
/** Transpose 3x3 matrix */
static inline struct weston_mat3f
weston_m3f_transpose(struct weston_mat3f M)
{
struct weston_mat3f R;
unsigned i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
R.col[j].el[i] = M.col[i].el[j];
return R;
}
/** Matrix-vector multiplication A * b */
static inline struct weston_vec3f
weston_m3f_mul_v3f(struct weston_mat3f A, struct weston_vec3f b)
{
struct weston_vec3f result;
unsigned r;
for (r = 0; r < 3; r++) {
struct weston_vec3f row =
WESTON_VEC3F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r]);
result.el[r] = weston_v3f_dot_v3f(row, b);
}
return result;
}
/** Matrix multiplication A * B */
static inline struct weston_mat3f
weston_m3f_mul_m3f(struct weston_mat3f A, struct weston_mat3f B)
{
struct weston_mat3f result;
unsigned c;
for (c = 0; c < 3; c++)
result.col[c] = weston_m3f_mul_v3f(A, B.col[c]);
return result;
}
/** Element-wise matrix subtraction A - B */
static inline struct weston_mat3f
weston_m3f_sub_m3f(struct weston_mat3f A, struct weston_mat3f B)
{
struct weston_mat3f R;
unsigned i;
for (i = 0; i < 3 * 3; i++)
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
return R;
}
/** Element-wise scalar multiplication */
static inline struct weston_mat3f
weston_m3f_mul_scalar(struct weston_mat3f M, float scalar)
{
struct weston_mat3f R;
unsigned i;
for (i = 0; i < 3 * 3; i++)
R.colmaj[i] = scalar * M.colmaj[i];
return R;
}
bool
weston_m3f_invert(struct weston_mat3f *out, struct weston_mat3f M);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,206 @@
/*
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <math.h>
#include <libweston/linalg-types.h>
/* ================= 4-vectors and 4x4 matrices ============== */
/** Construct a column vector from elements */
#define WESTON_VEC4F(x, y, z, w) ((struct weston_vec4f){ .el = { (x), (y), (z), (w) }})
/** Construct the [0, 0, 0, 0]^T vector */
#define WESTON_VEC4F_ZERO ((struct weston_vec4f){ .el = {}})
/** Construct matrix from elements a{row}{column} */
#define WESTON_MAT4F(a00, a01, a02, a03, \
a10, a11, a12, a13, \
a20, a21, a22, a23, \
a30, a31, a32, a33) \
((struct weston_mat4f){ .colmaj = { \
a00, a10, a20, a30, \
a01, a11, a21, a31, \
a02, a12, a22, a32, \
a03, a13, a23, a33, \
}})
/** Construct the identity 4x4 matrix */
#define WESTON_MAT4F_IDENTITY \
((struct weston_mat4f){ .colmaj = { \
1.0f, 0.0f, 0.0f, 0.0f, \
0.0f, 1.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 1.0f, 0.0f, \
0.0f, 0.0f, 0.0f, 1.0f, \
}})
/** Construct a translation matrix */
static inline struct weston_mat4f
weston_m4f_translation(float tx, float ty, float tz)
{
return WESTON_MAT4F(
1.0f, 0.0f, 0.0f, tx,
0.0f, 1.0f, 0.0f, ty,
0.0f, 0.0f, 1.0f, tz,
0.0f, 0.0f, 0.0f, 1.0f);
}
/** Construct a scaling matrix */
static inline struct weston_mat4f
weston_m4f_scaling(float sx, float sy, float sz)
{
return WESTON_MAT4F(
sx, 0.0f, 0.0f, 0.0f,
0.0f, sy, 0.0f, 0.0f,
0.0f, 0.0f, sz, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
/** Construct a 2D x-y rotation matrix
*
* \param cos_th Cosine of the counter-clockwise angle.
* \param sin_th Sine of the counter-clockwise angle.
*/
static inline struct weston_mat4f
weston_m4f_rotation_xy(float cos_th, float sin_th)
{
return WESTON_MAT4F(
cos_th, -sin_th, 0.0f, 0.0f,
sin_th, cos_th, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
static inline struct weston_mat4f
weston_m4f_from_m3f_v3f(struct weston_mat3f R, struct weston_vec3f t)
{
return WESTON_MAT4F(
R.col[0].el[0], R.col[1].el[0], R.col[2].el[0], t.el[0],
R.col[0].el[1], R.col[1].el[1], R.col[2].el[1], t.el[1],
R.col[0].el[2], R.col[1].el[2], R.col[2].el[2], t.el[2],
0.0f, 0.0f, 0.0f, 1.0f
);
}
/** 4-vector dot product */
static inline float
weston_v4f_dot_v4f(struct weston_vec4f a, struct weston_vec4f b)
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
/**
* Matrix infinity-norm
*
* http://www.netlib.org/lapack/lug/node75.html
*/
static inline float
weston_m4f_inf_norm(struct weston_mat4f M)
{
unsigned row;
double infnorm = -1.0;
for (row = 0; row < 4; row++) {
unsigned col;
double sum = 0.0;
for (col = 0; col < 4; col++)
sum += fabsf(M.col[col].el[row]);
if (infnorm < sum)
infnorm = sum;
}
return infnorm;
}
/** Transpose 4x4 matrix */
static inline struct weston_mat4f
weston_m4f_transpose(struct weston_mat4f M)
{
struct weston_mat4f R;
unsigned i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
R.col[j].el[i] = M.col[i].el[j];
return R;
}
/** Matrix-vector multiplication A * b */
static inline struct weston_vec4f
weston_m4f_mul_v4f(struct weston_mat4f A, struct weston_vec4f b)
{
struct weston_vec4f result;
unsigned r;
for (r = 0; r < 4; r++) {
struct weston_vec4f row =
WESTON_VEC4F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r], A.col[3].el[r]);
result.el[r] = weston_v4f_dot_v4f(row, b);
}
return result;
}
/** Matrix multiplication A * B */
static inline struct weston_mat4f
weston_m4f_mul_m4f(struct weston_mat4f A, struct weston_mat4f B)
{
struct weston_mat4f result;
unsigned c;
for (c = 0; c < 4; c++)
result.col[c] = weston_m4f_mul_v4f(A, B.col[c]);
return result;
}
/** Element-wise matrix subtraction A - B */
static inline struct weston_mat4f
weston_m4f_sub_m4f(struct weston_mat4f A, struct weston_mat4f B)
{
struct weston_mat4f R;
unsigned i;
for (i = 0; i < 4 * 4; i++)
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
return R;
}
bool
weston_m4f_invert(struct weston_mat4f *out, struct weston_mat4f M);
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -23,36 +23,54 @@
* SOFTWARE.
*/
#include "config.h"
#pragma once
/*
* Common main() for test programs.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
/** Column 3-vector */
struct weston_vec3f {
union {
float el[3];
struct {
float x, y, z;
};
struct {
float r, g, b;
};
struct {
float Y, Cb, Cr;
};
};
};
#include "zunitc/zunitc.h"
/** 3x3 matrix, column-major */
struct weston_mat3f {
union {
struct weston_vec3f col[3];
float colmaj[3 * 3];
};
};
int
main(int argc, char* argv[])
{
bool helped = false;
int rc = zuc_initialize(&argc, argv, &helped);
/** Column 4-vector */
struct weston_vec4f {
union {
float el[4];
struct {
float x, y, z, w;
};
};
};
if ((rc == EXIT_SUCCESS) && !helped) {
/* Stop if any unrecognized parameters were encountered. */
if (argc > 1) {
printf("%s: unrecognized option '%s'\n",
argv[0], argv[1]);
printf("Try '%s --help' for more information.\n",
argv[0]);
rc = EXIT_FAILURE;
} else {
rc = ZUC_RUN_TESTS();
}
}
/** 4x4 matrix, column-major */
struct weston_mat4f {
union {
struct weston_vec4f col[4];
float colmaj[4 * 4];
};
};
zuc_cleanup();
return rc;
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2015 Samsung Electronics Co., Ltd
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -23,16 +23,16 @@
* SOFTWARE.
*/
#ifndef ZUC_BASE_LOGGER_H
#define ZUC_BASE_LOGGER_H
#pragma once
struct zuc_event_listener;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Creates a new logger that outputs data to console in the default
* format.
*/
struct zuc_event_listener *
zuc_base_logger_create(void);
#include <libweston/linalg-types.h>
#include <libweston/linalg-3.h>
#include <libweston/linalg-4.h>
#endif /* ZUC_BASE_LOGGER_H */
#ifdef __cplusplus
}
#endif

View file

@ -31,6 +31,7 @@
#include <stdbool.h>
#include <wayland-server-protocol.h>
#include <libweston/linalg-types.h>
#ifdef __cplusplus
extern "C" {
@ -44,12 +45,12 @@ enum weston_matrix_transform_type {
};
struct weston_matrix {
float d[16];
struct weston_mat4f M;
unsigned int type;
};
struct weston_vector {
float f[4];
struct weston_vec4f v;
};
/** Arbitrary coordinates in any space */
@ -209,7 +210,7 @@ weston_coord_surface_sub(struct weston_coord_surface a,
static inline struct weston_coord __attribute__ ((warn_unused_result))
weston_coord_truncate(struct weston_coord in)
{
return (struct weston_coord){ (int)in.x, (int)in.y };
return (struct weston_coord){ (double)(int) in.x, (double)(int) in.y };
}
static inline struct weston_coord_surface __attribute__ ((warn_unused_result))

View file

@ -1,6 +1,11 @@
install_headers(
'colorimetry.h',
'config-parser.h',
'libweston.h',
'linalg.h',
'linalg-3.h',
'linalg-4.h',
'linalg-types.h',
'desktop.h',
'matrix.h',
'plugin-registry.h',

View file

@ -75,6 +75,13 @@ weston_shell_utils_curtain_destroy(struct weston_curtain *curtain);
enum weston_layer_position
weston_shell_utils_view_get_layer_position(struct weston_view *view);
void
weston_output_set_shell_private(struct weston_output *output,
void *private_data);
void *
weston_output_get_shell_private(struct weston_output *output);
#ifdef __cplusplus
}
#endif

View file

@ -146,6 +146,12 @@ struct weston_log_scope *
weston_log_scopes_iterate(struct weston_log_context *log_ctx,
struct weston_log_scope *nscope);
void
weston_add_scope_to_advertised_list(struct weston_log_context *ctx,
const char *name);
bool
weston_log_scope_to_be_advertised(struct weston_log_context *ctx, const char *name);
#ifdef __cplusplus
}
#endif

View file

@ -32,6 +32,10 @@ extern "C" {
#include <libweston/plugin-registry.h>
#ifndef ARRAY_LENGTH
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
#endif
struct weston_compositor;
struct weston_output;
@ -99,7 +103,8 @@ weston_windowed_output_get_api(struct weston_compositor *compositor,
if (type >= ARRAY_LENGTH(api_names))
return NULL;
return weston_plugin_api_get(compositor, api_names[type],
return (const struct weston_windowed_output_api *)
weston_plugin_api_get(compositor, api_names[type],
sizeof(struct weston_windowed_output_api));
}

View file

@ -1455,6 +1455,8 @@ ivi_hmi_controller_UI_ready(struct wl_client *client,
hmi_ctrl->interface->commit_changes();
ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
hmi_ctrl->interface->screen_ready(hmi_ctrl->workspace_background_output);
hmi_ctrl->is_initialized = 1;
}

View file

@ -219,6 +219,17 @@ struct ivi_layout_interface {
*/
void (*add_listener_configure_desktop_surface)(struct wl_listener *listener);
/**
* \brief add a listener for desktop_surface ping timeout notification
*
* When a desktop_client fails to respond to compositor pings within
* the configured timeout period, this signal is emitted to registered
* listeners. The void* data argument will contain a pointer to the
* weston_desktop_client associated with the unresponsive surface.
*/
void (*add_listener_desktop_surface_ping_timeout)(struct wl_listener *listener);
/**
* \brief Get all ivi_surfaces which are currently registered and managed
* by the services
@ -636,6 +647,12 @@ struct ivi_layout_interface {
* See add_listener_show_input_panel for more details.
*/
void (*add_listener_update_input_panel)(struct wl_listener *listener);
/**
* \brief Set weston_output ready to be painted
*/
void (*screen_ready)(struct weston_output *output);
};
static inline const struct ivi_layout_interface *

View file

@ -115,6 +115,7 @@ struct ivi_layout {
struct wl_signal removed;
struct wl_signal configure_changed;
struct wl_signal configure_desktop_changed;
struct wl_signal ping_timeout;
} surface_notification;
struct {

View file

@ -46,6 +46,9 @@ void
ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height);
void
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client);
struct ivi_layout_surface*
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
struct weston_desktop_surface *surface);

View file

@ -63,6 +63,7 @@
#include "frontend/weston.h"
#include <libweston/libweston.h>
#include <libweston/shell-utils.h>
#include "ivi-shell.h"
#include "ivi-layout-export.h"
#include "ivi-layout-private.h"
@ -284,7 +285,7 @@ destroy_screen(struct ivi_layout_screen *iviscrn)
}
static void
output_destroyed_event(struct wl_listener *listener, void *data)
output_destroy_iviscreen(struct wl_listener *listener, void *data)
{
struct weston_output *destroyed_output = data;
struct ivi_layout_screen *iviscrn;
@ -295,8 +296,8 @@ output_destroyed_event(struct wl_listener *listener, void *data)
}
static void
add_screen(struct weston_output *output)
static struct ivi_layout_screen *
create_screen(struct weston_output *output)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn = NULL;
@ -309,26 +310,24 @@ add_screen(struct weston_output *output)
wl_list_init(&iviscrn->pending.layer_list);
wl_list_init(&iviscrn->order.layer_list);
wl_list_insert(&layout->screen_list, &iviscrn->link);
return iviscrn;
}
static void
output_created_event(struct wl_listener *listener, void *data)
create_ivi_screen(struct ivi_layout *layout, struct weston_output *output)
{
struct weston_output *created_output = data;
add_screen(created_output);
create_screen(output);
}
/**
* Internal API to initialize ivi_screens found from output_list of weston_compositor.
* Called by ivi_layout_init.
*/
static void
create_screen(struct weston_compositor *ec)
output_create_iviscreen(struct wl_listener *listener, void *data)
{
struct weston_output *output = NULL;
struct ivi_layout *layout =
container_of(listener, struct ivi_layout, output_created);
struct weston_output *output = data;
wl_list_for_each(output, &ec->output_list, link)
add_screen(output);
create_ivi_screen(layout, output);
}
/**
@ -463,33 +462,33 @@ calc_inverse_matrix_transform(const struct weston_matrix *matrix,
}
/* The vectors and matrices involved will always produce f[3] == 1.0. */
top_left.f[0] = rect_input->x;
top_left.f[1] = rect_input->y;
top_left.f[2] = 0.0f;
top_left.f[3] = 1.0f;
top_left.v.el[0] = rect_input->x;
top_left.v.el[1] = rect_input->y;
top_left.v.el[2] = 0.0f;
top_left.v.el[3] = 1.0f;
bottom_right.f[0] = rect_input->x + rect_input->width;
bottom_right.f[1] = rect_input->y + rect_input->height;
bottom_right.f[2] = 0.0f;
bottom_right.f[3] = 1.0f;
bottom_right.v.el[0] = rect_input->x + rect_input->width;
bottom_right.v.el[1] = rect_input->y + rect_input->height;
bottom_right.v.el[2] = 0.0f;
bottom_right.v.el[3] = 1.0f;
weston_matrix_transform(&m, &top_left);
weston_matrix_transform(&m, &bottom_right);
if (top_left.f[0] < bottom_right.f[0]) {
rect_output->x = floorf(top_left.f[0]);
rect_output->width = ceilf(bottom_right.f[0] - rect_output->x);
if (top_left.v.el[0] < bottom_right.v.el[0]) {
rect_output->x = floor(top_left.v.el[0]);
rect_output->width = ceil(bottom_right.v.el[0] - rect_output->x);
} else {
rect_output->x = floorf(bottom_right.f[0]);
rect_output->width = ceilf(top_left.f[0] - rect_output->x);
rect_output->x = floor(bottom_right.v.el[0]);
rect_output->width = ceil(top_left.v.el[0] - rect_output->x);
}
if (top_left.f[1] < bottom_right.f[1]) {
rect_output->y = floorf(top_left.f[1]);
rect_output->height = ceilf(bottom_right.f[1] - rect_output->y);
if (top_left.v.el[1] < bottom_right.v.el[1]) {
rect_output->y = floor(top_left.v.el[1]);
rect_output->height = ceil(bottom_right.v.el[1] - rect_output->y);
} else {
rect_output->y = floorf(bottom_right.f[1]);
rect_output->height = ceilf(top_left.f[1] - rect_output->y);
rect_output->y = floor(bottom_right.v.el[1]);
rect_output->height = ceil(top_left.v.el[1] - rect_output->y);
}
ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
@ -988,6 +987,16 @@ ivi_layout_add_listener_configure_desktop_surface(struct wl_listener *listener)
wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener);
}
static void
ivi_layout_add_listener_desktop_surface_ping_timeout(struct wl_listener *listener)
{
struct ivi_layout *layout = get_instance();
assert(listener);
wl_signal_add(&layout->surface_notification.ping_timeout, listener);
}
static int32_t
ivi_layout_shell_add_destroy_listener_once(struct wl_listener *listener, wl_notify_func_t destroy_handler)
{
@ -1564,6 +1573,12 @@ ivi_layout_screen_set_render_order(struct weston_output *output,
iviscrn->order.dirty = 1;
}
static void
ivi_layout_set_screen_ready(struct weston_output *output)
{
weston_output_set_ready(output);
}
/**
* This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
* The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
@ -1912,6 +1927,14 @@ ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
ivisurf);
}
void
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client)
{
struct ivi_layout *layout = get_instance();
wl_signal_emit_mutable(&layout->surface_notification.ping_timeout, client);
}
struct ivi_layout_surface*
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
struct weston_desktop_surface *surface)
@ -2098,6 +2121,7 @@ void
ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
{
struct ivi_layout *layout = get_instance();
struct weston_output *output;
layout->shell = shell;
@ -2113,6 +2137,7 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
wl_signal_init(&layout->surface_notification.removed);
wl_signal_init(&layout->surface_notification.configure_changed);
wl_signal_init(&layout->surface_notification.configure_desktop_changed);
wl_signal_init(&layout->surface_notification.ping_timeout);
wl_signal_init(&layout->input_panel_notification.configure_changed);
wl_signal_init(&layout->input_panel_notification.show);
@ -2126,12 +2151,13 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
weston_layer_set_position(&layout->layout_layer,
WESTON_LAYER_POSITION_NORMAL);
create_screen(ec);
layout->output_created.notify = output_created_event;
layout->output_created.notify = output_create_iviscreen;
wl_signal_add(&ec->output_created_signal, &layout->output_created);
layout->output_destroyed.notify = output_destroyed_event;
wl_list_for_each(output, &ec->output_list, link)
create_ivi_screen(layout, output);
layout->output_destroyed.notify = output_destroy_iviscreen;
wl_signal_add(&ec->output_destroyed_signal, &layout->output_destroyed);
layout->transitions = ivi_layout_transition_set_create(ec);
@ -2146,6 +2172,10 @@ void
ivi_layout_fini(void)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn, *iviscrn_tmp;
wl_list_for_each_safe(iviscrn, iviscrn_tmp, &layout->screen_list, link)
destroy_screen(iviscrn);
weston_layer_fini(&layout->layout_layer);
@ -2168,6 +2198,7 @@ static struct ivi_layout_interface ivi_layout_interface = {
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
.add_listener_desktop_surface_ping_timeout = ivi_layout_add_listener_desktop_surface_ping_timeout,
.get_surface = shell_get_ivi_layout_surface,
.get_surfaces = ivi_layout_get_surfaces,
.get_id_of_surface = ivi_layout_get_id_of_surface,
@ -2216,6 +2247,7 @@ static struct ivi_layout_interface ivi_layout_interface = {
.screen_add_layer = ivi_layout_screen_add_layer,
.screen_remove_layer = ivi_layout_screen_remove_layer,
.screen_set_render_order = ivi_layout_screen_set_render_order,
.screen_ready = ivi_layout_set_screen_ready,
/**
* animation

View file

@ -51,6 +51,7 @@
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "frontend/weston.h"
#include <libweston/shell-utils.h>
/* Representation of ivi_surface protocol object. */
struct ivi_shell_surface
@ -214,7 +215,7 @@ ivi_shell_surface_get_label(struct weston_surface *surface,
{
struct ivi_shell_surface *shell_surf = get_ivi_shell_surface(surface);
return snprintf(buf, len, "ivi-surface %#x", shell_surf->id_surface);
return snprintf(buf, len, "ivi-surface %u", shell_surf->id_surface);
}
static void
@ -622,7 +623,7 @@ static void
desktop_surface_ping_timeout(struct weston_desktop_client *client,
void *user_data)
{
/* Not supported */
ivi_layout_desktop_surface_ping_timeout(client);
}
static void
@ -646,6 +647,8 @@ desktop_surface_added(struct weston_desktop_surface *surface,
ivisurf = xzalloc(sizeof *ivisurf);
weston_surface_set_label_func(weston_surf, weston_shell_utils_surface_get_label);
ivisurf->shell = shell;
ivisurf->id_surface = IVI_INVALID_ID;

View file

@ -96,3 +96,9 @@ workspace-id=3
icon-id=4010
icon=@westondatadir@/icon_ivi_smoke.png
path=@bindir@/weston-smoke
[ivi-launcher]
workspace-id=3
icon-id=4011
icon=@westondatadir@/icon_ivi_simple-egl-vertical.png
command=@bindir@/weston-simple-egl -v

View file

@ -137,7 +137,7 @@ xwayland_get_xwayland_name(struct kiosk_shell_surface *shsurf, enum window_atom_
static void
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
struct weston_output *output);
struct kiosk_shell_output *shoutput);
static void
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *parent);
@ -147,9 +147,6 @@ kiosk_shell_output_set_active_surface_tree(struct kiosk_shell_output *shoutput,
static void
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
struct kiosk_shell_surface *shroot);
static struct kiosk_shell_output *
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
struct weston_output *output);
static void
kiosk_shell_surface_notify_parent_destroy(struct wl_listener *listener, void *data)
@ -183,7 +180,7 @@ kiosk_shell_surface_get_parent_root(struct kiosk_shell_surface *shsurf)
static bool
kiosk_shell_output_has_app_id(char *config_app_ids, const char *app_id);
static struct weston_output *
static struct kiosk_shell_output *
kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *shsurf)
{
struct kiosk_shell_output *shoutput;
@ -208,7 +205,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
if (found_wm_name && found_wm_class) {
shsurf->appid_output_assigned = true;
return shoutput->output;
return shoutput;
}
}
}
@ -219,7 +216,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_name_app_ids,
wm_name)) {
shsurf->appid_output_assigned = true;
return shoutput->output;
return shoutput;
}
}
}
@ -229,7 +226,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_class_app_ids,
wm_class)) {
shsurf->appid_output_assigned = true;
return shoutput->output;
return shoutput;
}
}
}
@ -237,7 +234,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
return NULL;
}
static struct weston_output *
static struct kiosk_shell_output *
kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
{
struct weston_output *output;
@ -255,14 +252,14 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
wl_list_for_each(shoutput, &shsurf->shell->output_list, link) {
if (kiosk_shell_output_has_app_id(shoutput->app_ids, app_id)) {
shsurf->appid_output_assigned = true;
return shoutput->output;
return shoutput;
}
}
}
output = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
if (output)
return output;
shoutput = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
if (shoutput)
return shoutput;
/* Group all related windows in the same output. */
root = kiosk_shell_surface_get_parent_root(shsurf);
@ -271,20 +268,20 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
output = weston_shell_utils_get_focused_output(shsurf->shell->compositor);
if (output)
return output;
return weston_output_get_shell_private(output);
output = weston_shell_utils_get_default_output(shsurf->shell->compositor);
if (output)
return output;
return weston_output_get_shell_private(output);
return NULL;
}
static void
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
struct weston_output *output)
struct kiosk_shell_output *shoutput)
{
shsurf->output = output;
shsurf->output = shoutput;
if (shsurf->output_destroy_listener.notify) {
wl_list_remove(&shsurf->output_destroy_listener.link);
@ -296,39 +293,39 @@ kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
shsurf->output_destroy_listener.notify =
kiosk_shell_surface_notify_output_destroy;
wl_signal_add(&shsurf->output->destroy_signal,
wl_signal_add(&shsurf->output->output->destroy_signal,
&shsurf->output_destroy_listener);
}
static void
kiosk_shell_surface_set_fullscreen(struct kiosk_shell_surface *shsurf,
struct weston_output *output)
struct kiosk_shell_output *shoutput)
{
if (!output)
output = kiosk_shell_surface_find_best_output(shsurf);
if (!shoutput)
shoutput = kiosk_shell_surface_find_best_output(shsurf);
kiosk_shell_surface_set_output(shsurf, output);
kiosk_shell_surface_set_output(shsurf, shoutput);
weston_desktop_surface_set_fullscreen(shsurf->desktop_surface, true);
if (shsurf->output)
weston_desktop_surface_set_size(shsurf->desktop_surface,
shsurf->output->width,
shsurf->output->height);
shsurf->output->output->width,
shsurf->output->output->height);
}
static void
kiosk_shell_surface_set_maximized(struct kiosk_shell_surface *shsurf)
{
struct weston_output *output =
struct kiosk_shell_output *shoutput =
kiosk_shell_surface_find_best_output(shsurf);
kiosk_shell_surface_set_output(shsurf, output);
kiosk_shell_surface_set_output(shsurf, shoutput);
weston_desktop_surface_set_maximized(shsurf->desktop_surface, true);
if (shsurf->output)
weston_desktop_surface_set_size(shsurf->desktop_surface,
shsurf->output->width,
shsurf->output->height);
shsurf->output->output->width,
shsurf->output->output->height);
}
static void
@ -382,9 +379,7 @@ static void
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *parent)
{
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell,
shsurf->output);
struct kiosk_shell_output *shoutput = shsurf->output;
struct kiosk_shell_surface *shroot = parent ?
kiosk_shell_surface_get_parent_root(parent) :
kiosk_shell_surface_get_parent_root(shsurf);
@ -436,20 +431,22 @@ static void
kiosk_shell_surface_reconfigure_for_output(struct kiosk_shell_surface *shsurf)
{
struct weston_desktop_surface *desktop_surface;
struct weston_output *w_output;
if (!shsurf->output)
return;
w_output = shsurf->output->output;
desktop_surface = shsurf->desktop_surface;
if (weston_desktop_surface_get_maximized(desktop_surface) ||
weston_desktop_surface_get_fullscreen(desktop_surface)) {
weston_desktop_surface_set_size(desktop_surface,
shsurf->output->width,
shsurf->output->height);
w_output->width,
w_output->height);
}
weston_shell_utils_center_on_output(shsurf->view, shsurf->output);
weston_shell_utils_center_on_output(shsurf->view, w_output);
weston_view_update_transform(shsurf->view);
}
@ -530,8 +527,7 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
struct weston_surface *surface =
weston_desktop_surface_get_surface(dsurface);
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
struct kiosk_shell_output *shoutput = shsurf->output;
/* keyboard focus */
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
@ -824,8 +820,11 @@ kiosk_shell_output_create(struct kiosk_shell *shell, struct weston_output *outpu
wl_list_insert(shell->output_list.prev, &shoutput->link);
weston_output_set_shell_private(output, shoutput);
kiosk_shell_output_recreate_background(shoutput);
kiosk_shell_output_configure(shoutput);
weston_output_set_ready(output);
return shoutput;
}
@ -870,6 +869,9 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
struct weston_layer *layer;
struct weston_view *view;
if (!shsurf->output)
return NULL;
wl_list_for_each(layer, layers, link) {
struct kiosk_shell *shell = shsurf->shell;
@ -885,7 +887,7 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
continue;
/* pick views only on the same output */
if (view->output != shsurf->output)
if (view->output != shsurf->output->output)
continue;
view_shsurf = get_kiosk_shell_surface(view->surface);
@ -947,7 +949,7 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
successor = find_focus_successor(shsurf,
kiosk_seat->focused_surface);
shoutput = kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
shoutput = shsurf->output;
if (shoutput && successor) {
enum weston_layer_position succesor_view_layer_pos;
@ -991,17 +993,17 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
return;
if (!shsurf->appid_output_assigned && app_id) {
struct weston_output *output = NULL;
struct kiosk_shell_output *shoutput = NULL;
/* reset previous output being set in _added() as the output is
* being cached */
shsurf->output = NULL;
output = kiosk_shell_surface_find_best_output(shsurf);
shoutput = kiosk_shell_surface_find_best_output(shsurf);
kiosk_shell_surface_set_output(shsurf, output);
kiosk_shell_surface_set_output(shsurf, shoutput);
weston_desktop_surface_set_size(shsurf->desktop_surface,
shsurf->output->width,
shsurf->output->height);
shoutput->output->width,
shoutput->output->height);
/* even if we couldn't find an appid set for a particular
* output still flag the shsurf as to a avoid changing the
* output every time */
@ -1021,7 +1023,7 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
if (!weston_surface_is_mapped(surface) || (is_resized && is_fullscreen)) {
if (is_fullscreen || !shsurf->xwayland.is_set) {
weston_shell_utils_center_on_output(shsurf->view,
shsurf->output);
shsurf->output->output);
} else {
struct weston_coord_surface offset;
struct weston_geometry geometry =
@ -1040,9 +1042,7 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
if (!weston_surface_is_mapped(surface)) {
struct weston_seat *seat =
get_kiosk_shell_first_seat(shsurf->shell);
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell,
shsurf->output);
struct kiosk_shell_output *shoutput = shsurf->output;
struct kiosk_shell_seat *kiosk_seat;
weston_surface_map(surface);
@ -1134,6 +1134,10 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
{
struct kiosk_shell_surface *shsurf =
weston_desktop_surface_get_user_data(desktop_surface);
struct kiosk_shell_output *shoutput = NULL;
if (output)
shoutput = weston_output_get_shell_private(output);
/* We should normally be able to ignore fullscreen requests for
* top-level surfaces, since we set them as fullscreen at creation
@ -1148,7 +1152,7 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
*/
if (!shsurf->parent || fullscreen)
kiosk_shell_surface_set_fullscreen(shsurf, output);
kiosk_shell_surface_set_fullscreen(shsurf, shoutput);
else
kiosk_shell_surface_set_normal(shsurf);
}
@ -1232,20 +1236,6 @@ static const struct weston_desktop_api kiosk_shell_desktop_api = {
* kiosk_shell
*/
static struct kiosk_shell_output *
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
struct weston_output *output)
{
struct kiosk_shell_output *shoutput;
wl_list_for_each(shoutput, &shell->output_list, link) {
if (shoutput->output == output)
return shoutput;
}
return NULL;
}
static void
kiosk_shell_activate_view(struct kiosk_shell *shell,
struct weston_view *view,
@ -1334,7 +1324,7 @@ kiosk_shell_handle_output_resized(struct wl_listener *listener, void *data)
container_of(listener, struct kiosk_shell, output_resized_listener);
struct weston_output *output = data;
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shell, output);
weston_output_get_shell_private(output);
struct weston_view *view;
kiosk_shell_output_recreate_background(shoutput);

View file

@ -57,7 +57,7 @@ struct kiosk_shell_surface {
struct kiosk_shell *shell;
struct weston_output *output;
struct kiosk_shell_output *output;
struct wl_listener output_destroy_listener;
struct wl_signal destroy_signal;

View file

@ -199,7 +199,19 @@ weston_view_animation_frame(struct weston_animation *base,
struct weston_compositor *compositor =
animation->view->surface->compositor;
if (base->frame_counter <= 1)
/* Animations are created with timestamp 0, so we need to set a
* real time base on the first repaint.
*
* In some cases, such as when the repaint loop has just started
* for a new display, the time we're given could be 0 for our
* second call - but this is ok because weston_spring_update() will
* do nothing as long as spring.timestamp == time.
*
* We can safely just keep updating the timestamp until we get
* something non-zero, and the spring will start updating after
* that.
*/
if (!timespec_to_msec(&animation->spring.timestamp))
animation->spring.timestamp = *time;
weston_spring_update(&animation->spring, time);
@ -275,7 +287,6 @@ weston_view_animation_run(struct weston_view_animation *animation)
{
struct timespec zero_time = { 0 };
animation->animation.frame_counter = 0;
weston_view_animation_frame(&animation->animation, NULL, &zero_time);
}

View file

@ -40,26 +40,12 @@
#include "pixman-renderer.h"
#include "pixel-formats.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-assert.h"
#include "shared/weston-egl-ext.h"
#include "linux-dmabuf.h"
#include "linux-explicit-synchronization.h"
static struct gbm_device *
create_gbm_device(int fd)
{
struct gbm_device *gbm;
/* GBM will load a dri driver, but even though they need symbols from
* libglapi, in some version of Mesa they are not linked to it. Since
* only the gl-renderer module links to it, the call above won't make
* these symbols globally available, and loading the DRI driver fails.
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
gbm = gbm_create_device(fd);
return gbm;
}
#include "shared/xalloc.h"
/* When initializing EGL, if the preferred buffer format isn't available
* we may be able to substitute an ARGB format for an XRGB one.
@ -99,12 +85,32 @@ drm_backend_create_gl_renderer(struct drm_backend *b)
&options.base);
}
static int
drm_backend_create_vulkan_renderer(struct drm_backend *b)
{
const struct pixel_format_info *format[3] = {
b->format,
fallback_format_for(b->format),
};
struct vulkan_renderer_display_options options = {
.formats = format,
.formats_count = 1,
};
if (format[1])
options.formats_count = 2;
return weston_compositor_init_renderer(b->compositor,
WESTON_RENDERER_VULKAN,
&options.base);
}
int
init_egl(struct drm_backend *b)
{
struct drm_device *device = b->drm;
b->gbm = create_gbm_device(device->drm.fd);
b->gbm = gbm_create_device(device->drm.fd);
if (!b->gbm)
return -1;
@ -117,6 +123,24 @@ init_egl(struct drm_backend *b)
return 0;
}
int
init_vulkan(struct drm_backend *b)
{
struct drm_device *device = b->drm;
b->gbm = gbm_create_device(device->drm.fd);
if (!b->gbm)
return -1;
if (drm_backend_create_vulkan_renderer(b) < 0) {
gbm_device_destroy(b->gbm);
b->gbm = NULL;
return -1;
}
return 0;
}
static void drm_output_fini_cursor_egl(struct drm_output *output)
{
unsigned int i;
@ -130,6 +154,19 @@ static void drm_output_fini_cursor_egl(struct drm_output *output)
}
}
static void drm_output_fini_cursor_vulkan(struct drm_output *output)
{
unsigned int i;
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
/* This cursor does not have a GBM device */
if (output->gbm_cursor_fb[i] && !output->gbm_cursor_fb[i]->bo)
output->gbm_cursor_fb[i]->type = BUFFER_PIXMAN_DUMB;
drm_fb_unref(output->gbm_cursor_fb[i]);
output->gbm_cursor_fb[i] = NULL;
}
}
static int
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
{
@ -179,6 +216,55 @@ err:
return -1;
}
static int
drm_output_init_cursor_vulkan(struct drm_output *output, struct drm_backend *b)
{
struct drm_device *device = output->device;
unsigned int i;
/* No point creating cursors if we don't have a plane for them. */
if (!output->cursor_plane)
return 0;
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
struct gbm_bo *bo;
if (gbm_device_get_fd(b->gbm) != output->device->drm.fd) {
output->gbm_cursor_fb[i] =
drm_fb_create_dumb(output->device,
device->cursor_width,
device->cursor_height,
DRM_FORMAT_ARGB8888);
/* Override buffer type, since we know it is a cursor */
output->gbm_cursor_fb[i]->type = BUFFER_CURSOR;
output->gbm_cursor_handle[i] =
output->gbm_cursor_fb[i]->handles[0];
} else {
bo = gbm_bo_create(b->gbm, device->cursor_width, device->cursor_height,
GBM_FORMAT_ARGB8888,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
if (!bo)
goto err;
output->gbm_cursor_fb[i] =
drm_fb_get_from_bo(bo, device, false, BUFFER_CURSOR);
if (!output->gbm_cursor_fb[i]) {
gbm_bo_destroy(bo);
goto err;
}
output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
}
}
return 0;
err:
weston_log("cursor buffers unavailable, using vulkan cursors\n");
device->cursors_are_broken = true;
drm_output_fini_cursor_vulkan(output);
return -1;
}
static void
create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
{
@ -229,26 +315,213 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
output->gbm_bo_flags);
}
enum format_alpha_required {
FORMAT_ALPHA_REQUIRED = true,
FORMAT_ALPHA_NOT_REQUIRED = false,
};
enum format_component_type {
FORMAT_COMPONENT_TYPE_ANY,
FORMAT_COMPONENT_TYPE_FLOAT_ONLY,
};
static const struct pixel_format_info *
find_compatible_format(struct weston_compositor *compositor,
struct wl_array *formats, int min_bpc,
enum format_component_type component_type,
enum format_alpha_required alpha_required)
{
const struct pixel_format_info **tmp, *p;
const struct pixel_format_info *candidate = NULL;
/**
* Given a format array, this looks for a format respecting a few
* criteria. First of all, this ignores formats that do not contain an
* alpha channel when alpha_required == FORMAT_ALPHA_REQUIRED. Similar
* for formats that are not floating point when component_type ==
* FORMAT_COMPONENT_TYPE_FLOAT_ONLY. Also, it ignores formats that do
* not have bits per color channel (bpc) bigger or equal to min_bpc.
*
* When we have multiple formats matching these criteria, we use the
* following to choose:
*
* 1. a format with lower bytes per pixel (bpp) is favored.
*
* 2. if FORMAT_ALPHA_REQUIRED:
* we prefer the format with more bits on the alpha channel
* else
* we prefer the format with more bits on the color channels
*/
wl_array_for_each(tmp, formats) {
p = *tmp;
/* Skip candidates that do not match minimum criteria. */
if (component_type == FORMAT_COMPONENT_TYPE_FLOAT_ONLY &&
p->component_type != PIXEL_COMPONENT_TYPE_FLOAT)
continue;
if (alpha_required == FORMAT_ALPHA_REQUIRED && p->bits.a == 0)
continue;
if (p->bits.r < min_bpc || p->bits.g < min_bpc || p->bits.b < min_bpc)
continue;
/* No other good candidate so far, so pick this one. */
if (!candidate) {
candidate = p;
continue;
}
/**
* New candidate, let's compare with old and untie.
*/
if (p->bpp > candidate->bpp)
continue;
if (alpha_required == FORMAT_ALPHA_REQUIRED) {
if (p->bits.a <= candidate->bits.a)
continue;
} else {
if (p->bits.r + p->bits.g + p->bits.b <=
candidate->bits.r + candidate->bits.g + candidate->bits.b)
continue;
}
candidate = p;
}
return candidate;
}
static bool
drm_output_pick_format_egl(struct drm_output *output)
{
struct drm_device *device = output->device;
struct drm_backend *b = device->backend;
struct weston_compositor *compositor = b->compositor;
const struct weston_renderer *renderer = compositor->renderer;
const struct pixel_format_info **renderer_formats;
const struct pixel_format_info **f;
unsigned int renderer_formats_count;
struct wl_array supported_formats;
enum format_component_type component_type;
uint32_t min_bpc;
unsigned int i;
bool ret = true;
bool found;
wl_array_init(&supported_formats);
/**
* This computes the intersection between renderer formats supported by
* EGL and the output->scanout_plane supported formats. We need that as
* we want to select a format supported by both.
*/
renderer_formats =
renderer->gl->get_supported_rendering_formats(b->compositor,
&renderer_formats_count);
for (i = 0; i < renderer_formats_count; i++) {
if (!weston_drm_format_array_find_format(&output->scanout_plane->formats,
renderer_formats[i]->format))
continue;
f = wl_array_add(&supported_formats, sizeof(*f));
*f = renderer_formats[i];
}
if (output->base.from_blend_to_output_by_backend) {
component_type = FORMAT_COMPONENT_TYPE_FLOAT_ONLY;
min_bpc = 16;
} else if (output->base.eotf_mode != WESTON_EOTF_MODE_SDR) {
component_type = FORMAT_COMPONENT_TYPE_ANY;
min_bpc = 10;
} else {
/**
* If no requirements, we simply use b->format instead of
* looking for a format with bpc >= min_bpc.
*/
min_bpc = 0;
}
if (min_bpc != 0) {
if (b->has_underlay) {
output->format =
find_compatible_format(compositor, &supported_formats,
min_bpc, component_type,
FORMAT_ALPHA_REQUIRED);
if (output->format)
goto done;
weston_log("Disabling underlay planes: EGL GBM or the primary plane for output '%s'\n" \
"does not support format with min bpc %u and alpha channel.\n",
output->base.name, min_bpc);
b->has_underlay = false;
}
output->format =
find_compatible_format(compositor, &supported_formats,
min_bpc, component_type,
FORMAT_ALPHA_NOT_REQUIRED);
if (output->format)
goto done;
weston_log("Error: EGL GBM or the primary plane for output '%s' does not support format\n" \
"with min bpc %u.\n", output->base.name, min_bpc);
ret = false;
goto done;
}
found = false;
wl_array_for_each(f, &supported_formats) {
if ((*f)->format == b->format->format) {
found = true;
break;
}
}
if (!found) {
weston_log("Error: format %s unsupported by EGL GBM or the primary plane for output '%s'.\n",
b->format->drm_format_name, output->base.name);
ret = false;
goto done;
}
if (b->has_underlay && (b->format->bits.a == 0)) {
weston_log("Disabling underlay planes: b->format %s does not have alpha channel,\n"
"which is required to support underlay planes.\n",
b->format->drm_format_name);
b->has_underlay = false;
}
output->format = b->format;
done:
wl_array_release(&supported_formats);
return ret;
}
/* Init output state that depends on gl or gbm */
int
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
{
const struct weston_renderer *renderer = b->compositor->renderer;
const struct weston_mode *mode = output->base.current_mode;
const struct pixel_format_info *format[2] = {
output->format,
fallback_format_for(output->format),
};
struct gl_renderer_output_options options = {
.formats = format,
.formats_count = 1,
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
const struct pixel_format_info *format[2] = { 0 };
struct gl_renderer_output_options options;
if (!output->format && !drm_output_pick_format_egl(output))
return -1;
format[0] = output->format;
if (!b->has_underlay)
format[1] = fallback_format_for(output->format);
options.formats = format;
options.formats_count = format[1] ? 2 : 1;
options.area.x = 0;
options.area.y = 0;
options.area.width = mode->width;
options.area.height = mode->height;
options.fb_size.width = mode->width;
options.fb_size.height = mode->height;
assert(output->gbm_surface == NULL);
create_gbm_surface(b->gbm, output);
@ -257,8 +530,6 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
return -1;
}
if (options.formats[1])
options.formats_count = 2;
options.window_for_legacy = (EGLNativeWindowType) output->gbm_surface;
options.window_for_platform = output->gbm_surface;
if (renderer->gl->output_window_create(&output->base, &options) < 0) {
@ -273,6 +544,208 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
return 0;
}
static struct gbm_bo *
drm_gbm_create_bo(struct gbm_device *gbm, struct drm_output *output)
{
struct weston_mode *mode = output->base.current_mode;
struct drm_plane *plane = output->scanout_plane;
struct weston_drm_format *fmt;
const uint64_t *modifiers;
unsigned int num_modifiers;
struct gbm_bo *bo = NULL;
/*
* TODO: Currently, this method allocates a buffer based on the list
* of acceptable modifiers received from the DRM backend but does not
* check it against formats renderable by the renderer.
* To support cases where the renderer may not support the same
* modifiers (e.g. Vulkan software renderer) it should match against
* renderer modifiers.
*/
fmt = weston_drm_format_array_find_format(&plane->formats,
output->format->format);
if (!fmt) {
weston_log("format %s not supported by output %s\n",
output->format->drm_format_name,
output->base.name);
return NULL;
}
if (!weston_drm_format_has_modifier(fmt, DRM_FORMAT_MOD_INVALID)) {
modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
bo = gbm_bo_create_with_modifiers(gbm, mode->width, mode->height,
output->format->format,
modifiers, num_modifiers);
}
/*
* If we cannot use modifiers to allocate the GBM surface and
* the GBM device differs from the KMS display device, try to
* use linear buffers and hope that the allocated GBM surface
* is correctly displayed on the KMS device.
*/
if (gbm_device_get_fd(gbm) != output->device->drm.fd)
output->gbm_bo_flags |= GBM_BO_USE_LINEAR;
if (!bo) {
bo = gbm_bo_create(gbm, mode->width, mode->height,
output->format->format, output->gbm_bo_flags);
}
return bo;
}
struct drm_gbm_dmabuf {
struct linux_dmabuf_memory base;
struct gbm_bo *bo;
};
static void
drm_gbm_dmabuf_destroy(struct linux_dmabuf_memory *dmabuf)
{
struct dmabuf_attributes *attributes;
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
struct gbm_bo *bo;
drm_gbm_dmabuf = container_of(dmabuf, struct drm_gbm_dmabuf, base);
bo = drm_gbm_dmabuf->bo;
assert(bo);
gbm_bo_destroy(bo);
attributes = dmabuf->attributes;
for (int i = 0; i < attributes->n_planes; ++i)
close(attributes->fd[i]);
free(dmabuf->attributes);
free(dmabuf);
}
static struct drm_gbm_dmabuf *
drm_gbm_bo_get_dmabuf(struct gbm_device *gbm, struct drm_output *output, struct gbm_bo *bo)
{
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
struct dmabuf_attributes *attributes;
attributes = xzalloc(sizeof(*attributes));
attributes->width = gbm_bo_get_width(bo);
attributes->height = gbm_bo_get_height(bo);
attributes->format = gbm_bo_get_format(bo);
attributes->n_planes = gbm_bo_get_plane_count(bo);
for (int i = 0; i < attributes->n_planes; ++i) {
attributes->fd[i] = gbm_bo_get_fd(bo);
attributes->stride[i] = gbm_bo_get_stride_for_plane(bo, i);
attributes->offset[i] = gbm_bo_get_offset(bo, i);
}
attributes->modifier = gbm_bo_get_modifier(bo);
drm_gbm_dmabuf = xzalloc(sizeof(*drm_gbm_dmabuf));
drm_gbm_dmabuf->base.attributes = attributes;
drm_gbm_dmabuf->base.destroy = drm_gbm_dmabuf_destroy;
drm_gbm_dmabuf->bo = bo;
return drm_gbm_dmabuf;
}
static void
create_renderbuffers(struct gbm_device *gbm, struct drm_output *output, unsigned int n)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
for (unsigned int i = 0; i < n; i++) {
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
struct gbm_bo *bo;
bo = drm_gbm_create_bo(gbm, output);
if (!bo) {
weston_log("failed to allocate bo\n");
return;
}
drm_gbm_dmabuf = drm_gbm_bo_get_dmabuf(gbm, output, bo);
if (!drm_gbm_dmabuf) {
weston_log("failed to allocate dmabuf\n");
return;
}
output->renderbuffer[i] =
renderer->create_renderbuffer_dmabuf(&output->base,
&drm_gbm_dmabuf->base,
NULL, NULL);
if (!output->renderbuffer[i]) {
weston_log("failed to allocate renderbuffer\n");
return;
}
output->linux_dmabuf_memory[i] = &drm_gbm_dmabuf->base;
}
}
static bool
drm_output_pick_format_vulkan(struct drm_output *output)
{
struct drm_device *device = output->device;
struct drm_backend *b = device->backend;
/* Any other value of eotf_mode requires color-management, which is not
* yet supported by vulkan-renderer. */
assert(output->base.eotf_mode == WESTON_EOTF_MODE_SDR);
if (!b->format->vulkan_format) {
weston_log("Error: failed to pick format for output '%s', format %s unsupported by vulkan-renderer.\n",
output->base.name, b->format->drm_format_name);
return false;
}
assert(b->format);
output->format = b->format;
if (b->has_underlay && (output->format->bits.a == 0)) {
weston_log("Disabling underlay planes: output '%s' with format %s does not have alpha channel,\n"
"which is required to support underlay planes.\n",
output->base.name, output->format->drm_format_name);
b->has_underlay = false;
}
return true;
}
/* Init output state that depends on vulkan */
int
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
{
const struct weston_mode *mode = output->base.current_mode;
struct weston_renderer *renderer = b->compositor->renderer;
if (!output->format && !drm_output_pick_format_vulkan(output))
return -1;
const struct vulkan_renderer_surfaceless_options options = {
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
weston_log("failed to create vulkan renderer output state\n");
return -1;
}
create_renderbuffers(b->gbm, output, ARRAY_LENGTH(output->renderbuffer));
if (!output->linux_dmabuf_memory[0]) {
weston_log("failed to create dmabufs\n");
return -1;
}
drm_output_init_cursor_vulkan(output, b);
return 0;
}
void
drm_output_fini_egl(struct drm_output *output)
{
@ -293,6 +766,26 @@ drm_output_fini_egl(struct drm_output *output)
drm_output_fini_cursor_egl(output);
}
void
drm_output_fini_vulkan(struct drm_output *output)
{
struct drm_backend *b = output->backend;
const struct weston_renderer *renderer = b->compositor->renderer;
if (!b->compositor->shutting_down &&
output->scanout_plane->state_cur->fb &&
output->scanout_plane->state_cur->fb->type == BUFFER_DMABUF_BACKEND) {
drm_plane_reset_state(output->scanout_plane);
}
for (unsigned int i = 0; i < ARRAY_LENGTH(output->renderbuffer); i++)
renderer->destroy_renderbuffer(output->renderbuffer[i]);
renderer->vulkan->output_destroy(&output->base);
drm_output_fini_cursor_vulkan(output);
}
struct drm_fb *
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
{
@ -324,3 +817,36 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
return ret;
}
struct drm_fb *
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
{
struct drm_output *output = state->output;
struct drm_device *device = output->device;
struct linux_dmabuf_memory *dmabuf;
struct drm_fb *ret;
output->base.compositor->renderer->repaint_output(&output->base,
damage,
output->renderbuffer[output->current_image]);
dmabuf = output->linux_dmabuf_memory[output->current_image];
if (!dmabuf) {
weston_log("failed to get dmabuf\n");
return NULL;
}
/* Output transparent/opaque image according to the format required by
* the client. */
ret = drm_fb_get_from_dmabuf_attributes(dmabuf->attributes, device,
!output->format->opaque_substitute,
false, true, NULL);
if (!ret) {
weston_log("failed to get drm_fb for dmabuf\n");
return NULL;
}
output->current_image = (output->current_image + 1) % ARRAY_LENGTH(output->renderbuffer);
return ret;
}

View file

@ -78,6 +78,10 @@
#define DRM_PLANE_ALPHA_OPAQUE 0xffffUL
#endif
#ifndef MAX_DMABUF_PLANES
#define MAX_DMABUF_PLANES 4
#endif
/**
* A small wrapper to print information into the 'drm-backend' debug scope.
*
@ -149,27 +153,6 @@ struct drm_property_info {
uint64_t range_values[2];
};
/**
* Reasons why placing a view on a plane failed. Needed by the dma-buf feedback.
*/
enum try_view_on_plane_failure_reasons {
FAILURE_REASONS_NONE = 0,
FAILURE_REASONS_FORCE_RENDERER = 1 << 0,
FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = 1 << 1,
FAILURE_REASONS_DMABUF_MODIFIER_INVALID = 1 << 2,
FAILURE_REASONS_ADD_FB_FAILED = 1 << 3,
FAILURE_REASONS_NO_PLANES_AVAILABLE = 1 << 4,
FAILURE_REASONS_PLANES_REJECTED = 1 << 5,
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION = 1 << 6,
FAILURE_REASONS_INCOMPATIBLE_TRANSFORM = 1 << 7,
FAILURE_REASONS_NO_BUFFER = 1 << 8,
FAILURE_REASONS_BUFFER_TYPE = 1 << 9,
FAILURE_REASONS_GLOBAL_ALPHA = 1 << 10,
FAILURE_REASONS_NO_GBM = 1 << 11,
FAILURE_REASONS_GBM_BO_IMPORT_FAILED = 1 << 12,
FAILURE_REASONS_GBM_BO_GET_HANDLE_FAILED = 1 << 13,
};
/**
* We use this to keep track of actions we need to do with the dma-buf feedback
* in order to keep it up-to-date with the info we get from the DRM-backend.
@ -180,6 +163,12 @@ enum actions_needed_dmabuf_feedback {
ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
};
enum drm_plane_subtype {
PLANE_SUBTYPE_OVERLAY_ONLY = 0,
PLANE_SUBTYPE_UNDERLAY_ONLY = 1,
PLANE_SUBTYPE_BOTH = 2,
};
struct drm_device {
struct drm_backend *backend;
@ -232,6 +221,9 @@ struct drm_device {
/* drm_backend::kms_list */
struct wl_list link;
/* struct drm_colorop_3x1d_lut::link */
struct wl_list drm_colorop_3x1d_lut_list;
};
struct drm_backend {
@ -253,6 +245,8 @@ struct drm_backend {
bool use_pixman_shadow;
bool offload_blend_to_output;
struct udev_input input;
uint32_t pageflip_timeout;
@ -261,6 +255,15 @@ struct drm_backend {
bool has_underlay;
struct weston_log_scope *debug;
struct {
uint32_t frame_counter_interval;
struct wl_event_source *pageflip_timer_counter;
bool timer_armed;
} perf_page_flips_stats;
/* True if we need a workaround for some very old kernels */
bool stale_timestamp_workaround;
};
struct drm_mode {
@ -273,6 +276,7 @@ enum drm_fb_type {
BUFFER_INVALID = 0, /**< never used */
BUFFER_CLIENT, /**< directly sourced from client */
BUFFER_DMABUF, /**< imported from linux_dmabuf client */
BUFFER_DMABUF_BACKEND, /**< imported from dmabuf renderbuffer */
BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
BUFFER_GBM_SURFACE, /**< internal EGL rendering */
BUFFER_CURSOR, /**< internal cursor buffer */
@ -287,9 +291,9 @@ struct drm_fb {
int refcnt;
uint32_t fb_id, size;
uint32_t handles[4];
uint32_t strides[4];
uint32_t offsets[4];
uint32_t handles[MAX_DMABUF_PLANES];
uint32_t strides[MAX_DMABUF_PLANES];
uint32_t offsets[MAX_DMABUF_PLANES];
int num_planes;
const struct pixel_format_info *format;
uint64_t modifier;
@ -302,6 +306,12 @@ struct drm_fb {
struct gbm_bo *bo;
struct gbm_surface *gbm_surface;
/* Used when direct-display extension is turned on for that dmabuf */
bool direct_display;
int fds[MAX_DMABUF_PLANES];
/* tracks how many fds we've dup'ed */
int num_duped_fds;
/* Used by dumb fbs */
void *map;
};
@ -329,6 +339,15 @@ struct drm_pending_state {
struct wl_list output_list;
};
enum drm_output_propose_state_mode {
DRM_OUTPUT_PROPOSE_STATE_INVALID = 0, /**< Invalid state */
DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR, /**< only assign to renderer & cursor plane */
DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer */
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< no renderer use, only planes */
DRM_OUTPUT_PROPOSE_STATE_REUSE = 128, /**< bit indicates reuse prior state with new buffers */
};
/*
* Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
* plus >= 1 each of encoder/connector/plane. Since everything but the planes
@ -342,11 +361,13 @@ struct drm_pending_state {
struct drm_output_state {
struct drm_pending_state *pending_state;
struct drm_output *output;
enum drm_output_propose_state_mode mode;
struct wl_list link;
enum dpms_enum dpms;
enum weston_hdcp_protection protection;
struct wl_list plane_list;
bool tear;
bool planes_enabled;
};
/**
@ -379,6 +400,9 @@ struct drm_plane_state {
uint64_t zpos;
uint16_t alpha;
enum wdrm_plane_color_encoding color_encoding;
enum wdrm_plane_color_range color_range;
bool complete;
/* We don't own the fd, so we shouldn't close it */
@ -410,6 +434,8 @@ struct drm_plane {
struct drm_device *device;
enum wdrm_plane_type type;
/* Whether this plane supports overlay, underlay, or both */
enum drm_plane_subtype subtype;
uint32_t possible_crtcs;
uint32_t plane_id;
@ -417,8 +443,6 @@ struct drm_plane {
uint32_t crtc_id;
struct drm_property_info props[WDRM_PLANE__COUNT];
/* True if the plane's zpos_max < primary plane's zpos_min. */
bool is_underlay;
/* The last state submitted to the kernel for this plane. */
struct drm_plane_state *state_cur;
@ -492,6 +516,19 @@ struct drm_writeback {
struct weston_drm_format_array formats;
};
struct drm_colorop_3x1d_lut {
/* drm_device::drm_colorop_3x1d_lut_list */
struct wl_list link;
struct drm_device *device;
uint64_t lut_size;
struct weston_color_transform *xform;
struct wl_listener destroy_listener;
uint32_t blob_id;
};
struct drm_head {
struct weston_head base;
struct drm_connector connector;
@ -522,6 +559,9 @@ struct drm_crtc {
/* Holds the properties for the CRTC */
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
/* CRTC prop WDRM_CRTC_GAMMA_LUT_SIZE */
uint32_t lut_size;
};
struct drm_output {
@ -548,6 +588,7 @@ struct drm_output {
int current_cursor;
struct gbm_surface *gbm_surface;
struct linux_dmabuf_memory *linux_dmabuf_memory[2];
const struct pixel_format_info *format;
uint32_t gbm_bo_flags;
@ -557,8 +598,9 @@ struct drm_output {
unsigned max_bpc;
enum wdrm_colorspace connector_colorspace;
bool deprecated_gamma_is_set;
bool legacy_gamma_not_supported;
uint16_t legacy_gamma_size;
struct drm_colorop_3x1d_lut *blend_to_output_xform;
/* Plane being displayed directly on the CRTC */
struct drm_plane *scanout_plane;
@ -573,7 +615,7 @@ struct drm_output {
struct drm_writeback_state *wb_state;
struct drm_fb *dumb[2];
struct weston_renderbuffer *renderbuffer[2];
weston_renderbuffer_t renderbuffer[2];
int current_image;
struct vaapi_recorder *recorder;
@ -581,6 +623,12 @@ struct drm_output {
struct wl_event_source *pageflip_timer;
/* how many page flips */
uint32_t page_flips_counted;
/* how many page flips / interval */
float page_flips_per_timer_interval;
bool is_virtual;
void (*virtual_destroy)(struct weston_output *base);
@ -656,7 +704,18 @@ drm_output_get_plane_type_name(struct drm_plane *p)
case WDRM_PLANE_TYPE_CURSOR:
return "cursor";
case WDRM_PLANE_TYPE_OVERLAY:
return p->is_underlay ? "underlay" : "overlay";
switch (p->subtype) {
case PLANE_SUBTYPE_OVERLAY_ONLY:
return "overlay";
case PLANE_SUBTYPE_UNDERLAY_ONLY:
return "underlay";
case PLANE_SUBTYPE_BOTH:
return "over/underlay";
default:
assert(0);
break;
}
// fall through
default:
assert(0);
break;
@ -748,10 +807,6 @@ drm_pending_state_apply(struct drm_pending_state *pending_state);
int
drm_pending_state_apply_sync(struct drm_pending_state *pending_state);
void
drm_output_set_gamma(struct weston_output *output_base,
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
void
drm_output_update_msc(struct drm_output *output, unsigned int seq);
void
@ -768,6 +823,11 @@ drm_fb_unref(struct drm_fb *fb);
struct drm_fb *
drm_fb_create_dumb(struct drm_device *device, int width, int height,
uint32_t format);
struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
struct drm_device *device, bool is_opaque,
uint32_t *try_view_on_plane_failure_reasons);
struct drm_fb *
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
bool is_opaque, enum drm_fb_type type);
@ -784,15 +844,23 @@ wdrm_colorspace_from_output(struct weston_output *output);
#ifdef BUILD_DRM_GBM
extern struct drm_fb *
drm_fb_get_from_paint_node(struct drm_output_state *state,
struct weston_paint_node *pnode);
struct weston_paint_node *pnode,
uint32_t *try_view_on_plane_failure_reasons);
extern bool
drm_can_scanout_dmabuf(struct weston_backend *backend,
struct linux_dmabuf_buffer *dmabuf);
struct drm_fb *
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
struct drm_device *device, bool is_opaque,
bool direct_display, bool is_internal,
uint32_t *try_view_on_plane_failure_reasons);
#else
static inline struct drm_fb *
drm_fb_get_from_paint_node(struct drm_output_state *state,
struct weston_paint_node *pnode)
struct weston_paint_node *pnode,
uint32_t *try_view_on_plane_failure_reasons)
{
return NULL;
}
@ -849,7 +917,7 @@ void
drm_plane_state_free(struct drm_plane_state *state, bool force);
void
drm_plane_state_put_back(struct drm_plane_state *state);
bool
void
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
struct weston_paint_node *node,
uint64_t zpos);
@ -862,6 +930,14 @@ drm_assign_planes(struct weston_output *output_base);
bool
drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
bool
drm_plane_supports_color_encoding(struct drm_plane *plane,
enum wdrm_plane_color_encoding encoding);
bool
drm_plane_supports_color_range(struct drm_plane *plane,
enum wdrm_plane_color_range range);
void
drm_output_render(struct drm_output_state *state);
@ -893,6 +969,18 @@ drm_output_fini_egl(struct drm_output *output);
struct drm_fb *
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
int
init_vulkan(struct drm_backend *b);
int
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b);
void
drm_output_fini_vulkan(struct drm_output *output);
struct drm_fb *
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage);
#else
inline static int
init_egl(struct drm_backend *b)
@ -917,4 +1005,29 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
{
return NULL;
}
inline static int
init_vulkan(struct drm_backend *b)
{
weston_log("Compiled without GBM support\n");
return -1;
}
inline static int
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
{
return -1;
}
inline static void
drm_output_fini_vulkan(struct drm_output *output)
{
}
inline static struct drm_fb *
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
{
return NULL;
}
#endif

View file

@ -56,6 +56,8 @@ enum wdrm_plane_property {
WDRM_PLANE_ZPOS,
WDRM_PLANE_ROTATION,
WDRM_PLANE_ALPHA,
WDRM_PLANE_COLOR_ENCODING,
WDRM_PLANE_COLOR_RANGE,
WDRM_PLANE__COUNT
};
@ -82,6 +84,27 @@ enum wdrm_plane_rotation {
WDRM_PLANE_ROTATION__COUNT,
};
/**
* Possible values for the WDRM_PLANE_COLOR_ENCODING property.
*/
enum wdrm_plane_color_encoding {
WDRM_PLANE_COLOR_ENCODING_BT601 = 0,
WDRM_PLANE_COLOR_ENCODING_BT709,
WDRM_PLANE_COLOR_ENCODING_BT2020,
WDRM_PLANE_COLOR_ENCODING__COUNT
};
#define WDRM_PLANE_COLOR_ENCODING_DEFAULT WDRM_PLANE_COLOR_ENCODING_BT709
/**
* Possible values for the WDRM_PLANE_COLOR_RANGE property.
*/
enum wdrm_plane_color_range {
WDRM_PLANE_COLOR_RANGE_LIMITED = 0,
WDRM_PLANE_COLOR_RANGE_FULL,
WDRM_PLANE_COLOR_RANGE__COUNT
};
#define WDRM_PLANE_COLOR_RANGE_DEFAULT WDRM_PLANE_COLOR_RANGE_LIMITED
/**
* List of properties attached to a DRM connector
*/
@ -100,6 +123,7 @@ enum wdrm_connector_property {
WDRM_CONNECTOR_MAX_BPC,
WDRM_CONNECTOR_CONTENT_TYPE,
WDRM_CONNECTOR_COLORSPACE,
WDRM_CONNECTOR_VRR_CAPABLE,
WDRM_CONNECTOR__COUNT
};

View file

@ -38,6 +38,7 @@
#include "drm-internal.h"
#include "pixel-formats.h"
#include "renderer-gl/gl-renderer.h"
#include "shared/weston-assert.h"
#define POISON_PTR ((void *)8)
@ -205,6 +206,7 @@ static int
drm_virtual_output_repaint(struct weston_output *output_base)
{
struct drm_output_state *state = NULL;
struct weston_compositor *compositor = output_base->compositor;
struct drm_output *output = to_drm_output(output_base);
struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_plane_state *scanout_state;
@ -227,14 +229,10 @@ drm_virtual_output_repaint(struct weston_output *output_base)
assert(!output->state_last);
/* If planes have been disabled in the core, we might not have
* hit assign_planes at all, so might not have valid output state
* here. */
/* assign_planes() is always called before a repaint, so we must have a
* valid output state here. */
state = drm_pending_state_get_output(pending_state, output);
if (!state)
state = drm_output_state_duplicate(output->state_cur,
pending_state,
DRM_OUTPUT_STATE_CLEAR_PLANES);
weston_assert_ptr_not_null(compositor, state);
drm_output_render(state);
scanout_state = drm_output_state_get_plane(state, scanout_plane);
@ -318,8 +316,6 @@ drm_virtual_output_enable(struct weston_output *output_base)
output->base.assign_planes = drm_assign_planes;
output->base.set_dpms = NULL;
output->base.switch_mode = NULL;
output->base.gamma_size = 0;
output->base.set_gamma = NULL;
weston_compositor_stack_plane(b->compositor,
&output->scanout_plane->base,

File diff suppressed because it is too large Load diff

View file

@ -114,13 +114,21 @@ static void gem_handle_put(struct drm_device *device, int handle)
static int
drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
{
int bo_fd;
int bo_fd = -1;
uint32_t handle;
int ret;
/* neither a BO nor a direct-display means we shouldn't be calling this */
assert(!!fb->bo ^ fb->direct_display);
if (fb->bo) {
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
if (bo_fd < 0)
return bo_fd;
}
if (fb->direct_display)
bo_fd = fb->fds[plane];
/*
* drmPrimeFDToHandle is dangerous, because the GEM handles are
@ -147,6 +155,9 @@ drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
fb->handles[plane] = gem_handle_get(device, handle);
out:
/* on the direct-display path the dup'ed fds will be closed by
* drm_fb_destroy_dmabuf */
if (fb->bo)
close(bo_fd);
return ret;
}
@ -171,11 +182,14 @@ drm_fb_maybe_import(struct drm_device *device, struct drm_fb *fb)
struct gbm_device *gbm_device;
int ret = 0;
int plane;
int num_planes;
/* No import possible, if there is no gbm bo */
if (!fb->bo)
/* No import possible, if there is no gbm bo or fb is not using
* direct-display */
if (!fb->bo && !fb->direct_display)
return 0;
if (fb->bo) {
/* No import necessary, if the gbm bo and the fb use the same device */
gbm_device = gbm_bo_get_device(fb->bo);
if (gbm_device_get_fd(gbm_device) == fb->fd)
@ -187,7 +201,13 @@ drm_fb_maybe_import(struct drm_device *device, struct drm_fb *fb)
return -1;
}
for (plane = 0; plane < gbm_bo_get_plane_count(fb->bo); plane++) {
num_planes = gbm_bo_get_plane_count(fb->bo);
}
if (fb->direct_display)
num_planes = fb->num_planes;
for (plane = 0; plane < num_planes; plane++) {
ret = drm_fb_import_plane(device, fb, plane);
if (ret)
goto err;
@ -364,27 +384,35 @@ drm_fb_destroy_dmabuf(struct drm_fb *fb)
* If we imported the dmabuf into a scanout device, we are responsible
* for closing the GEM handle.
*/
for (i = 0; i < 4; i++)
if (fb->scanout_device && fb->handles[i] != 0)
for (i = 0; i < MAX_DMABUF_PLANES; i++) {
if (fb->scanout_device && fb->handles[i] != 0) {
gem_handle_put(fb->scanout_device, fb->handles[i]);
fb->handles[i] = 0;
}
}
for (i = 0; i < fb->num_duped_fds; i++)
close(fb->fds[i]);
drm_fb_destroy(fb);
}
static struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
struct drm_fb *
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
struct drm_device *device, bool is_opaque,
bool direct_display, bool is_internal,
uint32_t *try_view_on_plane_failure_reasons)
{
struct drm_backend *backend = device->backend;
struct drm_fb *fb;
int i;
struct gbm_import_fd_modifier_data import_mod = {
.width = dmabuf->attributes.width,
.height = dmabuf->attributes.height,
.format = dmabuf->attributes.format,
.num_fds = dmabuf->attributes.n_planes,
.modifier = dmabuf->attributes.modifier,
.width = attributes->width,
.height = attributes->height,
.format = attributes->format,
.num_fds = attributes->n_planes,
.modifier = attributes->modifier,
};
/* We should not import to KMS a buffer that has been allocated using no
@ -394,7 +422,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
* KMS driver can't know. So giving the buffer to KMS is not safe, as
* not knowing its layout can result in garbage being displayed. In
* short, importing a buffer to KMS requires explicit modifiers. */
if (dmabuf->attributes.modifier == DRM_FORMAT_MOD_INVALID) {
if (attributes->modifier == DRM_FORMAT_MOD_INVALID) {
if (try_view_on_plane_failure_reasons)
*try_view_on_plane_failure_reasons |=
FAILURE_REASONS_DMABUF_MODIFIER_INVALID;
@ -410,7 +438,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
* these types of buffers should be handled through buffer
* transforms and not as spot-checks requiring specific
* knowledge. */
if (dmabuf->attributes.flags)
if (attributes->flags)
return NULL;
fb = zalloc(sizeof *fb);
@ -418,12 +446,30 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
return NULL;
fb->refcnt = 1;
fb->type = BUFFER_DMABUF;
fb->type = is_internal ? BUFFER_DMABUF_BACKEND : BUFFER_DMABUF;
fb->backend = device->backend;
ARRAY_COPY(import_mod.fds, dmabuf->attributes.fd);
ARRAY_COPY(import_mod.strides, dmabuf->attributes.stride);
ARRAY_COPY(import_mod.offsets, dmabuf->attributes.offset);
ARRAY_COPY(import_mod.fds, attributes->fd);
ARRAY_COPY(import_mod.strides, attributes->stride);
ARRAY_COPY(import_mod.offsets, attributes->offset);
/* skip bo import if dmabuf is using direct-display extension */
if (direct_display) {
fb->direct_display = true;
/* we're making a dup of the fds from attributes->fd as
* opposed to just copying the fds with ARRAY_COPY() */
for (i = 0; i < attributes->n_planes; i++) {
fb->fds[i] = dup(attributes->fd[i]);
if (fb->fds[i] == -1) {
weston_log("failed to dup dmabuf attribute fd: %s\n",
strerror(errno));
goto err_free;
}
fb->num_duped_fds++;
}
goto bo_import_skip;
}
fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER,
&import_mod, GBM_BO_USE_SCANOUT);
@ -434,19 +480,20 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
goto err_free;
}
fb->width = dmabuf->attributes.width;
fb->height = dmabuf->attributes.height;
fb->modifier = dmabuf->attributes.modifier;
bo_import_skip:
fb->width = attributes->width;
fb->height = attributes->height;
fb->modifier = attributes->modifier;
fb->size = 0;
fb->fd = device->drm.fd;
ARRAY_COPY(fb->strides, dmabuf->attributes.stride);
ARRAY_COPY(fb->offsets, dmabuf->attributes.offset);
ARRAY_COPY(fb->strides, attributes->stride);
ARRAY_COPY(fb->offsets, attributes->offset);
fb->format = pixel_format_get_info(dmabuf->attributes.format);
fb->format = pixel_format_get_info(attributes->format);
if (!fb->format) {
weston_log("couldn't look up format info for 0x%lx\n",
(unsigned long) dmabuf->attributes.format);
(unsigned long) attributes->format);
goto err_free;
}
@ -461,8 +508,8 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
goto err_free;
}
fb->num_planes = dmabuf->attributes.n_planes;
for (i = 0; i < dmabuf->attributes.n_planes; i++) {
fb->num_planes = attributes->n_planes;
for (i = 0; fb->bo && i < attributes->n_planes; i++) {
union gbm_bo_handle handle;
handle = gbm_bo_get_handle_for_plane(fb->bo, i);
@ -488,6 +535,18 @@ err_free:
return NULL;
}
struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
struct drm_device *device, bool is_opaque,
uint32_t *try_view_on_plane_failure_reasons)
{
return drm_fb_get_from_dmabuf_attributes(&dmabuf->attributes,
device, is_opaque,
dmabuf->direct_display,
false,
try_view_on_plane_failure_reasons);
}
struct drm_fb *
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
bool is_opaque, enum drm_fb_type type)
@ -582,6 +641,7 @@ drm_fb_unref(struct drm_fb *fb)
gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
break;
case BUFFER_DMABUF:
case BUFFER_DMABUF_BACKEND:
drm_fb_destroy_dmabuf(fb);
break;
#endif
@ -674,7 +734,8 @@ drm_fb_handle_buffer_destroy(struct wl_listener *listener, void *data)
struct drm_fb *
drm_fb_get_from_paint_node(struct drm_output_state *state,
struct weston_paint_node *pnode)
struct weston_paint_node *pnode,
uint32_t *try_view_on_plane_failure_reasons)
{
struct drm_output *output = state->output;
struct drm_backend *b = output->backend;
@ -689,13 +750,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
if (ev->surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
ev->surface->desired_protection > output->base.current_protection) {
pnode->try_view_on_plane_failure_reasons |=
*try_view_on_plane_failure_reasons |=
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION;
return NULL;
}
if (!buffer) {
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
return NULL;
}
@ -711,7 +772,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
wl_list_for_each(buf_fb, &private->buffer_fb_list, link) {
if (buf_fb->device == device) {
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
return buf_fb->fb ? drm_fb_ref(buf_fb->fb) : NULL;
}
}
@ -722,7 +783,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
/* GBM is used for dmabuf import as well as from client wl_buffer. */
if (!b->gbm) {
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
goto unsuitable;
}
@ -741,13 +802,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
fb = drm_fb_get_from_bo(bo, device, is_opaque, BUFFER_CLIENT);
if (!fb) {
pnode->try_view_on_plane_failure_reasons |=
(1 << FAILURE_REASONS_ADD_FB_FAILED);
*try_view_on_plane_failure_reasons |=
FAILURE_REASONS_ADD_FB_FAILED;
gbm_bo_destroy(bo);
goto unsuitable;
}
} else {
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
goto unsuitable;
}
@ -776,7 +837,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
return fb;
unsuitable:
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
return NULL;
}
#endif

View file

@ -79,6 +79,27 @@ struct drm_property_enum_info plane_rotation_enums[] = {
},
};
struct drm_property_enum_info plane_color_encoding_enums[] = {
[WDRM_PLANE_COLOR_ENCODING_BT601] = {
.name = "ITU-R BT.601 YCbCr",
},
[WDRM_PLANE_COLOR_ENCODING_BT709] = {
.name = "ITU-R BT.709 YCbCr",
},
[WDRM_PLANE_COLOR_ENCODING_BT2020] = {
.name = "ITU-R BT.2020 YCbCr",
},
};
struct drm_property_enum_info plane_color_range_enums[] = {
[WDRM_PLANE_COLOR_RANGE_LIMITED] = {
.name = "YCbCr limited range",
},
[WDRM_PLANE_COLOR_RANGE_FULL] = {
.name = "YCbCr full range",
},
};
const struct drm_property_info plane_props[] = {
[WDRM_PLANE_TYPE] = {
.name = "type",
@ -105,6 +126,16 @@ const struct drm_property_info plane_props[] = {
.num_enum_values = WDRM_PLANE_ROTATION__COUNT,
},
[WDRM_PLANE_ALPHA] = { .name = "alpha" },
[WDRM_PLANE_COLOR_ENCODING] = {
.name = "COLOR_ENCODING",
.enum_values = plane_color_encoding_enums,
.num_enum_values = WDRM_PLANE_COLOR_ENCODING__COUNT,
},
[WDRM_PLANE_COLOR_RANGE] = {
.name = "COLOR_RANGE",
.enum_values = plane_color_range_enums,
.num_enum_values = WDRM_PLANE_COLOR_RANGE__COUNT,
},
};
struct drm_property_enum_info dpms_state_enums[] = {
@ -218,6 +249,9 @@ const struct drm_property_info connector_props[] = {
.enum_values = colorspace_enums,
.num_enum_values = WDRM_COLORSPACE__COUNT,
},
[WDRM_CONNECTOR_VRR_CAPABLE] = {
.name = "vrr_capable",
},
};
const struct drm_property_info crtc_props[] = {
@ -395,6 +429,17 @@ drm_rotation_from_output_transform(struct drm_plane *plane,
return out;
}
static int
wdrm_vrr_enabled_from_output(struct drm_output *drm_output)
{
struct weston_output *output = &drm_output->base;
if (output->vrr_mode == WESTON_VRR_MODE_GAME)
return 1;
return 0;
}
/**
* Cache DRM property values
*
@ -626,26 +671,36 @@ fallback:
return 0;
}
void
drm_output_set_gamma(struct weston_output *output_base,
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
bool
drm_plane_supports_color_encoding(struct drm_plane *plane,
enum wdrm_plane_color_encoding encoding)
{
int rc;
struct drm_output *output = to_drm_output(output_base);
struct drm_device *device = output->device;
const struct drm_property_info *info;
const struct drm_property_enum_info *enum_info;
assert(output);
assert(encoding >= 0);
assert(encoding < WDRM_PLANE_COLOR_ENCODING__COUNT);
/* check */
if (output_base->gamma_size != size)
return;
info = &plane->props[WDRM_PLANE_COLOR_ENCODING];
enum_info = &info->enum_values[encoding];
output->deprecated_gamma_is_set = true;
rc = drmModeCrtcSetGamma(device->drm.fd,
output->crtc->crtc_id,
size, r, g, b);
if (rc)
weston_log("set gamma failed: %s\n", strerror(errno));
return enum_info->valid;
}
bool
drm_plane_supports_color_range(struct drm_plane *plane,
enum wdrm_plane_color_range range)
{
const struct drm_property_info *info;
const struct drm_property_enum_info *enum_info;
assert(range >= 0);
assert(range < WDRM_PLANE_COLOR_RANGE__COUNT);
info = &plane->props[WDRM_PLANE_COLOR_RANGE];
enum_info = &info->enum_values[range];
return enum_info->valid;
}
/**
@ -765,7 +820,7 @@ err:
static void
drm_output_reset_legacy_gamma(struct drm_output *output)
{
uint32_t len = output->base.gamma_size;
uint32_t len = output->legacy_gamma_size;
uint16_t *lut;
uint32_t i;
int ret;
@ -820,18 +875,6 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
connectors[n_conn++] = head->connector.connector_id;
}
/* If disable_planes is set then assign_planes() wasn't
* called for this render, so we could still have a stale
* cursor plane set up.
*/
if (output->base.disable_planes) {
drm_output_set_cursor_view(output, NULL);
if (output->cursor_plane) {
output->cursor_plane->base.x = INT32_MIN;
output->cursor_plane->base.y = INT32_MIN;
}
}
if (state->dpms != WESTON_DPMS_ON) {
if (output->cursor_plane) {
ret = drmModeSetCursor(device->drm.fd, crtc->crtc_id,
@ -890,7 +933,6 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
goto err;
}
if (!output->deprecated_gamma_is_set)
drm_output_reset_legacy_gamma(output);
}
@ -1197,6 +1239,47 @@ drm_connector_set_colorspace(struct drm_connector *connector,
WDRM_CONNECTOR_COLORSPACE, enum_info->value);
}
static int
drm_plane_set_color_encoding(struct drm_plane *plane,
enum wdrm_plane_color_encoding color_encoding,
drmModeAtomicReq *req)
{
if (color_encoding == WDRM_PLANE_COLOR_ENCODING__COUNT)
return 0;
if (plane->props[WDRM_PLANE_COLOR_ENCODING].prop_id == 0) {
if (color_encoding == WDRM_PLANE_COLOR_ENCODING_DEFAULT)
return 0;
return -1;
}
assert(drm_plane_supports_color_encoding(plane, color_encoding));
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_ENCODING,
color_encoding);
}
static int
drm_plane_set_color_range(struct drm_plane *plane,
enum wdrm_plane_color_range color_range,
drmModeAtomicReq *req)
{
if (color_range == WDRM_PLANE_COLOR_RANGE__COUNT)
return 0;
if (plane->props[WDRM_PLANE_COLOR_RANGE].prop_id == 0) {
if (color_range == WDRM_PLANE_COLOR_RANGE_DEFAULT)
return 0;
return -1;
}
assert(drm_plane_supports_color_range(plane, color_range));
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_RANGE, color_range);
}
static int
drm_output_apply_state_atomic(struct drm_output_state *state,
drmModeAtomicReq *req,
@ -1238,14 +1321,18 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
current_mode->blob_id);
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 1);
if (!output->deprecated_gamma_is_set) {
ret |= crtc_add_prop_zero_ok(req, crtc,
WDRM_CRTC_GAMMA_LUT, 0);
ret |= crtc_add_prop_zero_ok(req, crtc,
WDRM_CRTC_DEGAMMA_LUT, 0);
}
if (output->base.from_blend_to_output_by_backend &&
output->blend_to_output_xform)
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_GAMMA_LUT,
output->blend_to_output_xform->blob_id);
else
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_GAMMA_LUT, 0);
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_DEGAMMA_LUT, 0);
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_CTM, 0);
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED, 0);
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED,
wdrm_vrr_enabled_from_output(output));
/* No need for the DPMS property, since it is implicit in
* routing and CRTC activity. */
@ -1265,6 +1352,11 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
ret |= connector_add_prop(req, &wb_state->wb->connector,
WDRM_CONNECTOR_WRITEBACK_OUT_FENCE_PTR,
(uintptr_t)&wb_state->out_fence_fd);
drm_debug(b, "\t\t\t[CONN:%lu] FORMAT: %s\n",
(unsigned long) wb_state->wb->connector.connector_id,
wb_state->fb->format->drm_format_name);
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY))
wb_state->state = DRM_OUTPUT_WB_SCREENSHOT_CHECK_FENCE;
}
@ -1282,11 +1374,13 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
wl_list_for_each(head, &output->base.head_list, base.output_link)
ret |= connector_add_prop(req, &head->connector,
WDRM_CONNECTOR_CRTC_ID, 0);
}
wl_list_for_each_safe(head, tmp, &output->disable_head,
disable_head_link) {
wl_list_for_each_safe(head, tmp, &output->disable_head, disable_head_link) {
ret |= connector_add_prop(req, &head->connector,
WDRM_CONNECTOR_CRTC_ID, 0);
*flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
wl_list_remove(&head->disable_head_link);
wl_list_init(&head->disable_head_link);
}
@ -1373,6 +1467,13 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
WDRM_PLANE_ALPHA,
plane_state->alpha);
ret |= drm_plane_set_color_encoding(plane,
plane_state->color_encoding,
req);
ret |= drm_plane_set_color_range(plane,
plane_state->color_range, req);
if (ret != 0) {
weston_log("couldn't set plane state\n");
return ret;
@ -1524,6 +1625,9 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
if (ret != 0) {
weston_log("atomic: couldn't compile atomic state\n");
if (mode == DRM_STATE_TEST_ONLY)
goto out_test_only;
else
goto out;
}
if (may_tear)
@ -1542,12 +1646,8 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
if (ret == 0)
drm_pending_state_clear_tearing(pending_state);
}
/* Test commits do not take ownership of the state; return
* without freeing here. */
if (mode == DRM_STATE_TEST_ONLY) {
drmModeAtomicFree(req);
return ret;
}
if (mode == DRM_STATE_TEST_ONLY)
goto out_test_only;
if (ret != 0) {
wl_list_for_each(output_state, &pending_state->output_list, link)
@ -1568,8 +1668,11 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
assert(wl_list_empty(&pending_state->output_list));
out:
drmModeAtomicFree(req);
drm_pending_state_free(pending_state);
/* Test commits do not take ownership of the state; return
* without freeing here. */
out_test_only:
drmModeAtomicFree(req);
return ret;
}
@ -1665,6 +1768,9 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
if (b->compositor->renderer->type == WESTON_RENDERER_GL) {
drm_output_fini_egl(output);
drm_output_init_egl(output, b);
} else if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
drm_output_fini_vulkan(output);
drm_output_init_vulkan(output, b);
}
}
}
@ -1758,6 +1864,7 @@ page_flip_handler(int fd, unsigned int frame,
assert(output->page_flip_pending);
output->page_flip_pending = false;
output->page_flips_counted++;
drm_output_update_complete(output, flags, sec, usec);
}
@ -1771,6 +1878,8 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
struct drm_crtc *crtc;
struct drm_output *output;
struct timespec now;
float page_flips_per_timer_interval;
uint32_t frame_counter_interval;
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
@ -1786,6 +1895,14 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
if (!output || !output->base.enabled)
return;
output->page_flips_counted++;
/* store them temporarily as drm_output_update_complete might destroy
* the output */
page_flips_per_timer_interval = output->page_flips_per_timer_interval;
frame_counter_interval =
output->backend->perf_page_flips_stats.frame_counter_interval;
drm_output_update_msc(output, frame);
if (output->state_cur->tear) {
@ -1806,6 +1923,8 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
drm_output_update_complete(output, flags, sec, usec);
drm_debug(b, "[atomic][CRTC:%u] flip processing completed\n", crtc_id);
drm_debug(b, "[atomic][CRTC:%u] %.2f page flips computed in %d seconds\n",
crtc_id, page_flips_per_timer_interval, frame_counter_interval);
}
int
@ -1875,10 +1994,29 @@ init_kms_caps(struct drm_device *device)
return -1;
}
if (!getenv("WESTON_DISABLE_ATOMIC")) {
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
if (ret != 0)
cap = 0;
/* Between Linux 3.16 and Linux 4.1 there was a bug that
* could result in a stale timestamp being returned.
*
* The workaround for this has can make it impossible
* to display images with precise timing.
*
* It's somewhat difficult to determine whether we need
* that workaround or not, but we know that the
* DRM_CAP_CRTC_IN_VBLANK_EVENT drm cap exists in 4.12
* and on. We'll use its presence to gate the workaround.
*/
if (!cap) {
weston_log("DRM Warning: stale timestamp workaround for Kernel older than 4.12\n");
device->backend->stale_timestamp_workaround = true;
} else {
device->backend->stale_timestamp_workaround = false;
}
if (!getenv("WESTON_DISABLE_ATOMIC")) {
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
device->atomic_modeset = ((ret == 0) && (cap == 1));
}

View file

@ -2,20 +2,6 @@ if not get_option('backend-drm')
subdir_done()
endif
dep_libdisplay_info = dependency(
'libdisplay-info',
version: ['>= 0.1.1', '< 0.3.0'],
fallback: ['display-info', 'di_dep'],
default_options: [
'werror=false',
],
required: true,
not_found_message: 'Required by DRM-backend.',
)
if dep_libdisplay_info.version().version_compare('>= 0.2.0')
config_h.set('HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY', '1')
endif
lib_backlight = static_library(
'backlight',
'libbacklight.c',
@ -48,6 +34,7 @@ srcs_drm = [
deps_drm = [
dep_egl, # optional
dep_vulkan, # optional
dep_libm,
dep_libdl,
dep_libshared,
@ -69,7 +56,17 @@ if get_option('renderer-gl')
config_h.set('BUILD_DRM_GBM', '1')
endif
if get_option('backend-drm-screencast-vaapi')
if get_option('renderer-vulkan')
if not dep_gbm.found()
error('drm-backend with Vulkan renderer requires gbm which was not found. Or, you can use \'-Drenderer-vulkan=false\'.')
endif
deps_drm += dep_gbm
srcs_drm += 'drm-gbm.c'
config_h.set('BUILD_DRM_GBM', '1')
endif
if get_option('deprecated-backend-drm-screencast-vaapi')
warning('deprecated-backend-drm-screencast-vaapi enabled. This option will be removed in future versions.')
foreach name : [ 'libva', 'libva-drm' ]
d = dependency(name, version: '>= 0.34.0', required: false)
if not d.found()

View file

@ -31,6 +31,8 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <libdisplay-info/cta.h>
#include <libdisplay-info/edid.h>
#include <libdisplay-info/info.h>
#include "drm-internal.h"
@ -51,6 +53,10 @@ struct drm_head_info {
* enum weston_colorimetry_mode bits.
*/
uint32_t colorimetry_mask;
/* The monitor supported color foramts, combination of
* enum_weston_color_format bits. */
uint32_t color_format_mask;
};
static void
@ -227,8 +233,6 @@ parse_modeline(const char *s, drmModeModeInfo *mode)
return 0;
}
#ifdef HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY
static uint32_t
get_eotf_mask(const struct di_info *info)
{
@ -284,21 +288,75 @@ get_colorimetry_mask(const struct di_info *info)
return mask;
}
#else /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
static uint32_t
get_eotf_mask(const struct di_info *info)
static bool
has_yuv420_cap_map(const struct di_edid_cta *cta)
{
return WESTON_EOTF_MODE_SDR;
const struct di_cta_data_block *const *data_blocks;
enum di_cta_data_block_tag db_tag;
int i;
data_blocks = di_edid_cta_get_data_blocks(cta);
for (i = 0; data_blocks[i] != NULL; i++) {
db_tag = di_cta_data_block_get_tag(data_blocks[i]);
if (db_tag == DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP)
return true;
}
return false;
}
static uint32_t
get_colorimetry_mask(const struct di_info *info)
get_color_format_mask(const struct di_info *info)
{
return WESTON_COLORIMETRY_MODE_DEFAULT;
}
const struct di_edid *edid = di_info_get_edid(info);
const struct di_edid_color_encoding_formats *fmts =
di_edid_get_color_encoding_formats(edid);
const struct di_edid_ext *const *exts = di_edid_get_extensions(edid);
uint32_t mask = WESTON_COLOR_FORMAT_AUTO;
int i;
#endif /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
if (fmts) {
if (fmts->rgb444)
mask |= WESTON_COLOR_FORMAT_RGB;
if (fmts->ycrcb444)
mask |= WESTON_COLOR_FORMAT_YUV444;
if (fmts->ycrcb422)
mask |= WESTON_COLOR_FORMAT_YUV422;
}
for (i = 0; exts[i] ; i++) {
const struct di_edid_cta *cta;
const struct di_edid_cta_flags *cta_flags;
switch (di_edid_ext_get_tag(exts[i])) {
case DI_EDID_EXT_CEA:
cta = di_edid_ext_get_cta(exts[i]);
cta_flags = di_edid_cta_get_flags(cta);
mask |= WESTON_COLOR_FORMAT_RGB;
if (cta_flags->ycc444)
mask |= WESTON_COLOR_FORMAT_YUV444;
if (cta_flags->ycc422)
mask |= WESTON_COLOR_FORMAT_YUV422;
/* FIXME: YUV420 detection is really complicated,
* do it properly at some point...
*/
if (has_yuv420_cap_map(cta))
mask |= WESTON_COLOR_FORMAT_YUV420;
break;
default:
break;
}
}
return mask;
}
static struct di_info *
drm_head_info_from_edid(struct drm_head_info *dhi,
@ -325,6 +383,7 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
dhi->serial_number = di_info_get_serial(di_ctx);
dhi->eotf_mask = get_eotf_mask(di_ctx);
dhi->colorimetry_mask = get_colorimetry_mask(di_ctx);
dhi->color_format_mask = get_color_format_mask(di_ctx);
return di_ctx;
}
@ -597,26 +656,46 @@ void
update_head_from_connector(struct drm_head *head)
{
struct drm_connector *connector = &head->connector;
struct drm_backend *b = head->connector.device->backend;
drmModeObjectProperties *props = connector->props_drm;
drmModeConnector *conn = connector->conn;
int vrr_capable;
uint32_t vrr_mode_mask = 0;
uint32_t conn_id = head->connector.connector_id;
bool ret;
weston_head_set_non_desktop(&head->base,
ret = weston_head_set_non_desktop(&head->base,
check_non_desktop(connector, props));
weston_head_set_subpixel(&head->base,
if (ret)
drm_debug(b, "\t[CONN:%d] non-desktop property changed\n", conn_id);
ret = weston_head_set_subpixel(&head->base,
drm_subpixel_to_wayland(conn->subpixel));
if (ret)
drm_debug(b, "\t[CONN:%d] subpixel property changed\n", conn_id);
weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
ret = weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
if (ret)
drm_debug(b, "\t[CONN:%d] physical size changed\n", conn_id);
weston_head_set_transform(&head->base,
ret = weston_head_set_transform(&head->base,
get_panel_orientation(connector, props));
if (ret)
drm_debug(b, "\t[CONN:%d] transform property changed\n", conn_id);
/* Unknown connection status is assumed disconnected. */
weston_head_set_connection_status(&head->base,
ret = weston_head_set_connection_status(&head->base,
conn->connection == DRM_MODE_CONNECTED);
if (ret)
drm_debug(b, "\t[CONN:%d] connection status changed\n", conn_id);
/* If EDID did not change, skip everything about it */
if (!drm_head_maybe_update_display_data(head, props))
if (!drm_head_maybe_update_display_data(head, props)) {
if (!ret)
drm_debug(b, "\t[CONN:%d] Hot-plug event received "
"but no connector changes detected\n", conn_id);
return;
}
struct drm_head_info dhi;
@ -630,11 +709,18 @@ update_head_from_connector(struct drm_head *head)
dhi.serial_number);
prune_eotf_modes_by_kms_support(head, &dhi.eotf_mask);
weston_head_set_supported_eotf_mask(&head->base, dhi.eotf_mask);
dhi.colorimetry_mask &= drm_head_get_kms_colorimetry_modes(head);
weston_head_set_supported_colorimetry_mask(&head->base, dhi.colorimetry_mask);
vrr_capable = drm_property_get_value(&head->connector.props[WDRM_CONNECTOR_VRR_CAPABLE],
head->connector.props_drm, 0);
if (vrr_capable)
vrr_mode_mask = WESTON_VRR_MODE_GAME;
weston_head_set_supported_vrr_modes_mask(&head->base, vrr_mode_mask);
drm_head_info_fini(&dhi);
}

View file

@ -55,6 +55,9 @@ drm_plane_state_alloc(struct drm_output_state *state_output,
state->alpha = (plane->alpha_max < DRM_PLANE_ALPHA_OPAQUE) ?
plane->alpha_max : DRM_PLANE_ALPHA_OPAQUE;
state->color_encoding = WDRM_PLANE_COLOR_ENCODING__COUNT;
state->color_range = WDRM_PLANE_COLOR_RANGE__COUNT;
/* Here we only add the plane state to the desired link, and not
* set the member. Having an output pointer set means that the
* plane will be displayed on the output; this won't be the case
@ -213,7 +216,7 @@ drm_plane_state_put_back(struct drm_plane_state *state)
* Given a weston_view, fill the drm_plane_state's co-ordinates to display on
* a given plane.
*/
bool
void
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
struct weston_paint_node *node,
uint64_t zpos)
@ -228,8 +231,11 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
uint16_t min_alpha = state->plane->alpha_min;
uint16_t max_alpha = state->plane->alpha_max;
if (!drm_paint_node_transform_supported(node, state->plane))
return false;
/* The caller has already checked supported transforms when creating
* a list of candidate planes, so we should only ever get here with
* a supported transform.
*/
assert(drm_paint_node_transform_supported(node, state->plane));
assert(node->valid_transform);
state->rotation = drm_rotation_from_output_transform(state->plane, node->transform);
@ -312,8 +318,6 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
* never exceed max_alpha if ev->alpha <= 1.0.
*/
state->alpha = min_alpha + (uint16_t)round((max_alpha - min_alpha) * ev->alpha);
return true;
}
/**
@ -403,6 +407,9 @@ drm_output_state_duplicate(struct drm_output_state *src,
assert(dst);
/* The reuse bit isn't stored in the state */
assert(!(src->mode & DRM_OUTPUT_PROPOSE_STATE_REUSE));
/* Copy the whole structure, then individually modify the
* pending_state, as well as the list link into our pending
* state. */

File diff suppressed because it is too large Load diff

View file

@ -42,7 +42,8 @@
#include "pixel-formats.h"
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "gl-borders.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "renderer-borders.h"
#include "shared/weston-drm-fourcc.h"
#include "shared/weston-egl-ext.h"
#include "shared/cairo-util.h"
@ -69,6 +70,8 @@ struct headless_backend {
int refresh;
bool repaint_only_on_capture;
bool use_fake_seat;
};
struct headless_head {
@ -81,12 +84,10 @@ struct headless_output {
struct weston_mode mode;
struct wl_event_source *finish_frame_timer;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
struct frame *frame;
struct {
struct weston_gl_borders borders;
} gl;
struct weston_renderer_borders borders;
};
static const uint32_t headless_formats[] = {
@ -144,14 +145,14 @@ finish_frame_handler(void *data)
}
static void
headless_output_update_gl_border(struct headless_output *output)
headless_output_update_renderer_border(struct headless_output *output)
{
if (!output->frame)
return;
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
return;
weston_gl_borders_update(&output->gl.borders, output->frame,
weston_renderer_borders_update(&output->borders, output->frame,
&output->base);
}
@ -161,13 +162,12 @@ headless_output_repaint(struct weston_output *output_base)
struct headless_output *output = to_headless_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
int delay_msec;
assert(output);
ec = output->base.compositor;
headless_output_update_gl_border(output);
headless_output_update_renderer_border(output);
pixman_region32_init(&damage);
@ -178,8 +178,7 @@ headless_output_repaint(struct weston_output *output_base)
pixman_region32_fini(&damage);
delay_msec = millihz_to_nsec(output->mode.refresh) / 1000000;
wl_event_source_timer_update(output->finish_frame_timer, delay_msec);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;
}
@ -190,9 +189,9 @@ headless_output_disable_gl(struct headless_output *output)
struct weston_compositor *compositor = output->base.compositor;
const struct weston_renderer *renderer = compositor->renderer;
weston_gl_borders_fini(&output->gl.borders, &output->base);
weston_renderer_borders_fini(&output->borders, &output->base);
weston_renderbuffer_unref(output->renderbuffer);
renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
renderer->gl->output_destroy(&output->base);
@ -202,12 +201,30 @@ headless_output_disable_gl(struct headless_output *output)
}
}
static void
headless_output_disable_vulkan(struct headless_output *output)
{
struct weston_compositor *compositor = output->base.compositor;
const struct weston_renderer *renderer = compositor->renderer;
weston_renderer_borders_fini(&output->borders, &output->base);
renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
renderer->vulkan->output_destroy(&output->base);
if (output->frame) {
frame_destroy(output->frame);
output->frame = NULL;
}
}
static void
headless_output_disable_pixman(struct headless_output *output)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
weston_renderbuffer_unref(output->renderbuffer);
renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
renderer->pixman->output_destroy(&output->base);
}
@ -231,6 +248,9 @@ headless_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
headless_output_disable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
headless_output_disable_vulkan(output);
break;
case WESTON_RENDERER_PIXMAN:
headless_output_disable_pixman(output);
break;
@ -301,9 +321,8 @@ headless_output_enable_gl(struct headless_output *output)
}
output->renderbuffer =
renderer->gl->create_fbo(&output->base, b->formats[0],
options.fb_size.width,
options.fb_size.height, NULL);
renderer->create_renderbuffer(&output->base, b->formats[0],
NULL, 0, NULL, NULL);
if (!output->renderbuffer)
goto err_renderbuffer;
@ -315,10 +334,67 @@ err_renderbuffer:
return -1;
}
static int
headless_output_enable_vulkan(struct headless_output *output)
{
struct headless_backend *b = output->backend;
const struct weston_renderer *renderer = b->compositor->renderer;
const struct weston_mode *mode = output->base.current_mode;
struct vulkan_renderer_surfaceless_options options = { 0 };
if (b->decorate) {
/*
* Start with a dummy exterior size and then resize, because
* there is no frame_create() with interior size.
*/
output->frame = frame_create(b->theme, 100, 100,
FRAME_BUTTON_CLOSE, NULL, NULL);
if (!output->frame) {
weston_log("failed to create frame for output\n");
return -1;
}
frame_resize_inside(output->frame, mode->width, mode->height);
options.fb_size.width = frame_width(output->frame);
options.fb_size.height = frame_height(output->frame);
frame_interior(output->frame, &options.area.x, &options.area.y,
&options.area.width, &options.area.height);
} else {
options.area.x = 0;
options.area.y = 0;
options.area.width = mode->width;
options.area.height = mode->height;
options.fb_size.width = mode->width;
options.fb_size.height = mode->height;
}
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
weston_log("failed to create vulkan renderer output state\n");
if (output->frame) {
frame_destroy(output->frame);
output->frame = NULL;
}
return -1;
}
output->renderbuffer =
renderer->create_renderbuffer(&output->base, b->formats[0],
NULL, 0, NULL, NULL);
if (!output->renderbuffer)
goto err_renderbuffer;
return 0;
err_renderbuffer:
renderer->vulkan->output_destroy(&output->base);
return -1;
}
static int
headless_output_enable_pixman(struct headless_output *output)
{
const struct pixman_renderer_interface *pixman;
struct weston_renderer *renderer = output->base.compositor->renderer;
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
@ -328,22 +404,19 @@ headless_output_enable_pixman(struct headless_output *output)
.format = pixel_format_get_info(headless_formats[0])
};
pixman = output->base.compositor->renderer->pixman;
if (pixman->output_create(&output->base, &options) < 0)
if (renderer->pixman->output_create(&output->base, &options) < 0)
return -1;
output->renderbuffer =
pixman->create_image(&output->base, options.format,
output->base.current_mode->width,
output->base.current_mode->height);
renderer->create_renderbuffer(&output->base, options.format,
NULL, 0, NULL, NULL);
if (!output->renderbuffer)
goto err_renderer;
return 0;
err_renderer:
pixman->output_destroy(&output->base);
renderer->pixman->output_destroy(&output->base);
return -1;
}
@ -373,6 +446,9 @@ headless_output_enable(struct weston_output *base)
case WESTON_RENDERER_GL:
ret = headless_output_enable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
ret = headless_output_enable_vulkan(output);
break;
case WESTON_RENDERER_PIXMAN:
ret = headless_output_enable_pixman(output);
break;
@ -390,6 +466,19 @@ headless_output_enable(struct weston_output *base)
return 0;
}
static void
headless_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct headless_output *output = to_headless_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
headless_output_set_size(struct weston_output *base,
int width, int height)
@ -431,7 +520,7 @@ headless_output_set_size(struct weston_output *base,
output->base.repaint = headless_output_repaint;
output->base.assign_planes = NULL;
output->base.set_backlight = NULL;
output->base.set_dpms = NULL;
output->base.set_dpms = headless_set_dpms;
output->base.switch_mode = NULL;
return 0;
@ -511,6 +600,25 @@ headless_head_destroy(struct weston_head *base)
free(head);
}
static bool
headless_input_create(struct headless_backend *b)
{
weston_seat_init(&b->fake_seat, b->compositor, "default");
weston_seat_init_pointer(&b->fake_seat);
if (weston_seat_init_keyboard(&b->fake_seat, NULL) < 0)
return false;
return true;
}
static void
headless_input_destroy(struct headless_backend *b)
{
weston_seat_release(&b->fake_seat);
}
static void
headless_destroy(struct weston_backend *backend)
{
@ -528,6 +636,9 @@ headless_destroy(struct weston_backend *backend)
if (b->theme)
theme_destroy(b->theme);
if (b->use_fake_seat)
headless_input_destroy(b);
free(b->formats);
free(b);
@ -559,6 +670,12 @@ headless_backend_create(struct weston_compositor *compositor,
b->base.supported_presentation_clocks =
WESTON_PRESENTATION_CLOCKS_SOFTWARE;
if (config->fake_seat) {
b->use_fake_seat = headless_input_create(b);
if (!b->use_fake_seat)
goto err_free;
}
b->base.destroy = headless_destroy;
b->base.create_output = headless_output_create;
@ -600,6 +717,16 @@ headless_backend_create(struct weston_compositor *compositor,
&options.base);
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
ret = weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base);
break;
}
case WESTON_RENDERER_PIXMAN:
if (config->decorate) {
weston_log("Error: Pixman renderer does not support decorations.\n");
@ -647,6 +774,8 @@ err_input:
if (b->theme)
theme_destroy(b->theme);
err_free:
if (b->use_fake_seat)
headless_input_destroy(b);
wl_list_remove(&b->base.link);
free(b);
return NULL;
@ -656,6 +785,7 @@ static void
config_init_to_defaults(struct weston_headless_backend_config *config)
{
config->refresh = DEFAULT_OUTPUT_REPAINT_REFRESH;
config->fake_seat = false;
}
WL_EXPORT int

View file

@ -17,7 +17,7 @@ plugin_headless = shared_library(
dep_libweston_private,
dep_libdrm_headers,
dep_lib_cairo_shared,
dep_lib_gl_borders,
dep_lib_renderer_borders,
],
name_prefix: '',
install: true,

View file

@ -56,9 +56,11 @@
#include <libweston/backend-pipewire.h>
#include <libweston/linux-dmabuf.h>
#include <libweston/weston-log.h>
#include "output-capture.h"
#include "pixel-formats.h"
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-egl-ext.h"
struct pipewire_backend {
@ -101,7 +103,7 @@ struct pipewire_head {
};
struct pipewire_frame_data {
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
struct pipewire_memfd *memfd;
struct pipewire_dmabuf *dmabuf;
};
@ -266,14 +268,16 @@ pipewire_output_connect(struct pipewire_output *output)
/* TODO: Add support for modifier discovery and negotiation. */
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
params[i++] = spa_pod_build_format(&builder,
output->base.width, output->base.height,
output->base.current_mode->width,
output->base.current_mode->height,
output->base.current_mode->refresh / 1000,
output->pixel_format->format,
modifier);
}
params[i++] = spa_pod_build_format(&builder,
output->base.width, output->base.height,
output->base.current_mode->width,
output->base.current_mode->height,
output->base.current_mode->refresh / 1000,
output->pixel_format->format, NULL);
@ -307,8 +311,8 @@ pipewire_output_enable_pixman(struct pipewire_output *output)
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.format = output->pixel_format,
};
@ -347,6 +351,29 @@ pipewire_output_enable_gl(struct pipewire_output *output)
return renderer->gl->output_fbo_create(&output->base, &options);
}
static int
pipewire_output_enable_vulkan(struct pipewire_output *output)
{
struct pipewire_backend *b = output->backend;
struct weston_renderer *renderer = b->compositor->renderer;
const struct weston_size fb_size = {
output->base.current_mode->width,
output->base.current_mode->height
};
const struct weston_geometry area = {
.x = 0,
.y = 0,
.width = fb_size.width,
.height = fb_size.height
};
const struct vulkan_renderer_surfaceless_options options = {
.fb_size = fb_size,
.area = area,
};
return renderer->vulkan->output_surfaceless_create(&output->base, &options);
}
static void
pipewire_output_disable_gl(struct pipewire_output *output)
{
@ -355,6 +382,14 @@ pipewire_output_disable_gl(struct pipewire_output *output)
renderer->gl->output_destroy(&output->base);
}
static void
pipewire_output_disable_vulkan(struct pipewire_output *output)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
renderer->vulkan->output_destroy(&output->base);
}
static int
pipewire_output_enable(struct weston_output *base)
{
@ -373,6 +408,9 @@ pipewire_output_enable(struct weston_output *base)
case WESTON_RENDERER_GL:
ret = pipewire_output_enable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
ret = pipewire_output_enable_vulkan(output);
break;
default:
unreachable("Valid renderer should have been selected");
}
@ -398,6 +436,9 @@ err:
case WESTON_RENDERER_GL:
pipewire_output_disable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
pipewire_output_disable_vulkan(output);
break;
default:
unreachable("Valid renderer should have been selected");
}
@ -426,6 +467,9 @@ pipewire_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
pipewire_output_disable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
pipewire_output_disable_vulkan(output);
break;
default:
unreachable("Valid renderer should have been selected");
}
@ -490,8 +534,8 @@ pipewire_output_create_dmabuf(struct pipewire_output *output)
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
width = output->base.current_mode->width;
height = output->base.current_mode->height;
linux_dmabuf_memory = renderer->dmabuf_alloc(renderer, width, height,
format->format,
@ -593,59 +637,6 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
pw_stream_update_params(output->stream, params, 2);
}
static struct weston_renderbuffer *
pipewire_output_stream_add_buffer_pixman(struct pipewire_output *output,
struct pw_buffer *buffer)
{
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
struct spa_buffer *buf = buffer->buffer;
struct spa_data *d = buf->datas;
const struct pixel_format_info *format;
unsigned int width;
unsigned int height;
unsigned int stride;
void *ptr;
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
stride = width * format->bpp / 8;
ptr = d[0].data;
return renderer->pixman->create_image_from_ptr(&output->base,
format, width, height,
ptr, stride);
}
static struct weston_renderbuffer *
pipewire_output_stream_add_buffer_gl(struct pipewire_output *output,
struct pw_buffer *buffer)
{
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
struct spa_buffer *buf = buffer->buffer;
struct spa_data *d = buf->datas;
const struct pixel_format_info *format;
unsigned int width;
unsigned int height;
void *ptr;
struct pipewire_frame_data *frame_data = buffer->user_data;
struct pipewire_dmabuf *dmabuf = frame_data->dmabuf;
if (dmabuf)
return renderer->create_renderbuffer_dmabuf(&output->base,
dmabuf->linux_dmabuf_memory);
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
ptr = d[0].data;
return renderer->gl->create_fbo(&output->base,
format, width, height, ptr);
}
struct pipewire_memfd {
int fd;
unsigned int size;
@ -665,8 +656,8 @@ pipewire_output_create_memfd(struct pipewire_output *output)
memfd = xzalloc(sizeof *memfd);
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
width = output->base.current_mode->width;
height = output->base.current_mode->height;
stride = width * format->bpp / 8;
size = height * stride;
@ -755,8 +746,15 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
return;
}
pipewire_output_setup_dmabuf(output, buffer, dmabuf);
frame_data->renderbuffer =
renderer->create_renderbuffer_dmabuf(&output->base,
dmabuf->linux_dmabuf_memory,
NULL, NULL);
frame_data->dmabuf = dmabuf;
} else if (buffertype & (1u << SPA_DATA_MemFd)) {
const struct pixel_format_info *format = output->pixel_format;
int stride = output->base.current_mode->width * format->bpp / 8;
struct pipewire_memfd *memfd;
memfd = pipewire_output_create_memfd(output);
@ -766,18 +764,12 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
return;
}
pipewire_output_setup_memfd(output, buffer, memfd);
frame_data->memfd = memfd;
}
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN:
frame_data->renderbuffer = pipewire_output_stream_add_buffer_pixman(output, buffer);
break;
case WESTON_RENDERER_GL:
frame_data->renderbuffer = pipewire_output_stream_add_buffer_gl(output, buffer);
break;
default:
unreachable("Valid renderer should have been selected");
frame_data->renderbuffer =
renderer->create_renderbuffer(&output->base, format,
d[0].data, stride, NULL,
NULL);
frame_data->memfd = memfd;
}
}
@ -800,21 +792,20 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
pipewire_output_debug(output, "remove buffer: %p", buffer);
if (frame_data->dmabuf) {
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
renderer->remove_renderbuffer_dmabuf(&output->base,
frame_data->renderbuffer);
if (frame_data->dmabuf)
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
}
if (frame_data->memfd) {
munmap(d[0].data, d[0].maxsize);
pipewire_destroy_memfd(output, frame_data->memfd);
}
if (frame_data->renderbuffer)
weston_renderbuffer_unref(frame_data->renderbuffer);
if (frame_data->renderbuffer) {
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
renderer->destroy_renderbuffer(frame_data->renderbuffer);
}
wl_list_for_each(fence_data, &output->fence_list, link) {
if (fence_data->buffer == buffer)
fence_data->buffer = NULL;
@ -955,7 +946,7 @@ pipewire_submit_buffer(struct pipewire_output *output,
if (dmabuf)
stride = dmabuf->linux_dmabuf_memory->attributes->stride[0];
else
stride = output->base.width * pixel_format->bpp / 8;
stride = output->base.current_mode->width * pixel_format->bpp / 8;
size = output->base.height * stride;
spa_buffer = buffer->buffer;
@ -1008,9 +999,20 @@ pipewire_schedule_submit_buffer(struct pipewire_output *output,
struct wl_event_loop *loop;
int fence_sync_fd;
switch (renderer->type) {
case WESTON_RENDERER_GL:
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
if (fence_sync_fd == -1)
return -1;
break;
case WESTON_RENDERER_VULKAN:
fence_sync_fd = renderer->vulkan->create_fence_fd(&output->base);
if (fence_sync_fd == -1)
return -1;
break;
default:
unreachable("invalid renderer");
}
fence_data = zalloc(sizeof *fence_data);
if (!fence_data) {
@ -1042,6 +1044,7 @@ pipewire_output_repaint(struct weston_output *base)
struct pipewire_frame_data *frame_data;
pixman_region32_t damage;
bool submit_scheduled = false;
bool rendered = false;
assert(output);
@ -1052,7 +1055,8 @@ pipewire_output_repaint(struct weston_output *base)
weston_output_flush_damage_for_primary_plane(base, &damage);
if (!pixman_region32_not_empty(&damage))
if (!pixman_region32_not_empty(&damage) &&
!weston_output_has_renderer_capture_tasks(base))
goto out;
buffer = pw_stream_dequeue_buffer(output->stream);
@ -1063,9 +1067,10 @@ pipewire_output_repaint(struct weston_output *base)
pipewire_output_debug(output, "dequeued buffer: %p", buffer);
frame_data = buffer->user_data;
if (frame_data->renderbuffer)
if (frame_data->renderbuffer) {
ec->renderer->repaint_output(&output->base, &damage, frame_data->renderbuffer);
else
rendered = true;
} else
output->base.full_repaint_needed = true;
if (buffer->buffer->datas[0].type == SPA_DATA_DmaBuf) {
@ -1076,6 +1081,21 @@ pipewire_output_repaint(struct weston_output *base)
pipewire_submit_buffer(output, buffer);
out:
/* We didn't have anywhere to render to, so capture tasks could be
* left dangling. Shoot them down.
*/
if (!rendered && weston_output_has_renderer_capture_tasks(base)) {
int width = base->current_mode->width;
int height = base->current_mode->height;
struct weston_capture_task *ct;
while ((ct = weston_output_pull_capture_task(base,
WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER,
width, height,
ec->read_format,
NULL)))
weston_capture_task_retire_failed(ct, "No pipewire buffer");
}
pixman_region32_fini(&damage);
@ -1116,6 +1136,19 @@ pipewire_ensure_matching_mode(struct weston_output *output, struct weston_mode *
target->refresh);
}
static void
pipewire_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct pipewire_output *output = to_pipewire_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
{
@ -1142,14 +1175,13 @@ pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode
}
static int
pipewire_output_set_size(struct weston_output *base, int width, int height)
pipewire_output_set_size(struct weston_output *base, int width, int height, int framerate)
{
struct pipewire_output *output = to_pipewire_output(base);
struct weston_head *head;
struct pipewire_head *pw_head;
struct weston_mode *current_mode;
struct weston_mode init_mode;
int framerate = -1;
/* We can only be called once. */
assert(!output->base.current_mode);
@ -1161,6 +1193,7 @@ pipewire_output_set_size(struct weston_output *base, int width, int height)
width = pw_head->config.width;
if (height == -1)
height = pw_head->config.height;
if (framerate == -1)
framerate = pw_head->config.framerate;
}
if (framerate == -1 || width == -1 || height == -1)
@ -1179,7 +1212,7 @@ pipewire_output_set_size(struct weston_output *base, int width, int height)
output->base.repaint = pipewire_output_repaint;
output->base.assign_planes = NULL;
output->base.set_backlight = NULL;
output->base.set_dpms = NULL;
output->base.set_dpms = pipewire_set_dpms;
output->base.switch_mode = pipewire_switch_mode;
return 0;
@ -1352,6 +1385,16 @@ pipewire_backend_create(struct weston_compositor *compositor,
&options.base);
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = backend->formats,
.formats_count = backend->formats_count,
};
ret = weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base);
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_compositor;
@ -1417,6 +1460,7 @@ weston_backend_init(struct weston_compositor *compositor,
switch (compositor->renderer->type) {
case WESTON_RENDERER_PIXMAN:
case WESTON_RENDERER_GL:
case WESTON_RENDERER_VULKAN:
break;
default:
weston_log("Renderer not supported by PipeWire backend\n");

View file

@ -9,6 +9,7 @@ dep_frdp2 = dependency('freerdp2', version: '>= 2.3.0', required: false)
if dep_frdp3.found()
config_h.set('USE_FREERDP_VERSION', '3')
config_h.set('WITHOUT_FREERDP_3x_DEPRECATED', '1')
dep_frdp = dep_frdp3
dep_frdp_server = dependency('freerdp-server3', version: '>= 3.0.0', required: false)
if not dep_frdp_server.found()

View file

@ -46,6 +46,7 @@
#include <libweston/pixel-formats.h>
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-egl-ext.h"
/* These can be removed when we bump FreeRDP dependency past 3.0.0 in the future */
@ -58,6 +59,12 @@
extern PWtsApiFunctionTable FreeRDP_InitWtsApi(void);
static struct rdp_buffer *
rdp_buffer_create(struct rdp_output *output);
static void
rdp_buffer_destroy(struct rdp_buffer *buffer);
static BOOL
xf_peer_adjust_monitor_layout(freerdp_peer *client);
@ -261,11 +268,11 @@ rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer)
rdpSettings *settings = peer->context->settings;
if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec))
rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
rdp_peer_refresh_rfx(region, output->buffer->shadow_surface, peer);
else if (freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
rdp_peer_refresh_nsc(region, output->buffer->shadow_surface, peer);
else
rdp_peer_refresh_raw(region, output->shadow_surface, peer);
rdp_peer_refresh_raw(region, output->buffer->shadow_surface, peer);
}
static int
@ -295,7 +302,7 @@ rdp_output_repaint(struct weston_output *output_base)
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(&output->base, &damage,
output->renderbuffer);
output->buffer->rb);
if (pixman_region32_not_empty(&damage)) {
pixman_region32_t transformed_damage;
@ -346,53 +353,15 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
struct weston_output *output = base;
struct rdp_peers_item *rdpPeer;
rdpSettings *settings;
struct weston_renderbuffer *new_renderbuffer;
mode->refresh = b->rdp_monitor_refresh_rate;
weston_output_set_single_mode(base, mode);
if (base->enabled) {
const struct weston_renderer *renderer;
pixman_image_t *new_image;
if (base->enabled)
weston_renderer_resize_output(output, &(struct weston_size){
.width = output->current_mode->width,
.height = output->current_mode->height }, NULL);
new_image = pixman_image_create_bits(b->formats[0]->pixman_format,
mode->width, mode->height,
NULL, mode->width * 4);
renderer = b->compositor->renderer;
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_interface *pixman;
pixman = renderer->pixman;
new_renderbuffer =
pixman->create_image_from_ptr(output, b->formats[0],
mode->width, mode->height,
pixman_image_get_data(new_image),
mode->width * 4);
break;
}
case WESTON_RENDERER_GL:
new_renderbuffer =
renderer->gl->create_fbo(output, b->formats[0],
mode->width, mode->height,
pixman_image_get_data(new_image));
break;
default:
unreachable("cannot have auto renderer at runtime");
}
pixman_image_composite32(PIXMAN_OP_SRC, rdpOutput->shadow_surface,
0, new_image, 0, 0, 0, 0, 0, 0,
mode->width, mode->height);
weston_renderbuffer_unref(rdpOutput->renderbuffer);
rdpOutput->renderbuffer = new_renderbuffer;
pixman_image_unref(rdpOutput->shadow_surface);
rdpOutput->shadow_surface = new_image;
}
/* Apparently settings->DesktopWidth is supposed to be primary only.
* For now we only work with a single monitor, so we don't need to
* check that we're primary here.
@ -415,6 +384,19 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
}
}
static void
rdp_output_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct rdp_output *output = to_rdp_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
rdp_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
{
@ -436,11 +418,88 @@ rdp_head_get_monitor(struct weston_head *base,
monitor->desktop_scale = h->config.attributes.desktopScaleFactor;
}
static bool
rdp_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
{
struct rdp_buffer *buffer = (struct rdp_buffer *) data;
struct rdp_output *output = buffer->output;
rdp_buffer_destroy(buffer);
output->buffer = rdp_buffer_create(output);
if (output->buffer == NULL)
return false;
return true;
}
static struct rdp_buffer *
rdp_buffer_create(struct rdp_output *output)
{
const struct pixel_format_info *format = output->backend->formats[0];
struct weston_renderer *rdr = output->base.compositor->renderer;
pixman_image_t *shadow_surface;
weston_renderbuffer_t rb;
struct rdp_buffer *buffer;
shadow_surface = pixman_image_create_bits(format->pixman_format,
output->base.current_mode->width,
output->base.current_mode->height,
NULL,
output->base.current_mode->width * 4);
buffer = xmalloc(sizeof *buffer);
rb = rdr->create_renderbuffer(&output->base, format,
pixman_image_get_data(shadow_surface),
output->base.current_mode->width * 4,
rdp_rb_discarded_cb, buffer);
if (rb == NULL) {
weston_log("Failed to create offscreen renderbuffer.\n");
pixman_image_unref(shadow_surface);
free(buffer);
return NULL;
}
buffer->output = output;
buffer->shadow_surface = shadow_surface;
buffer->rb = rb;
return buffer;
}
static void
rdp_buffer_destroy(struct rdp_buffer *buffer)
{
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
pixman_image_unref(buffer->shadow_surface);
rdr->destroy_renderbuffer(buffer->rb);
free(buffer);
}
static void
rdp_renderer_output_destroy(struct weston_output *base)
{
struct weston_renderer *rdr = base->compositor->renderer;
switch (rdr->type) {
case WESTON_RENDERER_PIXMAN:
rdr->pixman->output_destroy(base);
break;
case WESTON_RENDERER_GL:
rdr->gl->output_destroy(base);
break;
case WESTON_RENDERER_VULKAN:
rdr->vulkan->output_destroy(base);
break;
default:
unreachable("cannot have auto renderer at runtime");
}
}
static int
rdp_output_enable(struct weston_output *base)
{
const struct weston_renderer *renderer = base->compositor->renderer;
const struct pixman_renderer_interface *pixman = renderer->pixman;
struct rdp_output *output = to_rdp_output(base);
struct rdp_backend *b;
struct wl_event_loop *loop;
@ -449,12 +508,6 @@ rdp_output_enable(struct weston_output *base)
b = output->backend;
output->shadow_surface = pixman_image_create_bits(b->formats[0]->pixman_format,
output->base.current_mode->width,
output->base.current_mode->height,
NULL,
output->base.current_mode->width * 4);
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_output_options options = {
@ -465,23 +518,8 @@ rdp_output_enable(struct weston_output *base)
.format = b->formats[0],
};
if (renderer->pixman->output_create(&output->base, &options) < 0) {
if (renderer->pixman->output_create(&output->base, &options) < 0)
return -1;
}
output->renderbuffer =
pixman->create_image_from_ptr(&output->base, options.format,
output->base.current_mode->width,
output->base.current_mode->height,
pixman_image_get_data(output->shadow_surface),
output->base.current_mode->width * 4);
if (output->renderbuffer == NULL) {
weston_log("Failed to create surface for frame buffer.\n");
renderer->pixman->output_destroy(&output->base);
pixman_image_unref(output->shadow_surface);
output->shadow_surface = NULL;
return -1;
}
break;
}
case WESTON_RENDERER_GL: {
@ -496,19 +534,24 @@ rdp_output_enable(struct weston_output *base)
},
};
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
if (renderer->gl->output_fbo_create(&output->base, &options) < 0) {
return -1;
}
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_surfaceless_options options = {
.area = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
};
output->renderbuffer =
renderer->gl->create_fbo(&output->base, b->formats[0],
output->base.current_mode->width,
output->base.current_mode->height,
pixman_image_get_data(output->shadow_surface));
if (output->renderbuffer == NULL) {
weston_log("Failed to create surface for frame buffer.\n");
renderer->pixman->output_destroy(&output->base);
pixman_image_unref(output->shadow_surface);
output->shadow_surface = NULL;
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
return -1;
}
break;
@ -517,6 +560,12 @@ rdp_output_enable(struct weston_output *base)
unreachable("cannot have auto renderer at runtime");
}
output->buffer = rdp_buffer_create(output);
if (output->buffer == NULL) {
rdp_renderer_output_destroy(base);
return -1;
}
loop = wl_display_get_event_loop(b->compositor->wl_display);
output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output);
@ -526,7 +575,6 @@ rdp_output_enable(struct weston_output *base)
static int
rdp_output_disable(struct weston_output *base)
{
struct weston_renderer *renderer = base->compositor->renderer;
struct rdp_output *output = to_rdp_output(base);
assert(output);
@ -534,21 +582,9 @@ rdp_output_disable(struct weston_output *base)
if (!output->base.enabled)
return 0;
weston_renderbuffer_unref(output->renderbuffer);
output->renderbuffer = NULL;
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN:
renderer->pixman->output_destroy(&output->base);
break;
case WESTON_RENDERER_GL:
renderer->gl->output_destroy(&output->base);
break;
default:
unreachable("cannot have auto renderer at runtime");
}
pixman_image_unref(output->shadow_surface);
output->shadow_surface = NULL;
rdp_buffer_destroy(output->buffer);
output->buffer = NULL;
rdp_renderer_output_destroy(base);
wl_event_source_remove(output->finish_frame_timer);
return 0;
@ -584,6 +620,7 @@ rdp_output_create(struct weston_backend *backend, const char *name)
output->base.start_repaint_loop = rdp_output_start_repaint_loop;
output->base.repaint = rdp_output_repaint;
output->base.set_dpms = rdp_output_set_dpms;
output->base.switch_mode = rdp_output_switch_mode;
output->backend = b;
@ -985,6 +1022,9 @@ struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
{KBD_IRISH, 0, 0},
{KBD_BOSNIAN_CYRILLIC, "ba", "us"},
{KBD_UNITED_STATES_DVORAK, "us", "dvorak"},
{KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND, "us", "dvorak-l"},
{KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND, "us", "dvorak-r"},
{KBD_UNITED_STATES_DVORAK_PROGRAMMER, "us", "dvp"},
{KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "abnt2"},
{KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"},
{KBD_GAELIC, "ie", "CloGaelach"},
@ -1989,6 +2029,18 @@ rdp_backend_create(struct weston_compositor *compositor,
goto err_compositor;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0)
goto err_compositor;
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_free_strings;
@ -2113,6 +2165,7 @@ weston_backend_init(struct weston_compositor *compositor,
switch (compositor->renderer->type) {
case WESTON_RENDERER_PIXMAN:
case WESTON_RENDERER_GL:
case WESTON_RENDERER_VULKAN:
break;
default:
weston_log("Renderer not supported by RDP backend\n");

View file

@ -27,14 +27,6 @@
#ifndef RDP_H
#define RDP_H
/* Workaround an issue with clang and freerdp 3 headers. Another
* option would be to build with --std=c11 but weston itself isn't
* quite ready for that
*/
#if USE_FREERDP_VERSION >= 3 && defined(__clang__)
#pragma clang diagnostic ignored "-Wtypedef-redefinition"
#endif
#include <freerdp/version.h>
#include <freerdp/freerdp.h>
@ -55,6 +47,7 @@
#include <winpr/string.h>
#include "backend.h"
#include "libweston-internal.h"
#include "shared/helpers.h"
#include "shared/string-helpers.h"
@ -145,12 +138,17 @@ struct rdp_head {
rdpMonitor config;
};
struct rdp_buffer {
struct rdp_output *output;
pixman_image_t *shadow_surface;
weston_renderbuffer_t rb;
};
struct rdp_output {
struct weston_output base;
struct rdp_backend *backend;
struct wl_event_source *finish_frame_timer;
struct weston_renderbuffer *renderbuffer;
pixman_image_t *shadow_surface;
struct rdp_buffer *buffer;
};
struct rdp_peer_context {

View file

@ -3,7 +3,7 @@ if not get_option('backend-vnc')
endif
config_h.set('BUILD_VNC_COMPOSITOR', '1')
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.9.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.10.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
if not dep_neatvnc.found()
error('VNC backend requires neatvnc which was not found. Or, you can use \'-Dbackend-vnc=false\'.')
endif

View file

@ -56,6 +56,7 @@
#include "pixel-formats.h"
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-egl-ext.h"
#define DEFAULT_AXIS_STEP_DISTANCE 10
@ -108,9 +109,18 @@ struct vnc_head {
struct weston_head base;
};
struct vnc_buffer {
weston_renderbuffer_t rb;
struct nvnc_fb *fb;
struct vnc_output *output;
};
static void
vnc_output_destroy(struct weston_output *base);
static void
vnc_buffer_destroy(struct vnc_buffer *buffer);
static inline struct vnc_output *
to_vnc_output(struct weston_output *base)
{
@ -653,8 +663,7 @@ vnc_log_scope_print_region(struct weston_log_scope *log, pixman_region32_t *regi
}
static void
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
pixman_region32_t *update_damage)
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
{
char timestr[128];
@ -663,15 +672,51 @@ vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
weston_log_scope_timestamp(backend->debug, timestr, sizeof timestr);
weston_log_scope_printf(backend->debug, "%s buffer damage:", timestr);
vnc_log_scope_print_region(backend->debug, buffer_damage);
weston_log_scope_printf(backend->debug, "\n");
weston_log_scope_printf(backend->debug, "%s update damage:", timestr);
vnc_log_scope_print_region(backend->debug, update_damage);
weston_log_scope_printf(backend->debug, "%s damage:", timestr);
vnc_log_scope_print_region(backend->debug, damage);
weston_log_scope_printf(backend->debug, "\n\n");
}
static bool
vnc_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
{
struct vnc_buffer *buffer = (struct vnc_buffer *) data;
assert(nvnc_get_userdata(buffer->fb) == buffer);
nvnc_set_userdata(buffer->fb, NULL, NULL);
vnc_buffer_destroy(buffer);
return true;
}
static struct vnc_buffer *
vnc_buffer_create(struct nvnc_fb* fb, struct vnc_output *output)
{
const struct pixel_format_info *pfmt =
pixel_format_get_info(DRM_FORMAT_XRGB8888);
struct weston_renderer *rdr = output->base.compositor->renderer;
struct vnc_buffer *buffer = xmalloc(sizeof *buffer);
buffer->rb = rdr->create_renderbuffer(&output->base, pfmt,
nvnc_fb_get_addr(fb),
output->base.current_mode->width * 4,
vnc_rb_discarded_cb, buffer);
buffer->fb = fb;
buffer->output = output;
return buffer;
}
static void
vnc_buffer_destroy(struct vnc_buffer *buffer)
{
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
rdr->destroy_renderbuffer(buffer->rb);
free(buffer);
}
static void
vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
{
@ -679,7 +724,7 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
struct vnc_backend *backend = nvnc_get_userdata(server);
struct vnc_output *output = backend->output;
struct weston_compositor *ec = output->base.compositor;
struct weston_renderbuffer *renderbuffer;
struct vnc_buffer *buffer;
pixman_region32_t local_damage;
pixman_region16_t nvnc_damage;
struct nvnc_fb *fb;
@ -687,49 +732,16 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
fb = nvnc_fb_pool_acquire(output->fb_pool);
assert(fb);
renderbuffer = nvnc_get_userdata(fb);
if (!renderbuffer) {
const struct pixel_format_info *pfmt;
pfmt = pixel_format_get_info(DRM_FORMAT_XRGB8888);
switch (ec->renderer->type) {
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_interface *pixman;
pixman = ec->renderer->pixman;
renderbuffer =
pixman->create_image_from_ptr(&output->base, pfmt,
output->base.width,
output->base.height,
nvnc_fb_get_addr(fb),
output->base.width * 4);
break;
}
case WESTON_RENDERER_GL: {
renderbuffer =
ec->renderer->gl->create_fbo(&output->base, pfmt,
output->base.width,
output->base.height,
nvnc_fb_get_addr(fb));
break;
}
default:
unreachable("cannot have auto renderer at runtime");
buffer = nvnc_get_userdata(fb);
if (!buffer) {
buffer = vnc_buffer_create(fb, output);
nvnc_set_userdata(fb, buffer,
(nvnc_cleanup_fn) vnc_buffer_destroy);
}
/* This is a new buffer, so the whole surface is damaged. */
pixman_region32_copy(&renderbuffer->damage,
&output->base.region);
vnc_log_damage(backend, damage);
nvnc_set_userdata(fb, renderbuffer,
(nvnc_cleanup_fn)weston_renderbuffer_unref);
}
vnc_log_damage(backend, &renderbuffer->damage, damage);
ec->renderer->repaint_output(&output->base, damage, renderbuffer);
ec->renderer->repaint_output(&output->base, damage, buffer->rb);
/* Convert to local coordinates */
pixman_region32_init(&local_damage);
@ -809,8 +821,8 @@ vnc_output_enable(struct weston_output *base)
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_output_options options = {
.fb_size = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.format = backend->formats[0],
};
@ -821,18 +833,33 @@ vnc_output_enable(struct weston_output *base)
case WESTON_RENDERER_GL: {
const struct gl_renderer_fbo_options options = {
.area = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.fb_size = {
.width = output->base.width,
.height = output->base.height,
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
};
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
return -1;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_surfaceless_options options = {
.area = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
};
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0)
return -1;
break;
}
default:
unreachable("cannot have auto renderer at runtime");
}
@ -842,10 +869,10 @@ vnc_output_enable(struct weston_output *base)
finish_frame_handler,
output);
output->fb_pool = nvnc_fb_pool_new(output->base.width,
output->base.height,
output->fb_pool = nvnc_fb_pool_new(output->base.current_mode->width,
output->base.current_mode->height,
backend->formats[0]->format,
output->base.width);
output->base.current_mode->width);
output->display = nvnc_display_new(0, 0);
@ -879,6 +906,9 @@ vnc_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
renderer->gl->output_destroy(&output->base);
break;
case WESTON_RENDERER_VULKAN:
renderer->vulkan->output_destroy(&output->base);
break;
default:
unreachable("cannot have auto renderer at runtime");
}
@ -1052,6 +1082,9 @@ vnc_output_assign_planes(struct weston_output *base)
assert(output);
if (output->base.disable_planes)
return;
if (wl_list_empty(&output->peers))
return;
@ -1060,6 +1093,19 @@ vnc_output_assign_planes(struct weston_output *base)
vnc_output_assign_cursor_plane(output);
}
static void
vnc_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct vnc_output *output = to_vnc_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
{
@ -1073,7 +1119,14 @@ vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
fb_size.width = target_mode->width;
fb_size.height = target_mode->height;
weston_renderer_resize_output(base, &fb_size, NULL);
/* vnc_buffers are stored as user data pointers into the renderbuffers
* for the discarded callback. weston_renderer_resize_output(), which
* triggers the renderbuffer's discarded callbacks, must be called
* before nvnc_fb_pool_resize(), which destroys all the nvnc_fbs and
* their associated vnc_buffers, so that the vnc_buffers are valid at
* callback. */
if (!weston_renderer_resize_output(base, &fb_size, NULL))
return -1;
nvnc_fb_pool_resize(output->fb_pool, target_mode->width,
target_mode->height, DRM_FORMAT_XRGB8888,
@ -1105,7 +1158,7 @@ vnc_output_set_size(struct weston_output *base, int width, int height,
output->base.repaint = vnc_output_repaint;
output->base.assign_planes = vnc_output_assign_planes;
output->base.set_backlight = NULL;
output->base.set_dpms = NULL;
output->base.set_dpms = vnc_set_dpms;
output->base.switch_mode = vnc_switch_mode;
output->resizeable = resizeable;
@ -1183,6 +1236,17 @@ vnc_backend_create(struct weston_compositor *compositor,
goto err_compositor;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = backend->formats,
.formats_count = backend->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0)
goto err_compositor;
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_compositor;
@ -1324,6 +1388,7 @@ weston_backend_init(struct weston_compositor *compositor,
switch (compositor->renderer->type) {
case WESTON_RENDERER_PIXMAN:
case WESTON_RENDERER_GL:
case WESTON_RENDERER_VULKAN:
break;
default:
weston_log("Renderer not supported by VNC backend\n");

View file

@ -6,8 +6,6 @@ config_h.set('BUILD_WAYLAND_COMPOSITOR', '1')
srcs_wlwl = [
'wayland.c',
fullscreen_shell_unstable_v1_client_protocol_h,
fullscreen_shell_unstable_v1_protocol_c,
presentation_time_protocol_c,
presentation_time_server_protocol_h,
xdg_shell_client_protocol_h,
@ -21,7 +19,7 @@ deps_wlwl = [
dep_libweston_private,
dep_libdrm_headers,
dep_lib_cairo_shared,
dep_lib_gl_borders,
dep_lib_renderer_borders,
]
if get_option('renderer-gl')
@ -33,6 +31,10 @@ if get_option('renderer-gl')
deps_wlwl += dep_egl # for gl-renderer.h
endif
if get_option('renderer-vulkan')
deps_wlwl += dep_vulkan # for vulkan-renderer.h
endif
plugin_wlwl = shared_library(
'wayland-backend',
srcs_wlwl,

View file

@ -48,7 +48,8 @@
#include <libweston/libweston.h>
#include <libweston/backend-wayland.h>
#include "renderer-gl/gl-renderer.h"
#include "gl-borders.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "renderer-borders.h"
#include "shared/weston-drm-fourcc.h"
#include "shared/weston-egl-ext.h"
#include "pixman-renderer.h"
@ -58,7 +59,6 @@
#include "shared/cairo-util.h"
#include "shared/timespec-util.h"
#include "shared/xalloc.h"
#include "fullscreen-shell-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
#include "presentation-time-server-protocol.h"
#include "linux-dmabuf.h"
@ -86,7 +86,6 @@ struct wayland_backend {
struct wl_registry *registry;
struct wl_compositor *compositor;
struct xdg_wm_base *xdg_wm_base;
struct zwp_fullscreen_shell_v1 *fshell;
struct wl_shm *shm;
struct wl_list output_list;
@ -99,7 +98,6 @@ struct wayland_backend {
bool fullscreen;
struct theme *theme;
cairo_device_t *frame_device;
struct wl_cursor_theme *cursor_theme;
struct wl_cursor *cursor;
@ -135,7 +133,6 @@ struct wayland_output {
struct {
struct wl_egl_window *egl_window;
struct weston_gl_borders borders;
} gl;
struct {
@ -143,6 +140,8 @@ struct wayland_output {
struct wl_list free_buffers;
} shm;
struct weston_renderer_borders borders;
struct weston_mode mode;
struct weston_mode native_mode;
@ -192,7 +191,7 @@ struct wayland_shm_buffer {
int height;
int frame_damaged;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
cairo_surface_t *c_surface;
};
@ -266,9 +265,14 @@ to_wayland_backend(struct weston_backend *base)
static void
wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
{
struct wayland_output *output = buffer->output;
const struct weston_renderer *renderer;
cairo_surface_destroy(buffer->c_surface);
if (buffer->output)
weston_renderbuffer_unref(buffer->renderbuffer);
if (output) {
renderer = output->base.compositor->renderer;
renderer->destroy_renderbuffer(buffer->renderbuffer);
}
wl_buffer_destroy(buffer->buffer);
munmap(buffer->data, buffer->size);
@ -290,6 +294,22 @@ buffer_release(void *data, struct wl_buffer *buffer)
}
}
static bool
wayland_rb_discarded_cb(weston_renderbuffer_t renderbuffer, void *data)
{
struct wayland_shm_buffer *sb = data;
const struct weston_renderer *renderer;
if (sb->renderbuffer) {
renderer = sb->output->backend->compositor->renderer;
renderer->destroy_renderbuffer(sb->renderbuffer);
sb->renderbuffer = NULL;
}
sb->output = NULL;
return true;
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
@ -298,7 +318,6 @@ static struct wayland_shm_buffer *
wayland_output_get_shm_buffer(struct wayland_output *output)
{
const struct weston_renderer *renderer;
const struct pixman_renderer_interface *pixman;
struct wayland_backend *b = output->backend;
const struct pixel_format_info *pfmt = b->formats[0];
uint32_t shm_format = pixel_format_get_shm_format(pfmt);
@ -384,26 +403,23 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
if (output->frame) {
frame_interior(output->frame, &area.x, &area.y,
&area.width, &area.height);
assert(area.width == output->base.current_mode->width);
assert(area.height == output->base.current_mode->height);
} else {
area.x = 0;
area.y = 0;
area.width = output->base.current_mode->width;
area.height = output->base.current_mode->height;
}
renderer = b->compositor->renderer;
pixman = renderer->pixman;
/* Address only the interior, excluding output decorations */
if (renderer->type == WESTON_RENDERER_PIXMAN) {
if (renderer->type == WESTON_RENDERER_PIXMAN)
sb->renderbuffer =
pixman->create_image_from_ptr(&output->base, pfmt,
area.width, area.height,
renderer->create_renderbuffer(&output->base, pfmt,
(uint32_t *)(data + area.y * stride) + area.x,
stride);
pixman_region32_copy(&sb->renderbuffer->damage,
&output->base.region);
}
stride,
wayland_rb_discarded_cb,
sb);
return sb;
}
@ -435,33 +451,16 @@ static const struct wl_callback_listener frame_listener = {
frame_done
};
#if defined(ENABLE_EGL) || defined(ENABLE_VULKAN)
static void
draw_initial_frame(struct wayland_output *output)
{
struct wayland_shm_buffer *sb;
sb = wayland_output_get_shm_buffer(output);
/* If we are rendering with GL, then orphan it so that it gets
* destroyed immediately */
if (output->gl.egl_window)
sb->output = NULL;
wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
wl_surface_damage(output->parent.surface, 0, 0,
sb->width, sb->height);
}
#ifdef ENABLE_EGL
static void
wayland_output_update_gl_border(struct wayland_output *output)
wayland_output_update_renderer_border(struct wayland_output *output)
{
if (!output->frame)
return;
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
return;
weston_gl_borders_update(&output->gl.borders, output->frame,
weston_renderer_borders_update(&output->borders, output->frame,
&output->base);
}
#endif
@ -502,7 +501,36 @@ wayland_output_repaint_gl(struct weston_output *output_base)
output->frame_cb = wl_surface_frame(output->parent.surface);
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
wayland_output_update_gl_border(output);
wayland_output_update_renderer_border(output);
ec->renderer->repaint_output(&output->base, &damage, NULL);
pixman_region32_fini(&damage);
return 0;
}
#endif
#ifdef ENABLE_VULKAN
static int
wayland_output_repaint_vulkan(struct weston_output *output_base)
{
struct wayland_output *output = to_wayland_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
assert(output);
ec = output->base.compositor;
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
output->frame_cb = wl_surface_frame(output->parent.surface);
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
wayland_output_update_renderer_border(output);
ec->renderer->repaint_output(&output->base, &damage, NULL);
@ -665,14 +693,6 @@ wayland_output_destroy_shm_buffers(struct wayland_output *output)
/* Throw away any remaining SHM buffers */
wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
wayland_shm_buffer_destroy(buffer);
/* These will get thrown away when they get released */
wl_list_for_each(buffer, &output->shm.buffers, link) {
if (buffer->renderbuffer) {
weston_renderbuffer_unref(buffer->renderbuffer);
buffer->renderbuffer = NULL;
}
buffer->output = NULL;
}
}
static int
@ -694,11 +714,18 @@ wayland_output_disable(struct weston_output *base)
break;
#ifdef ENABLE_EGL
case WESTON_RENDERER_GL:
weston_gl_borders_fini(&output->gl.borders, &output->base);
weston_renderer_borders_fini(&output->borders, &output->base);
renderer->gl->output_destroy(&output->base);
wl_egl_window_destroy(output->gl.egl_window);
break;
#endif
#ifdef ENABLE_VULKAN
case WESTON_RENDERER_VULKAN:
weston_renderer_borders_fini(&output->borders, &output->base);
renderer->vulkan->output_destroy(&output->base);
break;
#endif
default:
unreachable("invalid renderer");
@ -780,6 +807,47 @@ cleanup_window:
}
#endif
#ifdef ENABLE_VULKAN
static int
wayland_output_init_vulkan_renderer(struct wayland_output *output)
{
const struct weston_mode *mode = output->base.current_mode;
struct wayland_backend *b = output->backend;
const struct weston_renderer *renderer;
struct vulkan_renderer_surface_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (output->frame) {
frame_interior(output->frame, &options.area.x, &options.area.y,
&options.area.width, &options.area.height);
options.fb_size.width = frame_width(output->frame);
options.fb_size.height = frame_height(output->frame);
} else {
options.area.x = 0;
options.area.y = 0;
options.area.width = mode->width;
options.area.height = mode->height;
options.fb_size.width = mode->width;
options.fb_size.height = mode->height;
}
options.wayland_display = b->parent.wl_display;
options.wayland_surface = output->parent.surface;
renderer = output->base.compositor->renderer;
if (renderer->vulkan->output_surface_create(&output->base, &options) < 0)
goto cleanup_window;
return 0;
cleanup_window:
return -1;
}
#endif
static int
wayland_output_init_pixman_renderer(struct wayland_output *output)
{
@ -814,6 +882,9 @@ wayland_output_resize_surface(struct wayland_output *output)
struct weston_geometry opa = area;
struct wl_region *region;
assert(b->compositor);
assert(b->compositor->renderer);
if (output->frame) {
frame_resize_inside(output->frame, area.width, area.height);
frame_interior(output->frame, &area.x, &area.y, NULL, NULL);
@ -849,7 +920,15 @@ wayland_output_resize_surface(struct wayland_output *output)
weston_renderer_resize_output(&output->base, &fb_size, &area);
/* These will need to be re-created due to the resize */
weston_gl_borders_fini(&output->gl.borders, &output->base);
weston_renderer_borders_fini(&output->borders, &output->base);
} else
#endif
#ifdef ENABLE_VULKAN
if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
weston_renderer_resize_output(&output->base, &fb_size, &area);
/* These will need to be re-created due to the resize */
weston_renderer_borders_fini(&output->borders, &output->base);
} else
#endif
{
@ -917,104 +996,6 @@ wayland_output_set_fullscreen(struct wayland_output *output,
}
}
static struct weston_mode *
wayland_output_choose_mode(struct wayland_output *output,
struct weston_mode *ref_mode)
{
struct weston_mode *mode;
/* First look for an exact match */
wl_list_for_each(mode, &output->base.mode_list, link)
if (mode->width == ref_mode->width &&
mode->height == ref_mode->height &&
mode->refresh == ref_mode->refresh)
return mode;
/* If we can't find an exact match, ignore refresh and try again */
wl_list_for_each(mode, &output->base.mode_list, link)
if (mode->width == ref_mode->width &&
mode->height == ref_mode->height)
return mode;
/* Yeah, we failed */
return NULL;
}
enum mode_status {
MODE_STATUS_UNKNOWN,
MODE_STATUS_SUCCESS,
MODE_STATUS_FAIL,
MODE_STATUS_CANCEL,
};
static void
mode_feedback_successful(void *data,
struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
{
enum mode_status *value = data;
printf("Mode switch successful\n");
*value = MODE_STATUS_SUCCESS;
}
static void
mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
{
enum mode_status *value = data;
printf("Mode switch failed\n");
*value = MODE_STATUS_FAIL;
}
static void
mode_feedback_cancelled(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
{
enum mode_status *value = data;
printf("Mode switch cancelled\n");
*value = MODE_STATUS_CANCEL;
}
struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
mode_feedback_successful,
mode_feedback_failed,
mode_feedback_cancelled,
};
static enum mode_status
wayland_output_fullscreen_shell_mode_feedback(struct wayland_output *output,
struct weston_mode *mode)
{
struct wayland_backend *b = output->backend;
struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
enum mode_status mode_status;
int ret = 0;
mode_feedback =
zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
output->parent.surface,
output->parent.output,
mode->refresh);
zwp_fullscreen_shell_mode_feedback_v1_add_listener(mode_feedback,
&mode_feedback_listener,
&mode_status);
draw_initial_frame(output);
wl_surface_commit(output->parent.surface);
mode_status = MODE_STATUS_UNKNOWN;
while (mode_status == MODE_STATUS_UNKNOWN && ret >= 0)
ret = wl_display_dispatch(b->parent.wl_display);
zwp_fullscreen_shell_mode_feedback_v1_destroy(mode_feedback);
return mode_status;
}
static int
wayland_output_switch_mode_finish(struct wayland_output *output)
{
@ -1033,6 +1014,13 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
if (wayland_output_init_gl_renderer(output) < 0)
return -1;
break;
#endif
#ifdef ENABLE_VULKAN
case WESTON_RENDERER_VULKAN:
renderer->vulkan->output_destroy(&output->base);
if (wayland_output_init_vulkan_renderer(output) < 0)
return -1;
break;
#endif
default:
unreachable("invalid renderer");
@ -1043,56 +1031,6 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
return 0;
}
static int
wayland_output_switch_mode_fshell(struct wayland_output *output,
struct weston_mode *mode)
{
struct wayland_backend *b;
struct wl_surface *old_surface;
struct weston_mode *old_mode;
enum mode_status mode_status;
b = output->backend;
mode = wayland_output_choose_mode(output, mode);
if (mode == NULL)
return -1;
if (output->base.current_mode == mode)
return 0;
old_mode = output->base.current_mode;
old_surface = output->parent.surface;
output->base.current_mode = mode;
output->parent.surface =
wl_compositor_create_surface(b->parent.compositor);
wl_surface_set_user_data(output->parent.surface, output);
/* Blow the old buffers because we changed size/surfaces */
wayland_output_resize_surface(output);
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, mode);
/* This should kick-start things again */
wayland_output_start_repaint_loop(&output->base);
if (mode_status == MODE_STATUS_FAIL) {
output->base.current_mode = old_mode;
wl_surface_destroy(output->parent.surface);
output->parent.surface = old_surface;
wayland_output_resize_surface(output);
return -1;
}
old_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
wl_surface_destroy(old_surface);
return wayland_output_switch_mode_finish(output);
}
static int
wayland_output_switch_mode_xdg(struct wayland_output *output,
struct weston_mode *mode)
@ -1136,8 +1074,6 @@ wayland_output_switch_mode(struct weston_output *output_base,
if (output->parent.xdg_surface)
return wayland_output_switch_mode_xdg(output, mode);
if (output->backend->parent.fshell)
return wayland_output_switch_mode_fshell(output, mode);
return -1;
}
@ -1257,7 +1193,6 @@ wayland_output_enable(struct weston_output *base)
const struct weston_renderer *renderer = base->compositor->renderer;
struct wayland_output *output = to_wayland_output(base);
struct wayland_backend *b;
enum mode_status mode_status;
int ret = 0;
assert(output);
@ -1293,6 +1228,14 @@ wayland_output_enable(struct weston_output *base)
output->base.repaint = wayland_output_repaint_gl;
break;
#endif
#ifdef ENABLE_VULKAN
case WESTON_RENDERER_VULKAN:
if (wayland_output_init_vulkan_renderer(output) < 0)
goto err_output;
output->base.repaint = wayland_output_repaint_vulkan;
break;
#endif
default:
unreachable("invalid renderer");
@ -1304,20 +1247,7 @@ wayland_output_enable(struct weston_output *base)
output->base.set_dpms = NULL;
output->base.switch_mode = wayland_output_switch_mode;
if (b->sprawl_across_outputs) {
if (b->parent.fshell) {
wayland_output_resize_surface(output);
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, &output->mode);
if (mode_status == MODE_STATUS_FAIL)
zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
output->parent.surface,
ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
output->parent.output);
}
} else if (b->fullscreen) {
if (b->fullscreen) {
wayland_output_set_fullscreen(output, 0, NULL);
} else {
wayland_output_set_windowed(output);
@ -2690,10 +2620,6 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
&xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(b->parent.xdg_wm_base,
&wm_base_listener, b);
} else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
b->parent.fshell =
wl_registry_bind(registry, name,
&zwp_fullscreen_shell_v1_interface, 1);
} else if (strcmp(interface, "wl_seat") == 0) {
display_start_add_seat(b, name, version);
} else if (strcmp(interface, "wl_output") == 0) {
@ -2791,18 +2717,12 @@ wayland_destroy(struct weston_backend *backend)
if (b->parent.xdg_wm_base)
xdg_wm_base_destroy(b->parent.xdg_wm_base);
if (b->parent.fshell)
zwp_fullscreen_shell_v1_release(b->parent.fshell);
if (b->parent.compositor)
wl_compositor_destroy(b->parent.compositor);
if (b->theme)
theme_destroy(b->theme);
if (b->frame_device)
cairo_device_destroy(b->frame_device);
wl_cursor_theme_destroy(b->cursor_theme);
free(b->formats);
@ -2951,6 +2871,22 @@ wayland_backend_create(struct weston_compositor *compositor,
goto err_display;
}
break;
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0) {
weston_log("Failed to initialize the Vulkan renderer\n");
goto err_display;
}
/* For now Vulkan does not fall back to anything automatically,
* like GL renderer does. */
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_display;
@ -2990,8 +2926,6 @@ wayland_backend_destroy(struct wayland_backend *b)
if (b->theme)
theme_destroy(b->theme);
if (b->frame_device)
cairo_device_destroy(b->frame_device);
wl_cursor_theme_destroy(b->cursor_theme);
wl_list_remove(&b->base.link);
@ -3039,7 +2973,7 @@ weston_backend_init(struct weston_compositor *compositor,
if (!b)
return -1;
if (new_config.sprawl || b->parent.fshell) {
if (new_config.sprawl) {
b->sprawl_across_outputs = true;
wl_display_roundtrip(b->parent.wl_display);

View file

@ -57,6 +57,7 @@
#include "shared/timespec-util.h"
#include "shared/file-util.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-drm-fourcc.h"
#include "shared/weston-egl-ext.h"
#include "shared/xalloc.h"
@ -140,7 +141,7 @@ struct x11_output {
xcb_gc_t gc;
xcb_shm_seg_t segment;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
int shm_id;
void *buf;
uint8_t depth;
@ -168,6 +169,10 @@ to_x11_head(struct weston_head *base)
static void
x11_output_destroy(struct weston_output *base);
static int
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
const struct pixel_format_info *pfmt);
static inline struct x11_output *
to_x11_output(struct weston_output *base)
{
@ -451,6 +456,29 @@ x11_output_repaint_gl(struct weston_output *output_base)
return 0;
}
static int
x11_output_repaint_vulkan(struct weston_output *output_base)
{
struct x11_output *output = to_x11_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
assert(output);
ec = output->base.compositor;
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(output_base, &damage, NULL);
pixman_region32_fini(&damage);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;
}
static void
set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region)
{
@ -507,8 +535,6 @@ static int
x11_output_repaint_shm(struct weston_output *output_base)
{
struct x11_output *output = to_x11_output(output_base);
const struct weston_renderer *renderer;
pixman_image_t *image;
struct weston_compositor *ec;
struct x11_backend *b;
xcb_void_cookie_t cookie;
@ -518,11 +544,8 @@ x11_output_repaint_shm(struct weston_output *output_base)
assert(output);
ec = output->base.compositor;
renderer = ec->renderer;
b = output->backend;
image = renderer->pixman->renderbuffer_get_image(output->renderbuffer);
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
@ -534,11 +557,11 @@ x11_output_repaint_shm(struct weston_output *output_base)
pixman_region32_fini(&damage);
cookie = xcb_shm_put_image_checked(b->conn, output->window, output->gc,
pixman_image_get_width(image),
pixman_image_get_height(image),
output_base->current_mode->width,
output_base->current_mode->height,
0, 0,
pixman_image_get_width(image),
pixman_image_get_height(image),
output_base->current_mode->width,
output_base->current_mode->height,
0, 0, output->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
0, output->segment, 0);
err = xcb_request_check(b->conn, cookie);
@ -568,7 +591,7 @@ x11_output_deinit_shm(struct x11_backend *b, struct x11_output *output)
xcb_generic_error_t *err;
xcb_free_gc(b->conn, output->gc);
weston_renderbuffer_unref(output->renderbuffer);
b->compositor->renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
cookie = xcb_shm_detach_checked(b->conn, output->segment);
err = xcb_request_check(b->conn, cookie);
@ -793,17 +816,40 @@ x11_output_get_shm_pixel_format(struct x11_output *output)
}
}
static bool
x11_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
{
struct x11_output *output = (struct x11_output *) data;
const struct pixel_format_info *pfmt;
if (output->base.compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
x11_output_deinit_shm(output->backend, output);
pfmt = x11_output_get_shm_pixel_format(output);
if (!pfmt)
return false;
if (x11_output_init_shm(output->backend, output, pfmt) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
return false;
}
}
return true;
}
static int
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
const struct pixel_format_info *pfmt, int width, int height)
const struct pixel_format_info *pfmt)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
int bitsperpixel = pfmt->bpp;
size_t size = output->base.current_mode->width *
output->base.current_mode->height * (bitsperpixel / 8);
int stride = output->base.current_mode->width * (bitsperpixel / 8);
xcb_void_cookie_t cookie;
xcb_generic_error_t *err;
/* Create SHM segment and attach it */
output->shm_id = shmget(IPC_PRIVATE, width * height * (bitsperpixel / 8), IPC_CREAT | S_IRWXU);
output->shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRWXU);
if (output->shm_id == -1) {
weston_log("x11shm: failed to allocate SHM segment\n");
return -1;
@ -827,10 +873,9 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
/* Now create pixman image */
output->renderbuffer =
renderer->pixman->create_image_from_ptr(&output->base,
pfmt, width, height,
output->buf,
width * (bitsperpixel / 8));
renderer->create_renderbuffer(&output->base, pfmt, output->buf,
stride, x11_rb_discarded_cb,
output);
output->gc = xcb_generate_id(b->conn);
xcb_create_gc(b->conn, output->gc, output->window, 0, NULL);
@ -838,6 +883,19 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
return 0;
}
static void
x11_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct x11_output *output = to_x11_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
{
@ -875,20 +933,8 @@ x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
fb_size.width = output->mode.width = mode->width;
fb_size.height = output->mode.height = mode->height;
weston_renderer_resize_output(&output->base, &fb_size, NULL);
if (base->compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
const struct pixel_format_info *pfmt;
x11_output_deinit_shm(b, output);
pfmt = x11_output_get_shm_pixel_format(output);
if (!pfmt)
if (!weston_renderer_resize_output(&output->base, &fb_size, NULL))
return -1;
if (x11_output_init_shm(b, output, pfmt,
fb_size.width, fb_size.height) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
return -1;
}
}
output->resize_pending = false;
output->window_resized = false;
@ -920,6 +966,9 @@ x11_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
renderer->gl->output_destroy(&output->base);
break;
case WESTON_RENDERER_VULKAN:
renderer->vulkan->output_destroy(&output->base);
break;
default:
unreachable("invalid renderer");
}
@ -1068,8 +1117,7 @@ x11_output_enable(struct weston_output *base)
weston_log("Failed to create pixman renderer for output\n");
goto err;
}
if (x11_output_init_shm(b, output, options.format,
mode->width, mode->height) < 0) {
if (x11_output_init_shm(b, output, options.format) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
renderer->pixman->output_destroy(&output->base);
goto err;
@ -1102,6 +1150,29 @@ x11_output_enable(struct weston_output *base)
output->base.repaint = x11_output_repaint_gl;
break;
}
case WESTON_RENDERER_VULKAN: {
struct vulkan_renderer_surface_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
options.xcb_connection = b->conn;
options.xcb_visualid = screen->root_visual;
options.xcb_window = output->window;
ret = renderer->vulkan->output_surface_create(base, &options);
if (ret < 0)
goto err;
output->base.repaint = x11_output_repaint_vulkan;
break;
}
default:
unreachable("invalid renderer");
}
@ -1109,7 +1180,7 @@ x11_output_enable(struct weston_output *base)
output->base.start_repaint_loop = x11_output_start_repaint_loop;
output->base.assign_planes = NULL;
output->base.set_backlight = NULL;
output->base.set_dpms = NULL;
output->base.set_dpms = x11_set_dpms;
output->base.switch_mode = x11_output_switch_mode;
loop = wl_display_get_event_loop(b->compositor->wl_display);
@ -1952,6 +2023,17 @@ x11_backend_create(struct weston_compositor *compositor,
goto err_xdisplay;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0)
goto err_xdisplay;
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_xdisplay;

Some files were not shown because too many files have changed in this diff Show more