compositor/native: Track what Wayland surface is a scanout candidate

For the current candidate, set the candidate CRTC on that surface. This
will later be used to send DMA buffer feedback for direct scanout purposes.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
This commit is contained in:
Jonas Ådahl 2021-08-06 17:00:19 +02:00 committed by Marge Bot
parent 9a47766a96
commit 43161c6660
4 changed files with 127 additions and 13 deletions

View File

@ -23,11 +23,14 @@
#include "compositor/meta-compositor-native.h" #include "compositor/meta-compositor-native.h"
#include "backends/meta-logical-monitor.h" #include "backends/meta-logical-monitor.h"
#include "backends/native/meta-crtc-kms.h"
#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-surface-actor-wayland.h"
struct _MetaCompositorNative struct _MetaCompositorNative
{ {
MetaCompositorServer parent; MetaCompositorServer parent;
MetaWaylandSurface *current_scanout_candidate;
}; };
G_DEFINE_TYPE (MetaCompositorNative, meta_compositor_native, G_DEFINE_TYPE (MetaCompositorNative, meta_compositor_native,
@ -62,57 +65,88 @@ get_window_view (MetaRenderer *renderer,
static void static void
maybe_assign_primary_plane (MetaCompositor *compositor) maybe_assign_primary_plane (MetaCompositor *compositor)
{ {
MetaCompositorNative *compositor_native = META_COMPOSITOR_NATIVE (compositor);
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaRenderer *renderer = meta_backend_get_renderer (backend); MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaWindowActor *window_actor; MetaWindowActor *window_actor;
MetaWindow *window; MetaWindow *window;
MetaRendererView *view; MetaRendererView *view;
MetaCrtc *crtc;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
CoglOnscreen *onscreen; CoglOnscreen *onscreen;
MetaSurfaceActor *surface_actor; MetaSurfaceActor *surface_actor;
MetaSurfaceActorWayland *surface_actor_wayland; MetaSurfaceActorWayland *surface_actor_wayland;
MetaWaylandSurface *surface;
MetaWaylandSurface *old_candidate =
compositor_native->current_scanout_candidate;
MetaWaylandSurface *new_candidate = NULL;
g_autoptr (CoglScanout) scanout = NULL; g_autoptr (CoglScanout) scanout = NULL;
if (meta_compositor_is_unredirect_inhibited (compositor)) if (meta_compositor_is_unredirect_inhibited (compositor))
return; goto done;
window_actor = meta_compositor_get_top_window_actor (compositor); window_actor = meta_compositor_get_top_window_actor (compositor);
if (!window_actor) if (!window_actor)
return; goto done;
if (meta_window_actor_effect_in_progress (window_actor)) if (meta_window_actor_effect_in_progress (window_actor))
return; goto done;
if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor))) if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor)))
return; goto done;
if (clutter_actor_get_n_children (CLUTTER_ACTOR (window_actor)) != 1) if (clutter_actor_get_n_children (CLUTTER_ACTOR (window_actor)) != 1)
return; goto done;
window = meta_window_actor_get_meta_window (window_actor); window = meta_window_actor_get_meta_window (window_actor);
if (!window) if (!window)
return; goto done;
view = get_window_view (renderer, window); view = get_window_view (renderer, window);
if (!view) if (!view)
return; goto done;
crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (view));
if (!META_IS_CRTC_KMS (crtc))
goto done;
framebuffer = clutter_stage_view_get_framebuffer (CLUTTER_STAGE_VIEW (view)); framebuffer = clutter_stage_view_get_framebuffer (CLUTTER_STAGE_VIEW (view));
if (!COGL_IS_ONSCREEN (framebuffer)) if (!COGL_IS_ONSCREEN (framebuffer))
return; goto done;
surface_actor = meta_window_actor_get_surface (window_actor); surface_actor = meta_window_actor_get_surface (window_actor);
if (!META_IS_SURFACE_ACTOR_WAYLAND (surface_actor)) if (!META_IS_SURFACE_ACTOR_WAYLAND (surface_actor))
return; goto done;
surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor); surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor);
surface = meta_surface_actor_wayland_get_surface (surface_actor_wayland);
if (!surface)
goto done;
new_candidate = surface;
onscreen = COGL_ONSCREEN (framebuffer); onscreen = COGL_ONSCREEN (framebuffer);
scanout = meta_surface_actor_wayland_try_acquire_scanout (surface_actor_wayland, scanout = meta_surface_actor_wayland_try_acquire_scanout (surface_actor_wayland,
onscreen); onscreen);
if (!scanout) if (!scanout)
return; goto done;
clutter_stage_view_assign_next_scanout (CLUTTER_STAGE_VIEW (view), scanout); clutter_stage_view_assign_next_scanout (CLUTTER_STAGE_VIEW (view), scanout);
done:
if (old_candidate && old_candidate != new_candidate)
{
meta_wayland_surface_set_scanout_candidate (old_candidate, NULL);
g_clear_weak_pointer (&compositor_native->current_scanout_candidate);
}
if (new_candidate)
{
meta_wayland_surface_set_scanout_candidate (surface, crtc);
g_set_weak_pointer (&compositor_native->current_scanout_candidate,
surface);
}
} }
static void static void
@ -137,6 +171,16 @@ meta_compositor_native_new (MetaDisplay *display,
NULL); NULL);
} }
static void
meta_compositor_native_finalize (GObject *object)
{
MetaCompositorNative *compositor_native = META_COMPOSITOR_NATIVE (object);
g_clear_weak_pointer (&compositor_native->current_scanout_candidate);
G_OBJECT_CLASS (meta_compositor_native_parent_class)->finalize (object);
}
static void static void
meta_compositor_native_init (MetaCompositorNative *compositor_native) meta_compositor_native_init (MetaCompositorNative *compositor_native)
{ {
@ -145,7 +189,10 @@ meta_compositor_native_init (MetaCompositorNative *compositor_native)
static void static void
meta_compositor_native_class_init (MetaCompositorNativeClass *klass) meta_compositor_native_class_init (MetaCompositorNativeClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass); MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass);
object_class->finalize = meta_compositor_native_finalize;
compositor_class->before_paint = meta_compositor_native_before_paint; compositor_class->before_paint = meta_compositor_native_before_paint;
} }

