Commit graph

668 commits

Author SHA1 Message Date
Derek Foreman
01b7e9d015 compositor: store frame flags from finish frame
These are used to determine if the previous frame was displayed with
tearing, which is useful in determining when the next frame time should
be.

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

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

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

We currently chose the mode's native refresh rate.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-16 10:21:43 -06:00
Derek Foreman
cb97abd4f7 compositor: Add the fifo-v1 protocol
Add support for the fifo protocol, which allows an application to submit
a content update that can only be applied after the previous content
update has been active for a display refresh.

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

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

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

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

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

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

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

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

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

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

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

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

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

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-12-04 12:38:17 -06:00
Derek Foreman
b44cf1b6af animation: Change how we seed the initial time
With the addition of the weston_output_set_ready() call, the shell fade
animation is now started during the very first repaint. The first repaint
doesn't have an accurate frame_time for the previous repaint, as none has
occurred yet.

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

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

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

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

fixes #1072

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

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

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

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

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

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-11-19 15:47:13 +02:00
Pekka Paalanen
d69e816b54 compositor: fix finish_frame presentation feedback crash
This was brought up in issue 1063. The assertion in
weston_presentation_feedback_present_list() will trigger randomly during
repeated suspend/resume testing, presumably while a client is animating
and asking for presentation feedback.

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

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

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

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

References: https://gitlab.freedesktop.org/wayland/weston/-/issues/1063
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
2025-11-13 11:38:34 +02:00
Derek Foreman
0bfcb700b9 compositor/shells: Require shells to flag outputs as ready to allow repaint
We've added a curtain to the shells so at startup we have something to
render, but this causes a flicker if someone is trying to have a seamless
transition from boot to weston.

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

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-27 05:55:51 +00:00
Derek Foreman
6070dd8069 compositor: Add a WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY
This already existed for surface, so it is trivial to add.

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

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

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

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

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

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

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

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

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

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

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-21 08:54:13 -05:00
Derek Foreman
8591578090 compositor: Update view transform when setting surface size
since abfe874a51 we no longer do a full view list rebuild after a
surface_set_size(), but that was ensuring we always had an up to
date transform in the repaint loop.

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

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

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

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

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

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

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

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

Add the region as a parameter.

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

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

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

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

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

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

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

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

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

Signed-off-by: Robert Mader <robert.mader@collabora.com>
2025-10-17 15:06:11 +02:00
Derek Foreman
992ab893f9 compositor: Validate that paint node holes have planes
If the backend says a hole is necessary, it must assign a plane for it.

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

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

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

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

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

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

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

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

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

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

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-10-10 09:15:07 -05:00
Daniel Stone
c6b519ab12 paint-node: Set draw_solid for single-pixel buffers
Single-pixel buffers are, by definition, a single-colour fill across the
entire paint node. Use the draw_solid path for these where we can.

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

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

Signed-off-by: Daniel Stone <daniels@collabora.com>
2025-10-09 14:01:12 +01:00
Philipp Zabel
847952b711 compositor: Fix warning on 32-bit architectures
On 32-bit ARM, tv_sec is of type long long int. Cast to int64_t and
use PRId64 from inttypes.h instead of %ld to silence these format
warnings:

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

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
2025-10-09 13:29:01 +01:00
Marius Vlad
bcb7676ed7 backend-drm: Add some further debug message for hot-plug events
And also for connector changes. This would allow tracking hot-plug
events from the udev/kernel and figure out that connector properties
changed.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2025-09-25 14:07:48 +01:00
Leandro Ribeiro
6fe0cfc2b8 color: introduce output color effects
Output color effects are applied to the whole output scenegraph. It
depends on color-management being disabled, as the color effects are
applied in sRGB content.

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

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

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

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

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-17 11:39:03 +00:00
Derek Foreman
439aea0188 compositor: Track DIRTY_POS properly
For clients using old protocol versions, the WESTON_SURFACE_DIRTY_POS bit
currently gets set on any attachment. It should really only be set if
the attachment is non-zero.

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

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

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
2025-09-08 08:14:09 +00:00