Initially we generate the new part of fb_clip_region from the new part
of redraw_clip, scale it up and clamp. But the clamping means the new
part of fb_clip_region might now represent a slightly larger area than
the new part of redraw_clip, by one pixel.
In some rare cases where a foreground actor honours redraw_clip, but
the background actor does not (meaning it might fill all fb_clip_region),
you could find 1px rendering glitches in that gap as the background
actor paints there but the foreground actor does not.
To ensure such glitches can never happen we now regenerate the final
redraw_clip as a clamped superset of the final fb_clip_region. That's
the minimum area we must paint to ensure no gaps appear inside
fb_clip_region.
Although the fix here sounds like the intent of the old code, the old
code forgot to include the new part of fb_clip_region in the clamping
of the final redraw_clip. So the new part of redraw_clip was sometimes
kept too small for the new part of fb_clip_region.
We also move the code to the main path because technically it's also
needed when `has_buffer_age == FALSE`.
Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1500
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1554>
Before each frame is maybe redrawn, push any new cursor KMS state to the
pending update. It'll then either be posted during the next page flip,
or when the same frame finishes, in case nothing was redrawn.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This makes it possible to post a symbolic page flip and frame callback,
meant to be used by immediate symbolic page flip reply when emulating
cursor plane changes using legacy drmMode* functions.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Just as with the frame clock, add an API to communicate that a frame did
not result in a presentation. This can't happen yet but will when we
emulate atomic cursor plane changes using legacy drmMode API.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
In constrast to notify_presented(), notify_ready() also returns the
state machine to the idle state, but without providing new frame
information, as no frame was actually presented.
This will happen for example with the simple KMS impl backend will do a
cursor movement, which will trigger a symbolic "page flip" reply in
order to emulate atomic KMS behavior. When this happen, we should just
try to reschedule again.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Don't mode set each CRTC in separate KMS updates, as reconfiguring one
CRTC might cause other CRTCs to be implicitly reset thus as well,
causing KMS return EBUSY if using atomic modesetting.
Prepare for this by compositing each CRTC first including adding steps
to the KMS update, but wait until all views has rendered at least once
before posting the initial update. After this each CRTC is posted
separately.
Using EGLStreams instead of normal page flipping seems to fail when
doing this though, so handle that the old way for the EGLStream case,
i.e. eglSwapBuffers() -> mode set with dumb buffer -> eglStream
"acquire" (resulting in page flip under the hood).
For this we also introduce a new error code so that we don't use client
buffers when doing mode sets, which could accidentally configure the
CRTC in a way that is incompatible with the primary plane buffers.
Do the same also when we're in power save mode, to only have one special
case path for this scenario in the regular swap-buffer path.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Instead of setting the frame result in the most generic layer, have the
backends do it themselves. This is necessary to communicate that a
swap-buffer call didn't really succeed completely to present the swapped
buffer, e.g. errors from KMS.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This argument is intended to be used by clutter to be able to
communicate with the onscreen backend, that happens to be the native
backend. It will be used to pass a ClutterFrame pointer, where the
result of page flips, mode sets etc can be communicated whenever it is
available.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
ClutterFrame aims to carry information valid during dispatching a frame.
A frame may or may not include redrawing, but will always end with a
result.
A asynchronous page flip, for example, will result in a
CLUTTER_FRAME_RESULT_PENDING_PRESENTED, while a frame that only
dispatched events etc will result in CLUTTER_FRAME_RESULT_IDLE. Instead
of this being implicit, make the ClutterStageWindow implementation
handle this itself.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
ClutterClickEvent currently doesn't check if button press and release
happen within the drag threshold, which can be surprising sometimes.
Only emit the "clicked" signal if the button press and release happen
within the area of drag threshold.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1667>
In clutter_timeline_set_actor() we currently always unset the
priv->frame_clock pointer of the old actor when a new actor gets set.
The priv->frame_clock pointer takes a reference on the ClutterFrameClock
though, so we leak ClutterFrameClocks here.
To fix it, simply rely on update_frame_clock(), which will call
set_frame_clock_internal() unconditionally to update the
priv->frame_clock pointer for us.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1632>
Some effects such as the BrightnessContrastEffect try to skip rendering
by returning early with a FALSE return value in pre_paint() in cases
where the effect would not change the rendering. This stopped working
when effects were ported to paint nodes.
In the case of OffscreenEffects, like BrightnessContrastEffect,
pre_paint() is responsible for setting up the offscreen buffer which is
then used in paint_node(). However if pre_paint() fails, this buffer is
not created and attempting to use it will result in several error
messages and broken rendering.
Instead of trying to call paint_node() of the effect if pre_paint()
failed, just draw the actor.
Fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1576
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1658>
When using alt-tab to switch between windows, on a key handler we
undo the compositor grab, which triggers a repick, which generates
crossing events, which are handled in place, and trigger these
reentrancy checks.
On one hand, we do intend these crossings to take effect in place,
rather than being queued (possibly after a number of already queued
events). On the other hand, we now outright discourage generating
events from random places (and hope to make it just not possible,
eventually) thus we can afford not to protect against reentrancy
caused by API misuse.
So just drop these checks, and let these crossing events be
properly handled.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1657>
This is the very same code than meta_wayland_pointer_repick(),
made part of Clutter, so triggering repicks on the same pointer
coordinates is made easy.
The intention is to remove meta_wayland_pointer_repick() in favor
of this call.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1654>
Updating the state before emitting the CLUTTER_LEAVE event allows its
handlers to query the pointer actor, and avoid getting the same actor
again. Conceptually, this makes picking more "atomic", and the events a
notification of the change.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1654>
Turns out GObject implicitly notifies all properties by default as soon
as a property setter is called, no matter if the property actually
changed or not. One can opt-out of this behavior by setting the
G_PARAM_EXPLICIT_NOTIFY flag.
So since almost all our properties get notified explicitely (well,
except ClutterActors deprecated show-on-set-parent property), set this
flag for all properties of ClutterActor and ClutterStage now. This
significantly reduces the number of notify:: signals emitted on
ClutterActors, because in gnome-shell javascript we usually set GObject
properties directly, not by going through the extra setter method.
More cleanups can be done in the future, since this flag is suitable for
almost every property in Clutter and even Mutter.
This fixes a crash where we'd hit a newly introduced assertion in
on_device_actor_reactive_changed() of ClutterStage because
notify::reactive got emitted multiple times.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1651>
Due to a few reasons currently the updating of input devices after stage
relayouts isn't working right now. Since we now have a list of pointer
devices in ClutterStage, we can simply use that list and can avoid
asking the input thread. Also we no longer need to check whether the
devices are pointer devices, since our list only consists of pointer
devices.
So switch to ClutterStages private list of pointer devices, which also
includes the core pointer (as opposed to the list returned by
clutter_seat_peek_devices()). This fixes picking after relayouts.
Note that this doesn't catch every possible change that might need a
repick, actors might also need a repick after transformation changes or
in case their custom clip has been changed.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1634>
As planned and prepared with the last commits, let ClutterStage take
care of tracking input devices and their respective actors. This means
we now can remove the old infrastructure for this from
ClutterInputDevice.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1633>
We're moving keeping track of input devices and their associated actors
out of ClutterInputDevice, this commit basically adds replacements for
clutter_input_device_update() and clutter_input_device_set_actor() to
clutter-main and shuffles the internals of those functions around a bit
for clarity.
clutter_stage_update_device() is made available in clutter-mutter.h
because we need to update the actor of input devices not only from
ClutterStage (when repicking after relayout), but also from
MetaWaylandPointer (inside meta_wayland_pointer_repick()).
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1633>
With the introduction of the input thread, we want to avoid modifying
ClutterInputDevices from the main thread, since they're owned and
updated by the thread.
There's one part of ClutterInputDevice that's still modified from the
main thread though, that is device-actors of pointer devices, and we're
going to move that state-tracking into ClutterStage instead.
So start that by adding the infrastructure to ClutterStage to keep track
of those things. It consists of two hashtables which associate devices
and touch sequences with actors, those hashtables get updated using
clutter_stage_update_device_entry() and
clutter_stage_remove_device_entry(), they can be queried by calling
clutter_stage_get_device_actor(), which will replace
clutter_input_device_get_actor().
clutter_stage_get_device_coords() is added and made available in
clutter-mutter.h because we need to get the coordinates when repicking
in meta_wayland_pointer_repick().
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1633>
The n_steps variable corresponds to the number of *pairs* of
texture lookups that the blur shader does. For example, when
n_steps = 1, the for-loop reads 1 pixel before and 1 pixel
after the current one.
Our blur shader is heavily inspired in WebRender's blur shader,
the biggest difference being that we calculate the gaussian
samples in the fragment shader itself, and not in the vertex
shader. (This could be an improvement in performance for the
future though!)
WebRender's blur shader calculates n_steps differently than what
we currently do, though. It calculates n_step in such a way that
at least 2 steps are performed for evey non-zero sigma value.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1646>
The shader already operates on floating point sigma, and
there's just no reason for us to force it to be an unsigned
integer. It's still important that sigma must be positive
though.
Make sigma a float, and make sure it's a positive number.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1646>
Yet another way to reduce the instruction count of the fragment
shader. Passing a pair of floats once is virtually free, compared
to computing horizontal and vertical on each fragment run.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1646>
New entries indirectly added to `pending_queue_redraw` during the loop
would make our iterator invalid and cause `g_hash_table_iter_next` to
fail without having visited all elements. That was seen as assertion
failures but also likely resulted in incomplete paint clips.
Now we steal the iterator's entry before such corruption can happen,
free it manually, and reset the iterator to the beginning on every
iteration. This is actually safe and efficient because we're removing each
entry we visit. So no time is wasted in resuming from the (new) beginning
of the hash table.
Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1557
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1615>
Add a new pair of APIs corresponding to CoglFramebuffer's draw_rectangles()
and draw_textured_rectangles(). They're generally more performance compared
to adding multiple single-rect operations. These variants are heavily used
by GNOME Shell's CSS implementation.
The op array is built to match cogl_framebuffer_draw_textured_rectangles()
always, which means it's a series of 8 floats composed (x1 y1 x2 y2) and
(s1 t1 s2 t2). To avoid adding new struct fields to ClutterPaintOperation,
which is a performance and memory sensitive structure, simply divide the
array length by 8 (which is guaranteed to be correct).
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1637>
Setting an ortho projection gives us pretty much the same result as
manually calculating the projection matrix. The ortho projection is
actually more "complete" than the custom projection we've been using,
as it also considers z-near and z-far, but in practice the generated
pixels are exactly equal.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1642>
In the purely paint node based rendering future, ClutterEffects
simply add more paint nodes to the tree when painting the actor.
This is the leap to achieve that future.
Add paint nodes to pre_paint, paint, and post_paint, and move the
ClutterEffectNode creation to _clutter_effect_paint().
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1355>
The paint node tree that ClutterOffscreenEffect generates is
simple:
Root
|------------+
| |
Layer Pipeline
|
Actor
Right now, both pre-paint and ClutterLayerNode push the offscreen
to the framebuffer stack. That's harmless, and will go away soon
anyway.
The actor node is created and added in a separate function because
it'll be reused by the next commit.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1355>
Add a new ClutterPaintNode parameter to the paint_target() vfunc.
For now, create a temporary ClutterEffectNode that is passed to
paint_target() and immediately painted; next commits will move
this to upper layers.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1355>
The blur pipeline is still cached on ClutterBlurEffect, and we
simply update the uniforms when asked to create the pipeline.
Now that ClutterOffscreenEffect will use the blur pipeline, it
doesn't need to override the paint_target() vfunc anymore.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1355>