View File

@ -79,8 +79,7 @@ meta_surface_actor_wayland_try_acquire_scanout (MetaSurfaceActorWayland *self,
return NULL; return NULL;
surface = meta_surface_actor_wayland_get_surface (self); surface = meta_surface_actor_wayland_get_surface (self);
if (!surface) g_return_val_if_fail (surface, NULL);
return NULL;
scanout = meta_wayland_surface_try_acquire_scanout (surface, onscreen); scanout = meta_wayland_surface_try_acquire_scanout (surface, onscreen);
if (!scanout) if (!scanout)

View File

@ -77,6 +77,17 @@ typedef struct _MetaWaylandSurfaceRolePrivate
MetaWaylandSurface *surface; MetaWaylandSurface *surface;
} MetaWaylandSurfaceRolePrivate; } MetaWaylandSurfaceRolePrivate;
enum
{
PROP_0,
PROP_SCANOUT_CANDIDATE,
N_PROPS
};
static GParamSpec *obj_props[N_PROPS];
G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT); G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT);
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole, G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole,
@ -1412,6 +1423,7 @@ wl_surface_destructor (struct wl_resource *resource)
g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0); g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0);
g_clear_object (&surface->scanout_candidate);
g_clear_object (&surface->role); g_clear_object (&surface->role);
if (surface->unassigned.buffer) if (surface->unassigned.buffer)
@ -1693,11 +1705,41 @@ meta_wayland_surface_init (MetaWaylandSurface *surface)
g_node_prepend_data (surface->subsurface_branch_node, surface); g_node_prepend_data (surface->subsurface_branch_node, surface);
} }
static void
meta_wayland_surface_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaWaylandSurface *surface = META_WAYLAND_SURFACE (object);
switch (prop_id)
{
case PROP_SCANOUT_CANDIDATE:
g_value_set_object (value, surface->scanout_candidate);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void static void
meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass) meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = meta_wayland_surface_get_property;
obj_props[PROP_SCANOUT_CANDIDATE] =
g_param_spec_object ("scanout-candidate",
"scanout-candidate",
"Scanout candidate for given CRTC",
META_TYPE_CRTC,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props);
surface_signals[SURFACE_DESTROY] = surface_signals[SURFACE_DESTROY] =
g_signal_new ("destroy", g_signal_new ("destroy",
G_TYPE_FROM_CLASS (object_class), G_TYPE_FROM_CLASS (object_class),
@ -2100,3 +2142,21 @@ meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface,
return scanout; return scanout;
} }
MetaCrtc *
meta_wayland_surface_get_scanout_candidate (MetaWaylandSurface *surface)
{
return surface->scanout_candidate;
}
void
meta_wayland_surface_set_scanout_candidate (MetaWaylandSurface *surface,
MetaCrtc *crtc)
{
if (surface->scanout_candidate == crtc)
return;
g_set_object (&surface->scanout_candidate, crtc);
g_object_notify_by_pspec (G_OBJECT (surface),
obj_props[PROP_SCANOUT_CANDIDATE]);
}

View File

@ -247,6 +247,9 @@ struct _MetaWaylandSurface
*/ */
uint64_t sequence; uint64_t sequence;
} presentation_time; } presentation_time;
/* dma-buf feedback */
MetaCrtc *scanout_candidate;
}; };
void meta_wayland_shell_init (MetaWaylandCompositor *compositor); void meta_wayland_shell_init (MetaWaylandCompositor *compositor);
@ -363,6 +366,11 @@ int meta_wayland_surface_get_height (MetaWaylandSurface *surface
CoglScanout * meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface, CoglScanout * meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface,
CoglOnscreen *onscreen); CoglOnscreen *onscreen);
MetaCrtc * meta_wayland_surface_get_scanout_candidate (MetaWaylandSurface *surface);
void meta_wayland_surface_set_scanout_candidate (MetaWaylandSurface *surface,
MetaCrtc *crtc);
static inline GNode * static inline GNode *
meta_get_next_subsurface_sibling (GNode *n) meta_get_next_subsurface_sibling (GNode *n)
{ {