Compare commits

...

311 commits

Author SHA1 Message Date
Consolatis
c66a910753 render/pixman: fix bilinear filtering to match gles2 renderer
Before this patch the pixman renderer would use "constant padding"
for bilinear scaling which meant that the edges would either be dark
or turn transparent. The effect was most obvious when trying to scale
a single row buffer to a height like 100. The center would have the
desired color but the edges to both sides would fade into transparency.

We now use PIXMAN_REPEAT_PAD which clamps out-of-bound pixels and
seems to match the behavior of the gles2 renderer.
2026-04-02 00:59:44 +02:00
Isaac Freund
e22084f639
ext_image_capture_source_v1/scene: fix extents
Currently the width/height of the extents is too small if the first node
visited has position/dimensions 0,0,100,100 and the second node has
position/dimensions -20,-20,10,10.

In this case the current code calculates total extents as
-20,-20,100,100 but the correct extents are -20,-20,120,120.

References: https://codeberg.org/river/river-classic/issues/17
2026-03-30 17:23:02 +02:00
Simon Ser
334019f839 render/drm_syncobj: use drmSyncobjEventfd()
Avoids using a raw IOCTL directly.

This function was introduced way back in libdrm 2.4.116.
2026-03-27 18:09:07 +00:00
Simon Ser
a1ed6fca52 render/drm_syncobj: fix flags docs for wlr_drm_syncobj_timeline_waiter_init()
wlr_drm_syncobj_timeline_check() is a bit different because zero
will error out if the point has not materialized yet.

Kernel docs for struct drm_syncobj_eventfd:
https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#c.drm_syncobj_eventfd
2026-03-27 18:02:46 +00:00
Félix Poisot
f295d0322a render: explicit sync for wlr_texture_read_pixels() 2026-03-26 12:44:09 +00:00
Simon Zeni
413664e0b0 render/vulkan: compile against vulkan 1.2 header
Uses the EXT version of VK_PIPELINE_COMPILE_REQUIRED in `vulkan_strerror` func since it requires
Vulkan 1.3, switch to VK_EXT_global_priority instead of VK_KHR_global_priority which is only
promoted to core in Vulkan 1.3 as well.
2026-03-24 12:33:12 -04:00
Félix Poisot
fd870f6d27 linux_drm_syncobj_v1: fix handling of empty first commit
As reported in
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4979#note_3385626,
bfd6e619fc did not correctly handle clients
that don't immediately follow their call to
`wp_linux_drm_syncobj_manager_v1.get_surface` with a commit attaching
a buffer

Fixes: bfd6e619fc
2026-03-20 15:36:16 +00:00
Simon Ser
4ca40004fd color_management_v1: ignore surface update if no-op
If the new image description is identical to the old one, skip the
event.
2026-03-19 21:46:28 +00:00
Simon Ser
7287f700ab color_management_v1: use early continue in surface loop 2026-03-19 21:46:28 +00:00
Simon Ser
8fe3034948 tinywl: bump wlroots version to 0.21 2026-03-19 20:23:35 +01:00
Simon Ser
627da39e76 build: bump version to 0.21.0-dev 2026-03-19 20:14:53 +01:00
Félix Poisot
8d454e1e34 output/drm: don't use OUT_FENCE_PTR
The returned fence is not required to be signalled at the earliest
possible time. It is not intended to replace the drm flip event, and is
expected to be signalled only much later
2026-03-17 18:14:35 +00:00
Félix Poisot
cd555f9261 backend/drm: properly delay syncobj signalling
DRM CRTC signals when scanout begins, but
wlr_output_state_set_signal_timeline() is defined to signal buffer
release. Delay to the next page flip
2026-03-17 18:14:35 +00:00
Félix Poisot
b2f6a390a4 scene: transfer sample syncobj to client timeline 2026-03-17 18:14:35 +00:00
Félix Poisot
bfd6e619fc linux_drm_syncobj_v1: add release point accumulation
This changes the behavior of wlr_linux_drm_syncobj_surface_v1 to
automatically signal release of previous commits as they are replaced.

Users must call wlr_linux_drm_syncobj_v1_state_add_release_point or
wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer to delay the
signal as appropriate.
2026-03-17 18:14:35 +00:00
Félix Poisot
e83a679e23 drm/syncobj: add timeline point merger utility 2026-03-17 18:14:35 +00:00
Félix Poisot
1f3d351abb scene: add buffer release point to 'sample' event 2026-03-17 18:14:35 +00:00
Félix Poisot
0af9b9d003 render/drm_syncobj: add wlr_drm_syncobj_timeline_signal() 2026-03-17 18:13:10 +00:00
David Turner
abb6eeb422 backend/drm/atomic: Add support for color representation
Basic implementation of color representation in drm/atomic: when buffers
are presented for scanout which have color-representation data attached,
set the correct color encoding and range on the plane.  If the plane
does not support color-representation then the commit will fail and the
caller can retry without color-representation.
2026-03-17 16:32:30 +00:00
David Turner
dca0703dac backend/drm: Add color_range/encoding properties
Add the following optional DRM properties, for use by the
color-representation-v1 protocol:
- COLOR_ENCODING
- COLOR_RANGE
2026-03-17 16:32:30 +00:00
David Turner
80bcef908b scene: Set color representation on scanout
When doing direct-scanout, if the surface has color-representation
metadata present then pass on that metadata to the output state.

Also, if a buffer has color representation IDENTITY+FULL then normalise
this to NONE+NONE which is equivalent.
2026-03-17 16:32:30 +00:00
David Turner
58c158dba6 output: Add color-representation to output state
Add color_representation to wlr_output_state, holding color
representation metadata about the primary buffer.  This can be set
using wlr_output_state_set_primary_color_representation() and a
new enum value WLR_OUTPUT_STATE_COLOR_REPRESENTATION in
wlr_output_state.committed indicates when this data is present.

Also add color-representation to wlr_output, and discard
color-representation in wlr_output_state if it matches what's already
been committed to the output.
2026-03-17 16:32:30 +00:00
Isaac Freund
1fa8bb8f7a
virtual-keyboard: handle seat destroy
We must make the virtual keyboard inert when the seat is destroyed.
2026-03-17 09:53:32 +01:00
Isaac Freund
ec746d3e3e virtual-keyboard: add wlr_virtual_keyboard_v1_from_resource()
I want to use the zwp_virtual_keyboard_v1 object in a custom river
protocol and need to be able to obtain the corresponding wlroots struct.
2026-03-17 08:45:12 +00:00
Scott Moreau
1fc928d528 wlr_ext_image_copy_capture_v1: Fix crash when client creates a cursor session not implemented server side
This guards against a crash where the server implements
wlr_ext_image_capture_source_v1_interface without setting .get_pointer_cursor().
In general, we should install a NULL check here because this is a crash
waiting to happen. Now, instead of crashing, the resource will be created and
the copy capture session will be stopped.
2026-03-14 19:04:42 +00:00
llyyr
3cb2cf9425 scene: use wl_list_for_each_safe to iterate outputs
The outputs loop in handle_scene_buffer_outputs_update may remove entries
from the list while iterating, so use wl_list_for_each_safe instead of
wl_list_for_each.

Fixes: 39e918edc8 ("scene: avoid redundant wl_surface.enter/leave events")
2026-03-13 23:32:06 +05:30
Alexander Orzechowski
7f87c7fe90 wlr_scene: Nuke buffer output_enter / output_leave
outputs_update should be used instead.
2026-03-13 13:19:06 -04:00
Isaac Freund
39e918edc8
scene: avoid redundant wl_surface.enter/leave events
Currently we send wl_surface.enter/leave when a surface is hidden
and shown again on the same output. In practice, this happens very
often since compositors like river and sway enable and disable
the scene nodes of surfaces as part of their atomic transaction
strategy involving rendering saved buffers while waiting for
clients to submit new buffers of the desired size.

The new strategy documented in the new comments avoids sending
redundant events in this case.
2026-03-13 17:59:13 +01:00
Diego Viola
736c0f3f25 wlr-export-dmabuf-unstable-v1: fix typo 2026-03-12 11:03:57 +00:00
Jonathan Marler
3c8d199ec1 backend/x11: ignore DestroyNotify events
The X11 backend subscribes to StructureNotify events, so when
output_destroy() calls xcb_destroy_window() the server sends a
DestroyNotify back. This is expected and harmless but was logged
as an unhandled event. Silence it the same way MAP_NOTIFY and
UNMAP_NOTIFY are already silenced.
2026-03-10 22:44:56 -06:00
Kenny Levinsen
7ccef7d9eb Adopt wlr_box_intersects where useful
This makes wlr_scene_node_at roughly 50% faster, and gives a minor boost
to node modification as well.

Before:

create test tree:               7030 nodes, 473.510 s, 15 nodes/ms
wlr_scene_node_at:              10000 iters, 894.945 s, 78552 nodes/ms (hits: 10/10000)
wlr_scene_node_for_each_buffer: 10000 iters, 330.597 s, 212646 nodes/ms (hits: 0/10000)

After:

create test tree:               7030 nodes, 385.930 s, 18 nodes/ms
wlr_scene_node_at:              10000 iters, 586.013 s, 119963 nodes/ms (hits: 10/10000)
wlr_scene_node_for_each_buffer: 10000 iters, 334.559 s, 210127 nodes/ms (hits: 0/10000)
2026-03-09 22:09:40 +00:00
Kenny Levinsen
2938c10cd3 ci: Run tests and benchmarks 2026-03-09 22:09:40 +00:00
Kenny Levinsen
648790f43a tests: Initial test and benchmark setup
Add a unit test for wlr_box and benchmark for wlr_scene_node_at as our
first test examples, lowering the barrier for adding more tests as
suitable.
2026-03-09 22:09:40 +00:00
Kenny Levinsen
ff7d093800 util/box: Add wlr_box_intersects
wlr_box_intersection generates a new box based on the intersection of
two boxes. Often we simply want to know *if* two boxes intersected,
which we can answer much cheaper.

Add wlr_box_intersects, in similar vein as wlr_box_contains_box but
returning true for any overlap.
2026-03-09 22:09:40 +00:00
Kenny Levinsen
285cee5f3a util/box: Use integer min/max for intersection
wlr_box_intersection only operates on integers, so we shouldn't use
fmin/fmax. Do the usual and add a local integer min/max helper.
2026-03-09 22:09:40 +00:00
Christopher Snowhill
9a931d9ffa scene: fix color format compare
bool doesn't really support negative values.

Fixes: 7cb3393e7 (scene: send color_management_v1 surface feedback)
2026-03-06 18:44:26 -08:00
hrdl
3dafaa4df3 render/vulkan: relax minimum Vulkan API version to 1.0
This allows using the vulkan renderer on platforms that provide all
the necessary Vulkan extensions.

Tested on a Mali G52 platform with Mesa 26.0.0 and 25.3.5, which only
support Vulkan API 1.0.
2026-03-06 15:45:05 +01:00
Simon Zeni
67ce318b1f ci: update dalligi upstream repo 2026-03-06 09:37:31 -05:00
YaoBing Xiao
14b3c96c1e treewide: make type-check helpers take const pointers 2026-03-06 16:04:21 +08:00
Andri Yngvason
3336d28813 image_capture_source/output: Update constraints on enable
Without observing the enable event, clients receive no pixel formats and
buffer dimensions are reported as 0 after an output has been re-enabled.
2026-03-05 21:28:55 +00:00
Simon Ser
2d39166146 build: bump version to 0.20.0-rc4 2026-03-05 19:54:06 +01:00
liupeng
1b8c3ea8c5 screencopy: simplify capture error handling
Signed-off-by: liupeng <liupeng01@kylinos.cn>
2026-03-04 21:09:47 +08:00
YaoBing Xiao
55bb69e2c4 render/gles: use optimized clears for unblended rects 2026-03-03 11:02:08 +00:00
Wang Yu
a55b85e2e1 xwayland: fix memory leak on pipe() failure
When pipe() fails in xwm_selection_send_data(), the function
returns without cleaning up the allocated transfer structure
and initialized wl_array. This causes a memory leak.

Add wl_array_release() and free() to clean up resources when
pipe() fails.

Signed-off-by: Wang Yu <wangyu@uniontech.com>
2026-03-03 14:37:42 +08:00
Diego Viola
6d9aa17572 treewide: fix typos
Signed-off-by: Diego Viola <diego.viola@gmail.com>
2026-02-28 04:26:47 -03:00
Kenny Levinsen
1ce992d7cb scene/layer_shell_v1: Add support for exclusive_edge
The v5 layer shell interface allows the client to specify which edge the
exclusive zone will apply to, instead of deducing it from the anchor
points. Add support for this to the layer shell scene helper.
2026-02-24 13:28:46 +00:00
Simon Ser
2367d78c3c render/vulkan: fix missing DMA-BUF implicit write fence for render buffer
Same as previous commit for the read side, but this one waits for
all readers to be done before starting to write.
2026-02-23 09:33:27 -05:00
Simon Ser
8c8d6363a1 render/vulkan: add "acquire" to vulkan_sync_foreign_texture()
Makes it more obvious that this is about the acquire side, not the
release side.
2026-02-23 09:33:27 -05:00
Simon Ser
ff4ce12179 render/vulkan: introduce buffer_export_sync_file()
Same as buffer_import_sync_file(), but for the export side.
2026-02-23 09:33:27 -05:00
Simon Ser
43b37e34d6 render/vulkan: fix missing DMA-BUF implicit read fence for textures
When we're reading from a DMA-BUF texture using implicit sync, we
need to (1) wait for any writer to be done and (2) prevent any
writers from mutating the texture while we're still reading. We
were doing (1) but not (2).

Fix this by calling dmabuf_import_sync_file() with DMA_BUF_SYNC_READ
for all DMA-BUF textures we've used in the render pass.
2026-02-23 09:33:27 -05:00
Simon Ser
73bbad8433 render/vulkan: take render pass in vulkan_sync_render_buffer()
We'll need to grab textures from there in the next commit.

Also rename it to better reflect what it does: synchronize release
fences after a render pass has been submitted.
2026-02-23 09:33:27 -05:00
Simon Ser
a6e5807e86 render/vulkan: introduce buffer_import_sync_file()
Will be used in two spots in a following commit.
2026-02-23 09:33:27 -05:00
Simon Ser
7be5e3689c build: bump version to 0.20.0-rc3 2026-02-22 23:38:52 +01:00
hrdl
25bec59c75 CONTRIBUTING.md: update git host
gitlab.freedesktop.org -> ssh.gitlab.freedesktop.org
2026-02-20 00:31:06 +01:00
Kenny Levinsen
1efb216c6d backend/drm: Close non-master drm fd on failure
If we are not able to prepare the fd for non-master usage, close the fd
before returning an error.
2026-02-19 15:11:56 +00:00
Simon Ser
884d29e5f3 backend/libinput: guard against new enum entries
When libinput introduces new enum entries, we'd abort or send bogus
events to the compositor. Instead, log a message and ignore the
event.

Keep all enums without a default case so that the compiler warns
when we're missing a case.
2026-02-13 09:41:02 -05:00
Isaac Freund
25f94c5965
backend/x11: reject shm buffers with non-min strides
This fixes an X11 backend direct scanout bug with foot.

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/4046
2026-02-13 11:56:08 +01:00
Simon Ser
910fd264fb build: bump version to 0.20.0-rc2 2026-02-12 22:47:22 +01:00
Aleksei Bavshin
3676ab4df0
backend/libinput: add support for LIBINPUT_SWITCH_KEYPAD_SLIDE 2026-02-08 11:01:06 -08:00
Aleksei Bavshin
c1452d8811
backend/libinput: fix build with libinput 1.31 2026-02-08 10:56:16 -08:00
Steve Williams
436bcf9a47 color-representation-v1: fix condition in surface commit 2026-02-07 08:36:29 +04:00
Steve Williams
ef88246642 types/wlr_buffer: add buffer_get_drm_format helper function 2026-02-06 13:53:46 +00:00
Steve Williams
bb78861ca9 color-representation: add support for identity+full 2026-02-06 13:53:46 +00:00
Steve Williams
439985fe95 color_representation: ensure encoding/range/drm formats compatibility 2026-02-06 13:53:46 +00:00
Steve Williams
4c81cb1b9e vulkan: make use of new pixel_format_is_ycbcr function 2026-02-06 13:53:46 +00:00
Steve Williams
19d6829601 render/pixel-format: add function to determine YCbCr from drm fourcc 2026-02-06 13:53:46 +00:00
YaoBing Xiao
dfccf5ff02 output/cursor: fix missing newline at end of file 2026-02-06 09:05:52 +00:00
rewine
bc11ac92ab
ext_image_capture_source_v1: remove unused variable 2026-02-06 10:41:42 +08:00
YaoBing Xiao
d362ed1eb9 xwayland: fix wl_array rollback when adding selection targets
Ensure mime_types and mime_types_atoms remain in sync when
wl_array_add() fails. Roll back the partially added entry and
free the allocated mime type to avoid leaks and inconsistent
state.
2026-02-05 09:26:55 +08:00
Simon Ser
90f9f59041 xwayland: try flushing immediately in xwm_schedule_flush()
wl_event_source_fd_update() goes through another event loop cycle, which
delays writes. This extra cycle was introduced in 6ada67da9b
("xwayland/xwm: implement somewhat asynchronous request flushing").

Try flushing the X11 WM FD immediately if we can.

References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/4044
2026-02-04 00:14:49 +01:00
rewine
7cb4e30bfd
wlr_cursor: fix event type in handle_tablet_tool_button 2026-02-03 21:25:50 +08:00
rewine
98196bbd89
wlr_cursor: add comments for signal parameters 2026-02-03 21:24:32 +08:00
rewine
4fe51aa439 types: Simplify wlr_keyboard_group_destroy
If the wlr_keyboard_group_remove_keyboard function is expanded, the code
is equivalent to:

```
	wl_list_for_each_safe(device, tmp_device, &group->devices, link) {
		struct wlr_keyboard_group *_group = group;
		struct wlr_keyboard *_keyboard = device->keyboard;
		struct keyboard_group_device *_device, *_tmp;
		wl_list_for_each_safe(_device, _tmp, &_group->devices, link) {
			if (_device->keyboard == _keyboard) {
				remove_keyboard_group_device(_device);
				continue;
			}
		}
	}
```

It's just running one more loop meaninglessly.
2026-02-02 10:46:20 -05:00
liupeng
12c9502edf render/drm_syncobj: fix function name in drmSyncobjTimelineWait() error log
Signed-off-by: liupeng <liupeng01@kylinos.cn>
2026-02-02 09:12:39 +08:00
liupeng
7f87e258b2 render/drm_syncobj: drop unnecessary drmSyncobjTimelineWait() arg
Signed-off-by: liupeng <liupeng01@kylinos.cn>
2026-02-02 09:11:41 +08:00
Simon Ser
4477ca7d32 build: bump version to 0.20.0-rc1 2026-02-01 21:13:18 +01:00
Simon Ser
d6c7a161c7 color_representation_v1: send chroma_location protocol error
This error has been added in:
46f46863b7
2026-02-01 20:09:45 +00:00
tokyo4j
82d5ffb09e ext-workspace-v1: add implementation
Co-authored-by: Consolatis <40171-Consolatis@users.noreply.gitlab.freedesktop.org>
2026-01-31 01:44:23 +09:00
Kenny Levinsen
5e32b6663b ext_image_copy_capture_v1: Only render scene source on damage
wlr_scene_output_needs_frame checks wlr_output.needs_frame and
wlr_scene_output.gamma_lut_changed, neither of which incur damage. The
needs_frame flag is often set by e.g., cursor movement.

For the purpose of a capture frame we are only interested in frames with
damage. Continue without damage causes session_handle_source_frame to
silently skip copying the frame, which causes the session to get stuck:
no ready or failed event is emitted, and frame_pending is still set so
no further output frame events will occur.

Only render in case there is damage, but send frame callbacks
regardless.
2026-01-24 22:49:40 +00:00
Félix Poisot
5a40da7e15 render: don't infer luminance multipliers from color TF
Make scene pass them explicitly instead. Ref #3995
2026-01-23 19:41:14 +00:00
Félix Poisot
68052f34d3 color_management_v1: new enum value for 'srgb' transfer function
ref https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/442
2026-01-23 18:50:09 +00:00
Félix Poisot
bb882e97f1 color_management_v1: use 64bit image description identities
ref https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/385
2026-01-23 18:50:09 +00:00
Félix Poisot
58f0867c04 color_management_v1: relax restrictions on maxCLL and maxFALL
ref https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/428
2026-01-23 18:50:09 +00:00
Félix Poisot
e6ddb6cdd3 meson: bump minimum wayland-protocols version
1.47 brings updates to color-management
2026-01-23 18:50:09 +00:00
Kenny Levinsen
5661ac1cd2 output-swapchain-manager: Reject zero resolution
If an output with no mode and no valid pending resolution is attempted
enabled, it will trigger an assert in swapchain allocation instead of
failing on a rejected atomic commit or pre-commit test.

We can sometimes get such broken outputs if e.g., the underlying driver
failed to retrieve EDID, and so crashing on assert is suboptimal.

Reject zero-sized swapchains early and log the issue.
2026-01-22 12:55:13 +01:00
xurui
91c08d5a53 xwayland/selection/dnd: fix parameter type
Signed-off-by: xurui <xurui@kylinos.cn>
2026-01-20 16:39:08 +08:00
Jens Peters
3eb07b1fdb backend/libinput: expose libinput_tablet_tool
Exposing libinput_tablet_tool from libinput allows compositors
to set tool specific configuration options like pressure range
and eraser button behavior.

See 'libinput_tablet_tool_*()' functions which require a
'libinput_tablet_tool' handle:
https://wayland.freedesktop.org/libinput/doc/1.30.0/api/group__config.html
(libinput 1.30.0, latest at the time of writing).
2026-01-19 20:45:39 +01:00
Stephane Fontaine
b7312b4f95 xwm: don't leak msg in case of realloc failure 2026-01-18 17:42:25 +04:00
Isaac Freund
f735439543
xwayland: add set_size_hints signal
Currently there is no way for the compositor to be notified when an
Xwayland client sets/modifies its size hints.
2026-01-15 11:49:49 +01:00
Robin Ebert
ba76d37b0b
wlr_ext_image_copy_capture_v1: Fix segmentation fault when using cursor session
Fixes: 3b9f599cbe
2026-01-12 12:40:34 +01:00
Alexander Orzechowski
1f0fb95e3b wlr_scene: Add documentation to scene_node_update() 2026-01-08 13:03:46 -05:00
Alexander Orzechowski
ed7b633669 wlr_scene: Only do disable cleanup when explicit damage is given
We don't want to iterate the subtree for trivial update scenarios. We only
care when a scene is reparented or disabled in which both cases provides
us with explicit damage
2026-01-08 13:03:46 -05:00
Alexander Orzechowski
ef19f52ca9 wlr_scene: Update outputs when node is disabled 2026-01-08 13:03:46 -05:00
Alexander Orzechowski
56eb27ab0b wlr_scene: Don't recurse when disabling scene node if a child is already disabled
If a child is disabled, that means the node already went through the
rigamarole of cleaning up its state. Don't do it again.
2026-01-08 13:03:46 -05:00
Alexander Orzechowski
edc12e81d9 wlr_scene: Make restack_xwayland_surface_below generic
more stuff will be put here
2026-01-08 13:03:46 -05:00
Peter Kaplan
49576469ec image_capture_source: wlr_output_try_from_ext_image_capture_source_v1() 2026-01-07 09:18:25 +01:00
Peter Kaplan
3b9f599cbe wlr_ext_image_copy_capture_v1: new_session event
And a destroy event in wlr_ext_image_copy_capture_session_v1.
2026-01-07 09:18:25 +01:00
Simon Ser
368dcfb9f6 ext_image_capture_source_v1: wait for capture client before sending frame event
We were sending an output frame event as soon as we were done
rendering. As a result, the output would render in a busy loop when
a client was using the capture output for frame pacing purposes.

Instead, use the request_frame hook introduced in the previous
commit to throttle output frame events.

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/4036
2026-01-05 15:03:18 -05:00
Simon Ser
f93865ed1f ext_image_copy_capture_v1: replace schedule_frame with request_frame
schedule_frame is only called when the client has submitted damage
and a new frame should be rendered immediately. schedule_frame is
not called when the capture client is waiting for the next frame
but hasn't submitted damage.

Sources implementing a rendering loop based on the capture rate
need to know when a capture client is ready to accept a new frame.
Such sources want to trigger a redraw if and only if (1) they are
dirty (their contents have changed) and (2) the capture client is
ready to accept a new frame.

Replace schedule_frame with request_frame, triggered each time a
client sends a capture request. A flag indicates whether the capture
client has submitted damage.
2026-01-05 15:03:18 -05:00
llyyr
6ae54dca23 xwayland: lock new buffer instead of the old one
Fixes: 84d603acc0
2026-01-05 20:53:34 +05:30
Simon Ser
84d603acc0 xwayland: take wlr_buffer in wlr_xwayland_set_cursor() 2026-01-05 10:10:32 -05:00
Simon Ser
53d75a41c7 cursor: use wlr_xcursor_image_get_buffer() 2026-01-05 10:10:32 -05:00
Simon Ser
d7f7b68f49 xcursor: introduce wlr_xcursor_image_get_buffer()
This makes it so callers no longer need to juggle with raw pixel
pointers anymore, and only need a single wlr_buffer-based codepath.

Additionally, cursors can be unloaded without risking use-after-free.
2026-01-05 10:10:32 -05:00
Simon Ser
98733c91b4 xcursor: add shared helper to create a wlr_xcursor_image
This logic was duplicated in two spots.
2026-01-05 10:10:32 -05:00
Simon Ser
89c9ef6692 render/gles2: skip glslang check when shaders are unchanged
Currently, the glslang check is run every time ninja is invoked,
even with an up-to-date build directory when GLSL shaders haven't
been modified. This is due to glslang not creating any output
file: the _check file never exists so ninja keeps trying to
generate it by running the command.

Unfortunately Meson doesn't support running commands with no
outputs [1]. Create an empty output file to fix this by setting
`capture: true`.

This doesn't work out-of-the-box, because glslang prints messages
to stdout, and provides no way to change this [2]. As a result,
shader errors are not surfaced back to the user - they end up in
the _check file. Workaround this with a thin wrapper which
redirects stdout to stderr when invoking glslang.

[1]: https://github.com/mesonbuild/meson/issues/11506
[2]: https://github.com/KhronosGroup/glslang/pull/4138
2026-01-05 09:59:58 -05:00
Simon Ser
2c64b30a67 scene: add knob to turn off Xwayland surface restacking
This is useful in these cases:

- The same surface is added to two different scene-graphs. wlroots
  can't figure out on its own which scene-graph should drive the
  Xwayland stacking.
- A compositor uses multiple Xwayland servers (e.g. one per app).
  wlroots will try to restack surfaces from different Xwayland
  instances and this will not go well.
2026-01-04 16:02:52 +00:00
Simon Ser
b094f8aeb3 scene/surface: don't cache frame pacing output
Storing the frame pacing output in a per-scene and per-surface
struct doesn't play well with multiple scenes. outputs_update is
only triggered for outputs the scene knows about, but operates on
all outputs the surface has entered regardless of the scene. Thus
leaving an output on one scene will not refresh the frame pacing
output on other scenes, and these other scenes will operate with
a stale frame pacing output. The surface will not receive any more
wl_surface.frame done events.

This also avoids keeping a dangling pointer around when the frame
pacing output is destroyed but the output isn't added in the scene.

References: https://github.com/swaywm/sway/issues/8885
2026-01-04 14:40:18 +01:00
Simon Ser
2699b68b34 ext_image_capture_source_v1/scene: fix stop for parallel captures
The stop handler disables the output. However, the same source can
be captured multiple times in parallel. In that case, stop might
be called while another capture session is still ongoing.

Only disable the output if the last session is stopped.
2026-01-04 00:34:39 +00:00
Simon Ser
caed9d78d7 render: drop <linux/dma-buf.h> compat defines
It's been 3 years, so these defines are widespread enough by now.
2026-01-04 00:30:34 +00:00
Simon Ser
3f9a164484 scene: keep last preferred configuration when leaving last output
Before this patch, when a surface became occluded on all outputs,
we'd reconfigure it with a base configuration (scale set to 1,
transform set to NORMAL, image description set to gamma 2.2/sRGB).
As a result, when quickly hiding a toplevel and showing it again,
the client would render to switch to the base configuration, then
render again to switch to the output configuration.

