cogl_framebuffer_finish can result in a CPU-side stall because it waits for
the primary GPU to flush and execute all commands that were queued before
that. By using a GPU-side EGLSync we can let the primary GPU inform us when
it is done with the queued commands instead. We then create another EGLSync
on the secondary GPU using the same fd so the primary GPU effectively
signals the secondary GPU when it is done rendering, causing the latter
to wait for the former before copying part of the frames it needs for
monitors attached to it directly.
This solves the corruption that cogl_framebuffer_finish also solved, but
without needing a CPU-side stall.
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
See previous commit log on the effects of this.
This means the deadline evasion needs to be added in both cases in
clutter_frame_clock_notify_presented.
v2:
* Use meta_kms_update_set_sync_fd. (Jonas Ådahl)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3958>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
If the KMS thread is using the deadline timer, and a valid sync_file
descriptor is passed in:
1. The update is deferred, and the deadline timer is left armed, until
the sync_fd signals (becomes readable).
2. Implicit synchronization is disabled for the KMS update.
This means cursor updates should no longer miss a display refresh
cycle due to mutter's compositing GPU work finishing too late.
v2:
* Use g_autoptr for GSource in meta_kms_impl_device_handle_update.
(Sebastian Wick)
v3:
* Use meta_kms_update_get_sync_fd, don't track sync_fd in
CrtcFrame::submitted_update. (Jonas Ådahl)
v4:
* Clean up CrtcFrame::submitted_update members in crtc_frame_free.
v5:
* Coding style cleanup in meta_kms_impl_device_handle_update.
(Jonas Ådahl)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3958>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
To META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC. This describes the
effect of the flag, instead of the circumstances it's currently used
for.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3958>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
If both crtc->shortterm_max_dispatch_duration_us and
crtc->deadline_evasion_us are 0, i.e. we're not using the deadline
timer.
v2:
* Fix coding style. (Jonas Ådahl)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3958>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
And take it into account in meta_kms_crtc_get_deadline_evasion.
This uses the same fundamental approach as clutter frame clock scheduling:
Measure the deadline timer dispatch duration, keep track of the longest
duration, and set the timer to fire such that the longest measured
dispatch duration would result in it completing shortly before start of
vblank.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3612
v2:
* Move DEADLINE_EVASION_CONSTANT_US addition from
meta_kms_crtc_determine_deadline to meta_kms_crtc_get_deadline_evasion.
* Calculate how long before start of vblank dispatch completed for
debug output in crtc_frame_deadline_dispatch.
* Shorten over-long lines in crtc_frame_deadline_dispatch.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3934>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
(cherry picked from commit 88e7f353)
And also "completion" time to measure when the commit returned.
This is structured so as to measure all timestamps first before logging
anything. That way our results shouldn't be (don't seem to be) affected
by the logging itself.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3265>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
If we finish compositing in time, the composited result will be
submitted prior to the deadline timer is triggered, and we'll be fine,
and if not, at least the cursor updates will be smooth, which makes it
appear smoother than not.
There is a risk that this can negatively impact composited updates when
moving the cursor, so make it possible to toggle a paint-debug flag for
now until this has been more tested.
This also mean we need to disarm the deadline timer after handling
update, as there might be a scheduled cursor update pending, but we
already handled it, so disarm the timer.
Here is an illustration of the difference.
In the following scenario, with disarming, the composited frame E, and
the cursor movement C gets presented. With this branch, only the cursor
movement C gets presented.
```
* A: beginning of composited frame
* B: begin notification reaches KMS thread
* C: cursor moved
* D: calculated deadline dispatch time (disabled with the branch)
* E: KMS update posted
* F: KMS update reaches KMS thread
* G: actual deadline (and with branch and gets committed)
Compositor thread: --------A---------------E---------
\ \
\ \
KMS thread: -----------B------C----D---F-G----
```
In the following scenario, by not disarming, the cursor update C will be
presented, and the would-be-delayed composited frame E would be delayed
anyway, i.e. fixing cursor stutter.
```
* A: beginning of composited frame
* B: begin notification reaches KMS thread
* C: cursor moved
* D: calculated deadline dispatch time (and with branch will be dispatched)
* E: KMS update posted
* F: actual deadline
* G: KMS update reaches KMS thread (and with branch gets postponed)
Compositor thread: --------A---------------E---------
\ \
\ \
KMS thread: -----------B------C----D-F-G------
```
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3184>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
The deadline evasion depends on debug flags, but they are not trackable,
so update the deadline evasion each time we schedule an update.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3184>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
(cherry picked from commit 6ec1312384)
This is meant to be the amount of time before a CRTC deadline we're
usually dispatching at. It's not yet set by anything however.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3184>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
And return early from `swap_buffers_with_damage` if the error would have
led to flipping a NULL buffer.
This is also the perfect time to remove the `egl_context_changed` parameter
and move `_cogl_winsys_egl_ensure_current` closer to the code that actually
needs it.
Related: https://bugs.launchpad.net/bugs/2069565
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3817>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
So that swap failure messages are not also followed by:
meta_stage_native_redraw_view: runtime check failed: (!META_IS_CRTC_KMS (crtc))
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3817>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
It won't be used until later when we flip, and in fact assigning
it early could have led to its own assertion failing on the next frame
in the unlikely event that we return with "Failed to ensure KMS FB ID...
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3891>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
`update_secondary_gpu_state_post_swap_buffers` decides what our front
buffer object will be. There is only one answer. So return it as the
function result instead of making the caller figure it out.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3830>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
It's always equal to `onscreen_native->next_frame` and we can't eliminate
that copy so easily. Removing the parameter removes all ambiguity about
where the next frame will come from.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3829>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
Let the ClutterFrame (or rather MetaFrameNative) own both the scanout
object and the framebuffer object, and let the frame itself live for as
long as it's needed. This allows to place fields that is related to a
single frame together, aiming to help reasoning about the lifetime of
the fields that were previously directly stored in MetaOnscreenNative.
Also take the opportunity to rename "current" to "presenting", to make
it clearer that frame's buffer is what is currently presenting to the
user.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3799>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
g_array_sized_new() creates a new GArray with a preallocated size, but,
after creation, the array length is still zero [1].
Store the modifiers in a EGLuint64KHR array and use g_array_new_take()
to create a new GArray with the correct size.
Because no modifiers were returned, gbm_surface_create() was used
instead gbm_surface_create_with_modifiers() on multi-GPU setups.
[1] https://docs.gtk.org/glib/type_func.Array.sized_new.html
Fixes: aec85281ba ("native/renderer: Retrieve the right modifiers set for each GPU")
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3998>
(cherry picked from commit cf5508bdeb)
The tablet tool is initialized with a device but if that device is later
removed we never update tool->device. This eventually causes a crash
when we're passing that device into
meta_wayland_input_invalidate_focus().
The tool keeps track of the current tablet anyway so instead of caching
this pointer in the tool, use the current tablet's device.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3642
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3959>
(cherry picked from commit e4004a7c4f)
If the window_drag->handle ClutterActor:visible property is FALSE,
then we avoid a full-framebuffer damage on the monitor when beginning
and ending a drag.
Testing with `mutter --wayland --display-server` still shows a full-
framebuffer damage on the first drag, but that appears to be unrelated
to this. Subsequent full-framebuffer damage which would occur on
drag-begin and drag-end have been elided.
Related: #3630
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3975>
(cherry picked from commit 030270ba3b)
We're already inhibiting real time scheduling when reading new KMS state
after hot plugs, as well as when during mode sets, due to the kernel not
being able to reliably handle these within the 250 ms limit. However, we
didn't do this during initial probing, which meant that occasionally
we'd run into these kind of issues during startup.
Handle this by always inhibiting real time scheduling up front, and
don't uninhibit until all initially discovered device have finished
processing their initial mode set.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3628
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3960>
(cherry picked from commit d2be0b6950)
If an application is maximised, clutter_stage_pick_and_update_device()
goes into the
if ((flags & CLUTTER_DEVICE_UPDATE_IGNORE_CACHE) == 0)
condition and returns the current actor for the device. This means no
CLUTTER_LEAVE/ENTER events are generated and in turn means the focus is
never invalidated and updated.
This leads to tool->focus_surface always being NULL and all events are
discarded.
Notably, tool->current is set to the right surface but
that one never changes either so meta_wayland_tablet_tool_set_current_surface()
exits early too because surface == tool->current and we thus never call
meta_wayland_input_invalidate_focus().
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3616
Fixes: fb8ac5dff7 ("wayland: Track current tablet tool focus surface")
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3956>
(cherry picked from commit d866590b78)
Clutter's "device-removed" signal is sent in
clutter_seat_handle_event_post(). Our tablet code is set up to handle
that signal to then notify wayland clients of removed tablet devices.
However, returning CLUTTER_EVENT_STOP for a DEVICE_REMOVED event means
we never get to the point where we send out the signals and thus never
remove the tablets.
Fixes: a37fd34bbb ("wayland: Make MetaWaylandSeat in charge of its own tablet seat")
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3615
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3955>
(cherry picked from commit c03e64ef1d)
The first event happening for a new touch will be the CLUTTER_ENTER
event generated when picking it. Use this event for registration of
the touch info, so that MetaWaylandEventHandler.get_focus_surface may
get the right focus surface for the device/sequence on the first try.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3889>
(cherry picked from commit 2e82a2049f)
And notably, don't cancel touch when an event handler is being
removed. Touch events are largely unaffected by most Wayland
grabs (pointer constraints, popups), so we might be cancelling
input too early if one of these wayland grabs was effective when
touch interaction began, but stopped sometime between touch updates.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3889>
(cherry picked from commit 77b21ef8dc)
Touch events are implicitly grabbed to the surface they began in,
and are not affected by the focus handler. However these events
will appear to come from the core pointer device, which might lead
to the wrong device being updated.
Ignore events with a sequence, since the default focus handler
does not intend to do anything with them.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3889>
(cherry picked from commit 08c903a359)
On a hybrid machine with i915 primary and nvidia-drm (470) secondary,
`meta_render_device_egl_stream_initable_init` calls
`meta_kms_inhibit_kernel_thread` to change from the default 'kernel'
thread type to 'user'. And soon after that it would
`meta_render_device_egl_stream_finalize` because I'm not actually
using that GPU, and calls `meta_kms_uninhibit_kernel_thread`.
So during startup Mutter would default to a realtime kernel thread,
switch to a user thread (which doesn't support realtime), and then
switch back to a realtime kernel thread.
In the middle of all that, while the thread type was 'user' and
realtime disabled, something was invoking `ensure_crtc_frame` which
created a `CrtcFrame` without a deadline timer. Soon after that the
thread type changed back to 'kernel' with deadline timers expected, but
our existing `CrtcFrame` has no deadline timer associated with it. And
so it would never fire, causing the cursor to freeze whenever the primary
plane isn't changing. And the problem was permanent, not just the first
frame because each `CrtcFrame` gets repeatedly reused (maybe shouldn't
be called a "Frame"?).
Now we adapt to switching between kernel and user thread types by adding
and removing the deadline timer as required.
Close: https://gitlab.gnome.org/GNOME/mutter/-/issues/3464
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3950>
(cherry picked from commit c436e7cb17)
Although we track updates for EGL_DEVICE, they are often empty because
the primary plane has a custom page flip method. That means there's
no CRTC latched yet, but we do know exactly which CRTC is associated
with the flip. Set it so the update can still be processed.
Fixes: 27ed069766 ("kms/impl-device: Add deadline based KMS commit scheduling")
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3939>
(cherry picked from commit cfb2100d40)
If other handlers (e.g. DnD) are on top of the popup grab focus, we
may want it to move outside same-client surfaces as the popup grab
specifies.
Check that it is the current handler before making same-client checks,
so that these handlers on top have an opportunity to find other
surfaces, e.g. during DnD from a popup.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1681
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3937>
(cherry picked from commit c179bebb70)
Move away from tracking presses/releases directly, since there might be
other event handlers on top that might prevent the popup event handler
to fully track all events. The replacement is using event state modifiers,
which will use information set from the backend, and is enough to determine
there's no more pressed buttons without tracking prior event history.
This makes the popup event handler able to interact with other event
handlers that might be on top, and consume button release events for
themselves (e.g. DnD), no longer resulting in a stuck popup grab.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3937>
(cherry picked from commit 22362378ea)
When the screen is scaled and we are recording/sharing the screen we may
end up crash as per trying to create a 0-sized texture due to missing
ceiling of the texture size.
This is similar to what was fixed in commit 4d4e8e5862 and the same
fix was included in commit 422ee4515, but hidden under a compilation fix
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3978>
When triple buffering, `meta_onscreen_native_prepare_frame` for the next
frame is called before `notify_view_crtc_presented` for the previous frame.
So our booleans were unfortunately still TRUE in the second prepare_frame,
resulting in two frames with the same property updates.
When double buffering, having roughly one frame interval between
`meta_onscreen_native_prepare_frame` and `notify_view_crtc_presented`
meant that property updates signalled between the swap and presentation
wouldn't get attached to a KMS update, and would be forgotten when
`notify_view_crtc_presented` resets the flags to FALSE.
To solve these we now keep a separate flag and counter per property,
tracking invalidation and pending updates respectively. The latter is a
counter rather than a boolean in support of triple buffering where two
updates may be pending concurrently (next and posted).
Origin: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3912
(cherry picked from commit a04d90d9e7)
This is usually an indication of a failed drop operation if the
drop site didn't request any target. Check for this specifically
on XDnD button release, so that we can cancel the DnD operation
right away.
Inspired on a fix from Jonas Ådahl.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3821>
(cherry picked from commit ef3de1e58e)
We were relying on the drag source surface to keep receiving events
thanks to it being implicitly grabbed by the button press. This
broke at some point, making the Xdnd drag source unable to keep
directing the DnD operation as it is expected by X11 clients.
To fix this, make the Xdnd MetaWaylandEventInterface stick itself
to the drag source surface keeping the focus of the device driving
the DnD operation, so that the X11 client can still handle events
from it.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3511
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3821>
(cherry picked from commit fd1d8c778b)
Using GL_BGRA8_EXT as internalformat for TexSubImage2D was not allowed
in the EXT_texture_format_BGRA8888 extension. This changed recently:
https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_format_BGRA8888.txt
1.4, 23/06/2024 Erik Faye-Lund: Add GL_BGRA8_EXT for ES 2.0 and later.
Mesa already supports this which is why 7f943613a8 ("cogl: Use sized
internal renderable formats") worked as intended. Technically spec
compliant and our CI had an up-to-date driver.
So while this is no bug, it's still not great because older drivers will
generate GL errors. This commit changes this specific format back to an
unsized internal format which means we could, in theory, get less than
8bpc framebuffers.
We can try to revert this commit when newer driver versions have
propagated far enough.
Fixes: 7f943613a8 ("cogl: Use sized internal renderable formats")
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3954>
(cherry picked from commit 45dcfeb0cc)
There is one define for the format (GL_BGRA_EXT) and one for the
internal format (GL_BGRA8_EXT). Use them appropriately.
This also adds defines to consistenly not use the _EXT postfix.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3914>
(cherry picked from commit c3eb01e547)
The opaque fp16 Cogl format variants need a required format that is
already premultiplied whereas the fp16 formats with an alpha channel can
be either straight or premult.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3914>
(cherry picked from commit d820fe030a)