Avoi this needless back-and-forth by retaining the last sent
preferred configuration when a surface leaves all outputs.
2026-01-04 00:24:47 +00:00
Simon Ser
ca8b49d858 render/vulkan: add new 16- and 32-bits-per-component pixel formats
Compatibility table based on pixfmtdb.
2026-01-03 17:47:19 +00:00
Simon Ser
1723f851d2 render/gles2: add BGR161616F and BGR161616 2026-01-03 17:47:19 +00:00
Simon Ser
d512c00791 render: add new 16- and 32-bits-per-component pixel formats
These new formats have been introduced in libdrm 2.4.129:
31e68ea81c
2026-01-03 17:47:19 +00:00
Simon Ser
53cdceb371 scene: constify pixman_region32_t
Makes it easier to figure out which functions build regions, and
which functions consume them.
2025-12-28 22:56:55 +01:00
Simon Ser
8611aa8440 scene: don't assign outputs to invisible nodes
If a node has no visible areas, leave active_outputs empty.

Fixes: 95b2771bfd ("scene: ignore outputs with too small intersection with nodes")
2025-12-28 22:30:25 +01:00
sunzhguy
9119b8aa85 session: simplify libudev unref handling
Signed-off-by: sunzhguy <sunzhigang1@kylinos.cn>
2025-12-22 10:55:08 +08:00
John Lindgren
16cb509a6e render/allocator: add missing wlr_buffer_finish() in destroy impls
Fixes use-after-free on exit of labwc running nested:

==50906== Invalid write of size 8
==50906==    at 0x4A85403: wl_list_remove (wayland-util.c:57)
==50906==    by 0x40BBAF9: destroy_wl_buffer (output.c:146)
==50906==    by 0x40B9B4F: backend_destroy (backend.c:488)
==50906==    by 0x409E96F: wlr_backend_destroy (backend.c:68)
==50906==    by 0x40B78A6: multi_backend_destroy (backend.c:62)
==50906==    by 0x409E96F: wlr_backend_destroy (backend.c:68)
==50906==    by 0x4043DA0: server_finish (server.c:788)
==50906==    by 0x403AA85: main (main.c:277)
==50906==  Address 0xb4435e8 is 40 bytes inside a block of size 136 free'd
==50906==    at 0x4A3E8EF: free (vg_replace_malloc.c:989)
==50906==    by 0x409C954: buffer_destroy (shm.c:28)
==50906==    by 0x40E96F4: buffer_consider_destroy (buffer.c:42)
==50906==    by 0x40E9754: wlr_buffer_drop (buffer.c:52)
==50906==    by 0x41498DA: slot_reset (swapchain.c:44)
==50906==    by 0x4149933: wlr_swapchain_destroy (swapchain.c:53)
==50906==    by 0x40CB1FA: wlr_output_finish (output.c:410)
==50906==    by 0x40BE00B: output_destroy (output.c:957)
==50906==    by 0x40CB2FC: wlr_output_destroy (output.c:436)
==50906==    by 0x40B9AFC: backend_destroy (backend.c:481)
==50906==    by 0x409E96F: wlr_backend_destroy (backend.c:68)
==50906==    by 0x40B78A6: multi_backend_destroy (backend.c:62)
==50906==  Block was alloc'd at
==50906==    at 0x4A42C13: calloc (vg_replace_malloc.c:1675)
==50906==    by 0x409CA84: allocator_create_buffer (shm.c:68)
==50906==    by 0x409C7BA: wlr_allocator_create_buffer (allocator.c:186)
==50906==    by 0x4149B80: wlr_swapchain_acquire (swapchain.c:102)
==50906==    by 0x40C90DA: render_cursor_buffer (cursor.c:246)
==50906==    by 0x40C93DC: output_cursor_attempt_hardware (cursor.c:303)
==50906==    by 0x40C9A61: output_cursor_set_texture (cursor.c:420)
==50906==    by 0x40C9738: wlr_output_cursor_set_buffer (cursor.c:352)
==50906==    by 0x40F13A0: output_cursor_set_xcursor_image (wlr_cursor.c:507)
==50906==    by 0x40F1B28: cursor_output_cursor_update (wlr_cursor.c:630)
==50906==    by 0x40F1C2A: cursor_update_outputs (wlr_cursor.c:657)
==50906==    by 0x40F1CF9: wlr_cursor_set_xcursor (wlr_cursor.c:674)

Fixes: 7963ba6a0d
("buffer: introduce wlr_buffer_finish()")
2025-12-20 15:02:08 -05:00
liupeng
0ad8395ae6 backend/session: respond to event hangup or error
Signed-off-by: liupeng <liupeng01@kylinos.cn>
2025-12-19 10:38:26 +00:00
Félix Poisot
450d90a55d render/color: assert that wlr_color_transform_pipeline contains no NULLs
Consumers of transform pipelines are not expected to handle no-op
stages
2025-12-18 14:58:28 +00:00
Félix Poisot
32d5fc1d11 render/color: introduce color_transform_compose
It flattens color transform pipelines, and facilitates building
pipelines of variable content
2025-12-18 14:58:28 +00:00
Simon Ser
3d8c471aef color_management_v1: add BT.1886 to TF-from-renderer helper
BT.1886 support has been added to wlroots after this helper got
written.
2025-12-18 09:54:27 -05:00
Simon Ser
c0b93a9e7c render/pixman: add support for ABGR16161616
PIXMAN_a16b16g16r16 has been added in Pixman in this commit:
c0d38585f1
2025-12-18 09:48:02 -05:00
Simon Ser
322291cdcf tinywl: fix duplicate object files passed to linker
On BSD make, $> is an alias for $^. On both GNU and BSD make, $^
is supported. Specifying both resulted in duplicate object files
passed to the linker:

    ld: error: duplicate symbol: main
    >>> defined at tinywl.c:887
    >>>            tinywl.o:(main)
    >>> defined at tinywl.c:887
    >>>            tinywl.o:(.text+0x0)
    cc: error: linker command failed with exit code 1 (use -v to see invocation)

Only use $^ and remove $>.
2025-12-18 15:22:33 +01:00
Simon Ser
9b4d9eabb1 color_management_v1: add helpers to get supported TFs/primaries
This avoids hardcoding lists of TFs/primaries in compositors.

I've considered adding wlr_color_manager_v1_create_with_renderer()
instead, but I'm worried that some aspects of the options struct
don't really depend on the renderer, but on the compositor. Such
things are features and render intents.

I've considered returning a const array, but this would tie our
hands if we want to make the renderer advertise the set of
TFs/primaries it supports, instead of having a single flag gating
all of them.
2025-12-15 11:07:26 -05:00
tokyo4j
ba931024a5 Add wlr_version_get_{major,minor,micro}()
Can be used to detect wlroots version at runtime rather than
compile-time.
2025-12-13 11:06:28 +00:00
Ilia Bozhinov
0e9c6ddefa seat: add wlr_seat_touch_notify_clear_focus
This is needed for cases where the touch operation goes over a region
where no surfaces are present. In this case, we'd want to notify the
touch grabs (for example DnD grabs) that no focus is currently focused.
2025-12-11 21:10:59 +00:00
Ilia Bozhinov
03b465f324 drag: destroy data source on touch_up
This is in case we drop the drag with no focus, we want to destroy the
drag to tell the client the drag was cancelled.
2025-12-11 21:10:59 +00:00
llyyr
bf9452433c render/vulkan: normalize luminance range in bt.1886 formula
BT.1886 is different from other EOTFs in that the spec says that offset
b must be in electrical domain, so use the assumed display environment
from the specification as Lmin and Lmax then normalize bt.1886 to
produce optical luminance L in [0, 1]. See discussion at
https://gitlab.freedesktop.org/pq/color-and-hdr/-/merge_requests/63#note_3090016
2025-12-11 21:04:41 +00:00
Félix Poisot
a962d58727 render/color: make wlr_color_primaries_from_named public 2025-12-05 19:14:49 +00:00
llyyr
c45b3b1f5f color_representation_v1: don't leak supported_* on display destroy 2025-12-04 15:27:22 +05:30
Dale Turner
47486545b1 Add "const" to eliminate "error: initialization discards ‘const’ qualifier from pointer target type" 2025-12-03 20:02:29 -04:00
tokyo4j
abf80b529e wlr-foreign-toplevel: avoid wl_resource_find_for_client()
If the client application is composed of multiple components and they
bind the manager global separately, choosing a single toplevel resource
with wl_resource_find_for_client() may result in a component only seeing
unknown toplevel handles from another component.

Maybe we should track which toplevel handle resource originate from
which manager resource so that a component never sees toplevel handles
resources from another component, but it's too annoying to implement.
2025-11-25 18:54:20 +00:00
Félix Poisot
811765ffa0 output: don't rebuild cursor color transform for each update 2025-11-24 23:26:14 +00:00
Félix Poisot
7101a69804 scene: don't rebuild color transforms each frame 2025-11-24 23:26:14 +00:00
Félix Poisot
3d3d5fb1b7 render: remove buffer primaries from pass options
colorspace conversion is now carried explicitely by setting a
wlr_color_transform_matrix in the color transform
2025-11-24 23:26:14 +00:00
Félix Poisot
fdb473e675 scene: always apply user gamma after scene color transform
Fixes 989cffe, making renderer-applied transform consistent with
hardware-applied transform
2025-11-24 23:26:14 +00:00
Félix Poisot
2cac711e55 render/vulkan: apply "matrix" color transforms in shader 2025-11-24 23:26:14 +00:00
Simon Ser
2995f31102 render/color: introduce wlr_color_transform_matrix
This is useful to perform color space conversions.
2025-11-24 23:26:14 +00:00
Félix Poisot
17f3f28865 render/color: add wlr_color_primaries_transform_absolute_colorimetric 2025-11-24 23:26:14 +00:00
Guido Günther
9b9d7d845d input-method-unstable-v2: surrounding text sends surrounding text
Don't claim it sends preedit

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-11-23 17:14:01 +00:00
Guido Günther
bd861267e3 input-method-unstable-v2: There are no enable / disable events
So don't mention them

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-11-23 17:14:01 +00:00
Félix Poisot
b98904705d render/vulkan: fix single-pass linear path
Fixes d1c88e9 "render/vulkan: add linear single-subpass"

`find_or_create_render_setup` still assumed a single-buffer setup
always implied use of an srgb format
2025-11-23 10:30:51 +00:00
Félix Poisot
106f0f9506 output/state: add missing unref for color_transform 2025-11-14 11:10:37 +00:00
Simon Ser
fa7b66bcf4 color_representation_v1: add helper to create global from renderer 2025-11-13 10:35:56 -05:00
Simon Ser
87c3cb5c52 scene: add support for color-representation-v1 coeffs and range 2025-11-13 10:35:56 -05:00
Simon Ser
2fbc0b5ac1 scene: add support for color encoding and range 2025-11-13 10:35:56 -05:00
Simon Ser
e8f9e9eea6 color_representation_v1: make supported_alpha_modes const 2025-11-13 10:35:56 -05:00
Simon Ser
fecaf6d1e8 render/vulkan: add suport for color encoding and range 2025-11-13 10:35:56 -05:00
Simon Ser
2a87ec8a35 render: add color encoding and range to wlr_render_texture_options 2025-11-13 10:35:56 -05:00
Simon Ser
378a491823 render/color: turn enum wlr_color_encoding into a bitfield
This will allow us to describe the set of supported encodings as
a bitfield.
2025-11-13 10:35:56 -05:00
Félix Poisot
0d24cdb822 cursor: apply output image description when preparing texture 2025-11-11 21:55:06 +00:00
David96
aef84f0e4d wlr_virtual_pointer: Set axis source on all axis
Currently it is possible to crash a wlroots compositor by setting any
axis source other than 0 and sending an axis event in the HORIZONTAL
direction from wlr_virtual_pointer since the axis source is only set on
the first axis.
This then hits the assert in wlr_seat_pointer.c:332.

Fix by always setting the source on all axis.
2025-11-06 16:02:58 +00:00
Félix Poisot
8f7d763ad1 drm: save edid color characteristics in wlr_output 2025-11-06 10:29:12 +00:00
xurui
47d0a90274 types/wlr_input_device: name maybe NULL
Signed-off-by: xurui <xurui@kylinos.cn>
2025-11-04 17:29:23 +08:00
llyyr
604fcdb1db render/vulkan: clip negative values before applying transfer function
Not all eotf or eotf inverse are well defined for values outside the
intended domain, so just ignore it and clamp it away.

An alternative solution would be to use sign preserving pow here (i.e.
sign(x) * pow(abs(x), p)), however I'm not sure that makes sense or is
defined anywhere. Negative values here are likely a result of colors
being outside the gamut range, so clipping them to 0 is more correct
than mirroring from 0.
2025-10-29 03:09:11 +05:30
David Turner
879243e370 xwm: Fix double-close
When an FD is passed to xcb_connect_to_fd(), xcb takes ownership of that
FD and is responsible for closing it, which it does when
xcb_disconnect() is called.  But the xwayland handler code also keeps a
copy of the FD and closes it via safe_close() in
server_finish_process().

This double-close can cause all sorts of problems if another part of
wlroots allocates another FD between the two closes - the latter close
will close the wrong FD and things go horribly wrong (in my case leading
to use-after-free and segfaults).

Fix this by setting wm_fd[0]=-1 after calling xwm_create(), and ensuring
that xwm_create() closes the FD if startup errors occur.
2025-10-20 14:02:29 +01:00
Simon Ser
989cffe70d scene: add software fallback for gamma LUT 2025-10-18 20:36:01 +02:00
Simon Ser
3e08e3be4a gamma_control_v1: introduce fallback_gamma_size 2025-10-18 20:36:01 +02:00
Simon Ser
91f4890ec2 gamma_control_v1: add wlr_gamma_control_v1_get_color_transform() 2025-10-18 20:36:01 +02:00
Simon Ser
74ce6c22a5 output: check for color transform no-op changes
This allows callers to always set this state and not care whether
the output currently has the same color transform applied.
2025-10-18 20:36:01 +02:00
Simon Ser
0b58bddf13 render/color: add wlr_color_transform_pipeline
Useful to apply multiple transforms in sequence, e.g. sRGB inverse
EOTF followed by gamma LUTs.
2025-10-18 20:36:01 +02:00
Simon Ser
3d36ab9211 render/color: add wlr_color_transform_eval()
Makes it so the Vulkan renderer can handle arbitrary color
transforms, and doesn't need to be updated each time a new one is
added.
2025-10-18 20:35:02 +02:00
Furkan Sahin
d786e07899 backend/session: use device boot_display
shouldn't need to check for `boot_vga` if newer, more general
sysfs `boot_display` is set.
closes https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/4016
2025-10-17 17:35:51 +00:00
Simon Ser
6d63871f05 linux_drm_syncobj_v1: fix use-after-free in surface_commit_destroy()
surface_commit_destroy() accesses a field from
struct wlr_linux_drm_syncobj_surface_v1, however that struct may have
been free'd earlier:

    ==1103==ERROR: AddressSanitizer: heap-use-after-free on address 0x7cdef7a6e288 at pc 0x7feefaac335a bp 0x7ffc4de8f570 sp 0x7ffc4de8f560
    READ of size 8 at 0x7cdef7a6e288 thread T0
        #0 0x7feefaac3359 in surface_commit_destroy ../subprojects/wlroots/types/wlr_linux_drm_syncobj_v1.c:195
        #1 0x7feefaac34cd in surface_commit_handle_surface_destroy ../subprojects/wlroots/types/wlr_linux_drm_syncobj_v1.c:211
        #2 0x7feefbd194cf in wl_signal_emit_mutable (/usr/lib/libwayland-server.so.0+0x84cf) (BuildId: b9664217748f523995e3f855fa197cf8e59942d1)
        #3 0x7feefaa52b22 in surface_handle_resource_destroy ../subprojects/wlroots/types/wlr_compositor.c:730
        #4 0x7feefbd1bb9f  (/usr/lib/libwayland-server.so.0+0xab9f) (BuildId: b9664217748f523995e3f855fa197cf8e59942d1)
        #5 0x7feefaa46a18 in surface_handle_destroy ../subprojects/wlroots/types/wlr_compositor.c:65
        #6 0x7feef89afac5  (/usr/lib/libffi.so.8+0x7ac5) (BuildId: d5e3b0d8921923f35438adefa9f864745abc5e90)
        #7 0x7feef89ac76a  (/usr/lib/libffi.so.8+0x476a) (BuildId: d5e3b0d8921923f35438adefa9f864745abc5e90)
        #8 0x7feef89af06d in ffi_call (/usr/lib/libffi.so.8+0x706d) (BuildId: d5e3b0d8921923f35438adefa9f864745abc5e90)
        #9 0x7feefbd17531  (/usr/lib/libwayland-server.so.0+0x6531) (BuildId: b9664217748f523995e3f855fa197cf8e59942d1)
        #10 0x7feefbd1cd2f  (/usr/lib/libwayland-server.so.0+0xbd2f) (BuildId: b9664217748f523995e3f855fa197cf8e59942d1)
        #11 0x7feefbd1b181 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xa181) (BuildId: b9664217748f523995e3f855fa197cf8e59942d1)
        #12 0x7feefbd1d296 in wl_display_run (/usr/lib/libwayland-server.so.0+0xc296) (BuildId: b9664217748f523995e3f855fa197cf8e59942d1)
        #13 0x555bf0a55a40 in server_run ../sway/server.c:615
        #14 0x555bf0a4a654 in main ../sway/main.c:376
        #15 0x7feef9227674  (/usr/lib/libc.so.6+0x27674) (BuildId: 4fe011c94a88e8aeb6f2201b9eb369f42b4a1e9e)
        #16 0x7feef9227728 in __libc_start_main (/usr/lib/libc.so.6+0x27728) (BuildId: 4fe011c94a88e8aeb6f2201b9eb369f42b4a1e9e)
        #17 0x555bf0a03f54 in _start (/home/leo/code/stuff/sway/build/sway/sway+0x390f54) (BuildId: e3d4e653af1aa0885f0426c403e16fc87c086d33)

    0x7cdef7a6e288 is located 8 bytes inside of 176-byte region [0x7cdef7a6e280,0x7cdef7a6e330)
    freed by thread T0 here:
        #0 0x7feefb71f79d in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:51
        #1 0x7feefaac29f1 in surface_destroy ../subprojects/wlroots/types/wlr_linux_drm_syncobj_v1.c:84
        #2 0x7feefaac2e47 in surface_handle_resource_destroy ../subprojects/wlroots/types/wlr_linux_drm_syncobj_v1.c:143
        #3 0x7feefbd1bb9f  (/usr/lib/libwayland-server.so.0+0xab9f) (BuildId: b9664217748f523995e3f855fa197cf8e59942d1)
        #4 0x7feefaac2a12 in surface_handle_destroy ../subprojects/wlroots/types/wlr_linux_drm_syncobj_v1.c:89
        #5 0x7feef89afac5  (/usr/lib/libffi.so.8+0x7ac5) (BuildId: d5e3b0d8921923f35438adefa9f864745abc5e90)

    previously allocated by thread T0 here:
        #0 0x7feefb7205dd in calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:74
        #1 0x7feefaac4abd in manager_handle_get_surface ../subprojects/wlroots/types/wlr_linux_drm_syncobj_v1.c:313
        #2 0x7feef89afac5  (/usr/lib/libffi.so.8+0x7ac5) (BuildId: d5e3b0d8921923f35438adefa9f864745abc5e90)

Fix this by storing the struct wlr_surface in the field.

Closes: https://github.com/swaywm/sway/issues/8917
2025-10-17 09:05:53 +00:00
tokyo4j
19c5d22beb util/box.c: use 1/256 instead of 1/65536 in wlr_box_closest_point()
This fixes the issue that a scrollbar in a maximized GTK/Chromium window
cannot be dragged when cursor is on the right/bottom edge of the output.

The issue was caused by rounding in `wl_fixed_from_double()` ([1]); if
`wlr_cursor_move()` constrains the x-position of the cursor to
`(output width)-1/65536`, `wl_fixed_from_double()` converts it to just
`(output width)`, which is perceived as outside of the window by
GTK/Chromium.

Using 1/256 (minimal unit of `wl_fixed_t`) instead of 1/65536 avoids
this rounding issue.

[1]: f246e619d1
2025-10-16 13:46:27 +00:00
Furkan Sahin
06275103f2 input-method-v2: Destroy keyboard grab before input method
Fixes race condition in where the keyboard grab tries to reference the
input manager after it's been set to null.
2025-10-16 12:07:47 +00:00
Simon Ser
03e7966650 ci: fix VKMS lookup after faux bus migration
VKMS has been migrated to the new faux bus. This causes breakage
in CI, because we used the platform bus to find the right device.

udev hasn't been updated yet to support the faux bus, so just use
sysfs instead.
2025-10-16 11:04:25 +02:00
llyyr
5529aae3e6 wlr_scene: fix direct scanout for gamma2.2 buffers
Fixes incorrectly rejecting scanout for gamma2.2 buffers when the output
has no image description set. This happens on `hdr off` mode on sway.

Also refactor the scanout check into its own function while at it to
make it easier to follow.
2025-10-05 23:53:25 +05:30
llyyr
6e1c8748ff render: introduce bt.1886 transfer function 2025-10-04 18:13:37 +05:30
Félix Poisot
d8fb7adcf0 scene, render: use Gamma 2.2 TF as default 2025-10-03 19:48:12 +00:00
Félix Poisot
c2d9ae2142 render: introduce Gamma 2.2 color transform 2025-10-03 19:39:17 +00:00
Simon Ser
6978509f64 Revert "wlr_scene: fix tf/prim comparison for scanout attempt"
This reverts commit dde07b6840.

This is incorrect as discussed here:
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5163#note_3118744
2025-10-03 20:42:21 +02:00
llyyr
2252854297 wlr_scene: return scene_direct_scanout_result instead of bool 2025-10-02 13:51:41 +05:30
llyyr
dde07b6840 wlr_scene: fix tf/prim comparison for scanout attempt
We were incorrectly doing comparison with `!= 0` to detect non-sRGB
tf/primaries. Since these enums are bit flags, the default sRGB values
are 1, not 0, so sRGB buffers were incorrectly rejected.

Fixes: bf40f396bf ("scene: grab image description from output state")
2025-10-02 11:57:52 +05:30
Simon Ser
406aa5f7f5 backend/session: fix crash on udev device remove event
libwayland adds phantom listeners here:
d81525a235/src/wayland-server.c (L2378)

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3982
2025-10-01 17:05:10 +02:00
Simon Ser
2ec4012559 backend/drm: avoid error message when EDID is missing
We'd attempt to parse an EDID even when the connector has no EDID,
printing "Failed to parse EDID" in logs. Instead, don't attempt to
parse the EDID and print a more appropriate log message.
2025-10-01 15:14:46 +02:00
Simon Ser
d039ad8da3 backend/wayland: continue reading on hangup
If we stop immediately, we won't see any wl_display.error events.
Make sure we've read everything before handling hangup.
2025-09-30 09:25:14 -04:00
Simon Ser
3f0d338643 backend/wayland: log when getting disconnected from remote display
It can be a bit confusing to understand why a compositor is shutting
down on its own. Log a message when we get disconnected from the
parent compositor to explain the cause.
2025-09-30 09:25:14 -04:00
Simon Ser
60d72724cd render/color: fix bounds check in lut_1d_get()
i == len is out-of-bounds.

Fixes: 74217a4d93 ("render/color: introduce COLOR_TRANSFORM_LUT_3X1D")
2025-09-30 09:34:40 +02:00
Simon Ser
7cb3393e75 scene: send color_management_v1 surface feedback
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3999
2025-09-23 09:22:00 -04:00
Simon Ser
26c1476827 color_management_v1: add destroy event to manager 2025-09-23 09:22:00 -04:00
Simon Ser
138210f01c color_management_v1: make from_wlr enum converters public
This can be useful for compositors to set surface feedback.
2025-09-23 09:22:00 -04:00
Simon Ser
845a7a581d color_management_v1: drop duplicated enum converters 2025-09-23 09:22:00 -04:00
Simon Ser
108d94f798 Add release script
This is useful to speed up the release process and avoid making
mistakes.
2025-09-22 10:12:43 -04:00
xurui
aaf82ee332 wlr_drag: drag motion signal also needs to be sent
Signed-off-by: xurui <xurui@kylinos.cn>
2025-09-22 10:04:30 -04:00
Simon Ser
d1c88e9497 render/vulkan: add linear single-subpass
When the TF is set to EXT_LINEAR, we can write out color values
straight up to a non-SRGB image view.
2025-09-20 10:50:22 +00:00
Simon Ser
3e88a79e6f render/vulkan: replace wlr_vk_render_pass.srgb_pathway with two_pass
The important bit here is whether this is using a single or two
sub-passes. The flag isn't used for anything else.

Preparation for an upcoming one-subpass codepath.
2025-09-20 10:50:22 +00:00
Simon Ser
b2d09cdee9 render/vulkan: add wlr_vk_render_pass.render_buffer_out
Simplifies the logic and prepares for a new render setup.
2025-09-20 10:50:22 +00:00
Simon Ser
35eba5f2fe render/vulkan: add wlr_vk_render_pass.render_setup
Simplifies the logic and prepares for a new render setup.
2025-09-20 10:50:22 +00:00
Simon Ser
a91f96b391 render/vulkan: introduce wlr_vk_render_buffer_out
Holds common state for final output buffer targets.
2025-09-20 10:50:22 +00:00
Simon Ser
6fee3623e4 render/vulkan: rename vulkan_setup_srgb_framebuffer() for linear
Rename to "one-pass" (to indicate no blending buffer is involved),
because this will get re-used when introducing a linear
single-subpass codepath.
2025-09-20 10:50:22 +00:00
Simon Ser
7f6d66ea62 render/vulkan: use sRGB image view when color transform is set
If the color transform is set to sRGB inverse EOTF, we can use the
sRGB image view just like when no color transform is passed in.
2025-09-20 10:50:22 +00:00
Simon Ser
54374b6fe6 render/vulkan: rename plain to two_pass
We will introduce a new subpass without any post-processing step.
Rename "plain" so that there's no confusion.
2025-09-20 10:50:22 +00:00
Kenny Levinsen
dd7f543189 render/vulkan: Handle multi-descriptor sets
A combined image sampler may need several descriptors in a descriptor
set. We are not currently checking how many descriptors are required,
nor is it presumably guaranteed that such multi-descriptor allocation
will not fail due to fragmentation.

If the pool free counter is not zero, try to allocate but continue with
the next pool and fall back to creating a new pool if the allocation
failed.

Fixes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/4010
2025-09-20 07:59:02 +00:00
JiDe Zhang
d7ae9a866b xwayland: fix assertion failure in wlr_xwayland_shell_v1
The issue occurred when `wlr_xwayland_shell_v1` was destroyed before
`wlr_xwayland`. This happened because `wlr_xwayland` didn't remove the
listener for the shell's destroy event in `handle_shell_destroy`.
2025-09-16 13:59:06 +08:00
Simon Ser
462046ffdc cursor: use source buffer to signal release timeline point
Same as 128cd07e91 ("scene/surface: use source buffer to signal
release timeline point"), but for the cursor.
2025-09-11 12:33:04 +00:00
Simon Ser
bd566225ea scene/surface: fix NULL deref when source buffer is destroyed
Fixes the following crash, witnessed after a GPU reset:

    #0  0x00007fba9a32774c n/a (libc.so.6 + 0x9774c)
    #1  0x00007fba9a2cddc0 raise (libc.so.6 + 0x3ddc0)
    #2  0x00007fba9a2b557a abort (libc.so.6 + 0x2557a)
    #3  0x00007fba9a2b54e3 n/a (libc.so.6 + 0x254e3)
    #4  0x00007fba9a53fb78 wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer (libwlroots-0.20.so + 0x26b78)
    #5  0x00007fba9a590846 surface_reconfigure (libwlroots-0.20.so + 0x77846)
    #6  0x00007fba9a590cbb scene_surface_set_clip (libwlroots-0.20.so + 0x77cbb)
    #7  0x00007fba9a590efa subsurface_tree_set_clip (libwlroots-0.20.so + 0x77efa)
    #8  0x00007fba9a590f1f subsurface_tree_set_clip (libwlroots-0.20.so + 0x77f1f)
    #9  0x00007fba9a590f1f subsurface_tree_set_clip (libwlroots-0.20.so + 0x77f1f)
    #10 0x00007fba9a590f8d wlr_scene_subsurface_tree_set_clip (libwlroots-0.20.so + 0x77f8d)

Reported-by: Hubert Hirtz <hubert@hirtz.pm>
2025-09-11 12:33:04 +00:00
Simon Ser
b62c6878e1 scene/surface: simplify single-pixel-buffer check in surface_reconfigure()
No need to call wlr_client_buffer_get() on wlr_client_buffer.base:
we're already manipulating a wlr_client_buffer.
2025-09-11 12:33:04 +00:00
Simon Ser
fd069ad4f2 output/cursor: fix missing second cursor
When attaching more than one cursor to wlr_output, the first one
will pick the output's hardware cursor, then for the second one
output_set_hardware_cursor() would fail (since the hardware cursor
was already taken), but we still ended up resetting the current
hardware cursor (by calling output_disable_hardware_cursor() below).
As a result only the second cursor would be displayed.

To fix this, move the current hardware cursor check to the caller.

Fixes: 510664e79b ("output: disable hardware cursor when falling back to software")
2025-09-11 12:21:52 +00:00
liupeng
5e5842cb1a drm_lease_v1: initialize device resource link during abnormal exit
Signed-off-by: liupeng <liupeng01@kylinos.cn>
2025-09-11 11:05:39 +08:00
rewine
cdd2c7e006 protocols: sync with wlr-protocols, apply non-breaking updates and doc improvements
This sync includes minor non-breaking updates from recent years:

- Fix typos and grammatical issues (e.g. "a an" → "an", "inexistent" → "nonexistent")
- Improve description consistency with `wl_output` (e.g. name, description, make, model, serial)
- Add `destructor` annotation to relevant events (e.g. `finished` in foreign-toplevel)
- Clarify event emission timing and behavior for output management
- No functional or semantic protocol changes introduced

These changes improve the accuracy and consistency of protocol descriptions without impacting compatibility.
2025-09-10 09:50:09 -04:00
David Turner
905465b0fa color-representation-v1: Actually set supported_*_len 2025-09-09 15:19:30 +01:00
tokyo4j
102a6bd415 input-method: use NULL when emitting signals 2025-09-08 10:56:57 -04:00
tokyo4j
06aacb2a6f input-method: rename input_method event to new_input_method 2025-09-08 10:56:57 -04:00
Simon Zeni
0166fd9eb7 drm-lease-v1: remove connector active_lease & lease connectors
Upon leasing, the wlr_drm_lease_connector_v1 will be automatically clean up by the wlr_output
destroy handler. There is no need for the wlr_drm_lease_manager to keep track of leased connectors.
2025-08-28 16:33:35 +00:00
Simon Zeni
423afc3fc9 types: deprecate wlr-screencopy-unstable-v1 2025-08-28 16:23:56 +00:00
Simon Ser
122310a2de build: add wayland-protocols to dependencies array
We grab header files from there, ensure include directories are
properly set up when building wlroots.

Fixes missing header files when a wayland-protocols subproject is
used.
2025-08-27 16:11:49 -04:00
rewine
b799ffc6ae docs: deprecate legacy wlr_data_control_v1 interface
Add deprecation notice for wlr_data_control_v1, indicating that
it's superseded by ext-data-control-v1.

Related: https://gitlab.freedesktop.org/wlroots/wlr-protocols/-/merge_requests/136
2025-08-27 14:53:28 -04:00
Simon Ser
e95117b700 render/vulkan: remove hardcoded counts
Use the array size instead.
2025-08-27 14:26:21 -04:00
Simon Ser
1a18e47efa render/vulkan: fix VkPushConstantRange for wlr_vk_frag_texture_pcr_data
We pass an alpha multiplier plus a luminance multiplier now.

Fixes the following validation layer error:

    vkCmdPushConstants(): is called with
    stageFlags (VK_SHADER_STAGE_FRAGMENT_BIT), offset (80), size (72)
    but the VkPipelineLayout 0x510000000051 doesn't have a VkPushConstantRange with VK_SHADER_STAGE_FRAGMENT_BIT.
    The Vulkan spec states: For each byte in the range specified by offset and size and for each shader stage in stageFlags, there must be a push constant range in layout that includes that byte and that stage (https://docs.vulkan.org/spec/latest/chapters/descriptorsets.html#VUID-vkCmdPushConstants-offset-01795) (VUID-vkCmdPushConstants-offset-01795)

Fixes: 56d95c2ecb ("render/vulkan: introduce wlr_vk_frag_texture_pcr_data")
2025-08-27 14:26:21 -04:00
Simon Ser
bbd9a49bdf tinywl: stop generating xdg-shell header
We don't need to do this anymore for wayland-protocols.
2025-08-27 14:21:23 -04:00
xurui
7bf5ff4c02 wlr_xdg_toplevel_icon_v1: check the correct resource
Signed-off-by: xurui <xurui@kylinos.cn>
2025-08-27 20:01:50 +08:00
xurui
b0c886ec77 render/allocator/gbm: insert buffer after export gbm bo
Signed-off-by: xurui <xurui@kylinos.cn>
2025-08-25 14:05:13 +08:00
Simon Ser
7431d840d0 color-management-v1: handle inert outputs in get_output
wlr_output_from_resource() can return NULL if the outputs no longer
exists on the compositor side.

Closes: https://github.com/swaywm/sway/issues/8847
2025-08-18 14:09:13 +02:00
Kirill Primak
bb1f8673b3 compositor: use wl_resource_post_error_vargs() 2025-08-13 20:59:13 +00:00
Kirill Primak
ad1b2f2819 Avoid including generated headers publicly where possible
This is possible now that w-p ships enum headers. The remaining includes
are from wlr-protocols.
2025-08-13 22:46:37 +02:00
Kirill Primak
812675ba34 fixes: add implementation 2025-08-13 20:41:21 +00:00
Simon Ser
7392b3313a backend, output: send commit events after applying all in wlr_backend_commit()
We were iterating over involved outputs, applying the new state and
sending the commit event for each one. This resulted in commit
events being fired while we weren't done applying the new state for
all outputs.

Fix this by first applying all of the states, then firing all of
the events.

Closes: https://github.com/swaywm/sway/issues/8829
2025-08-12 19:04:05 +02:00
Jesper Jensen
07e92fb868 output/cursor: Fix double cursor bug
When we fail to render the cursor (in my case because the cursor is too
large) we bail out of the output_cursor_attempt_hardware function. This
causes output_cursor_set_texture to clean up after us, but we've already
cleared the hardware_cursor, and so output_disable_hardware_cursor
thinks we don't have a hardware cursor to disable.

We shouldn't modify the hardware_cursor variable before we've
successfully changed the hardware cursor, this way the caller can clean
up after us like it expect to.

This was brought up by an actual bug when playing the game Kaizen. Which
uses oddly sized cursors, that fell back to software cursors for me, and
left the hardware cursor hanging around. This change has been tested to
fix that.

During the testing of this change, I have noticed that the previous code
worked fine the first time the cursor was switch to software. It only
failed on subsequent attempts. I haven't figured out why that is.
2025-08-07 22:25:39 +02:00
Simon Ser
12316417b0 ext_image_capture_source_v1: advertise fallback {A,X}RGB8888 formats
We can't expect all clients to support all fancy formats.
WebRTC's reference implementation doesn't support 10-bit formats
yet. More generally, clients are limited by the libraries they
use: for instance, Pixman doesn't implement all OpenGL/Vulkan
formats.

Another MR [1] suggests advertising all render formats. This is a
bit heavy-handed because:

- Upgrading a 8-bit buffer to a 10-bit buffer doesn't make a lot
  of sense. I don't think the compositor should expose arbitrary
  pixel format conversions.
- The protocol has no preference order. Clients generally pick the
  first format they receive and support.

As an alternative, only advertise two fallback formats, ARGB8888
and XRGB8888. These two are already hard-required by wl_shm and
all clients should be able to handle them.

[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5019
2025-07-31 14:13:24 +00:00
Christopher Snowhill
dd3c63f5e6
color-representation-v1: Fix missing destroy signal init
Fixes #4001

Reported-by: CreeperFace / @dy-tea
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2025-07-31 06:46:47 -07:00
rewine
c8b7600adc wlr_ext_data_control_v1: Make all listeners private
For more context, see: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4873
2025-07-30 12:37:19 +00:00
Christopher Snowhill
51a78cb0ed
color_management_v1: set output color properties
This reports the output properties according to the current image description.
Firefox needs this to report HDR support to documents, at least.

v2: Move abort() calls out of switch to eliminate default case. Rename
    functions so they don't use a wlr_ prefix like public functions do.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2025-07-29 02:03:18 -07:00
1beb25a1c8 tinywl: fix cursor disappears when focused window is closed
Add listener for wlr_seat->pointer_state.events.focus_change

Fix #3802
2025-07-25 12:56:05 +00:00
Simon Ser
2f2c0dfcc6 scene: use helpers to convert TF/primaries enums 2025-07-24 15:02:39 +00:00
Simon Ser
47a90d6f1a color_management_v1: add helpers to convert TF/primaries enums
This makes it easier for protocol implementers to tie everything
together with wlroots backends and renderers.
2025-07-24 15:02:39 +00:00
llyyr
db5e9ca04c meson: bump minimum wayland-protocols version
color-representation was added in 1.44.

Fixes: eff620770c
2025-07-24 14:51:37 +00:00
rewine
efb17980a8 ext_image_capture_source_v1: remove unused struct definition
Remove the redundant wlr_ext_foreign_toplevel_image_capture_source_v1
struct that was not used anywhere in the codebase.
2025-07-24 14:49:27 +00:00
liupeng
be5e266211 cursor: update output cursor even if output is disabled
During suspend, we first disable output and then remove the input device.
This causes cursor->state->surface released while cursor->texture leaves.
Which leads to use-after-free after resume.
2025-07-24 14:47:32 +00:00
Andri Yngvason
80c7e0f772 ext-image-capture-source: output: Apply transform to cursor
The cursor can be expected to also be transformed if the output is
transformed.
2025-07-23 15:06:24 +00:00
Yixue Wang
ccec4116b3 types/color_management: check on invalid image description
Check if image description is valid. If not, post error to client.
2025-07-20 23:01:58 +08:00
Yixue Wang
d2007d7dc1 types/color_representation: correctly cleanup in manager create
Global should be created after all other initialization finished.
Free manager in err_options.
2025-07-18 18:12:40 +08:00
David Turner
a4eb2cff46 color-representation-v1: Add wlr enums + converters
Add wlr-internal enums for the properties specified in
color-representation-v1 (encoding, range, chroma siting, alpha mode) so
that other parts of wlroots can use these without depending on the
protocol specifics and without needing to include the protocol headers.
Also add conversion functions to convert the protocol enum values into
the wlroots enum values.
2025-07-17 16:41:14 +01:00
David Turner
eff620770c color-representation-v1: new protocol
Add a minimal implementation of the color-representation-v1 protocol
(not including anything to actually use the new properties in
rendering/scanout)
2025-07-17 16:40:45 +01:00
David Turner
f5dc6416f0 util/mem: Move memdup to new util/mem.c file
This seems handy and I want to use this in wlr_color_representation.
2025-07-17 16:39:58 +01:00
YaoBing Xiao
c14aa1d0b8 render/vulkan: destroy vulkan instance when drm phdev mismatch 2025-07-15 08:59:37 +08:00
Consolatis
c39b3ce7a3 transient_seat: initialize seat destroy listener
This fixes a `wl_list_remove()` from an uninitialized listener
when using `wlr_transient_seat_v1_deny()` in a `create_seat`
handler.
2025-07-10 19:52:45 +02:00
Simon Ser
f4327f52cf xdg-toplevel-tag-v1: new protocol
References: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/238
2025-07-07 09:10:37 +00:00
Consolatis
6aa654b728 wlr_text_input_v3: remove event arguments from header
Fixes 2d5492c737
2025-07-06 14:10:25 +02:00
Félix Poisot
31b78a4f3a scene: fix output transfer functions
fixes: bf40f396b
2025-07-03 12:29:27 +00:00
David Turner
58c3680d96 scene: Block damage on single-pixel buffer textures
We cache whether buffers are single-pixel buffers (and if so what color
they are) to allow rendering optimizations.  But this breaks if the
client changes out the single-pixel buffer for one with a different
color, because this updates the texture in-place instead of actually
changing the buffer.

We can fix this by blocking in-place texture updates for single pixel
buffers.

Original bug: https://codeberg.org/ifreund/waylock/issues/121
See also: !5092
2025-07-01 11:38:56 +01:00
Simon Ser
48bd1831fe render/egl: fix software rendering check
Commit b4ce0d8b39 ("render/egl: accept negative DRM FD to select
software rendering") added an EXT_device_drm check to figure out
whether the user selected a device with a DRM FD or without one.
However, for KMS-only devices, Mesa will never advertise the
selected KMS node:
3f1d40d230/src/egl/main/egldevice.c (L109)

Instead, pass down a parameter to indicate whether a DRM FD was
passed in.

Fixes: b4ce0d8b39 ("render/egl: accept negative DRM FD to select software rendering")
2025-06-29 10:57:56 +02:00
Simon Ser
8c7041c4e8 backend/drm: relay full HDR metadata 2025-06-26 11:02:26 +00:00
Simon Ser
aecb867098 output: add full HDR metadata to wlr_output_image_description
This allows sinks to improve their tone mapping.
2025-06-26 11:02:26 +00:00
Simon Ser
bf40f396bf scene: grab image description from output state
Alternative to https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5089
2025-06-26 09:56:12 +00:00
Simon Ser
2498036e67 output: add output_pending_image_description() 2025-06-26 09:56:12 +00:00
Simon Ser
e76f8ac2b3 output: add wlr_output.image_description
Stores the current image description.
2025-06-26 09:56:12 +00:00
tokyo4j
6d8bb66f98 xwm: add support for _NET_WM_ICON 2025-06-26 08:50:02 +00:00
Isaac Freund
f5e7caf599 util/box: set dest to empty if boxes don't intersect
Currently if both box_a and box_b are non-empty but do not intersect,
this function does not set dest to an empty box. This contradicts the
doc comments and is surprising for users.
2025-06-21 09:54:24 +00:00
Simon Ser
98af337175 output: shorten output enabled checks
Use a more concise loop instead of repeated logic.

No behavior change.
2025-06-20 19:02:54 +02:00
Simon Ser
0c272a3842 scene: add support for color-management-v1 primaries 2025-06-18 19:37:55 +00:00
Simon Ser
071773cb27 scene: add primaries support to wlr_scene_buffer 2025-06-18 19:37:55 +00:00
Simon Ser
ae85c31176 render/vulkan: add luminance multiplier for texture shader 2025-06-18 19:37:55 +00:00
Simon Ser
fa1feb447f render, render/vulkan: add primaries to wlr_render_texture_options 2025-06-18 19:37:55 +00:00
Simon Ser
a8144088df render/vulkan: add support for PQ for textures 2025-06-18 19:37:55 +00:00
Simon Ser
3a51a5c623 render/vulkan: add texture color transformation matrix 2025-06-18 19:37:55 +00:00
Simon Ser
56d95c2ecb render/vulkan: introduce wlr_vk_frag_texture_pcr_data
Contains UBOs for texture.frag.
2025-06-18 19:37:55 +00:00
Simon Ser
ec422ac389 render/vulkan: prepare texture shader for new transforms 2025-06-18 19:37:55 +00:00
Simon Ser
7a1161438c scene: add support for color-management-v1 transfer functions 2025-06-18 19:37:55 +00:00
Simon Ser
4efec11721 scene: add transfer function support for wlr_scene_buffer 2025-06-18 19:37:55 +00:00
Simon Ser
8d1c6e42ac render/vulkan: add support for texture transfer functions 2025-06-18 19:37:55 +00:00
Simon Ser
b1a9dab03e render/vulkan: fix typo in wlr_vk_texture.views comment 2025-06-18 19:37:55 +00:00
Simon Ser
dd3d9be41e render/pass: add wlr_render_texture_options.transfer_function
Also add a bit in wlr_renderer.features to indicate support.
2025-06-18 19:37:55 +00:00
Simon Ser
c8d94000a6 color-management-v1: add EXT_LINEAR 2025-06-18 19:37:55 +00:00
Simon Ser
0ee0452af0 render/color, render/vulkan: add EXT_LINEAR to enum wlr_color_transfer_function 2025-06-18 19:37:55 +00:00
Simon Ser
f5a0992686 render/vulkan: fix multiplication order for output color matrix
This had the same bug as the texture side, but I forgot to fix it.

See:
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4988#note_2867416

Fixes: f3524de980 ("render, render/vulkan: add primaries to wlr_buffer_pass_options")
2025-06-18 21:25:37 +02:00
Simon Ser
7b6eec530c render/vulkan: add luminance multipler for output shader 2025-06-18 00:11:33 +02:00
Simon Ser
b482e9089b backend/drm: add support for image description transfer function 2025-06-18 00:11:33 +02:00
Simon Ser
dc258b2237 output: add transfer function to image description 2025-06-18 00:11:33 +02:00
Simon Ser
4470683591 render/color, render/vulkan: add support for PQ transfer function 2025-06-18 00:11:31 +02:00
Simon Ser
8430a1922d render/vulkan: add PQ inverse EOTF to output shader 2025-06-18 00:09:25 +02:00
Simon Ser
f024d1b8c8 backend/drm: add support for color primaries 2025-06-18 00:07:58 +02:00
Simon Ser
e64de4d55f output: add color primaries to output state 2025-06-18 00:07:58 +02:00
Simon Ser
f3524de980 render, render/vulkan: add primaries to wlr_buffer_pass_options 2025-06-18 00:07:35 +02:00
Simon Ser
a5706e2fb9 render/vulkan: use array declaration in encode_proj_matrix()
This makes it more obvious what the final layout of the matrix will
be.
2025-06-17 19:41:29 +02:00
Simon Ser
1df2274f6c render/vulkan: rename mat3_to_mat4() to encode_proj_matrix()
This function is specific to projection matrices.
2025-06-17 19:35:16 +02:00
Simon Ser
30c6efedf1 render/vulkan: use output_pipe_srgb for non-NULL sRGB color transform 2025-06-17 18:50:25 +02:00
Simon Ser
2ea0e386c4 render/vulkan: add color transformation matrix 2025-06-17 18:47:50 +02:00
Simon Ser
a30c102163 output: drop gamma LUT from state
This has been superseded by color transforms.
2025-06-16 09:06:10 +00:00
Simon Ser
bfcb4211f6 wlr_gamma_control_v1: use color transforms 2025-06-16 09:06:10 +00:00
Simon Ser
f10dd1da1c backend/drm: add support for color transforms 2025-06-16 09:06:10 +00:00
Simon Ser
97f6946c8d output: add color transform to state
Color transforms are better suited than raw gamma tables, because:

- They don't need to get copied around: they are ref'counted.
- They can represent more color operations (will be useful for the
  upcoming KMS color pipeline API, and for the Wayland color
  management protocol).
2025-06-16 09:06:10 +00:00
Simon Ser
74217a4d93 render/color: introduce COLOR_TRANSFORM_LUT_3X1D
This will be useful to apply LUTs applied via wlr_gamma_control_v1,
and to add wlr_color_transform support to wlr_output.
2025-06-16 09:06:10 +00:00
Simon Ser
3665b53e29 render/color: replace COLOR_TRANSFORM_LUT_3D with COLOR_TRANSFORM_LCMS2
Converting the LCMS2 transform to a 3D LUT early causes issues:

- It's a lossy process, the consumer will not be able to pick a
  3D LUT size on their own.
- It requires unnecessary conversions and allocations: an intermediate
  3D LUT is allocated, but the renderer already allocates one.
- It makes it harder to support arbitrary color transforms in the
  renderer, because each type needs to be handled differently.

Instead, expose a function to evaluate a color transform, and use
that to build the 3D LUT in the renderer.
2025-06-16 09:06:10 +00:00
Simon Ser
9b97e2607d render/color: use variable instead of type in sizeof()
Conforms to the wlroots code style.
2025-06-16 09:06:10 +00:00
Simon Ser
d421538b4a render/color: add wlr_color_transform_init() 2025-06-16 09:06:10 +00:00
Simon Ser
c6133f9912 scene: send surface preferred transform alongside DMA-BUF feedback
wl_surface.preferred_buffer_transform is mainly useful to make
direct scan-out more likely. It shouldn't make a difference with
GL/Vulkan rendering.
2025-06-16 07:54:00 +00:00
Simon Ser
6204fc3278 scene: use output with highest refresh rate for frame pacing
If a surface is mirrored on two outputs, we don't want to pick the
first output if the second has a higher refresh rate.

Also fixes duplicate frame/feedback events when a surface is added
to multiple scenes.
2025-06-16 07:54:00 +00:00
Simon Ser
51d051497d scene: filter frame_done primary output in surface handler
This lets the surface handler decide which output to send frame
callbacks from. The output_sample event already works this way.

Introduce wlr_scene_surface_send_frame_done() as a replacement for
wlr_scene_buffer_send_frame_done() when a compositor doesn't have
an output at hand.
2025-06-16 07:54:00 +00:00
Simon Ser
8713ac72fb scene: configure clients with the highest output scale
If a surface appears on two outputs with the same intersection
area, or even if a surface appears on an output with a small
intersection area, we want to use the highest scale.

Fixes flip-flop when a surface is added to multiple scenes.

References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3901
2025-06-16 07:54:00 +00:00
Simon Ser
95b2771bfd scene: ignore outputs with too small intersection with nodes
If a node has a very small intersection with an output, there's no
point in trying to adapt the node's rendering to that output.
2025-06-16 07:54:00 +00:00
Simon Ser
da820070f4 ext_image_capture_source_v1: add helper to capture scene nodes 2025-06-16 07:54:00 +00:00
Simon Ser
b066fd6b5a ext_image_capture_source_v1: add support for foreign toplevels 2025-06-16 07:54:00 +00:00
Simon Ser
8fb4e4dabb swapchain: assert that size is not empty at creation time
Failing later (at buffer allocation time) makes it more difficult
to track down where the issue comes from.
2025-06-16 07:54:00 +00:00
Simon Ser
bb50c7a5a4 render/allocator/gbm: require GBM 21.1
Mesa 21.1 was released back in 2021. Let's require it so that we
can simplify our build and remove the workaround.
2025-06-16 07:43:01 +00:00
Simon Ser
221b37355f xwayland: require xcb-xfixes 1.15
xcb-xfixes 1.15 was released back in 2022. Let's simplify our build
setup by requiring it.
2025-06-16 07:40:04 +00:00
Simon Ser
37992cf3b8 idle_notify_v1: drop trailing spaces 2025-06-15 12:25:36 +00:00
Rémi Bernon
6c78225160 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.
2025-06-12 08:56:09 +00:00
Rémi Bernon
83a5bdf5d5 xwayland: Create a dummy no_focus_window to use for non-X window focus 2025-06-12 08:56:09 +00:00
Kirill Primak
afe427d149 xdg-shell: add support for v7 2025-06-05 16:25:25 +00:00
DreamMaoMao
a08acfcee0 render/pass: Ensure the precision is consistent during comparison 2025-05-29 21:50:21 +08:00
Kirill Primak
af43d3b9e7 cursor-shape-v1: bump to version 2 2025-05-22 20:35:30 +03:00
Kirill Primak
aaeffe9769 cursor-shape-v1: use generated enum validator 2025-05-22 20:35:15 +03:00
David Turner
fae4c5097d xwayland: Remove has_utf8_title field 2025-05-22 15:10:26 +00:00
tokyo4j
170f7e0706 backend/libinput: don't leak udev_device 2025-05-20 01:15:19 +09:00
Guido Günther
2d5492c737 text-input-v3: Use NULL when emitting signals
Listeners can use `wl_container_of`.

Helps: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3851

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-15 13:36:58 +00:00
Guido Günther
536100488f text-input-v3: Name new text input event correctly
Helps: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3851

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2025-05-15 13:36:58 +00:00
Martin Rys
62c86fb975 Add support for XKB_LED_NAME_COMPOSE and XKB_LED_NAME_KANA USB HID LEDs
Requires xkbcommon 1.8.0
2025-05-15 09:14:48 +00:00
Simon Ser
c2327248f8 output: don't send make/model
- These are legacy wl_output properties [1]
- wl_output exposes name and description, which are better defined
- It's not clear what make/model/serial are for a virtual output
- Clients shouldn't rely on these fields

[1]: 8f1795f911/protocol/wayland.xml (L2508)

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/1623
2025-05-15 09:04:33 +00:00
David Turner
c9f0dbc159 Change all timespec pointers in events to owned
Follow-up from !4803.  Make things consistent by making all `struct
timespec`s in events owned.  Reduces the need for thinking about
ownership/lifetimes.
2025-05-15 08:59:56 +00:00
Simon Ser
f04ef79f61 build: bump version to 0.20.0-dev 2025-05-15 10:54:23 +02:00
201 changed files with 7400 additions and 1649 deletions

View file

@ -35,6 +35,9 @@ tasks:
cd wlroots
ninja -C build
sudo ninja -C build install
- test: |
cd wlroots
meson test -C build --verbose
- build-features-disabled: |
cd wlroots
meson setup build --reconfigure -Dauto_features=disabled

View file

@ -37,13 +37,18 @@ tasks:
- clang: |
cd wlroots/build-clang
ninja
- test: |
cd wlroots/build-gcc
meson test --verbose
meson test --benchmark --verbose
- smoke-test: |
cd wlroots/build-gcc/tinywl
sudo modprobe vkms
udevadm settle
card="/dev/dri/$(ls /sys/devices/faux/vkms/drm/ | grep ^card)"
export WLR_BACKENDS=drm
export WLR_RENDERER=pixman
export WLR_DRM_DEVICES=/dev/dri/by-path/platform-vkms-card
export WLR_DRM_DEVICES="$card"
export UBSAN_OPTIONS=halt_on_error=1
sudo chmod ugo+rw /dev/dri/by-path/platform-vkms-card
sudo chmod ugo+rw "$card"
sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ]

View file

@ -32,6 +32,9 @@ tasks:
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dallocators=gbm
ninja -C build
sudo ninja -C build install
- test: |
cd wlroots
meson test -C build --verbose
- tinywl: |
cd wlroots/tinywl
make

View file

@ -1,4 +1,4 @@
include: https://git.sr.ht/~emersion/dalligi/blob/master/templates/multi.yml
include: https://gitlab.freedesktop.org/emersion/dalligi/-/raw/master/templates/multi.yml
alpine:
extends: .dalligi
pages: true

View file

@ -22,7 +22,7 @@ don't, however, allow me to make a suggestion: feature branches pulled from
upstream. Try this:
1. Fork wlroots
2. `git clone git@gitlab.freedesktop.org:<username>/wlroots.git && cd wlroots`
2. `git clone git@ssh.gitlab.freedesktop.org:<username>/wlroots.git && cd wlroots`
3. `git remote add upstream https://gitlab.freedesktop.org/wlroots/wlroots.git`
You only need to do this once. You're never going to use your fork's master

View file

@ -485,5 +485,10 @@ bool wlr_backend_commit(struct wlr_backend *backend,
output_apply_commit(state->output, &state->base);
}
for (size_t i = 0; i < states_len; i++) {
const struct wlr_backend_output_state *state = &states[i];
output_send_commit_event(state->output, &state->base);
}
return true;
}

View file

@ -1,3 +1,4 @@
#include <assert.h>
#include <drm_fourcc.h>
#include <stdlib.h>
#include <stdio.h>
@ -10,6 +11,7 @@
#include "backend/drm/fb.h"
#include "backend/drm/iface.h"
#include "backend/drm/util.h"
#include "render/color.h"
static char *atomic_commit_flags_str(uint32_t flags) {
const char *const l[] = {
@ -177,6 +179,85 @@ bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm,
return true;
}
static uint8_t convert_cta861_eotf(enum wlr_color_transfer_function tf) {
switch (tf) {
case WLR_COLOR_TRANSFER_FUNCTION_SRGB:
abort(); // unsupported
case WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ:
return 2;
case WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR:
abort(); // unsupported
case WLR_COLOR_TRANSFER_FUNCTION_GAMMA22:
abort(); // unsupported
case WLR_COLOR_TRANSFER_FUNCTION_BT1886:
abort(); // unsupported
}
abort(); // unreachable
}
static uint16_t convert_cta861_color_coord(double v) {
if (v < 0) {
v = 0;
}
if (v > 1) {
v = 1;
}
return (uint16_t)round(v * 50000);
}
static bool create_hdr_output_metadata_blob(struct wlr_drm_backend *drm,
const struct wlr_output_image_description *img_desc, uint32_t *blob_id) {
if (img_desc == NULL) {
*blob_id = 0;
return true;
}
struct hdr_output_metadata metadata = {
.metadata_type = 0,
.hdmi_metadata_type1 = {
.eotf = convert_cta861_eotf(img_desc->transfer_function),
.metadata_type = 0,
.display_primaries = {
{
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.red.x),
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.red.y),
},
{
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.green.x),
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.green.y),
},
{
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.blue.x),
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.blue.y),
},
},
.white_point = {
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.white.x),
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.white.y),
},
.max_display_mastering_luminance = img_desc->mastering_luminance.max,
.min_display_mastering_luminance = img_desc->mastering_luminance.min * 0.0001,
.max_cll = img_desc->max_cll,
.max_fall = img_desc->max_fall,
},
};
if (drmModeCreatePropertyBlob(drm->fd, &metadata, sizeof(metadata), blob_id) != 0) {
wlr_log_errno(WLR_ERROR, "Failed to create HDR_OUTPUT_METADATA property");
return false;
}
return true;
}
static uint64_t convert_primaries_to_colorspace(uint32_t primaries) {
switch (primaries) {
case 0:
return 0; // Default
case WLR_COLOR_NAMED_PRIMARIES_BT2020:
return 9; // BT2020_RGB
}
abort(); // unreachable
}
static uint64_t max_bpc_for_format(uint32_t format) {
switch (format) {
case DRM_FORMAT_XRGB2101010:
@ -251,19 +332,25 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
}
uint32_t gamma_lut = crtc->gamma_lut;
if (state->base->committed & WLR_OUTPUT_STATE_GAMMA_LUT) {
if (state->base->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) {
size_t dim = 0;
uint16_t *lut = NULL;
if (state->base->color_transform != NULL) {
struct wlr_color_transform_lut_3x1d *tr =
color_transform_lut_3x1d_from_base(state->base->color_transform);
dim = tr->dim;
lut = tr->lut_3x1d;
}
// Fallback to legacy gamma interface when gamma properties are not
// available (can happen on older Intel GPUs that support gamma but not
// degamma).
if (crtc->props.gamma_lut == 0) {
if (!drm_legacy_crtc_set_gamma(drm, crtc,
state->base->gamma_lut_size,
state->base->gamma_lut)) {
if (!drm_legacy_crtc_set_gamma(drm, crtc, dim, lut)) {
return false;
}
} else {
if (!create_gamma_lut_blob(drm, state->base->gamma_lut_size,
state->base->gamma_lut, &gamma_lut)) {
if (!create_gamma_lut_blob(drm, dim, lut, &gamma_lut)) {
return false;
}
}
@ -295,11 +382,25 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
vrr_enabled = state->base->adaptive_sync_enabled;
}
uint32_t colorspace = conn->colorspace;
if (state->base->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) {
colorspace = convert_primaries_to_colorspace(
state->base->image_description ? state->base->image_description->primaries : 0);
}
uint32_t hdr_output_metadata = conn->hdr_output_metadata;
if ((state->base->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) &&
!create_hdr_output_metadata_blob(drm, state->base->image_description, &hdr_output_metadata)) {
return false;
}
state->mode_id = mode_id;
state->gamma_lut = gamma_lut;
state->fb_damage_clips = fb_damage_clips;
state->primary_in_fence_fd = in_fence_fd;
state->vrr_enabled = vrr_enabled;
state->colorspace = colorspace;
state->hdr_output_metadata = hdr_output_metadata;
return true;
}
@ -314,6 +415,7 @@ void drm_atomic_connector_apply_commit(struct wlr_drm_connector_state *state) {
crtc->own_mode_id = true;
commit_blob(drm, &crtc->mode_id, state->mode_id);
commit_blob(drm, &crtc->gamma_lut, state->gamma_lut);
commit_blob(drm, &conn->hdr_output_metadata, state->hdr_output_metadata);
conn->output.adaptive_sync_status = state->vrr_enabled ?
WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED;
@ -322,12 +424,8 @@ void drm_atomic_connector_apply_commit(struct wlr_drm_connector_state *state) {
if (state->primary_in_fence_fd >= 0) {
close(state->primary_in_fence_fd);
}
if (state->out_fence_fd >= 0) {
// TODO: error handling
wlr_drm_syncobj_timeline_import_sync_file(state->base->signal_timeline,
state->base->signal_point, state->out_fence_fd);
close(state->out_fence_fd);
}
conn->colorspace = state->colorspace;
}
void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state) {
@ -337,14 +435,12 @@ void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state)
rollback_blob(drm, &crtc->mode_id, state->mode_id);
rollback_blob(drm, &crtc->gamma_lut, state->gamma_lut);
rollback_blob(drm, &conn->hdr_output_metadata, state->hdr_output_metadata);
destroy_blob(drm, state->fb_damage_clips);
if (state->primary_in_fence_fd >= 0) {
close(state->primary_in_fence_fd);
}
if (state->out_fence_fd >= 0) {
close(state->out_fence_fd);
}
}
static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) {
@ -380,6 +476,62 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm,
atomic_add(atom, id, props->crtc_h, dst_box->height);
}
static void set_color_encoding_and_range(struct atomic *atom,
struct wlr_drm_backend *drm, struct wlr_drm_plane *plane,
enum wlr_color_encoding encoding, enum wlr_color_range range) {
uint32_t id = plane->id;
const struct wlr_drm_plane_props *props = &plane->props;
uint32_t color_encoding;
switch (encoding) {
case WLR_COLOR_ENCODING_NONE:
case WLR_COLOR_ENCODING_BT601:
color_encoding = WLR_DRM_COLOR_YCBCR_BT601;
break;
case WLR_COLOR_ENCODING_BT709:
color_encoding = WLR_DRM_COLOR_YCBCR_BT709;
break;
case WLR_COLOR_ENCODING_BT2020:
color_encoding = WLR_DRM_COLOR_YCBCR_BT2020;
break;
default:
wlr_log(WLR_DEBUG, "Unsupported color encoding %d", encoding);
atom->failed = true;
return;
}
if (props->color_encoding) {
atomic_add(atom, id, props->color_encoding, color_encoding);
} else {
wlr_log(WLR_DEBUG, "Plane %"PRIu32" is missing the COLOR_ENCODING property",
id);
atom->failed = true;
return;
}
uint32_t color_range;
switch (range) {
case WLR_COLOR_RANGE_NONE:
case WLR_COLOR_RANGE_LIMITED:
color_range = WLR_DRM_COLOR_YCBCR_LIMITED_RANGE;
break;
case WLR_COLOR_RANGE_FULL:
color_range = WLR_DRM_COLOR_YCBCR_FULL_RANGE;
break;
default:
assert(0); // Unreachable
}
if (props->color_range) {
atomic_add(atom, id, props->color_range, color_range);
} else {
wlr_log(WLR_DEBUG, "Plane %"PRIu32" is missing the COLOR_RANGE property",
id);
atom->failed = true;
return;
}
}
static bool supports_cursor_hotspots(const struct wlr_drm_plane *plane) {
return plane->props.hotspot_x && plane->props.hotspot_y;
}
@ -396,19 +548,6 @@ static void set_plane_in_fence_fd(struct atomic *atom,
atomic_add(atom, plane->id, plane->props.in_fence_fd, sync_file_fd);
}
static void set_crtc_out_fence_ptr(struct atomic *atom, struct wlr_drm_crtc *crtc,
int *fd_ptr) {
if (!crtc->props.out_fence_ptr) {
wlr_log(WLR_ERROR,
"CRTC %"PRIu32" is missing the OUT_FENCE_PTR property",
crtc->id);
atom->failed = true;
return;
}
atomic_add(atom, crtc->id, crtc->props.out_fence_ptr, (uintptr_t)fd_ptr);
}
static void atomic_connector_add(struct atomic *atom,
struct wlr_drm_connector_state *state, bool modeset) {
struct wlr_drm_connector *conn = state->connector;
@ -428,6 +567,12 @@ static void atomic_connector_add(struct atomic *atom,
if (modeset && active && conn->props.max_bpc != 0 && conn->max_bpc_bounds[1] != 0) {
atomic_add(atom, conn->id, conn->props.max_bpc, pick_max_bpc(conn, state->primary_fb));
}
if (conn->props.colorspace != 0) {
atomic_add(atom, conn->id, conn->props.colorspace, state->colorspace);
}
if (conn->props.hdr_output_metadata != 0) {
atomic_add(atom, conn->id, conn->props.hdr_output_metadata, state->hdr_output_metadata);
}
atomic_add(atom, crtc->id, crtc->props.mode_id, state->mode_id);
atomic_add(atom, crtc->id, crtc->props.active, active);
if (active) {
@ -440,6 +585,10 @@ static void atomic_connector_add(struct atomic *atom,
set_plane_props(atom, drm, crtc->primary, state->primary_fb, crtc->id,
&state->primary_viewport.dst_box, &state->primary_viewport.src_box);
if (state->base->committed & WLR_OUTPUT_STATE_COLOR_REPRESENTATION) {
set_color_encoding_and_range(atom, drm, crtc->primary,
state->base->color_encoding, state->base->color_range);
}
if (crtc->primary->props.fb_damage_clips != 0) {
atomic_add(atom, crtc->primary->id,
crtc->primary->props.fb_damage_clips, state->fb_damage_clips);
@ -447,9 +596,6 @@ static void atomic_connector_add(struct atomic *atom,
if (state->primary_in_fence_fd >= 0) {
set_plane_in_fence_fd(atom, crtc->primary, state->primary_in_fence_fd);
}
if (state->base->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
set_crtc_out_fence_ptr(atom, crtc, &state->out_fence_fd);
}
if (crtc->cursor) {
if (drm_connector_is_cursor_visible(conn)) {
struct wlr_fbox cursor_src = {

View file

@ -95,7 +95,7 @@ static const struct wlr_backend_impl backend_impl = {
.commit = backend_commit,
};
bool wlr_backend_is_drm(struct wlr_backend *b) {
bool wlr_backend_is_drm(const struct wlr_backend *b) {
return b->impl == &backend_impl;
}

View file

@ -24,6 +24,7 @@
#include "backend/drm/fb.h"
#include "backend/drm/iface.h"
#include "backend/drm/util.h"
#include "render/color.h"
#include "types/wlr_output.h"
#include "util/env.h"
#include "config.h"
@ -37,11 +38,13 @@ static const uint32_t COMMIT_OUTPUT_STATE =
WLR_OUTPUT_STATE_BUFFER |
WLR_OUTPUT_STATE_MODE |
WLR_OUTPUT_STATE_ENABLED |
WLR_OUTPUT_STATE_GAMMA_LUT |
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED |
WLR_OUTPUT_STATE_LAYERS |
WLR_OUTPUT_STATE_WAIT_TIMELINE |
WLR_OUTPUT_STATE_SIGNAL_TIMELINE;
WLR_OUTPUT_STATE_SIGNAL_TIMELINE |
WLR_OUTPUT_STATE_COLOR_TRANSFORM |
WLR_OUTPUT_STATE_IMAGE_DESCRIPTION |
WLR_OUTPUT_STATE_COLOR_REPRESENTATION;
static const uint32_t SUPPORTED_OUTPUT_STATE =
WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE;
@ -365,7 +368,17 @@ static void drm_plane_finish_surface(struct wlr_drm_plane *plane) {
}
drm_fb_clear(&plane->queued_fb);
if (plane->queued_release_timeline != NULL) {
wlr_drm_syncobj_timeline_signal(plane->queued_release_timeline, plane->queued_release_point);
wlr_drm_syncobj_timeline_unref(plane->queued_release_timeline);
plane->queued_release_timeline = NULL;
}
drm_fb_clear(&plane->current_fb);
if (plane->current_release_timeline != NULL) {
wlr_drm_syncobj_timeline_signal(plane->current_release_timeline, plane->current_release_point);
wlr_drm_syncobj_timeline_unref(plane->current_release_timeline);
plane->current_release_timeline = NULL;
}
finish_drm_surface(&plane->mgpu_surf);
}
@ -554,6 +567,18 @@ static void drm_connector_apply_commit(const struct wlr_drm_connector_state *sta
struct wlr_drm_crtc *crtc = conn->crtc;
drm_fb_copy(&crtc->primary->queued_fb, state->primary_fb);
if (crtc->primary->queued_release_timeline != NULL) {
wlr_drm_syncobj_timeline_signal(crtc->primary->queued_release_timeline, crtc->primary->queued_release_point);
wlr_drm_syncobj_timeline_unref(crtc->primary->queued_release_timeline);
}
if (state->base->signal_timeline != NULL) {
crtc->primary->queued_release_timeline = wlr_drm_syncobj_timeline_ref(state->base->signal_timeline);
crtc->primary->queued_release_point = state->base->signal_point;
} else {
crtc->primary->queued_release_timeline = NULL;
crtc->primary->queued_release_point = 0;
}
crtc->primary->viewport = state->primary_viewport;
if (crtc->cursor != NULL) {
drm_fb_copy(&crtc->cursor->queued_fb, state->cursor_fb);
@ -644,7 +669,6 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state,
.base = base,
.active = output_pending_enabled(&conn->output, base),
.primary_in_fence_fd = -1,
.out_fence_fd = -1,
};
struct wlr_output_mode *mode = conn->output.current_mode;
@ -856,6 +880,19 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo
}
}
if ((state->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) && state->color_transform != NULL &&
state->color_transform->type != COLOR_TRANSFORM_LUT_3X1D) {
wlr_drm_conn_log(conn, WLR_DEBUG,
"Only 3x1D LUT color transforms are supported");
return false;
}
if ((state->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) &&
conn->backend->iface != &atomic_iface) {
wlr_log(WLR_DEBUG, "Image descriptions are only supported by the atomic interface");
return false;
}
if (test_only && conn->backend->mgpu_renderer.wlr_rend) {
// If we're running as a secondary GPU, we can't perform an atomic
// commit without blitting a buffer.
@ -1284,7 +1321,7 @@ static const struct wlr_output_impl output_impl = {
.get_primary_formats = drm_connector_get_primary_formats,
};
bool wlr_output_is_drm(struct wlr_output *output) {
bool wlr_output_is_drm(const struct wlr_output *output) {
return output->impl == &output_impl;
}
@ -1702,7 +1739,11 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
size_t edid_len = 0;
uint8_t *edid = get_drm_prop_blob(drm->fd,
wlr_conn->id, wlr_conn->props.edid, &edid_len);
parse_edid(wlr_conn, edid_len, edid);
if (edid_len > 0) {
parse_edid(wlr_conn, edid_len, edid);
} else {
wlr_log(WLR_DEBUG, "Connector has no EDID");
}
free(edid);
char *subconnector = NULL;
@ -1999,6 +2040,14 @@ static void handle_page_flip(int fd, unsigned seq,
struct wlr_drm_plane *plane = conn->crtc->primary;
if (plane->queued_fb) {
drm_fb_move(&plane->current_fb, &plane->queued_fb);
if (plane->current_release_timeline != NULL) {
wlr_drm_syncobj_timeline_signal(plane->current_release_timeline, plane->current_release_point);
wlr_drm_syncobj_timeline_unref(plane->current_release_timeline);
}
plane->current_release_timeline = plane->queued_release_timeline;
plane->current_release_point = plane->queued_release_point;
plane->queued_release_timeline = NULL;
plane->queued_release_point = 0;
}
if (conn->crtc->cursor && conn->crtc->cursor->queued_fb) {
drm_fb_move(&conn->crtc->cursor->current_fb,
@ -2085,6 +2134,7 @@ int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend) {
if (drmIsMaster(fd) && drmDropMaster(fd) < 0) {
wlr_log_errno(WLR_ERROR, "Failed to drop master");
close(fd);
return -1;
}
@ -2119,7 +2169,7 @@ struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs,
wlr_log(WLR_DEBUG, "Connector %d", conn->id);
if (!drm_connector_alloc_crtc(conn)) {
wlr_log(WLR_ERROR, "Failled to allocate connector CRTC");
wlr_log(WLR_ERROR, "Failed to allocate connector CRTC");
return NULL;
}

View file

@ -7,6 +7,7 @@
#include "backend/drm/fb.h"
#include "backend/drm/iface.h"
#include "backend/drm/util.h"
#include "render/color.h"
#include "types/wlr_output.h"
static bool legacy_fb_props_match(struct wlr_drm_fb *fb1,
@ -124,9 +125,17 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
}
}
if (state->base->committed & WLR_OUTPUT_STATE_GAMMA_LUT) {
if (!drm_legacy_crtc_set_gamma(drm, crtc,
state->base->gamma_lut_size, state->base->gamma_lut)) {
if (state->base->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) {
size_t dim = 0;
uint16_t *lut = NULL;
if (state->base->color_transform != NULL) {
struct wlr_color_transform_lut_3x1d *tr =
color_transform_lut_3x1d_from_base(state->base->color_transform);
dim = tr->dim;
lut = tr->lut_3x1d;
}
if (!drm_legacy_crtc_set_gamma(drm, crtc, dim, lut)) {
return false;
}
}

View file

@ -352,10 +352,6 @@ static bool add_connector(drmModeAtomicReq *req,
liftoff_layer_set_property(crtc->liftoff_composition_layer,
"IN_FENCE_FD", state->primary_in_fence_fd);
}
if (state->base->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
ok = ok && add_prop(req, crtc->id, crtc->props.out_fence_ptr,
(uintptr_t)&state->out_fence_fd);
}
if (state->base->committed & WLR_OUTPUT_STATE_LAYERS) {
for (size_t i = 0; i < state->base->layers_len; i++) {

View file

@ -7,6 +7,7 @@ hwdata = dependency(
libdisplay_info = dependency(
'libdisplay-info',
version: '>=0.2.0',
required: 'drm' in backends,
fallback: 'libdisplay-info',
not_found_message: 'Required for the DRM backend.',

View file

@ -22,8 +22,10 @@ struct prop_info {
static const struct prop_info connector_info[] = {
#define INDEX(name) (offsetof(struct wlr_drm_connector_props, name) / sizeof(uint32_t))
{ "CRTC_ID", INDEX(crtc_id) },
{ "Colorspace", INDEX(colorspace) },
{ "DPMS", INDEX(dpms) },
{ "EDID", INDEX(edid) },
{ "HDR_OUTPUT_METADATA", INDEX(hdr_output_metadata) },
{ "PATH", INDEX(path) },
{ "content type", INDEX(content_type) },
{ "link-status", INDEX(link_status) },
@ -48,6 +50,8 @@ static const struct prop_info crtc_info[] = {
static const struct prop_info plane_info[] = {
#define INDEX(name) (offsetof(struct wlr_drm_plane_props, name) / sizeof(uint32_t))
{ "COLOR_ENCODING", INDEX(color_encoding) },
{ "COLOR_RANGE", INDEX(color_range) },
{ "CRTC_H", INDEX(crtc_h) },
{ "CRTC_ID", INDEX(crtc_id) },
{ "CRTC_W", INDEX(crtc_w) },

View file

@ -83,6 +83,28 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data)
output->model = di_info_get_model(info);
output->serial = di_info_get_serial(info);
const struct di_color_primaries *color_characteristics = di_info_get_default_color_primaries(info);
if (color_characteristics->has_primaries) {
output->default_primaries_value = (struct wlr_color_primaries) {
.red = { .x = color_characteristics->primary[0].x, .y = color_characteristics->primary[0].y },
.green = { .x = color_characteristics->primary[1].x, .y = color_characteristics->primary[1].y },
.blue = { .x = color_characteristics->primary[2].x, .y = color_characteristics->primary[2].y },
.white = { .x = color_characteristics->default_white.x, .y = color_characteristics->default_white.y },
};
output->default_primaries = &output->default_primaries_value;
}
const struct di_supported_signal_colorimetry *colorimetry = di_info_get_supported_signal_colorimetry(info);
bool has_bt2020 = colorimetry->bt2020_cycc || colorimetry->bt2020_ycc || colorimetry->bt2020_rgb;
if (conn->props.colorspace != 0 && has_bt2020) {
output->supported_primaries |= WLR_COLOR_NAMED_PRIMARIES_BT2020;
}
const struct di_hdr_static_metadata *hdr_static_metadata = di_info_get_hdr_static_metadata(info);
if (conn->props.hdr_output_metadata != 0 && hdr_static_metadata->type1 && hdr_static_metadata->pq) {
output->supported_transfer_functions |= WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ;
}
di_info_destroy(info);
}

View file

@ -81,6 +81,6 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_event_loop *loop) {
return &backend->backend;
}
bool wlr_backend_is_headless(struct wlr_backend *backend) {
bool wlr_backend_is_headless(const struct wlr_backend *backend) {
return backend->impl == &backend_impl;
}

View file

@ -106,7 +106,7 @@ static const struct wlr_output_impl output_impl = {
.move_cursor = output_move_cursor,
};
bool wlr_output_is_headless(struct wlr_output *wlr_output) {
bool wlr_output_is_headless(const struct wlr_output *wlr_output) {
return wlr_output->impl == &output_impl;
}

View file

@ -155,7 +155,7 @@ static const struct wlr_backend_impl backend_impl = {
.destroy = backend_destroy,
};
bool wlr_backend_is_libinput(struct wlr_backend *b) {
bool wlr_backend_is_libinput(const struct wlr_backend *b) {
return b->impl == &backend_impl;
}

View file

@ -249,3 +249,15 @@ void handle_libinput_event(struct wlr_libinput_backend *backend,
break;
}
}
bool button_state_from_libinput(enum libinput_button_state state, enum wlr_button_state *out) {
switch (state) {
case LIBINPUT_BUTTON_STATE_RELEASED:
*out = WLR_BUTTON_RELEASED;
return true;
case LIBINPUT_BUTTON_STATE_PRESSED:
*out = WLR_BUTTON_PRESSED;
return true;
}
return false;
}

View file

@ -2,6 +2,7 @@
#include <libinput.h>
#include <stdlib.h>
#include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/util/log.h>
#include "backend/libinput.h"
struct wlr_libinput_input_device *device_from_keyboard(
@ -30,6 +31,18 @@ void init_device_keyboard(struct wlr_libinput_input_device *dev) {
libinput_device_led_update(dev->handle, 0);
}
static bool key_state_from_libinput(enum libinput_key_state state, enum wl_keyboard_key_state *out) {
switch (state) {
case LIBINPUT_KEY_STATE_RELEASED:
*out = WL_KEYBOARD_KEY_STATE_RELEASED;
return true;
case LIBINPUT_KEY_STATE_PRESSED:
*out = WL_KEYBOARD_KEY_STATE_PRESSED;
return true;
}
return false;
}
void handle_keyboard_key(struct libinput_event *event,
struct wlr_keyboard *kb) {
struct libinput_event_keyboard *kbevent =
@ -39,13 +52,9 @@ void handle_keyboard_key(struct libinput_event *event,
.keycode = libinput_event_keyboard_get_key(kbevent),
.update_state = true,
};
switch (libinput_event_keyboard_get_key_state(kbevent)) {
case LIBINPUT_KEY_STATE_RELEASED:
wlr_event.state = WL_KEYBOARD_KEY_STATE_RELEASED;
break;
case LIBINPUT_KEY_STATE_PRESSED:
wlr_event.state = WL_KEYBOARD_KEY_STATE_PRESSED;
break;
if (!key_state_from_libinput(libinput_event_keyboard_get_key_state(kbevent), &wlr_event.state)) {
wlr_log(WLR_DEBUG, "Unhandled libinput key state");
return;
}
wlr_keyboard_notify_key(kb, &wlr_event);
}

View file

@ -29,3 +29,7 @@ features += { 'libinput-backend': true }
wlr_deps += libinput
internal_config.set10('HAVE_LIBINPUT_BUSTYPE', libinput.version().version_compare('>=1.26.0'))
internal_config.set10(
'HAVE_LIBINPUT_SWITCH_KEYPAD_SLIDE',
libinput.version().version_compare('>=1.30.901')
)

View file

@ -1,6 +1,7 @@
#include <assert.h>
#include <libinput.h>
#include <wlr/interfaces/wlr_pointer.h>
#include <wlr/util/log.h>
#include "backend/libinput.h"
const struct wlr_pointer_impl libinput_pointer_impl = {
@ -52,6 +53,38 @@ void handle_pointer_motion_abs(struct libinput_event *event,
wl_signal_emit_mutable(&pointer->events.frame, pointer);
}
static bool pointer_button_state_from_libinput(enum libinput_button_state state,
enum wl_pointer_button_state *out) {
switch (state) {
case LIBINPUT_BUTTON_STATE_PRESSED:
*out = WL_POINTER_BUTTON_STATE_PRESSED;
return true;
case LIBINPUT_BUTTON_STATE_RELEASED:
*out = WL_POINTER_BUTTON_STATE_RELEASED;
return true;
}
return false;
}
static bool axis_source_from_libinput(enum libinput_pointer_axis_source source,
enum wl_pointer_axis_source *out) {
switch (source) {
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
*out = WL_POINTER_AXIS_SOURCE_WHEEL;
return true;
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
*out = WL_POINTER_AXIS_SOURCE_FINGER;
return true;
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
*out = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
return true;
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
*out = WL_POINTER_AXIS_SOURCE_WHEEL_TILT;
return true;
}
return false;
}
void handle_pointer_button(struct libinput_event *event,
struct wlr_pointer *pointer) {
struct libinput_event_pointer *pevent =
@ -61,13 +94,10 @@ void handle_pointer_button(struct libinput_event *event,
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
.button = libinput_event_pointer_get_button(pevent),
};
switch (libinput_event_pointer_get_button_state(pevent)) {
case LIBINPUT_BUTTON_STATE_PRESSED:
wlr_event.state = WL_POINTER_BUTTON_STATE_PRESSED;
break;
case LIBINPUT_BUTTON_STATE_RELEASED:
wlr_event.state = WL_POINTER_BUTTON_STATE_RELEASED;
break;
if (!pointer_button_state_from_libinput(libinput_event_pointer_get_button_state(pevent),
&wlr_event.state)) {
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
return;
}
wlr_pointer_notify_button(pointer, &wlr_event);
wl_signal_emit_mutable(&pointer->events.frame, pointer);
@ -81,19 +111,9 @@ void handle_pointer_axis(struct libinput_event *event,
.pointer = pointer,
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
};
switch (libinput_event_pointer_get_axis_source(pevent)) {
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
wlr_event.source = WL_POINTER_AXIS_SOURCE_WHEEL;
break;
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
wlr_event.source = WL_POINTER_AXIS_SOURCE_FINGER;
break;
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
wlr_event.source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
break;
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
wlr_event.source = WL_POINTER_AXIS_SOURCE_WHEEL_TILT;
break;
if (!axis_source_from_libinput(libinput_event_pointer_get_axis_source(pevent), &wlr_event.source)) {
wlr_log(WLR_DEBUG, "Unhandled libinput pointer axis source");
return;
}
const enum libinput_pointer_axis axes[] = {
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,

View file

@ -1,7 +1,9 @@
#include <assert.h>
#include <libinput.h>
#include <wlr/interfaces/wlr_switch.h>
#include <wlr/util/log.h>
#include "backend/libinput.h"
#include "config.h"
const struct wlr_switch_impl libinput_switch_impl = {
.name = "libinput-switch",
@ -22,28 +24,49 @@ struct wlr_libinput_input_device *device_from_switch(
return dev;
}
static bool switch_type_from_libinput(enum libinput_switch type, enum wlr_switch_type *out) {
switch (type) {
case LIBINPUT_SWITCH_LID:
*out = WLR_SWITCH_TYPE_LID;
return true;
case LIBINPUT_SWITCH_TABLET_MODE:
*out = WLR_SWITCH_TYPE_TABLET_MODE;
return true;
#if HAVE_LIBINPUT_SWITCH_KEYPAD_SLIDE
case LIBINPUT_SWITCH_KEYPAD_SLIDE:
*out = WLR_SWITCH_TYPE_KEYPAD_SLIDE;
return true;
#endif
}
return false;
}
static bool switch_state_from_libinput(enum libinput_switch_state state, enum wlr_switch_state *out) {
switch (state) {
case LIBINPUT_SWITCH_STATE_OFF:
*out = WLR_SWITCH_STATE_OFF;
return true;
case LIBINPUT_SWITCH_STATE_ON:
*out = WLR_SWITCH_STATE_ON;
return true;
}
return false;
}
void handle_switch_toggle(struct libinput_event *event,
struct wlr_switch *wlr_switch) {
struct libinput_event_switch *sevent =
libinput_event_get_switch_event (event);
libinput_event_get_switch_event(event);
struct wlr_switch_toggle_event wlr_event = {
.time_msec = usec_to_msec(libinput_event_switch_get_time_usec(sevent)),
};
switch (libinput_event_switch_get_switch(sevent)) {
case LIBINPUT_SWITCH_LID:
wlr_event.switch_type = WLR_SWITCH_TYPE_LID;
break;
case LIBINPUT_SWITCH_TABLET_MODE:
wlr_event.switch_type = WLR_SWITCH_TYPE_TABLET_MODE;
break;
if (!switch_type_from_libinput(libinput_event_switch_get_switch(sevent), &wlr_event.switch_type)) {
wlr_log(WLR_DEBUG, "Unhandled libinput switch type");
return;
}
switch (libinput_event_switch_get_switch_state(sevent)) {
case LIBINPUT_SWITCH_STATE_OFF:
wlr_event.switch_state = WLR_SWITCH_STATE_OFF;
break;
case LIBINPUT_SWITCH_STATE_ON:
wlr_event.switch_state = WLR_SWITCH_STATE_ON;
break;
if (!switch_state_from_libinput(libinput_event_switch_get_switch_state(sevent), &wlr_event.switch_state)) {
wlr_log(WLR_DEBUG, "Unhandled libinput switch state");
return;
}
wl_signal_emit_mutable(&wlr_switch->events.toggle, &wlr_event);
}

View file

@ -104,6 +104,7 @@ void init_device_tablet_pad(struct wlr_libinput_input_device *dev) {
struct udev_device *udev = libinput_device_get_udev_device(handle);
char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *));
*dst = strdup(udev_device_get_syspath(udev));
udev_device_unref(udev);
int groups = libinput_device_tablet_pad_get_num_mode_groups(handle);
for (int i = 0; i < groups; ++i) {
@ -147,13 +148,9 @@ void handle_tablet_pad_button(struct libinput_event *event,
.group = libinput_tablet_pad_mode_group_get_index(
libinput_event_tablet_pad_get_mode_group(pevent)),
};
switch (libinput_event_tablet_pad_get_button_state(pevent)) {
case LIBINPUT_BUTTON_STATE_PRESSED:
wlr_event.state = WLR_BUTTON_PRESSED;
break;
case LIBINPUT_BUTTON_STATE_RELEASED:
wlr_event.state = WLR_BUTTON_RELEASED;
break;
if (!button_state_from_libinput(libinput_event_tablet_pad_get_button_state(pevent), &wlr_event.state)) {
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
return;
}
wl_signal_emit_mutable(&tablet_pad->events.button, &wlr_event);
}
@ -167,6 +164,7 @@ void handle_tablet_pad_ring(struct libinput_event *event,
.ring = libinput_event_tablet_pad_get_ring_number(pevent),
.position = libinput_event_tablet_pad_get_ring_position(pevent),
.mode = libinput_event_tablet_pad_get_mode(pevent),
.source = WLR_TABLET_PAD_RING_SOURCE_UNKNOWN,
};
switch (libinput_event_tablet_pad_get_ring_source(pevent)) {
case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
@ -188,6 +186,7 @@ void handle_tablet_pad_strip(struct libinput_event *event,
.strip = libinput_event_tablet_pad_get_strip_number(pevent),
.position = libinput_event_tablet_pad_get_strip_position(pevent),
.mode = libinput_event_tablet_pad_get_mode(pevent),
.source = WLR_TABLET_PAD_STRIP_SOURCE_UNKNOWN,
};
switch (libinput_event_tablet_pad_get_strip_source(pevent)) {
case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:

View file

@ -18,6 +18,16 @@ const struct wlr_tablet_impl libinput_tablet_impl = {
.name = "libinput-tablet-tool",
};
struct libinput_tablet_tool *wlr_libinput_get_tablet_tool_handle(
struct wlr_tablet_tool *wlr_tablet_tool) {
struct tablet_tool *tool =
wl_container_of(wlr_tablet_tool, tool, wlr_tool);
assert(tool);
return tool->handle;
}
void init_device_tablet(struct wlr_libinput_input_device *dev) {
const char *name = get_libinput_device_name(dev->handle);
struct wlr_tablet *wlr_tablet = &dev->tablet;
@ -37,6 +47,7 @@ void init_device_tablet(struct wlr_libinput_input_device *dev) {
struct udev_device *udev = libinput_device_get_udev_device(dev->handle);
char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *));
*dst = strdup(udev_device_get_syspath(udev));
udev_device_unref(udev);
wl_list_init(&dev->tablet_tools);
}
@ -67,27 +78,61 @@ struct wlr_libinput_input_device *device_from_tablet(
return dev;
}
static enum wlr_tablet_tool_type wlr_type_from_libinput_type(
enum libinput_tablet_tool_type value) {
switch (value) {
static bool type_from_libinput(enum libinput_tablet_tool_type type,
enum wlr_tablet_tool_type *out) {
switch (type) {
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
return WLR_TABLET_TOOL_TYPE_PEN;
*out = WLR_TABLET_TOOL_TYPE_PEN;
return true;
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
return WLR_TABLET_TOOL_TYPE_ERASER;
*out = WLR_TABLET_TOOL_TYPE_ERASER;
return true;
case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
return WLR_TABLET_TOOL_TYPE_BRUSH;
*out = WLR_TABLET_TOOL_TYPE_BRUSH;
return true;
case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
return WLR_TABLET_TOOL_TYPE_PENCIL;
*out = WLR_TABLET_TOOL_TYPE_PENCIL;
return true;
case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
return WLR_TABLET_TOOL_TYPE_AIRBRUSH;
*out = WLR_TABLET_TOOL_TYPE_AIRBRUSH;
return true;
case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
return WLR_TABLET_TOOL_TYPE_MOUSE;
*out = WLR_TABLET_TOOL_TYPE_MOUSE;
return true;
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
return WLR_TABLET_TOOL_TYPE_LENS;
*out = WLR_TABLET_TOOL_TYPE_LENS;
return true;
case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
return WLR_TABLET_TOOL_TYPE_TOTEM;
*out = WLR_TABLET_TOOL_TYPE_TOTEM;
return true;
}
abort(); // unreachable
return false;
}
static bool proximity_state_from_libinput(enum libinput_tablet_tool_proximity_state state,
enum wlr_tablet_tool_proximity_state *out) {
switch (state) {
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
*out = WLR_TABLET_TOOL_PROXIMITY_OUT;
return true;
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
*out = WLR_TABLET_TOOL_PROXIMITY_IN;
return true;
}
return false;
}
static bool tip_state_from_libinput(enum libinput_tablet_tool_tip_state state,
enum wlr_tablet_tool_tip_state *out) {
switch (state) {
case LIBINPUT_TABLET_TOOL_TIP_UP:
*out = WLR_TABLET_TOOL_TIP_UP;
return true;
case LIBINPUT_TABLET_TOOL_TIP_DOWN:
*out = WLR_TABLET_TOOL_TIP_DOWN;
return true;
}
return false;
}
static struct tablet_tool *get_tablet_tool(
@ -99,14 +144,19 @@ static struct tablet_tool *get_tablet_tool(
return tool;
}
enum wlr_tablet_tool_type type;
if (!type_from_libinput(libinput_tablet_tool_get_type(libinput_tool), &type)) {
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool type");
return NULL;
}
tool = calloc(1, sizeof(*tool));
if (tool == NULL) {
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_tablet_tool");
return NULL;
}
tool->wlr_tool.type = wlr_type_from_libinput_type(
libinput_tablet_tool_get_type(libinput_tool));
tool->wlr_tool.type = type;
tool->wlr_tool.hardware_serial =
libinput_tablet_tool_get_serial(libinput_tool);
tool->wlr_tool.hardware_wacom =
@ -198,14 +248,12 @@ void handle_tablet_tool_proximity(struct libinput_event *event,
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
};
switch (libinput_event_tablet_tool_get_proximity_state(tevent)) {
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_OUT;
break;
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_IN;
break;
if (!proximity_state_from_libinput(libinput_event_tablet_tool_get_proximity_state(tevent),
&wlr_event.state)) {
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool proximity state");
return;
}
wl_signal_emit_mutable(&wlr_tablet->events.proximity, &wlr_event);
if (libinput_event_tablet_tool_get_proximity_state(tevent) ==
@ -240,14 +288,11 @@ void handle_tablet_tool_tip(struct libinput_event *event,
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
};
switch (libinput_event_tablet_tool_get_tip_state(tevent)) {
case LIBINPUT_TABLET_TOOL_TIP_UP:
wlr_event.state = WLR_TABLET_TOOL_TIP_UP;
break;
case LIBINPUT_TABLET_TOOL_TIP_DOWN:
wlr_event.state = WLR_TABLET_TOOL_TIP_DOWN;
break;
if (!tip_state_from_libinput(libinput_event_tablet_tool_get_tip_state(tevent), &wlr_event.state)) {
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool tip state");
return;
}
wl_signal_emit_mutable(&wlr_tablet->events.tip, &wlr_event);
}
@ -266,13 +311,11 @@ void handle_tablet_tool_button(struct libinput_event *event,
.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)),
.button = libinput_event_tablet_tool_get_button(tevent),
};
switch (libinput_event_tablet_tool_get_button_state(tevent)) {
case LIBINPUT_BUTTON_STATE_RELEASED:
wlr_event.state = WLR_BUTTON_RELEASED;
break;
case LIBINPUT_BUTTON_STATE_PRESSED:
wlr_event.state = WLR_BUTTON_PRESSED;
break;
if (!button_state_from_libinput(libinput_event_tablet_tool_get_button_state(tevent), &wlr_event.state)) {
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
return;
}
wl_signal_emit_mutable(&wlr_tablet->events.button, &wlr_event);
}

View file

@ -173,7 +173,7 @@ struct wlr_backend *wlr_multi_backend_create(struct wl_event_loop *loop) {
return &backend->backend;
}
bool wlr_backend_is_multi(struct wlr_backend *b) {
bool wlr_backend_is_multi(const struct wlr_backend *b) {
return b->impl == &backend_impl;
}

View file

@ -36,6 +36,15 @@ static void handle_disable_seat(struct libseat *seat, void *data) {
static int libseat_event(int fd, uint32_t mask, void *data) {
struct wlr_session *session = data;
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
if (mask & WL_EVENT_ERROR) {
wlr_log(WLR_ERROR, "Failed to wait for libseat event");
} else {
wlr_log(WLR_INFO, "Failed to wait for libseat event");
}
wlr_session_destroy(session);
return 0;
}
if (libseat_dispatch(session->seat_handle, 0) == -1) {
wlr_log_errno(WLR_ERROR, "Failed to dispatch libseat");
wlr_session_destroy(session);
@ -367,7 +376,10 @@ void wlr_session_close_file(struct wlr_session *session,
}
assert(wl_list_empty(&dev->events.change.listener_list));
assert(wl_list_empty(&dev->events.remove.listener_list));
// TODO: assert that the "remove" listener list is empty as well. Listeners
// will typically call wlr_session_close_file() in response, and
// wl_signal_emit_mutable() installs two phantom listeners, so we'd count
// these two.
close(dev->fd);
wl_list_remove(&dev->link);
@ -476,6 +488,7 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
if (udev_enumerate_get_list_entry(en) == NULL) {
udev_enumerate_unref(en);
en = NULL;
wlr_log(WLR_INFO, "Waiting for a KMS device");
struct find_gpus_add_handler handler = {0};
@ -489,7 +502,6 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
if (ret < 0) {
wlr_log_errno(WLR_ERROR, "Failed to wait for KMS device: "
"wl_event_loop_dispatch failed");
udev_enumerate_unref(en);
return -1;
}
@ -516,8 +528,6 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
break;
}
bool is_boot_vga = false;
const char *path = udev_list_entry_get_name(entry);
struct udev_device *dev = udev_device_new_from_syspath(session->udev, path);
if (!dev) {
@ -533,28 +543,32 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
continue;
}
// This is owned by 'dev', so we don't need to free it
struct udev_device *pci =
udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL);
bool is_primary = false;
const char *boot_display = udev_device_get_sysattr_value(dev, "boot_display");
if (boot_display && strcmp(boot_display, "1") == 0) {
is_primary = true;
} else {
// This is owned by 'dev', so we don't need to free it
struct udev_device *pci =
udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL);
if (pci) {
const char *id = udev_device_get_sysattr_value(pci, "boot_vga");
if (id && strcmp(id, "1") == 0) {
is_boot_vga = true;
if (pci) {
const char *id = udev_device_get_sysattr_value(pci, "boot_vga");
if (id && strcmp(id, "1") == 0) {
is_primary = true;
}
}
}
struct wlr_device *wlr_dev =
session_open_if_kms(session, udev_device_get_devnode(dev));
udev_device_unref(dev);
if (!wlr_dev) {
udev_device_unref(dev);
continue;
}
udev_device_unref(dev);
ret[i] = wlr_dev;
if (is_boot_vga) {
if (is_primary) {
struct wlr_device *tmp = ret[0];
ret[0] = ret[i];
ret[i] = tmp;

View file

@ -55,14 +55,6 @@ struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *wlr_backe
static int dispatch_events(int fd, uint32_t mask, void *data) {
struct wlr_wl_backend *wl = data;
if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
if (mask & WL_EVENT_ERROR) {
wlr_log(WLR_ERROR, "Failed to read from remote Wayland display");
}
wlr_backend_destroy(&wl->backend);
return 0;
}
int count = 0;
if (mask & WL_EVENT_READABLE) {
count = wl_display_dispatch(wl->remote_display);
@ -75,6 +67,18 @@ static int dispatch_events(int fd, uint32_t mask, void *data) {
wl_display_flush(wl->remote_display);
}
// Make sure we've consumed all data before disconnecting due to hangup,
// so that we process any wl_display.error events
if (!(mask & WL_EVENT_READABLE) && (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR))) {
if (mask & WL_EVENT_ERROR) {
wlr_log(WLR_ERROR, "Failed to read from remote Wayland display");
} else {
wlr_log(WLR_DEBUG, "Disconnected from remote Wayland display");
}
wlr_backend_destroy(&wl->backend);
return 0;
}
if (count < 0) {
wlr_log(WLR_ERROR, "Failed to dispatch remote Wayland display");
wlr_backend_destroy(&wl->backend);
@ -573,7 +577,7 @@ static const struct wlr_backend_impl backend_impl = {
.get_drm_fd = backend_get_drm_fd,
};
bool wlr_backend_is_wl(struct wlr_backend *b) {
bool wlr_backend_is_wl(const struct wlr_backend *b) {
return b->impl == &backend_impl;
}

View file

@ -1027,7 +1027,7 @@ static const struct wlr_output_impl output_impl = {
.get_primary_formats = output_get_formats,
};
bool wlr_output_is_wl(struct wlr_output *wlr_output) {
bool wlr_output_is_wl(const struct wlr_output *wlr_output) {
return wlr_output->impl == &output_impl;
}

View file

@ -246,7 +246,7 @@ void init_seat_touch(struct wlr_wl_seat *seat) {
struct wlr_wl_output *output;
wl_list_for_each(output, &seat->backend->outputs, link) {
/* Multi-output touch not supproted */
/* Multi-output touch not supported */
seat->wlr_touch.output_name = strdup(output->wlr_output.name);
break;
}

View file

@ -115,6 +115,7 @@ static void handle_x11_event(struct wlr_x11_backend *x11,
handle_x11_error(x11, ev);
break;
}
case XCB_DESTROY_NOTIFY:
case XCB_UNMAP_NOTIFY:
case XCB_MAP_NOTIFY:
break;
@ -218,7 +219,7 @@ static const struct wlr_backend_impl backend_impl = {
.get_drm_fd = backend_get_drm_fd,
};
bool wlr_backend_is_x11(struct wlr_backend *backend) {
bool wlr_backend_is_x11(const struct wlr_backend *backend) {
return backend->impl == &backend_impl;
}

View file

@ -19,7 +19,9 @@
#include <wlr/util/log.h>
#include "backend/x11.h"
#include "render/pixel_format.h"
#include "util/time.h"
#include "types/wlr_buffer.h"
#include "types/wlr_output.h"
static const uint32_t SUPPORTED_OUTPUT_STATE =
@ -166,18 +168,20 @@ static bool output_test(struct wlr_output *wlr_output,
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
struct wlr_buffer *buffer = state->buffer;
struct wlr_dmabuf_attributes dmabuf_attrs;
struct wlr_shm_attributes shm_attrs;
uint32_t format = DRM_FORMAT_INVALID;
if (wlr_buffer_get_dmabuf(buffer, &dmabuf_attrs)) {
format = dmabuf_attrs.format;
} else if (wlr_buffer_get_shm(buffer, &shm_attrs)) {
format = shm_attrs.format;
}
uint32_t format = buffer_get_drm_format(buffer);
if (format != x11->x11_format->drm) {
wlr_log(WLR_DEBUG, "Unsupported buffer format");
return false;
}
struct wlr_shm_attributes shm;
if (wlr_buffer_get_shm(buffer, &shm)) {
const struct wlr_pixel_format_info *info = drm_get_pixel_format_info(format);
if (shm.stride != pixel_format_info_min_stride(info, shm.width)) {
// xcb_shm_create_pixmap() does not allow arbitrary strides.
wlr_log(WLR_DEBUG, "Unsupported shm buffer stride");
return false;
}
}
}
if (state->committed & WLR_OUTPUT_STATE_MODE) {
@ -267,6 +271,12 @@ static xcb_pixmap_t import_shm(struct wlr_x11_output *output,
return XCB_PIXMAP_NONE;
}
const struct wlr_pixel_format_info *info = drm_get_pixel_format_info(shm->format);
if (shm->stride != pixel_format_info_min_stride(info, shm->width)) {
// xcb_shm_create_pixmap() does not allow arbitrary strides.
return XCB_PIXMAP_NONE;
}
// xcb closes the FD after sending it
int fd = fcntl(shm->fd, F_DUPFD_CLOEXEC, 0);
if (fd < 0) {
@ -701,7 +711,7 @@ void handle_x11_configure_notify(struct wlr_x11_output *output,
wlr_output_state_finish(&state);
}
bool wlr_output_is_x11(struct wlr_output *wlr_output) {
bool wlr_output_is_x11(const struct wlr_output *wlr_output) {
return wlr_output->impl == &output_impl;
}

View file

@ -29,8 +29,12 @@ struct wlr_drm_plane {
/* Buffer submitted to the kernel, will be presented on next vblank */
struct wlr_drm_fb *queued_fb;
struct wlr_drm_syncobj_timeline *queued_release_timeline;
uint64_t queued_release_point;
/* Buffer currently displayed on screen */
struct wlr_drm_fb *current_fb;
struct wlr_drm_syncobj_timeline *current_release_timeline;
uint64_t current_release_point;
/* Viewport belonging to the last committed fb */
struct wlr_drm_viewport viewport;
@ -156,8 +160,10 @@ struct wlr_drm_connector_state {
uint32_t mode_id;
uint32_t gamma_lut;
uint32_t fb_damage_clips;
int primary_in_fence_fd, out_fence_fd;
int primary_in_fence_fd;
bool vrr_enabled;
uint32_t colorspace;
uint32_t hdr_output_metadata;
};
/**
@ -212,6 +218,10 @@ struct wlr_drm_connector {
// Last committed page-flip
struct wlr_drm_page_flip *pending_page_flip;
// Atomic modesetting only
uint32_t colorspace;
uint32_t hdr_output_metadata;
int32_t refresh;
};

View file

@ -26,6 +26,8 @@ struct wlr_drm_connector_props {
// atomic-modesetting only
uint32_t crtc_id;
uint32_t colorspace;
uint32_t hdr_output_metadata;
};
struct wlr_drm_crtc_props {
@ -63,6 +65,22 @@ struct wlr_drm_plane_props {
uint32_t hotspot_x;
uint32_t hotspot_y;
uint32_t in_fence_fd;
uint32_t color_encoding; // Not guaranteed to exist
uint32_t color_range; // Not guaranteed to exist
};
// Equivalent to wlr_drm_color_encoding defined in the kernel (but not exported)
enum wlr_drm_color_encoding {
WLR_DRM_COLOR_YCBCR_BT601,
WLR_DRM_COLOR_YCBCR_BT709,
WLR_DRM_COLOR_YCBCR_BT2020,
};
// Equivalent to wlr_drm_color_range defined in the kernel (but not exported)
enum wlr_drm_color_range {
WLR_DRM_COLOR_YCBCR_FULL_RANGE,
WLR_DRM_COLOR_YCBCR_LIMITED_RANGE,
};
bool get_drm_connector_props(int fd, uint32_t id,

View file

@ -132,4 +132,6 @@ void handle_tablet_pad_ring(struct libinput_event *event,
void handle_tablet_pad_strip(struct libinput_event *event,
struct wlr_tablet_pad *tablet_pad);
bool button_state_from_libinput(enum libinput_button_state state, enum wlr_button_state *out);
#endif

View file

@ -6,8 +6,11 @@
#include <wlr/util/addon.h>
enum wlr_color_transform_type {
COLOR_TRANSFORM_SRGB,
COLOR_TRANSFORM_LUT_3D,
COLOR_TRANSFORM_INVERSE_EOTF,
COLOR_TRANSFORM_LCMS2,
COLOR_TRANSFORM_LUT_3X1D,
COLOR_TRANSFORM_MATRIX,
COLOR_TRANSFORM_PIPELINE,
};
struct wlr_color_transform {
@ -17,39 +20,82 @@ struct wlr_color_transform {
enum wlr_color_transform_type type;
};
/**
* The formula is approximated via a 3D look-up table. A 3D LUT is a
* three-dimensional array where each element is an RGB triplet. The flat lut_3d
* array has a length of dim_len³.
*
* Color channel values in the range [0.0, 1.0] are mapped linearly to
* 3D LUT indices such that 0.0 maps exactly to the first element and 1.0 maps
* exactly to the last element in each dimension.
*
* The offset of the RGB triplet given red, green and blue indices r_index,
* g_index and b_index is:
*
* offset = 3 * (r_index + dim_len * g_index + dim_len * dim_len * b_index)
*/
struct wlr_color_transform_lut3d {
struct wlr_color_transform_inverse_eotf {
struct wlr_color_transform base;
float *lut_3d;
size_t dim_len;
enum wlr_color_transfer_function tf;
};
/**
* Gets a wlr_color_transform_lut3d from a generic wlr_color_transform.
* Asserts that the base type is COLOR_TRANSFORM_LUT_3D
* The formula is approximated via three 1D look-up tables. The flat lut_3x1d
* array has a length of 3 * dim.
*
* The offset of a color value for a given channel and color index is:
*
* offset = channel_index * dim + color_index
*/
struct wlr_color_transform_lut3d *wlr_color_transform_lut3d_from_base(
struct wlr_color_transform_lut_3x1d {
struct wlr_color_transform base;
uint16_t *lut_3x1d;
size_t dim;
};
struct wlr_color_transform_matrix {
struct wlr_color_transform base;
float matrix[9];
};
struct wlr_color_transform_pipeline {
struct wlr_color_transform base;
struct wlr_color_transform **transforms;
size_t len;
};
void wlr_color_transform_init(struct wlr_color_transform *tr,
enum wlr_color_transform_type type);
/**
* Get a struct wlr_color_transform_lcms2 from a generic struct wlr_color_transform.
* Asserts that the base type is COLOR_TRANSFORM_LCMS2.
*/
struct wlr_color_transform_lcms2 *color_transform_lcms2_from_base(
struct wlr_color_transform *tr);
void color_transform_lcms2_finish(struct wlr_color_transform_lcms2 *tr);
/**
* Evaluate a LCMS2 color transform for a given RGB triplet.
*/
void color_transform_lcms2_eval(struct wlr_color_transform_lcms2 *tr,
float out[static 3], const float in[static 3]);
/**
* Gets a wlr_color_transform_inverse_eotf from a generic wlr_color_transform.
* Asserts that the base type is COLOR_TRANSFORM_INVERSE_EOTF
*/
struct wlr_color_transform_inverse_eotf *wlr_color_transform_inverse_eotf_from_base(
struct wlr_color_transform *tr);
/**
* Obtain primaries values from a well-known primaries name.
* Get a struct wlr_color_transform_lut_3x1d from a generic
* struct wlr_color_transform. Asserts that the base type is
* COLOR_TRANSFORM_LUT_3X1D.
*/
void wlr_color_primaries_from_named(struct wlr_color_primaries *out,
enum wlr_color_named_primaries named);
struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base(
struct wlr_color_transform *tr);
/**
* Create a simplified / normalized wlr_color_transform pipeline.
* `transforms` may contain NULL transforms, they will be interpreted as the
* identity transform, and removed.
* `*result` may be set to a transform of a type different from
* `wlr_color_transform_pipeline`, or to NULL if all input transforms are NULL
*/
bool color_transform_compose(struct wlr_color_transform **result,
struct wlr_color_transform **transforms, size_t len);
/**
* Compute the matrix to convert RGB color values to CIE 1931 XYZ.

View file

@ -0,0 +1,44 @@
#ifndef WLR_RENDER_DRM_SYNCOBJ_MERGER_H
#define WLR_RENDER_DRM_SYNCOBJ_MERGER_H
#include <wayland-server-core.h>
/**
* Accumulate timeline points, to have a destination timeline point be
* signalled when all inputs are
*/
struct wlr_drm_syncobj_merger {
int n_ref;
struct wlr_drm_syncobj_timeline *dst_timeline;
uint64_t dst_point;
int sync_fd;
};
/**
* Create a new merger.
*
* The given timeline point will be signalled when all input points are
* signalled and the merger is destroyed.
*/
struct wlr_drm_syncobj_merger *wlr_drm_syncobj_merger_create(
struct wlr_drm_syncobj_timeline *dst_timeline, uint64_t dst_point);
struct wlr_drm_syncobj_merger *wlr_drm_syncobj_merger_ref(
struct wlr_drm_syncobj_merger *merger);
/**
* Target timeline point is materialized when all inputs are, and the merger is
* destroyed.
*/
void wlr_drm_syncobj_merger_unref(struct wlr_drm_syncobj_merger *merger);
/**
* Add a new timeline point to wait for.
*
* If the point is not materialized, the supplied event loop is used to schedule
* a wait.
*/
bool wlr_drm_syncobj_merger_add(struct wlr_drm_syncobj_merger *merger,
struct wlr_drm_syncobj_timeline *dst_timeline, uint64_t dst_point,
struct wl_event_loop *loop);
#endif

View file

@ -63,4 +63,9 @@ enum wl_shm_format convert_drm_format_to_wl_shm(uint32_t fmt);
*/
bool pixel_format_has_alpha(uint32_t fmt);
/**
* Return true if the DRM FourCC fmt belongs to a YCbCr colorspace family, false otherwise.
*/
bool pixel_format_is_ycbcr(uint32_t fmt);
#endif

View file

@ -7,6 +7,7 @@
#include <vulkan/vulkan.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/render/wlr_texture.h>
#include <wlr/render/color.h>
#include <wlr/render/drm_format_set.h>
#include <wlr/render/interface.h>
#include <wlr/util/addon.h>
@ -55,6 +56,10 @@ struct wlr_vk_device {
PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR;
PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR;
PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;
PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR;
PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR;
PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
} api;
uint32_t format_prop_count;
@ -85,7 +90,6 @@ struct wlr_vk_format {
uint32_t drm;
VkFormat vk;
VkFormat vk_srgb; // sRGB version of the format, or 0 if nonexistent
bool is_ycbcr;
};
extern const VkImageUsageFlags vulkan_render_usage, vulkan_shm_tex_usage, vulkan_dma_tex_usage;
@ -124,10 +128,17 @@ void vulkan_format_props_query(struct wlr_vk_device *dev,
const struct wlr_vk_format_modifier_props *vulkan_format_props_find_modifier(
const struct wlr_vk_format_props *props, uint64_t mod, bool render);
void vulkan_format_props_finish(struct wlr_vk_format_props *props);
bool vulkan_format_is_ycbcr(const struct wlr_vk_format *format);
struct wlr_vk_pipeline_layout_key {
const struct wlr_vk_format *ycbcr_format;
enum wlr_scale_filter_mode filter_mode;
// for YCbCr pipelines only
struct {
const struct wlr_vk_format *format;
enum wlr_color_encoding encoding;
enum wlr_color_range range;
} ycbcr;
};
struct wlr_vk_pipeline_layout {
@ -151,6 +162,9 @@ struct wlr_vk_pipeline_layout {
enum wlr_vk_texture_transform {
WLR_VK_TEXTURE_TRANSFORM_IDENTITY = 0,
WLR_VK_TEXTURE_TRANSFORM_SRGB = 1,
WLR_VK_TEXTURE_TRANSFORM_ST2084_PQ = 2,
WLR_VK_TEXTURE_TRANSFORM_GAMMA22 = 3,
WLR_VK_TEXTURE_TRANSFORM_BT1886 = 4,
};
enum wlr_vk_shader_source {
@ -161,8 +175,12 @@ enum wlr_vk_shader_source {
// Constants used to pick the color transform for the blend-to-output
// fragment shader. Must match those in shaders/output.frag
enum wlr_vk_output_transform {
WLR_VK_OUTPUT_TRANSFORM_INVERSE_SRGB = 0,
WLR_VK_OUTPUT_TRANSFORM_LUT3D = 1,
WLR_VK_OUTPUT_TRANSFORM_IDENTITY = 0,
WLR_VK_OUTPUT_TRANSFORM_INVERSE_SRGB = 1,
WLR_VK_OUTPUT_TRANSFORM_INVERSE_ST2084_PQ = 2,
WLR_VK_OUTPUT_TRANSFORM_LUT3D = 3,
WLR_VK_OUTPUT_TRANSFORM_INVERSE_GAMMA22 = 4,
WLR_VK_OUTPUT_TRANSFORM_INVERSE_BT1886 = 5,
};
struct wlr_vk_pipeline_key {
@ -189,16 +207,28 @@ struct wlr_vk_render_format_setup {
struct wl_list link; // wlr_vk_renderer.render_format_setups
const struct wlr_vk_format *render_format; // used in renderpass
bool use_blending_buffer;
bool use_srgb;
VkRenderPass render_pass;
VkPipeline output_pipe_identity;
VkPipeline output_pipe_srgb;
VkPipeline output_pipe_pq;
VkPipeline output_pipe_lut3d;
VkPipeline output_pipe_gamma22;
VkPipeline output_pipe_bt1886;
struct wlr_vk_renderer *renderer;
struct wl_list pipelines; // struct wlr_vk_pipeline.link
};
// Renderer-internal represenation of an wlr_buffer imported for rendering.
// Final output framebuffer and image view
struct wlr_vk_render_buffer_out {
VkImageView image_view;
VkFramebuffer framebuffer;
bool transitioned;
};
// Renderer-internal representation of an wlr_buffer imported for rendering.
struct wlr_vk_render_buffer {
struct wlr_buffer *wlr_buffer;
struct wlr_addon addon;
@ -209,36 +239,40 @@ struct wlr_vk_render_buffer {
uint32_t mem_count;
VkImage image;
// Framebuffer and image view for rendering directly onto the buffer image,
// without any color transform.
struct {
struct wlr_vk_render_buffer_out out;
struct wlr_vk_render_format_setup *render_setup;
} linear;
// Framebuffer and image view for rendering directly onto the buffer image.
// This requires that the image support an _SRGB VkFormat, and does
// not work with color transforms.
struct {
struct wlr_vk_render_buffer_out out;
struct wlr_vk_render_format_setup *render_setup;
VkImageView image_view;
VkFramebuffer framebuffer;
bool transitioned;
} srgb;
// Framebuffer, image view, and blending image to render indirectly
// onto the buffer image. This works for general image types and permits
// color transforms.
struct {
struct wlr_vk_render_buffer_out out;
struct wlr_vk_render_format_setup *render_setup;
VkImageView image_view;
VkFramebuffer framebuffer;
bool transitioned;
VkImage blend_image;
VkImageView blend_image_view;
VkDeviceMemory blend_memory;
VkDescriptorSet blend_descriptor_set;
struct wlr_vk_descriptor_pool *blend_attachment_pool;
bool blend_transitioned;
} plain;
} two_pass;
};
bool vulkan_setup_plain_framebuffer(struct wlr_vk_render_buffer *buffer,
bool vulkan_setup_one_pass_framebuffer(struct wlr_vk_render_buffer *buffer,
const struct wlr_dmabuf_attributes *dmabuf, bool srgb);
bool vulkan_setup_two_pass_framebuffer(struct wlr_vk_render_buffer *buffer,
const struct wlr_dmabuf_attributes *dmabuf);
struct wlr_vk_command_buffer {
@ -334,7 +368,14 @@ struct wlr_vk_vert_pcr_data {
float uv_size[2];
};
struct wlr_vk_frag_texture_pcr_data {
float matrix[4][4]; // only a 3x3 subset is used
float alpha;
float luminance_multiplier;
};
struct wlr_vk_frag_output_pcr_data {
float matrix[4][4]; // only a 3x3 subset is used
float lut_3d_offset;
float lut_3d_scale;
};
@ -342,6 +383,7 @@ struct wlr_vk_frag_output_pcr_data {
struct wlr_vk_texture_view {
struct wl_list link; // struct wlr_vk_texture.views
const struct wlr_vk_pipeline_layout *layout;
bool srgb;
VkDescriptorSet ds;
VkImageView image_view;
@ -356,7 +398,7 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
const struct wlr_vk_pipeline_layout_key *key);
struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(
struct wlr_vk_texture *texture,
const struct wlr_vk_pipeline_layout *layout);
const struct wlr_vk_pipeline_layout *layout, bool srgb);
// Creates a vulkan renderer for the given device.
struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev);
@ -368,7 +410,7 @@ VkCommandBuffer vulkan_record_stage_cb(struct wlr_vk_renderer *renderer);
// Submits the current stage command buffer and waits until it has
// finished execution.
bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer);
bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer, int wait_sync_file_fd);
struct wlr_vk_render_pass_texture {
struct wlr_vk_texture *texture;
@ -381,12 +423,14 @@ struct wlr_vk_render_pass {
struct wlr_render_pass base;
struct wlr_vk_renderer *renderer;
struct wlr_vk_render_buffer *render_buffer;
struct wlr_vk_render_buffer_out *render_buffer_out;
struct wlr_vk_render_format_setup *render_setup;
struct wlr_vk_command_buffer *command_buffer;
struct rect_union updated_region;
VkPipeline bound_pipeline;
float projection[9];
bool failed;
bool srgb_pathway; // if false, rendering via intermediate blending buffer
bool two_pass; // rendering via intermediate blending buffer
struct wlr_color_transform *color_transform;
struct wlr_drm_syncobj_timeline *signal_timeline;
@ -432,18 +476,22 @@ uint64_t vulkan_end_command_buffer(struct wlr_vk_command_buffer *cb,
void vulkan_reset_command_buffer(struct wlr_vk_command_buffer *cb);
bool vulkan_wait_command_buffer(struct wlr_vk_command_buffer *cb,
struct wlr_vk_renderer *renderer);
VkSemaphore vulkan_command_buffer_wait_sync_file(struct wlr_vk_renderer *renderer,
struct wlr_vk_command_buffer *render_cb, size_t sem_index, int sync_file_fd);
bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb,
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point);
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer,
struct wlr_vk_render_pass *pass);
bool vulkan_sync_foreign_texture_acquire(struct wlr_vk_texture *texture,
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
bool vulkan_sync_render_buffer_acquire(struct wlr_vk_render_buffer *render_buffer,
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
VkFormat src_format, VkImage src_image,
uint32_t drm_format, uint32_t stride,
uint32_t width, uint32_t height, uint32_t src_x, uint32_t src_y,
uint32_t dst_x, uint32_t dst_y, void *data);
uint32_t dst_x, uint32_t dst_y, void *data,
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point);
// State (e.g. image texture) associated with a surface.
struct wlr_vk_texture {
@ -453,13 +501,12 @@ struct wlr_vk_texture {
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
VkImage image;
const struct wlr_vk_format *format;
enum wlr_vk_texture_transform transform;
struct wlr_vk_command_buffer *last_used_cb; // to track when it can be destroyed
bool dmabuf_imported;
bool owned; // if dmabuf_imported: whether we have ownership of the image
bool transitioned; // if dma_imported: whether we transitioned it away from preinit
bool has_alpha; // whether the image is has alpha channel
bool using_mutable_srgb; // is this accessed through _SRGB format view
bool using_mutable_srgb; // can be accessed through _SRGB format view
struct wl_list foreign_link; // wlr_vk_renderer.foreign_textures
struct wl_list destroy_link; // wlr_vk_command_buffer.destroy_textures
struct wl_list link; // wlr_vk_renderer.textures
@ -468,7 +515,7 @@ struct wlr_vk_texture {
struct wlr_buffer *buffer;
struct wlr_addon buffer_addon;
struct wl_list views; // struct wlr_vk_texture_ds.link
struct wl_list views; // struct wlr_vk_texture_view.link
};
struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture);
@ -510,18 +557,23 @@ struct wlr_vk_buffer_span {
};
// Lookup table for a color transform
// Prepared form for a color transform
struct wlr_vk_color_transform {
struct wlr_addon addon; // owned by: wlr_vk_renderer
struct wl_list link; // wlr_vk_renderer, list of all color transforms
// if populated, carries the entire transform, other parameters are to be ignored
struct {
size_t dim;
VkImage image;
VkImageView image_view;
VkDeviceMemory memory;
VkDescriptorSet ds;
struct wlr_vk_descriptor_pool *ds_pool;
} lut_3d;
float color_matrix[9];
enum wlr_color_transfer_function inverse_eotf;
};
void vk_color_transform_destroy(struct wlr_addon *addon);

View file

@ -65,4 +65,10 @@ struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer,
bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer,
struct wlr_buffer *next, const pixman_region32_t *damage);
/**
* Return the DRM format of the buffer. If this buffer isn't shared
* memory or a DMA-BUF, returns DRM_FORMAT_INVALID.
*/
uint32_t buffer_get_drm_format(struct wlr_buffer *buffer);
#endif

View file

@ -8,6 +8,8 @@ void output_pending_resolution(struct wlr_output *output,
const struct wlr_output_state *state, int *width, int *height);
bool output_pending_enabled(struct wlr_output *output,
const struct wlr_output_state *state);
const struct wlr_output_image_description *output_pending_image_description(
struct wlr_output *output, const struct wlr_output_state *state);
bool output_pick_format(struct wlr_output *output,
const struct wlr_drm_format_set *display_formats,
@ -20,11 +22,14 @@ bool output_cursor_set_texture(struct wlr_output_cursor *cursor,
int dst_width, int dst_height, enum wl_output_transform transform,
int32_t hotspot_x, int32_t hotspot_y, struct wlr_drm_syncobj_timeline *wait_timeline,
uint64_t wait_point);
bool output_cursor_refresh_color_transform(struct wlr_output_cursor *cursor,
const struct wlr_output_image_description *img_desc);
void output_defer_present(struct wlr_output *output, struct wlr_output_event_present event);
bool output_prepare_commit(struct wlr_output *output, const struct wlr_output_state *state);
void output_apply_commit(struct wlr_output *output, const struct wlr_output_state *state);
void output_send_commit_event(struct wlr_output *output, const struct wlr_output_state *state);
void output_state_get_buffer_src_box(const struct wlr_output_state *state,
struct wlr_fbox *out);

View file

@ -5,6 +5,8 @@
struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height);
void scene_surface_set_clip(struct wlr_scene_surface *surface, struct wlr_box *clip);
#endif

14
include/util/mem.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef UTIL_MEM_H
#define UTIL_MEM_H
#include <stdbool.h>
#include <stddef.h>
/**
* Allocate a new block of memory and copy *src to it, then store the address
* of the new allocation in *out. Returns true if it worked, or false if
* allocation failed.
*/
bool memdup(void *out, const void *src, size_t size);
#endif // UTIL_MEM_H

View file

@ -39,8 +39,8 @@ struct wlr_drm_lease {
struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
struct wlr_device *dev, struct wlr_backend *parent);
bool wlr_backend_is_drm(struct wlr_backend *backend);
bool wlr_output_is_drm(struct wlr_output *output);
bool wlr_backend_is_drm(const struct wlr_backend *backend);
bool wlr_output_is_drm(const struct wlr_output *output);
/**
* Get the parent DRM backend, if any.

View file

@ -25,7 +25,7 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_event_loop *loop);
struct wlr_output *wlr_headless_add_output(struct wlr_backend *backend,
unsigned int width, unsigned int height);
bool wlr_backend_is_headless(struct wlr_backend *backend);
bool wlr_output_is_headless(struct wlr_output *output);
bool wlr_backend_is_headless(const struct wlr_backend *backend);
bool wlr_output_is_headless(const struct wlr_output *output);
#endif

View file

@ -15,6 +15,7 @@
#include <wlr/backend/session.h>
struct wlr_input_device;
struct wlr_tablet_tool;
struct wlr_backend *wlr_libinput_backend_create(struct wlr_session *session);
/**
@ -22,8 +23,13 @@ struct wlr_backend *wlr_libinput_backend_create(struct wlr_session *session);
*/
struct libinput_device *wlr_libinput_get_device_handle(
struct wlr_input_device *dev);
/**
* Gets the underlying struct libinput_tablet_tool handle for the given tablet tool.
*/
struct libinput_tablet_tool *wlr_libinput_get_tablet_tool_handle(
struct wlr_tablet_tool *wlr_tablet_tool);
bool wlr_backend_is_libinput(struct wlr_backend *backend);
bool wlr_backend_is_libinput(const struct wlr_backend *backend);
bool wlr_input_device_is_libinput(struct wlr_input_device *device);
#endif

View file

@ -26,7 +26,7 @@ bool wlr_multi_backend_add(struct wlr_backend *multi,
void wlr_multi_backend_remove(struct wlr_backend *multi,
struct wlr_backend *backend);
bool wlr_backend_is_multi(struct wlr_backend *backend);
bool wlr_backend_is_multi(const struct wlr_backend *backend);
bool wlr_multi_is_empty(struct wlr_backend *backend);
void wlr_multi_for_each_backend(struct wlr_backend *backend,

View file

@ -46,7 +46,7 @@ struct wlr_output *wlr_wl_output_create_from_surface(struct wlr_backend *backend
/**
* Check whether the provided backend is a Wayland backend.
*/
bool wlr_backend_is_wl(struct wlr_backend *backend);
bool wlr_backend_is_wl(const struct wlr_backend *backend);
/**
* Check whether the provided input device is a Wayland input device.
@ -56,7 +56,7 @@ bool wlr_input_device_is_wl(struct wlr_input_device *device);
/**
* Check whether the provided output device is a Wayland output device.
*/
bool wlr_output_is_wl(struct wlr_output *output);
bool wlr_output_is_wl(const struct wlr_output *output);
/**
* Sets the title of a struct wlr_output which is a Wayland toplevel.

View file

@ -31,7 +31,7 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend);
/**
* Check whether this backend is an X11 backend.
*/
bool wlr_backend_is_x11(struct wlr_backend *backend);
bool wlr_backend_is_x11(const struct wlr_backend *backend);
/**
* Check whether this input device is an X11 input device.
@ -41,7 +41,7 @@ bool wlr_input_device_is_x11(struct wlr_input_device *device);
/**
* Check whether this output device is an X11 output device.
*/
bool wlr_output_is_x11(struct wlr_output *output);
bool wlr_output_is_x11(const struct wlr_output *output);
/**
* Sets the title of a struct wlr_output which is an X11 window.

View file

@ -21,7 +21,7 @@ struct wlr_ext_image_capture_source_v1_interface {
// TODO: drop with_cursors flag
void (*start)(struct wlr_ext_image_capture_source_v1 *source, bool with_cursors);
void (*stop)(struct wlr_ext_image_capture_source_v1 *source);
void (*schedule_frame)(struct wlr_ext_image_capture_source_v1 *source);
void (*request_frame)(struct wlr_ext_image_capture_source_v1 *source, bool schedule_frame);
void (*copy_frame)(struct wlr_ext_image_capture_source_v1 *source,
struct wlr_ext_image_copy_capture_frame_v1 *dst_frame,
struct wlr_ext_image_capture_source_v1_frame_event *frame_event);

View file

@ -10,6 +10,7 @@
#define WLR_RENDER_COLOR_H
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
/**
@ -26,6 +27,60 @@ enum wlr_color_named_primaries {
enum wlr_color_transfer_function {
WLR_COLOR_TRANSFER_FUNCTION_SRGB = 1 << 0,
WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ = 1 << 1,
WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR = 1 << 2,
WLR_COLOR_TRANSFER_FUNCTION_GAMMA22 = 1 << 3,
WLR_COLOR_TRANSFER_FUNCTION_BT1886 = 1 << 4,
};
/**
* Specifies alpha blending modes. Note that premultiplied_electrical
* is the default, so there is no "none" or "unset" value.
*/
enum wlr_alpha_mode {
WLR_COLOR_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL,
WLR_COLOR_ALPHA_MODE_PREMULTIPLIED_OPTICAL,
WLR_COLOR_ALPHA_MODE_STRAIGHT,
};
/**
* Well-known color encodings, each representing a set of matrix coefficients
* used to convert that particular YCbCr encoding to RGB. NONE means the
* value is unset or unknown.
*/
enum wlr_color_encoding {
WLR_COLOR_ENCODING_NONE = 0,
WLR_COLOR_ENCODING_IDENTITY = 1 << 0,
WLR_COLOR_ENCODING_BT709 = 1 << 1,
WLR_COLOR_ENCODING_FCC = 1 << 2,
WLR_COLOR_ENCODING_BT601 = 1 << 3,
WLR_COLOR_ENCODING_SMPTE240 = 1 << 4,
WLR_COLOR_ENCODING_BT2020 = 1 << 5,
WLR_COLOR_ENCODING_BT2020_CL = 1 << 6,
WLR_COLOR_ENCODING_ICTCP = 1 << 7,
};
/**
* Specifies whether a particular color-encoding uses full- or limited-range
* values. NONE means the value is unset or unknown.
*/
enum wlr_color_range {
WLR_COLOR_RANGE_NONE,
WLR_COLOR_RANGE_LIMITED,
WLR_COLOR_RANGE_FULL,
};
/**
* Chroma sample locations, corresponding to Chroma420SampleLocType code
* points in H.273. NONE means the value is unset or unknown.
*/
enum wlr_color_chroma_location {
WLR_COLOR_CHROMA_LOCATION_NONE,
WLR_COLOR_CHROMA_LOCATION_TYPE0,
WLR_COLOR_CHROMA_LOCATION_TYPE1,
WLR_COLOR_CHROMA_LOCATION_TYPE2,
WLR_COLOR_CHROMA_LOCATION_TYPE3,
WLR_COLOR_CHROMA_LOCATION_TYPE4,
WLR_COLOR_CHROMA_LOCATION_TYPE5,
};
/**
@ -73,10 +128,31 @@ struct wlr_color_transform *wlr_color_transform_init_linear_to_icc(
const void *data, size_t size);
/**
* Initialize a color transformation to apply sRGB encoding.
* Returns NULL on failure.
* Initialize a color transformation to apply EOTF¹ encoding. Returns
* NULL on failure.
*/
struct wlr_color_transform *wlr_color_transform_init_srgb(void);
struct wlr_color_transform *wlr_color_transform_init_linear_to_inverse_eotf(
enum wlr_color_transfer_function tf);
/**
* Initialize a color transformation to apply three 1D look-up tables. dim
* is the number of elements in each individual LUT. Returns NULL on failure.
*/
struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim,
const uint16_t *r, const uint16_t *g, const uint16_t *b);
/**
* Initialize a color transformation to apply a 3×3 matrix. Returns NULL on
* failure.
*/
struct wlr_color_transform *wlr_color_transform_init_matrix(const float matrix[static 9]);
/**
* Initialize a color transformation to apply a sequence of color transforms
* one after another.
*/
struct wlr_color_transform *wlr_color_transform_init_pipeline(
struct wlr_color_transform **transforms, size_t len);
/**
* Increase the reference count of the color transform by 1.
@ -89,4 +165,23 @@ struct wlr_color_transform *wlr_color_transform_ref(struct wlr_color_transform *
*/
void wlr_color_transform_unref(struct wlr_color_transform *tr);
/**
* Evaluate a color transform for a given RGB triplet.
*/
void wlr_color_transform_eval(struct wlr_color_transform *tr,
float out[static 3], const float in[static 3]);
/**
* Obtain primaries values from a well-known primaries name.
*/
void wlr_color_primaries_from_named(struct wlr_color_primaries *out,
enum wlr_color_named_primaries named);
/**
* Compute the matrix to convert between two linear RGB color spaces
*/
void wlr_color_primaries_transform_absolute_colorimetric(
const struct wlr_color_primaries *source,
const struct wlr_color_primaries *destination, float matrix[static 9]);
#endif

View file

@ -90,10 +90,18 @@ bool wlr_drm_syncobj_timeline_transfer(struct wlr_drm_syncobj_timeline *dst,
*/
bool wlr_drm_syncobj_timeline_check(struct wlr_drm_syncobj_timeline *timeline,
uint64_t point, uint32_t flags, bool *result);
/**
* Signals a timeline point.
*/
bool wlr_drm_syncobj_timeline_signal(struct wlr_drm_syncobj_timeline *timeline, uint64_t point);
/**
* Asynchronously wait for a timeline point.
*
* See wlr_drm_syncobj_timeline_check() for a definition of flags.
* Flags can be:
*
* - 0 to wait for the point to be signalled
* - DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE to only wait for a fence to
* materialize
*
* A callback must be provided that will be invoked when the waiter has finished.
*/

View file

@ -42,9 +42,9 @@ struct wlr_gles2_texture_attribs {
bool has_alpha;
};
bool wlr_renderer_is_gles2(struct wlr_renderer *wlr_renderer);
bool wlr_render_timer_is_gles2(struct wlr_render_timer *timer);
bool wlr_texture_is_gles2(struct wlr_texture *texture);
bool wlr_renderer_is_gles2(const struct wlr_renderer *wlr_renderer);
bool wlr_render_timer_is_gles2(const struct wlr_render_timer *timer);
bool wlr_texture_is_gles2(const struct wlr_texture *texture);
void wlr_gles2_texture_get_attribs(struct wlr_texture *texture,
struct wlr_gles2_texture_attribs *attribs);

View file

@ -12,6 +12,7 @@
#include <pixman.h>
#include <stdint.h>
#include <wayland-server-core.h>
#include <wlr/render/color.h>
#include <wlr/util/box.h>
struct wlr_renderer;
@ -30,8 +31,9 @@ struct wlr_render_timer;
struct wlr_buffer_pass_options {
/* Timer to measure the duration of the render pass */
struct wlr_render_timer *timer;
/* Color transform to apply to the output of the render pass,
* leave NULL to indicate sRGB/no custom transform */
/* Color transform to apply to the output of the render pass.
* Leave NULL to indicate the default transform (Gamma 2.2 encoding for
* sRGB monitors) */
struct wlr_color_transform *color_transform;
/* Signal a timeline synchronization point when the render pass completes.
@ -99,6 +101,16 @@ struct wlr_render_texture_options {
enum wlr_scale_filter_mode filter_mode;
/* Blend mode */
enum wlr_render_blend_mode blend_mode;
/* Transfer function the source texture is encoded with */
enum wlr_color_transfer_function transfer_function;
/* Primaries describing the color volume of the source texture */
const struct wlr_color_primaries *primaries;
/* Color encoding of the source texture for YCbCr conversion to RGB */
enum wlr_color_encoding color_encoding;
/* Color range of the source texture */
enum wlr_color_range color_range;
/* Default: 1.0 */
const float *luminance_multiplier;
/* Wait for a timeline synchronization point before texturing.
*

View file

@ -14,8 +14,8 @@
struct wlr_renderer *wlr_pixman_renderer_create(void);
bool wlr_renderer_is_pixman(struct wlr_renderer *wlr_renderer);
bool wlr_texture_is_pixman(struct wlr_texture *texture);
bool wlr_renderer_is_pixman(const struct wlr_renderer *wlr_renderer);
bool wlr_texture_is_pixman(const struct wlr_texture *texture);
pixman_image_t *wlr_pixman_renderer_get_buffer_image(
struct wlr_renderer *wlr_renderer, struct wlr_buffer *wlr_buffer);

View file

@ -25,8 +25,8 @@ VkPhysicalDevice wlr_vk_renderer_get_physical_device(struct wlr_renderer *render
VkDevice wlr_vk_renderer_get_device(struct wlr_renderer *renderer);
uint32_t wlr_vk_renderer_get_queue_family(struct wlr_renderer *renderer);
bool wlr_renderer_is_vk(struct wlr_renderer *wlr_renderer);
bool wlr_texture_is_vk(struct wlr_texture *texture);
bool wlr_renderer_is_vk(const struct wlr_renderer *wlr_renderer);
bool wlr_texture_is_vk(const struct wlr_texture *texture);
void wlr_vk_texture_get_image_attribs(struct wlr_texture *texture,
struct wlr_vk_image_attribs *attribs);

View file

@ -29,6 +29,8 @@ struct wlr_renderer {
// Capabilities required for the buffer used as a render target (bitmask of
// enum wlr_buffer_cap)
uint32_t render_buffer_caps;
// Supported color encodings for YCbCr textures
uint32_t color_encodings; // bitmask of enum wlr_color_encoding
struct {
struct wl_signal destroy;
@ -41,6 +43,10 @@ struct wlr_renderer {
} events;
struct {
/**
* Whether color transforms are supported for input textures
*/
bool input_color_transform;
/**
* Does the renderer support color transforms on its output?
*/

View file

@ -37,6 +37,8 @@ struct wlr_texture_read_pixels_options {
uint32_t dst_x, dst_y;
/** Source box of the texture to read from. If empty, the full texture is assumed. */
const struct wlr_box src_box;
struct wlr_drm_syncobj_timeline *wait_timeline;
uint64_t wait_point;
};
bool wlr_texture_read_pixels(struct wlr_texture *texture,

View file

@ -9,11 +9,12 @@
#ifndef WLR_TYPES_WLR_COLOR_MANAGEMENT_V1_H
#define WLR_TYPES_WLR_COLOR_MANAGEMENT_V1_H
#include <wayland-server.h>
#include <wayland-server-core.h>
#include <wayland-protocols/color-management-v1-enum.h>
#include <wlr/render/color.h>
#include "color-management-v1-protocol.h"
struct wlr_renderer;
struct wlr_surface;
struct wlr_image_description_v1_data {
@ -58,6 +59,10 @@ struct wlr_color_manager_v1_options {
struct wlr_color_manager_v1 {
struct wl_global *global;
struct {
struct wl_signal destroy;
} events;
struct {
struct wlr_color_manager_v1_features features;
@ -73,7 +78,7 @@ struct wlr_color_manager_v1 {
struct wl_list outputs; // wlr_color_management_output_v1.link
struct wl_list surface_feedbacks; // wlr_color_management_surface_feedback_v1.link
uint32_t last_image_desc_identity;
uint64_t last_image_desc_identity;
struct wl_listener display_destroy;
} WLR_PRIVATE;
@ -89,4 +94,44 @@ void wlr_color_manager_v1_set_surface_preferred_image_description(
struct wlr_color_manager_v1 *manager, struct wlr_surface *surface,
const struct wlr_image_description_v1_data *data);
/**
* Convert a protocol transfer function to enum wlr_color_transfer_function.
* Aborts if there is no matching wlroots entry.
*/
enum wlr_color_transfer_function
wlr_color_manager_v1_transfer_function_to_wlr(enum wp_color_manager_v1_transfer_function tf);
/**
* Convert an enum wlr_color_transfer_function value into a protocol transfer function.
*/
enum wp_color_manager_v1_transfer_function
wlr_color_manager_v1_transfer_function_from_wlr(enum wlr_color_transfer_function tf);
/**
* Convert a protocol named primaries to enum wlr_color_named_primaries.
* Aborts if there is no matching wlroots entry.
*/
enum wlr_color_named_primaries
wlr_color_manager_v1_primaries_to_wlr(enum wp_color_manager_v1_primaries primaries);
/**
* Convert an enum wlr_color_named_primaries value into protocol primaries.
*/
enum wp_color_manager_v1_primaries
wlr_color_manager_v1_primaries_from_wlr(enum wlr_color_named_primaries primaries);
/**
* Get a list of supported transfer functions for a renderer. The caller is
* responsible for free'ing the array.
*/
enum wp_color_manager_v1_transfer_function *
wlr_color_manager_v1_transfer_function_list_from_renderer(struct wlr_renderer *renderer, size_t *len);
/**
* Get a list of supported named primaries for a renderer. The caller is
* responsible for free'ing the array.
*/
enum wp_color_manager_v1_primaries *
wlr_color_manager_v1_primaries_list_from_renderer(struct wlr_renderer *renderer, size_t *len);
#endif

View file

@ -0,0 +1,95 @@
/*
* This an unstable interface of wlroots. No guarantees are made regarding the
* future consistency of this API.
*/
#ifndef WLR_USE_UNSTABLE
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
#endif
#ifndef WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
#define WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
#include <wayland-server-core.h>
#include <wayland-protocols/color-representation-v1-enum.h>
#include <wlr/render/color.h>
struct wlr_surface;
struct wlr_renderer;
// Supported coefficients and range are always paired together
struct wlr_color_representation_v1_coeffs_and_range {
enum wp_color_representation_surface_v1_coefficients coeffs;
enum wp_color_representation_surface_v1_range range;
};
struct wlr_color_representation_manager_v1 {
struct wl_global *global;
struct {
// Manager is being destroyed
struct wl_signal destroy;
} events;
struct {
enum wp_color_representation_surface_v1_alpha_mode
*supported_alpha_modes;
size_t supported_alpha_modes_len;
struct wlr_color_representation_v1_coeffs_and_range
*supported_coeffs_and_ranges;
size_t supported_coeffs_and_ranges_len;
struct wl_listener display_destroy;
} WLR_PRIVATE;
};
// Options used when initialising a wlr_color_representation_manager_v1
struct wlr_color_representation_v1_options {
const enum wp_color_representation_surface_v1_alpha_mode *supported_alpha_modes;
size_t supported_alpha_modes_len;
const struct wlr_color_representation_v1_coeffs_and_range *supported_coeffs_and_ranges;
size_t supported_coeffs_and_ranges_len;
};
struct wlr_color_representation_manager_v1 *wlr_color_representation_manager_v1_create(
struct wl_display *display, uint32_t version,
const struct wlr_color_representation_v1_options *options);
struct wlr_color_representation_manager_v1 *wlr_color_representation_manager_v1_create_with_renderer(
struct wl_display *display, uint32_t version, struct wlr_renderer *renderer);
// This is all the color-representation state which can be attached to a
// surface, double-buffered and made current on commit
struct wlr_color_representation_v1_surface_state {
// The enum premultiplied_electrical has value zero and is defined
// to be the default if unspecified.
enum wp_color_representation_surface_v1_alpha_mode alpha_mode;
// If zero then indicates unset, otherwise values correspond to
// enum wp_color_representation_surface_v1_coefficients
uint32_t coefficients;
// If zero then indicates unset, otherwise values correspond to
// enum wp_color_representation_surface_v1_range
uint32_t range;
// If zero then indicates unset, otherwise values correspond to
// enum wp_color_representation_surface_v1_chroma_location
uint32_t chroma_location;
};
// Get the current color representation state committed to a surface
const struct wlr_color_representation_v1_surface_state *wlr_color_representation_v1_get_surface_state(
struct wlr_surface *surface);
enum wlr_alpha_mode wlr_color_representation_v1_alpha_mode_to_wlr(
enum wp_color_representation_surface_v1_alpha_mode wp_val);
enum wlr_color_encoding wlr_color_representation_v1_color_encoding_to_wlr(
enum wp_color_representation_surface_v1_coefficients wp_val);
enum wlr_color_range wlr_color_representation_v1_color_range_to_wlr(
enum wp_color_representation_surface_v1_range wp_val);
enum wlr_color_chroma_location wlr_color_representation_v1_chroma_location_to_wlr(
enum wp_color_representation_surface_v1_chroma_location wp_val);
#endif // WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H

View file

@ -10,7 +10,7 @@
#define WLR_TYPES_WLR_CONTENT_TYPE_V1_H
#include <wayland-server-core.h>
#include "content-type-v1-protocol.h"
#include <wayland-protocols/content-type-v1-enum.h>
struct wlr_surface;

View file

@ -49,30 +49,30 @@ struct wlr_cursor {
* your responsibility.
*/
struct {
struct wl_signal motion;
struct wl_signal motion_absolute;
struct wl_signal button;
struct wl_signal axis;
struct wl_signal motion; // struct wlr_pointer_motion_event
struct wl_signal motion_absolute; // struct wlr_pointer_motion_absolute_event
struct wl_signal button; // struct wlr_pointer_button_event
struct wl_signal axis; // struct wlr_pointer_axis_event
struct wl_signal frame;
struct wl_signal swipe_begin;
struct wl_signal swipe_update;
struct wl_signal swipe_end;
struct wl_signal pinch_begin;
struct wl_signal pinch_update;
struct wl_signal pinch_end;
struct wl_signal hold_begin;
struct wl_signal hold_end;
struct wl_signal swipe_begin; // struct wlr_pointer_swipe_begin_event
struct wl_signal swipe_update; // struct wlr_pointer_swipe_update_event
struct wl_signal swipe_end; // struct wlr_pointer_swipe_end_event
struct wl_signal pinch_begin; // struct wlr_pointer_pinch_begin_event
struct wl_signal pinch_update; // struct wlr_pointer_pinch_update_event
struct wl_signal pinch_end; // struct wlr_pointer_pinch_end_event
struct wl_signal hold_begin; // struct wlr_pointer_hold_begin_event
struct wl_signal hold_end; // struct wlr_pointer_hold_end_event
struct wl_signal touch_up;
struct wl_signal touch_down;
struct wl_signal touch_motion;
struct wl_signal touch_cancel;
struct wl_signal touch_up; // struct wlr_touch_up_event
struct wl_signal touch_down; // struct wlr_touch_down_event
struct wl_signal touch_motion; // struct wlr_touch_motion_event
struct wl_signal touch_cancel; // struct wlr_touch_cancel_event
struct wl_signal touch_frame;
struct wl_signal tablet_tool_axis;
struct wl_signal tablet_tool_proximity;
struct wl_signal tablet_tool_tip;
struct wl_signal tablet_tool_button;
struct wl_signal tablet_tool_axis; // struct wlr_tablet_tool_axis_event
struct wl_signal tablet_tool_proximity; // struct wlr_tablet_tool_proximity_event
struct wl_signal tablet_tool_tip; // struct wlr_tablet_tool_tip_event
struct wl_signal tablet_tool_button; // struct wlr_tablet_tool_button_event
} events;
void *data;

View file

@ -10,7 +10,7 @@
#define WLR_TYPES_WLR_CURSOR_SHAPE_V1_H
#include <wayland-server-core.h>
#include "cursor-shape-v1-protocol.h"
#include <wayland-protocols/cursor-shape-v1-enum.h>
/**
* Manager for the cursor-shape-v1 protocol.

View file

@ -12,6 +12,12 @@
#include <wayland-server-core.h>
#include <wlr/types/wlr_seat.h>
/**
* Deprecated: this protocol is legacy and superseded by ext-data-control-v1.
* The implementation will be dropped in a future wlroots version.
*
* Consider using `wlr_ext_data_control_manager_v1` as a replacement.
*/
struct wlr_data_control_manager_v1 {
struct wl_global *global;
struct wl_list devices; // wlr_data_control_device_v1.link

View file

@ -62,8 +62,6 @@ struct wlr_drm_lease_connector_v1 {
struct wlr_output *output;
struct wlr_drm_lease_device_v1 *device;
/** NULL if no client is currently leasing this connector */
struct wlr_drm_lease_v1 *active_lease;
struct wl_list link; // wlr_drm_lease_device_v1.connectors
@ -93,9 +91,6 @@ struct wlr_drm_lease_v1 {
struct wlr_drm_lease_device_v1 *device;
struct wlr_drm_lease_connector_v1 **connectors;
size_t n_connectors;
struct wl_list link; // wlr_drm_lease_device_v1.leases
void *data;

View file

@ -21,7 +21,9 @@ struct wlr_ext_data_control_manager_v1 {
struct wl_signal new_device; // wlr_ext_data_control_device_v1
} events;
struct wl_listener display_destroy;
struct {
struct wl_listener display_destroy;
} WLR_PRIVATE;
};
struct wlr_ext_data_control_device_v1 {
@ -33,9 +35,11 @@ struct wlr_ext_data_control_device_v1 {
struct wl_resource *selection_offer_resource; // current selection offer
struct wl_resource *primary_selection_offer_resource; // current primary selection offer
struct wl_listener seat_destroy;
struct wl_listener seat_set_selection;
struct wl_listener seat_set_primary_selection;
struct {
struct wl_listener seat_destroy;
struct wl_listener seat_set_selection;
struct wl_listener seat_set_primary_selection;
} WLR_PRIVATE;
};
struct wlr_ext_data_control_manager_v1 *wlr_ext_data_control_manager_v1_create(

View file

@ -13,6 +13,10 @@
#include <wayland-server-core.h>
#include <wlr/render/drm_format_set.h>
struct wlr_scene_node;
struct wlr_allocator;
struct wlr_renderer;
/**
* A screen capture source.
*
@ -79,6 +83,31 @@ struct wlr_ext_output_image_capture_source_manager_v1 {
} WLR_PRIVATE;
};
/**
* Interface exposing one screen capture source per foreign toplevel.
*/
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 {
struct wl_global *global;
struct {
struct wl_signal destroy;
struct wl_signal new_request; // struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request
} events;
struct {
struct wl_listener display_destroy;
} WLR_PRIVATE;
};
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request {
struct wlr_ext_foreign_toplevel_handle_v1 *toplevel_handle;
struct wl_client *client;
struct {
uint32_t new_id;
} WLR_PRIVATE;
};
/**
* Obtain a struct wlr_ext_image_capture_source_v1 from an ext_image_capture_source_v1
* resource.
@ -91,4 +120,23 @@ struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_from_res
struct wlr_ext_output_image_capture_source_manager_v1 *wlr_ext_output_image_capture_source_manager_v1_create(
struct wl_display *display, uint32_t version);
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(struct wl_display *display, uint32_t version);
bool wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request,
struct wlr_ext_image_capture_source_v1 *source);
struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_create_with_scene_node(
struct wlr_scene_node *node, struct wl_event_loop *event_loop,
struct wlr_allocator *allocator, struct wlr_renderer *renderer);
/**
* Returns the corresponding wlr_output for a image capture source
* managed by wlr_ext_output_image_capture_source_manager_v1
* or NULL if the image capture source is not managed by
* wlr_ext_output_image_capture_source_manager_v1.
*/
struct wlr_output *wlr_output_try_from_ext_image_capture_source_v1(struct wlr_ext_image_capture_source_v1 *source);
#endif

View file

@ -10,20 +10,42 @@
#define WLR_TYPES_WLR_EXT_IMAGE_COPY_CAPTURE_V1_H
#include <pixman.h>
#include <wayland-server.h>
#include <wayland-server-protocol.h>
#include <wayland-protocols/ext-image-copy-capture-v1-enum.h>
#include <time.h>
#include "ext-image-copy-capture-v1-protocol.h"
struct wlr_renderer;
struct wlr_ext_image_copy_capture_manager_v1 {
struct wl_global *global;
struct {
struct wl_signal new_session; // wlr_ext_image_copy_capture_session_v1
} events;
struct {
struct wl_listener display_destroy;
} WLR_PRIVATE;
};
struct wlr_ext_image_copy_capture_session_v1 {
struct wl_resource *resource;
struct wlr_ext_image_capture_source_v1 *source;
struct wlr_ext_image_copy_capture_frame_v1 *frame;
struct {
struct wl_signal destroy;
} events;
struct {
struct wl_listener source_destroy;
struct wl_listener source_constraints_update;
struct wl_listener source_frame;
pixman_region32_t damage;
} WLR_PRIVATE;
};
struct wlr_ext_image_copy_capture_frame_v1 {
struct wl_resource *resource;
bool capturing;

View file

@ -0,0 +1,144 @@
/*
* This an unstable interface of wlroots. No guarantees are made regarding the
* future consistency of this API.
*/
#ifndef WLR_USE_UNSTABLE
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
#endif
#ifndef WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
#define WLR_TYPES_WLR_EXT_WORKSPACE_V1_H
#include <wayland-server-core.h>
#include <wayland-protocols/ext-workspace-v1-enum.h>
struct wlr_output;
enum wlr_ext_workspace_v1_request_type {
WLR_EXT_WORKSPACE_V1_REQUEST_CREATE_WORKSPACE,
WLR_EXT_WORKSPACE_V1_REQUEST_ACTIVATE,
WLR_EXT_WORKSPACE_V1_REQUEST_DEACTIVATE,
WLR_EXT_WORKSPACE_V1_REQUEST_ASSIGN,
WLR_EXT_WORKSPACE_V1_REQUEST_REMOVE,
};
struct wlr_ext_workspace_v1_request {
enum wlr_ext_workspace_v1_request_type type;
struct wl_list link; // wlr_ext_workspace_manager_v1_resource.requests
union {
struct {
char *name;
struct wlr_ext_workspace_group_handle_v1 *group; // NULL if destroyed
} create_workspace;
struct {
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
} activate;
struct {
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
} deactivate;
struct {
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
struct wlr_ext_workspace_group_handle_v1 *group; // NULL if destroyed
} assign;
struct {
struct wlr_ext_workspace_handle_v1 *workspace; // NULL if destroyed
} remove;
};
};
struct wlr_ext_workspace_v1_commit_event {
struct wl_list *requests; // wlr_ext_workspace_v1_request.link
};
struct wlr_ext_workspace_manager_v1 {
struct wl_global *global;
struct wl_list groups; // wlr_ext_workspace_group_handle_v1.link
struct wl_list workspaces; // wlr_ext_workspace_handle_v1.link
struct {
struct wl_signal commit; // wlr_ext_workspace_v1_commit_event
struct wl_signal destroy;
} events;
void *data;
struct {
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
struct wl_event_source *idle_source;
struct wl_event_loop *event_loop;
struct wl_listener display_destroy;
} WLR_PRIVATE;
};
struct wlr_ext_workspace_group_handle_v1 {
struct wlr_ext_workspace_manager_v1 *manager;
uint32_t caps; // ext_workspace_group_handle_v1_group_capabilities
struct {
struct wl_signal destroy;
} events;
struct wl_list link; // wlr_ext_workspace_manager_v1.groups
void *data;
struct {
struct wl_list outputs; // wlr_ext_workspace_v1_group_output.link
struct wl_list resources; // wlr_ext_workspace_manager_v1_resource.link
} WLR_PRIVATE;
};
struct wlr_ext_workspace_handle_v1 {
struct wlr_ext_workspace_manager_v1 *manager;
struct wlr_ext_workspace_group_handle_v1 *group; // May be NULL
char *id;
char *name;
struct wl_array coordinates;
uint32_t caps; // ext_workspace_handle_v1_workspace_capabilities
uint32_t state; // ext_workspace_handle_v1_state
struct {
struct wl_signal destroy;
} events;
struct wl_list link; // wlr_ext_workspace_manager_v1.workspaces
void *data;
struct {
struct wl_list resources; // wlr_ext_workspace_v1_resource.link
} WLR_PRIVATE;
};
struct wlr_ext_workspace_manager_v1 *wlr_ext_workspace_manager_v1_create(
struct wl_display *display, uint32_t version);
struct wlr_ext_workspace_group_handle_v1 *wlr_ext_workspace_group_handle_v1_create(
struct wlr_ext_workspace_manager_v1 *manager, uint32_t caps);
void wlr_ext_workspace_group_handle_v1_destroy(
struct wlr_ext_workspace_group_handle_v1 *group);
void wlr_ext_workspace_group_handle_v1_output_enter(
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
void wlr_ext_workspace_group_handle_v1_output_leave(
struct wlr_ext_workspace_group_handle_v1 *group, struct wlr_output *output);
struct wlr_ext_workspace_handle_v1 *wlr_ext_workspace_handle_v1_create(
struct wlr_ext_workspace_manager_v1 *manager, const char *id, uint32_t caps);
void wlr_ext_workspace_handle_v1_destroy(struct wlr_ext_workspace_handle_v1 *workspace);
void wlr_ext_workspace_handle_v1_set_group(
struct wlr_ext_workspace_handle_v1 *workspace,
struct wlr_ext_workspace_group_handle_v1 *group);
void wlr_ext_workspace_handle_v1_set_name(
struct wlr_ext_workspace_handle_v1 *workspace, const char *name);
void wlr_ext_workspace_handle_v1_set_coordinates(
struct wlr_ext_workspace_handle_v1 *workspace,
const uint32_t *coords, size_t coords_len);
void wlr_ext_workspace_handle_v1_set_active(
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
void wlr_ext_workspace_handle_v1_set_urgent(
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
void wlr_ext_workspace_handle_v1_set_hidden(
struct wlr_ext_workspace_handle_v1 *workspace, bool enabled);
#endif

View file

@ -0,0 +1,28 @@
/*
* This an unstable interface of wlroots. No guarantees are made regarding the
* future consistency of this API.
*/
#ifndef WLR_USE_UNSTABLE
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
#endif
#ifndef WLR_TYPES_WLR_FIXES_H
#define WLR_TYPES_WLR_FIXES_H
#include <wayland-server-core.h>
struct wlr_fixes {
struct wl_global *global;
struct {
struct wl_signal destroy;
} events;
struct {
struct wl_listener display_destroy;
} WLR_PRIVATE;
};
struct wlr_fixes *wlr_fixes_create(struct wl_display *display, uint32_t version);
#endif

View file

@ -10,6 +10,11 @@ struct wlr_gamma_control_manager_v1 {
struct wl_global *global;
struct wl_list controls; // wlr_gamma_control_v1.link
// Fallback to use when an struct wlr_output doesn't support gamma LUTs.
// Can be used to apply gamma LUTs via a struct wlr_renderer. Leave zero to
// indicate that the fallback is unsupported.
size_t fallback_gamma_size;
struct {
struct wl_signal destroy;
struct wl_signal set_gamma; // struct wlr_gamma_control_manager_v1_set_gamma_event
@ -49,6 +54,8 @@ struct wlr_gamma_control_v1 *wlr_gamma_control_manager_v1_get_control(
struct wlr_gamma_control_manager_v1 *manager, struct wlr_output *output);
bool wlr_gamma_control_v1_apply(struct wlr_gamma_control_v1 *gamma_control,
struct wlr_output_state *output_state);
struct wlr_color_transform *wlr_gamma_control_v1_get_color_transform(
struct wlr_gamma_control_v1 *gamma_control);
void wlr_gamma_control_v1_send_failed_and_destroy(struct wlr_gamma_control_v1 *gamma_control);
#endif

View file

@ -48,10 +48,10 @@ struct wlr_input_method_v2 {
struct wl_list link;
struct {
struct wl_signal commit; // struct wlr_input_method_v2
struct wl_signal commit;
struct wl_signal new_popup_surface; // struct wlr_input_popup_surface_v2
struct wl_signal grab_keyboard; // struct wlr_input_method_keyboard_grab_v2
struct wl_signal destroy; // struct wlr_input_method_v2
struct wl_signal destroy;
} events;
struct {
@ -94,8 +94,8 @@ struct wlr_input_method_manager_v2 {
struct wl_list input_methods; // struct wlr_input_method_v2.link
struct {
struct wl_signal input_method; // struct wlr_input_method_v2
struct wl_signal destroy; // struct wlr_input_method_manager_v2
struct wl_signal new_input_method; // struct wlr_input_method_v2
struct wl_signal destroy;
} events;
struct {

View file

@ -16,12 +16,14 @@
#include <wlr/types/wlr_input_device.h>
#include <xkbcommon/xkbcommon.h>
#define WLR_LED_COUNT 3
#define WLR_LED_COUNT 5
enum wlr_keyboard_led {
WLR_LED_NUM_LOCK = 1 << 0,
WLR_LED_CAPS_LOCK = 1 << 1,
WLR_LED_SCROLL_LOCK = 1 << 2,
WLR_LED_COMPOSE = 1 << 3,
WLR_LED_KANA = 1 << 4,
};
#define WLR_MODIFIER_COUNT 8

View file

@ -19,8 +19,12 @@ struct wlr_linux_drm_syncobj_surface_v1_state {
struct wlr_drm_syncobj_timeline *acquire_timeline;
uint64_t acquire_point;
struct wlr_drm_syncobj_timeline *release_timeline;
uint64_t release_point;
struct {
bool committed;
struct wlr_drm_syncobj_timeline *release_timeline;
uint64_t release_point;
struct wlr_drm_syncobj_merger *release_merger;
} WLR_PRIVATE;
};
struct wlr_linux_drm_syncobj_manager_v1 {
@ -55,4 +59,19 @@ struct wlr_linux_drm_syncobj_surface_v1_state *wlr_linux_drm_syncobj_v1_get_surf
bool wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(
struct wlr_linux_drm_syncobj_surface_v1_state *state, struct wlr_buffer *buffer);
/**
* Register a release point for buffer usage.
*
* This function may be called multiple times for the same commit. The client's
* release point will be signalled when all registered points are signalled, and
* a new buffer has been committed.
*
* Because the given release point may not be materialized, a wl_event_loop must
* be supplied to schedule a wait internally, if needed
*/
bool wlr_linux_drm_syncobj_v1_state_add_release_point(
struct wlr_linux_drm_syncobj_surface_v1_state *state,
struct wlr_drm_syncobj_timeline *release_timeline, uint64_t release_point,
struct wl_event_loop *event_loop);
#endif

View file

@ -14,6 +14,7 @@
#include <time.h>
#include <wayland-server-protocol.h>
#include <wayland-util.h>
#include <wlr/render/color.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/util/addon.h>
@ -52,6 +53,7 @@ struct wlr_output_cursor {
struct {
struct wl_listener renderer_destroy;
struct wlr_color_transform *color_transform;
} WLR_PRIVATE;
};
@ -68,12 +70,14 @@ enum wlr_output_state_field {
WLR_OUTPUT_STATE_SCALE = 1 << 4,
WLR_OUTPUT_STATE_TRANSFORM = 1 << 5,
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED = 1 << 6,
WLR_OUTPUT_STATE_GAMMA_LUT = 1 << 7,
WLR_OUTPUT_STATE_RENDER_FORMAT = 1 << 8,
WLR_OUTPUT_STATE_SUBPIXEL = 1 << 9,
WLR_OUTPUT_STATE_LAYERS = 1 << 10,
WLR_OUTPUT_STATE_WAIT_TIMELINE = 1 << 11,
WLR_OUTPUT_STATE_SIGNAL_TIMELINE = 1 << 12,
WLR_OUTPUT_STATE_RENDER_FORMAT = 1 << 7,
WLR_OUTPUT_STATE_SUBPIXEL = 1 << 8,
WLR_OUTPUT_STATE_LAYERS = 1 << 9,
WLR_OUTPUT_STATE_WAIT_TIMELINE = 1 << 10,
WLR_OUTPUT_STATE_SIGNAL_TIMELINE = 1 << 11,
WLR_OUTPUT_STATE_COLOR_TRANSFORM = 1 << 12,
WLR_OUTPUT_STATE_IMAGE_DESCRIPTION = 1 << 13,
WLR_OUTPUT_STATE_COLOR_REPRESENTATION = 1 << 14,
};
enum wlr_output_state_mode_type {
@ -81,6 +85,30 @@ enum wlr_output_state_mode_type {
WLR_OUTPUT_STATE_MODE_CUSTOM,
};
/**
* Colorimetric image description.
*
* Carries information about the color encoding used for a struct wlr_buffer.
*
* Supported primaries are advertised in wlr_output.supported_primaries.
* Supported transfer functions are advertised in
* wlr_output.supported_transfer_functions.
*
* mastering_display_primaries, mastering_luminance, max_cll and max_fall are
* optional. Luminances are given in cd/m².
*/
struct wlr_output_image_description {
enum wlr_color_named_primaries primaries;
enum wlr_color_transfer_function transfer_function;
struct wlr_color_primaries mastering_display_primaries;
struct {
double min, max;
} mastering_luminance;
double max_cll; // max content light level
double max_fall; // max frame-average light level
};
/**
* Holds the double-buffered output state.
*/
@ -115,6 +143,10 @@ struct wlr_output_state {
* regular page-flip at the next wlr_output.frame event. */
bool tearing_page_flip;
// Set if (committed & WLR_OUTPUT_STATE_COLOR_REPRESENTATION)
enum wlr_color_encoding color_encoding;
enum wlr_color_range color_range;
enum wlr_output_state_mode_type mode_type;
struct wlr_output_mode *mode;
struct {
@ -122,9 +154,6 @@ struct wlr_output_state {
int32_t refresh; // mHz, may be zero
} custom_mode;
uint16_t *gamma_lut;
size_t gamma_lut_size;
struct wlr_output_layer_state *layers;
size_t layers_len;
@ -132,6 +161,10 @@ struct wlr_output_state {
uint64_t wait_point;
struct wlr_drm_syncobj_timeline *signal_timeline;
uint64_t signal_point;
struct wlr_color_transform *color_transform;
struct wlr_output_image_description *image_description;
};
struct wlr_output_impl;
@ -160,6 +193,7 @@ struct wlr_output {
char *description; // may be NULL
char *make, *model, *serial; // may be NULL
int32_t phys_width, phys_height; // mm
const struct wlr_color_primaries *default_primaries; // may be NULL
// Note: some backends may have zero modes
struct wl_list modes; // wlr_output_mode.link
@ -167,12 +201,18 @@ struct wlr_output {
int32_t width, height;
int32_t refresh; // mHz, may be zero
uint32_t supported_primaries; // bitfield of enum wlr_color_named_primaries
uint32_t supported_transfer_functions; // bitfield of enum wlr_color_transfer_function
bool enabled;
float scale;
enum wl_output_subpixel subpixel;
enum wl_output_transform transform;
enum wlr_output_adaptive_sync_status adaptive_sync_status;
uint32_t render_format;
enum wlr_color_encoding color_encoding;
enum wlr_color_range color_range;
const struct wlr_output_image_description *image_description;
// Indicates whether making changes to adaptive sync status is supported.
// If false, changes to adaptive sync status is guaranteed to fail. If
@ -235,6 +275,9 @@ struct wlr_output {
struct {
struct wl_listener display_destroy;
struct wlr_output_image_description image_description_value;
struct wlr_color_transform *color_transform;
struct wlr_color_primaries default_primaries_value;
} WLR_PRIVATE;
};
@ -245,13 +288,13 @@ struct wlr_output_event_damage {
struct wlr_output_event_precommit {
struct wlr_output *output;
struct timespec *when;
struct timespec when;
const struct wlr_output_state *state;
};
struct wlr_output_event_commit {
struct wlr_output *output;
struct timespec *when;
struct timespec when;
const struct wlr_output_state *state;
};
@ -527,17 +570,6 @@ void wlr_output_state_set_subpixel(struct wlr_output_state *state,
*/
void wlr_output_state_set_buffer(struct wlr_output_state *state,
struct wlr_buffer *buffer);
/**
* Sets the gamma table for an output. `r`, `g` and `b` are gamma ramps for
* red, green and blue. `size` is the length of the ramps and must not exceed
* the value returned by wlr_output_get_gamma_size().
*
* Providing zero-sized ramps resets the gamma table.
*
* This state will be applied once wlr_output_commit_state() is called.
*/
bool wlr_output_state_set_gamma_lut(struct wlr_output_state *state,
size_t ramp_size, const uint16_t *r, const uint16_t *g, const uint16_t *b);
/**
* Sets the damage region for an output. This is used as a hint to the backend
* and can be used to reduce power consumption or increase performance on some
@ -586,6 +618,28 @@ void wlr_output_state_set_wait_timeline(struct wlr_output_state *state,
*/
void wlr_output_state_set_signal_timeline(struct wlr_output_state *state,
struct wlr_drm_syncobj_timeline *timeline, uint64_t dst_point);
/**
* Set the color transform for an output.
*
* The color transform is applied after blending output layers.
*/
void wlr_output_state_set_color_transform(struct wlr_output_state *state,
struct wlr_color_transform *tr);
/**
* Set the colorimetry image description.
*/
bool wlr_output_state_set_image_description(struct wlr_output_state *state,
const struct wlr_output_image_description *image_desc);
/**
* Set the color encoding and range of the primary scanout buffer.
*
* Pass WLR_COLOR_ENCODING_NONE / WLR_COLOR_RANGE_NONE to reset to defaults.
*/
void wlr_output_state_set_color_encoding_and_range(
struct wlr_output_state *state,
enum wlr_color_encoding encoding, enum wlr_color_range range);
/**
* Copies the output state from src to dst. It is safe to then

View file

@ -11,10 +11,10 @@
#include <stdint.h>
#include <wayland-server-core.h>
#include <wayland-protocols/pointer-constraints-unstable-v1-enum.h>
#include <pixman.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_seat.h>
#include "pointer-constraints-unstable-v1-protocol.h"
struct wlr_seat;

View file

@ -43,6 +43,7 @@ struct wlr_scene_output_layout;
struct wlr_presentation;
struct wlr_linux_dmabuf_v1;
struct wlr_gamma_control_manager_v1;
struct wlr_color_manager_v1;
struct wlr_output_state;
typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)(
@ -102,11 +103,15 @@ struct wlr_scene {
// May be NULL
struct wlr_linux_dmabuf_v1 *linux_dmabuf_v1;
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
struct wlr_color_manager_v1 *color_manager_v1;
bool restack_xwayland_surfaces;
struct {
struct wl_listener linux_dmabuf_v1_destroy;
struct wl_listener gamma_control_manager_v1_destroy;
struct wl_listener gamma_control_manager_v1_set_gamma;
struct wl_listener color_manager_v1_destroy;
enum wlr_scene_debug_damage_option debug_damage_option;
bool direct_scanout;
@ -126,8 +131,6 @@ struct wlr_scene_surface {
struct wlr_addon addon;
struct wl_listener outputs_update;
struct wl_listener output_enter;
struct wl_listener output_leave;
struct wl_listener output_sample;
struct wl_listener frame_done;
struct wl_listener surface_destroy;
@ -150,6 +153,13 @@ struct wlr_scene_outputs_update_event {
struct wlr_scene_output_sample_event {
struct wlr_scene_output *output;
bool direct_scanout;
struct wlr_drm_syncobj_timeline *release_timeline;
uint64_t release_point;
};
struct wlr_scene_frame_done_event {
struct wlr_scene_output *output;
struct timespec when;
};
/** A scene-graph node displaying a buffer */
@ -161,10 +171,8 @@ struct wlr_scene_buffer {
struct {
struct wl_signal outputs_update; // struct wlr_scene_outputs_update_event
struct wl_signal output_enter; // struct wlr_scene_output
struct wl_signal output_leave; // struct wlr_scene_output
struct wl_signal output_sample; // struct wlr_scene_output_sample_event
struct wl_signal frame_done; // struct timespec
struct wl_signal frame_done; // struct wlr_scene_frame_done_event
} events;
// May be NULL
@ -173,8 +181,7 @@ struct wlr_scene_buffer {
/**
* The output that the largest area of this buffer is displayed on.
* This may be NULL if the buffer is not currently displayed on any
* outputs. This is the output that should be used for frame callbacks,
* presentation feedback, etc.
* outputs.
*/
struct wlr_scene_output *primary_output;
@ -184,6 +191,10 @@ struct wlr_scene_buffer {
int dst_width, dst_height;
enum wl_output_transform transform;
pixman_region32_t opaque_region;
enum wlr_color_transfer_function transfer_function;
enum wlr_color_named_primaries primaries;
enum wlr_color_encoding color_encoding;
enum wlr_color_range color_range;
struct {
uint64_t active_outputs;
@ -239,6 +250,11 @@ struct wlr_scene_output {
bool gamma_lut_changed;
struct wlr_gamma_control_v1 *gamma_lut;
struct wlr_color_transform *gamma_lut_color_transform;
struct wlr_color_transform *prev_gamma_lut_color_transform;
struct wlr_color_transform *prev_supplied_color_transform;
struct wlr_color_transform *combined_color_transform;
struct wl_listener output_commit;
struct wl_listener output_damage;
@ -250,6 +266,8 @@ struct wlr_scene_output {
struct wlr_drm_syncobj_timeline *in_timeline;
uint64_t in_point;
struct wlr_drm_syncobj_timeline *out_timeline;
uint64_t out_point;
} WLR_PRIVATE;
};
@ -356,6 +374,13 @@ void wlr_scene_set_linux_dmabuf_v1(struct wlr_scene *scene,
void wlr_scene_set_gamma_control_manager_v1(struct wlr_scene *scene,
struct wlr_gamma_control_manager_v1 *gamma_control);
/**
* Handles color_management_v1 feedback for all surfaces in the scene.
*
* Asserts that a struct wlr_color_manager_v1 hasn't already been set for the scene.
*/
void wlr_scene_set_color_manager_v1(struct wlr_scene *scene, struct wlr_color_manager_v1 *manager);
/**
* Add a node displaying nothing but its children.
*/
@ -416,6 +441,12 @@ struct wlr_scene_rect *wlr_scene_rect_from_node(struct wlr_scene_node *node);
struct wlr_scene_surface *wlr_scene_surface_try_from_buffer(
struct wlr_scene_buffer *scene_buffer);
/**
* Call wlr_surface_send_frame_done() if the surface is visible.
*/
void wlr_scene_surface_send_frame_done(struct wlr_scene_surface *scene_surface,
const struct timespec *when);
/**
* Add a node displaying a solid-colored rectangle to the scene-graph.
*
@ -527,11 +558,23 @@ void wlr_scene_buffer_set_opacity(struct wlr_scene_buffer *scene_buffer,
void wlr_scene_buffer_set_filter_mode(struct wlr_scene_buffer *scene_buffer,
enum wlr_scale_filter_mode filter_mode);
void wlr_scene_buffer_set_transfer_function(struct wlr_scene_buffer *scene_buffer,
enum wlr_color_transfer_function transfer_function);
void wlr_scene_buffer_set_primaries(struct wlr_scene_buffer *scene_buffer,
enum wlr_color_named_primaries primaries);
void wlr_scene_buffer_set_color_encoding(struct wlr_scene_buffer *scene_buffer,
enum wlr_color_encoding encoding);
void wlr_scene_buffer_set_color_range(struct wlr_scene_buffer *scene_buffer,
enum wlr_color_range range);
/**
* Calls the buffer's frame_done signal.
*/
void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer,
struct timespec *now);
struct wlr_scene_frame_done_event *event);
/**
* Add a viewport for the specified output to the scene-graph.
@ -552,6 +595,11 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
struct wlr_scene_output_state_options {
struct wlr_scene_timer *timer;
/**
* Color transform to apply before the output's color transform. Cannot be
* used when the output has a non-NULL image description set.
*/
struct wlr_color_transform *color_transform;
/**

View file

@ -14,6 +14,13 @@
#include <wlr/types/wlr_buffer.h>
#include <wlr/util/box.h>
/**
* Deprecated: this protocol is deprecated and superseded by ext-image-copy-capture-v1.
* The implementation will be dropped in a future wlroots version.
*
* Consider using `wlr_ext_image_capture_source_v1` instead.
*/
struct wlr_screencopy_manager_v1 {
struct wl_global *global;
struct wl_list frames; // wlr_screencopy_frame_v1.link

View file

@ -140,6 +140,8 @@ struct wlr_touch_grab_interface {
// Send wl_touch.cancel
void (*wl_cancel)(struct wlr_seat_touch_grab *grab,
struct wlr_seat_client *seat_client);
void (*clear_focus)(struct wlr_seat_touch_grab *grab, uint32_t time_msec,
struct wlr_touch_point *point);
};
/**
@ -685,6 +687,8 @@ void wlr_seat_touch_notify_cancel(struct wlr_seat *seat,
struct wlr_seat_client *seat_client);
void wlr_seat_touch_notify_frame(struct wlr_seat *seat);
void wlr_seat_touch_notify_clear_focus(struct wlr_seat *seat,
uint32_t time_msec, int32_t touch_id);
/**
* How many touch points are currently down for the seat.

View file

@ -36,6 +36,7 @@ struct wlr_switch {
enum wlr_switch_type {
WLR_SWITCH_TYPE_LID,
WLR_SWITCH_TYPE_TABLET_MODE,
WLR_SWITCH_TYPE_KEYPAD_SLIDE,
};
enum wlr_switch_state {

View file

@ -10,10 +10,9 @@
#define WLR_TYPES_WLR_TABLET_V2_H
#include <wayland-server-core.h>
#include <wayland-protocols/tablet-v2-enum.h>
#include <wlr/types/wlr_seat.h>
#include "tablet-v2-protocol.h"
/* This can probably be even lower,the tools don't have a lot of buttons */
#define WLR_TABLET_V2_TOOL_BUTTONS_CAP 16

View file

@ -11,11 +11,9 @@
#include <stdint.h>
#include <wayland-server-core.h>
#include <wayland-server-protocol.h>
#include <wayland-protocols/tearing-control-v1-enum.h>
#include <wlr/types/wlr_compositor.h>
#include "tearing-control-v1-protocol.h"
struct wlr_tearing_control_v1 {
struct wl_client *client;
struct wl_list link;

View file

@ -57,10 +57,10 @@ struct wlr_text_input_v3 {
struct wl_list link;
struct {
struct wl_signal enable; // struct wlr_text_input_v3
struct wl_signal commit; // struct wlr_text_input_v3
struct wl_signal disable; // struct wlr_text_input_v3
struct wl_signal destroy; // struct wlr_text_input_v3
struct wl_signal enable;
struct wl_signal commit;
struct wl_signal disable;
struct wl_signal destroy;
} events;
struct {
@ -74,8 +74,8 @@ struct wlr_text_input_manager_v3 {
struct wl_list text_inputs; // wlr_text_input_v3.link
struct {
struct wl_signal text_input; // struct wlr_text_input_v3
struct wl_signal destroy; // struct wlr_text_input_manager_v3
struct wl_signal new_text_input; // struct wlr_text_input_v3
struct wl_signal destroy;
} events;
struct {

View file

@ -33,12 +33,27 @@ struct wlr_virtual_keyboard_v1 {
bool has_keymap;
struct wl_list link; // wlr_virtual_keyboard_manager_v1.virtual_keyboards
struct {
struct wl_listener seat_destroy;
} WLR_PRIVATE;
};
struct wlr_virtual_keyboard_manager_v1* wlr_virtual_keyboard_manager_v1_create(
struct wl_display *display);
/**
* Get the struct wlr_virtual_keyboard_v1 corresponding to a zwp_virtual_keyboard_v1 resource.
*
* Asserts that the resource is a valid zwp_virtual_keyboard_v1 resource created by wlroots.
*
* Returns NULL if the resource is inert.
*/
struct wlr_virtual_keyboard_v1 *wlr_virtual_keyboard_v1_from_resource(
struct wl_resource *resource);
struct wlr_virtual_keyboard_v1 *wlr_input_device_get_virtual_keyboard(
struct wlr_input_device *wlr_dev);
#endif

View file

@ -10,10 +10,10 @@
#define WLR_TYPES_WLR_XDG_SHELL_H
#include <wayland-server-core.h>
#include <wayland-protocols/xdg-shell-enum.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/util/box.h>
#include "xdg-shell-protocol.h"
struct wlr_xdg_shell {
struct wl_global *global;
@ -141,6 +141,7 @@ enum wlr_xdg_surface_role {
struct wlr_xdg_toplevel_state {
bool maximized, fullscreen, resizing, activated, suspended;
uint32_t tiled; // enum wlr_edges
uint32_t constrained; // enum wlr_edges
int32_t width, height;
int32_t max_width, max_height;
int32_t min_width, min_height;
@ -168,6 +169,7 @@ struct wlr_xdg_toplevel_configure {
// The following fields must always be set to reflect the current state
bool maximized, fullscreen, resizing, activated, suspended;
uint32_t tiled; // enum wlr_edges
uint32_t constrained; // enum wlr_edges
int32_t width, height;
// Only for WLR_XDG_TOPLEVEL_CONFIGURE_BOUNDS
@ -454,6 +456,14 @@ uint32_t wlr_xdg_toplevel_set_wm_capabilities(struct wlr_xdg_toplevel *toplevel,
uint32_t wlr_xdg_toplevel_set_suspended(struct wlr_xdg_toplevel *toplevel,
bool suspended);
/**
* Request that this toplevel consider itself constrained and doesn't attempt to
* resize from some edges. `constrained_edges` is a bitfield of enum wlr_edges.
* Returns the associated configure serial.
*/
uint32_t wlr_xdg_toplevel_set_constrained(struct wlr_xdg_toplevel *toplevel,
uint32_t constrained_edges);
/**
* Request that this toplevel closes.
*/

View file

@ -0,0 +1,41 @@
/*
* This an unstable interface of wlroots. No guarantees are made regarding the
* future consistency of this API.
*/
#ifndef WLR_USE_UNSTABLE
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
#endif
#ifndef WLR_TYPES_WLR_XDG_TOPLEVEL_TAG_V1_H
#define WLR_TYPES_WLR_XDG_TOPLEVEL_TAG_V1_H
#include <wayland-server-core.h>
struct wlr_xdg_toplevel_tag_manager_v1 {
struct wl_global *global;
struct {
struct wl_signal set_tag; // struct wlr_xdg_toplevel_tag_manager_v1_set_tag_event
struct wl_signal set_description; // struct wlr_xdg_toplevel_tag_manager_v1_set_description_event
struct wl_signal destroy;
} events;
struct {
struct wl_listener display_destroy;
} WLR_PRIVATE;
};
struct wlr_xdg_toplevel_tag_manager_v1_set_tag_event {
struct wlr_xdg_toplevel *toplevel;
const char *tag;
};
struct wlr_xdg_toplevel_tag_manager_v1_set_description_event {
struct wlr_xdg_toplevel *toplevel;
const char *description;
};
struct wlr_xdg_toplevel_tag_manager_v1 *wlr_xdg_toplevel_tag_manager_v1_create(
struct wl_display *display, uint32_t version);
#endif

View file

@ -107,6 +107,13 @@ void wlr_fbox_transform(struct wlr_fbox *dest, const struct wlr_fbox *box,
#ifdef WLR_USE_UNSTABLE
/**
* Checks whether two boxes intersect.
*
* Returns false if either box is empty.
*/
bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b);
/**
* Returns true if the two boxes are equal, false otherwise.
*/

View file

@ -9,4 +9,9 @@
#define WLR_VERSION_NUM ((WLR_VERSION_MAJOR << 16) | (WLR_VERSION_MINOR << 8) | WLR_VERSION_MICRO)
/* For runtime version detection */
int wlr_version_get_major(void);
int wlr_version_get_minor(void);
int wlr_version_get_micro(void);
#endif

View file

@ -47,7 +47,7 @@
/**
* A still cursor image.
*
* The buffer contains pixels layed out in a packed DRM_FORMAT_ARGB8888 format.
* The buffer contains pixels laid out in a packed DRM_FORMAT_ARGB8888 format.
*/
struct wlr_xcursor_image {
uint32_t width; /* actual width */
@ -56,6 +56,10 @@ struct wlr_xcursor_image {
uint32_t hotspot_y; /* hot-spot y (must be inside image) */
uint32_t delay; /* animation delay to next frame (ms) */
uint8_t *buffer; /* pixel data */
struct {
struct wlr_readonly_data_buffer *readonly_buffer;
} WLR_PRIVATE;
};
/**
@ -119,6 +123,11 @@ struct wlr_xcursor *wlr_xcursor_theme_get_cursor(
*/
int wlr_xcursor_frame(struct wlr_xcursor *cursor, uint32_t time);
/**
* Get a struct wlr_buffer from a cursor image.
*/
struct wlr_buffer *wlr_xcursor_image_get_buffer(struct wlr_xcursor_image *image);
/**
* Get the name of the resize cursor for the given edges.
*/

View file

@ -17,6 +17,7 @@
#include <wlr/util/addon.h>
struct wlr_box;
struct wlr_buffer;
struct wlr_xwm;
struct wlr_data_source;
struct wlr_drag;
@ -41,7 +42,6 @@ struct wlr_xwayland {
bool own_server;
struct wlr_xwm *xwm;
struct wlr_xwayland_shell_v1 *shell_v1;
struct wlr_xwayland_cursor *cursor;
// Value the DISPLAY environment variable should be set to by the compositor
const char *display_name;
@ -67,6 +67,11 @@ struct wlr_xwayland {
void *data;
struct {
struct wlr_buffer *cursor_buffer;
struct {
int32_t x, y;
} cursor_hotspot;
struct wl_listener server_start;
struct wl_listener server_ready;
struct wl_listener server_destroy;
@ -146,7 +151,6 @@ struct wlr_xwayland_surface {
char *role;
char *startup_id;
pid_t pid;
bool has_utf8_title;
struct wl_list children; // wlr_xwayland_surface.parent_link
struct wlr_xwayland_surface *parent;
@ -217,11 +221,13 @@ struct wlr_xwayland_surface {
struct wl_signal set_startup_id;
struct wl_signal set_window_type;
struct wl_signal set_hints;
struct wl_signal set_size_hints;
struct wl_signal set_decorations;
struct wl_signal set_strut_partial;
struct wl_signal set_override_redirect;
struct wl_signal set_geometry;
struct wl_signal set_opacity;
struct wl_signal set_icon;
struct wl_signal focus_in;
struct wl_signal grab_focus;
/* can be used to set initial maximized/fullscreen geometry */
@ -279,8 +285,7 @@ struct wlr_xwayland *wlr_xwayland_create_with_server(struct wl_display *display,
void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland);
void wlr_xwayland_set_cursor(struct wlr_xwayland *wlr_xwayland,
uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height,
int32_t hotspot_x, int32_t hotspot_y);
struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y);
void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *surface,
bool activated);
@ -402,6 +407,15 @@ enum wlr_xwayland_icccm_input_model wlr_xwayland_surface_icccm_input_model(
void wlr_xwayland_set_workareas(struct wlr_xwayland *wlr_xwayland,
const struct wlr_box *workareas, size_t num_workareas);
/**
* Fetches the icon set via the _NET_WM_ICON property.
*
* Returns true on success. The caller is responsible for freeing the reply
* using xcb_ewmh_get_wm_icon_reply_wipe().
*/
bool wlr_xwayland_surface_fetch_icon(
const struct wlr_xwayland_surface *xsurface,
xcb_ewmh_get_wm_icon_reply_t *icon_reply);
/**
* Get the XCB connection of the XWM.

View file

@ -82,9 +82,9 @@ void xwm_handle_selection_notify(struct wlr_xwm *xwm,
xcb_selection_notify_event_t *event);
int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
xcb_xfixes_selection_notify_event_t *event);
bool data_source_is_xwayland(struct wlr_data_source *wlr_source);
bool data_source_is_xwayland(const struct wlr_data_source *wlr_source);
bool primary_selection_source_is_xwayland(
struct wlr_primary_selection_source *wlr_source);
const struct wlr_primary_selection_source *wlr_source);
void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag);

View file

@ -36,6 +36,7 @@ enum atom_name {
NET_WM_STATE,
NET_WM_STRUT_PARTIAL,
NET_WM_WINDOW_TYPE,
NET_WM_ICON,
WM_TAKE_FOCUS,
WINDOW,
NET_ACTIVE_WINDOW,
@ -115,6 +116,7 @@ struct wlr_xwm {
xcb_connection_t *xcb_conn;
xcb_screen_t *screen;
xcb_window_t window;
xcb_window_t no_focus_window;
xcb_visualid_t visual_id;
xcb_colormap_t colormap;
xcb_render_pictformat_t render_format_id;
@ -162,12 +164,13 @@ struct wlr_xwm {
struct wl_listener drop_focus_destroy;
};
// xwm_create takes ownership of wm_fd and will close it under all circumstances.
struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd);
void xwm_destroy(struct wlr_xwm *xwm);
void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride,
uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y);
void xwm_set_cursor(struct wlr_xwm *xwm, struct wlr_buffer *buffer,
int32_t hotspot_x, int32_t hotspot_y);
int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event);
int xwm_handle_selection_client_message(struct wlr_xwm *xwm,

View file

@ -1,7 +1,7 @@
project(
'wlroots',
'c',
version: '0.19.0',
version: '0.21.0-dev',
license: 'MIT',
meson_version: '>=1.3',
default_options: [
@ -86,7 +86,7 @@ internal_features = {
internal_config = configuration_data()
wayland_kwargs = {
'version': '>=1.23.1',
'version': '>=1.24.0',
'fallback': 'wayland',
'default_options': [
'tests=false',
@ -98,15 +98,15 @@ wayland_server = dependency('wayland-server',
)
drm = dependency('libdrm',
version: '>=2.4.122',
version: '>=2.4.129',
fallback: 'libdrm',
default_options: [
'auto_features=disabled',
'tests=false',
],
)
xkbcommon = dependency(
'xkbcommon',
xkbcommon = dependency('xkbcommon',
version: '>=1.8.0',
fallback: 'libxkbcommon',
default_options: [
'enable-tools=false',
@ -178,6 +178,10 @@ if get_option('examples')
subdir('tinywl')
endif
if get_option('tests')
subdir('test')
endif
pkgconfig = import('pkgconfig')
pkgconfig.generate(
lib_wlr,

View file

@ -7,5 +7,6 @@ option('backends', type: 'array', choices: ['auto', 'drm', 'libinput', 'x11'], v
option('allocators', type: 'array', choices: ['auto', 'gbm', 'udmabuf'], value: ['auto'],
description: 'Select built-in allocators')
option('session', type: 'feature', value: 'auto', description: 'Enable session support')
option('tests', type: 'boolean', value: true, description: 'Build tests and benchmarks')
option('color-management', type: 'feature', value: 'auto', description: 'Enable support for color management')
option('libliftoff', type: 'feature', value: 'auto', description: 'Enable support for libliftoff')

View file

@ -82,7 +82,7 @@
This event serves the purpose of providing the compositor with an
active input method.
This event resets all state associated with previous enable, disable,
This event resets all state associated with previous
surrounding_text, text_change_cause, and content_type events, as well
as the state associated with set_preedit_string, commit_string, and
delete_surrounding_text requests. In addition, it marks the
@ -120,7 +120,7 @@
If any preedit text is present, it is replaced with the cursor for the
purpose of this event.
The argument text is a buffer containing the preedit string, and must
The argument text is a buffer containing the surrounding text, and must
include the cursor position, and the complete selection. It should
contain additional characters before and after these. There is a
maximum length of wayland messages, so text can not be longer than 4000

View file

@ -1,9 +1,10 @@
wayland_protos = dependency('wayland-protocols',
version: '>=1.41',
version: '>=1.47',
fallback: 'wayland-protocols',
default_options: ['tests=false'],
)
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
wlr_deps += wayland_protos
wayland_scanner_dep = dependency('wayland-scanner',
kwargs: wayland_kwargs,
@ -25,6 +26,7 @@ protocols = {
# Staging upstream protocols
'alpha-modifier-v1': wl_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
'color-management-v1': wl_protocol_dir / 'staging/color-management/color-management-v1.xml',
'color-representation-v1': wl_protocol_dir / 'staging/color-representation/color-representation-v1.xml',
'content-type-v1': wl_protocol_dir / 'staging/content-type/content-type-v1.xml',
'cursor-shape-v1': wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
'drm-lease-v1': wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
@ -34,6 +36,7 @@ protocols = {
'ext-image-copy-capture-v1': wl_protocol_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml',
'ext-session-lock-v1': wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
'ext-data-control-v1': wl_protocol_dir / 'staging/ext-data-control/ext-data-control-v1.xml',
'ext-workspace-v1': wl_protocol_dir / 'staging/ext-workspace/ext-workspace-v1.xml',
'fractional-scale-v1': wl_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
'linux-drm-syncobj-v1': wl_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',
'security-context-v1': wl_protocol_dir / 'staging/security-context/security-context-v1.xml',
@ -42,6 +45,7 @@ protocols = {
'xdg-dialog-v1': wl_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
'xdg-system-bell-v1': wl_protocol_dir / 'staging/xdg-system-bell/xdg-system-bell-v1.xml',
'xdg-toplevel-icon-v1': wl_protocol_dir / 'staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml',
'xdg-toplevel-tag-v1': wl_protocol_dir / 'staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml',
'xwayland-shell-v1': wl_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
'tearing-control-v1': wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',

View file

@ -43,7 +43,7 @@
<request name="capture_output">
<description summary="capture a frame from an output">
Capture the next frame of a an entire output.
Capture the next frame of an entire output.
</description>
<arg name="frame" type="new_id" interface="zwlr_export_dmabuf_frame_v1"/>
<arg name="overlay_cursor" type="int"
@ -136,7 +136,7 @@
<arg name="stride" type="uint"
summary="line size in bytes"/>
<arg name="plane_index" type="uint"
summary="index of the the plane the data in the object applies to"/>
summary="index of the plane the data in the object applies to"/>
</event>
<event name="ready">
@ -192,7 +192,7 @@
<request name="destroy" type="destructor">
<description summary="delete this object, used or not">
Unreferences the frame. This request must be called as soon as its no
Unreferences the frame. This request must be called as soon as it's no
longer used.
It can be called at any time by the client. The client will still have

View file

@ -58,7 +58,7 @@
</description>
</request>
<event name="finished">
<event name="finished" type="destructor">
<description summary="the compositor has finished with the toplevel manager">
This event indicates that the compositor is done sending events to the
zwlr_foreign_toplevel_manager_v1. The server will destroy the object

View file

@ -72,7 +72,7 @@
tables. At any time the compositor can send a failed event indicating that
this object is no longer valid.
There must always be at most one gamma control object per output, which
There can only be at most one gamma control object per output, which
has exclusive access to this particular output. When the gamma control
object is destroyed, the gamma table is restored to its original value.
</description>

View file

@ -156,8 +156,8 @@
not assume that the name is a reflection of an underlying DRM
connector, X11 connection, etc.
If the compositor implements the xdg-output protocol and this head is
enabled, the xdg_output.name event must report the same name.
If this head matches a wl_output, the wl_output.name event must report
the same name.
The name event is sent after a wlr_output_head object is created. This
event is only sent once per object, and the name does not change over
@ -176,8 +176,8 @@
the make, model, serial of the underlying DRM connector or the display
name of the underlying X11 connection, etc.
If the compositor implements xdg-output and this head is enabled,
the xdg_output.description must report the same description.
If this head matches a wl_output, the wl_output.description event must
report the same name.
The description event is sent after a wlr_output_head object is created.
This event is only sent once per object, and the description does not
@ -191,6 +191,10 @@
This event describes the physical size of the head. This event is only
sent if the head has a physical size (e.g. is not a projector or a
virtual device).
The physical size event is sent after a wlr_output_head object is created. This
event is only sent once per object, and the physical size does not change over
the lifetime of the wlr_output_head object.
</description>
<arg name="width" type="int" summary="width in millimeters of the output"/>
<arg name="height" type="int" summary="height in millimeters of the output"/>
@ -264,9 +268,6 @@
<description summary="head manufacturer">
This event describes the manufacturer of the head.
This must report the same make as the wl_output interface does in its
geometry event.
Together with the model and serial_number events the purpose is to
allow clients to recognize heads from previous sessions and for example
load head-specific configurations back.
@ -278,6 +279,10 @@
identify the head by available information from other events but should
be aware that there is an increased risk of false positives.
If sent, the make event is sent after a wlr_output_head object is
created and only sent once per object. The make does not change over
the lifetime of the wlr_output_head object.
It is not recommended to display the make string in UI to users. For
that the string provided by the description event should be preferred.
</description>
@ -288,9 +293,6 @@
<description summary="head model">
This event describes the model of the head.
This must report the same model as the wl_output interface does in its
geometry event.
Together with the make and serial_number events the purpose is to
allow clients to recognize heads from previous sessions and for example
load head-specific configurations back.
@ -302,6 +304,10 @@
identify the head by available information from other events but should
be aware that there is an increased risk of false positives.
If sent, the model event is sent after a wlr_output_head object is
created and only sent once per object. The model does not change over
the lifetime of the wlr_output_head object.
It is not recommended to display the model string in UI to users. For
that the string provided by the description event should be preferred.
</description>
@ -323,6 +329,10 @@
available information from other events but should be aware that there
is an increased risk of false positives.
If sent, the serial number event is sent after a wlr_output_head object
is created and only sent once per object. The serial number does not
change over the lifetime of the wlr_output_head object.
It is not recommended to display the serial_number string in UI to
users. For that the string provided by the description event should be
preferred.

View file

@ -50,7 +50,7 @@
<request name="get_output_power">
<description summary="get a power management for an output">
Create a output power management mode control that can be used to
Create an output power management mode control that can be used to
adjust the power management mode for a given output.
</description>
<arg name="id" type="new_id" interface="zwlr_output_power_v1"/>
@ -79,7 +79,7 @@
</enum>
<enum name="error">
<entry name="invalid_mode" value="1" summary="inexistent power save mode"/>
<entry name="invalid_mode" value="1" summary="nonexistent power save mode"/>
</enum>
<request name="set_mode">

Some files were not shown because too many files have changed in this diff Show more