From 9239eebf53660d037c5b429e755e53ae1d34632d Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Fri, 28 Nov 2025 16:09:09 -0800 Subject: [PATCH 1/9] TILETEAR: Add MetaRenderTarget[Native] classes --- src/backends/meta-render-target.c | 144 ++++++++++++++++++ src/backends/meta-render-target.h | 43 ++++++ .../native/meta-render-target-native.c | 48 ++++++ .../native/meta-render-target-native.h | 36 +++++ src/meson.build | 4 + 5 files changed, 275 insertions(+) create mode 100644 src/backends/meta-render-target.c create mode 100644 src/backends/meta-render-target.h create mode 100644 src/backends/native/meta-render-target-native.c create mode 100644 src/backends/native/meta-render-target-native.h diff --git a/src/backends/meta-render-target.c b/src/backends/meta-render-target.c new file mode 100644 index 00000000000..117e9ea0ba0 --- /dev/null +++ b/src/backends/meta-render-target.c @@ -0,0 +1,144 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2025 ? + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/** + * MetaRendererTarget: + * + * Holds a collection of MetaCrtc and MetaOutput pointers that represent + * a single output. The common case is 1 of each. In the case of a tiled + * display, objects of this class will hold 1 crtc and output per tile. + * The first element of each member array is the "primary" one. + * There must be at least one crtc and output, and the number of + * crtcs and outputs must be identical. + */ + +#include "config.h" + +#include "backends/meta-render-target.h" + +#include + +struct _MetaRenderTarget +{ + GObject parent_instance; + + GPtrArray *crtcs; /* of type MetaCrtc * */ + GPtrArray *outputs; /* of type MetaOutput * */ +}; + +G_DEFINE_TYPE (MetaRenderTarget, meta_render_target, G_TYPE_OBJECT) + +void +meta_render_target_add (MetaRenderTarget *render_target, + MetaCrtc *crtc, + MetaOutput *output) +{ + g_ptr_array_add (render_target->crtcs, g_object_ref (crtc)); + g_ptr_array_add (render_target->outputs, g_object_ref (output)); +} + +MetaCrtc * +meta_render_target_get_primary_crtc (MetaRenderTarget *render_target) +{ + g_warn_if_fail (render_target->crtcs->len > 0); + return g_ptr_array_index (render_target->crtcs, 0); +} + +MetaOutput * +meta_render_target_get_primary_output (MetaRenderTarget *render_target) +{ + g_warn_if_fail (render_target->outputs->len > 0); + return g_ptr_array_index (render_target->outputs, 0); +} + +const char * +meta_render_target_get_name (MetaRenderTarget *render_target) +{ + MetaOutput *primary_output = meta_render_target_get_primary_output (render_target); + return meta_output_get_name (primary_output); +} + +GPtrArray * +meta_render_target_get_crtcs (MetaRenderTarget *render_target) +{ + return render_target->crtcs; +} + +GPtrArray * +meta_render_target_get_outputs (MetaRenderTarget *render_target) +{ + return render_target->outputs; +} + +MtkRectangle +meta_render_target_get_view_layout (MetaRenderTarget *render_target) +{ + MtkRectangle view_layout; + g_warn_if_fail (render_target->crtcs->len > 0); + const MetaCrtcConfig *crtc_config = meta_crtc_get_config (g_ptr_array_index (render_target->crtcs, 0)); + mtk_rectangle_from_graphene_rect (&crtc_config->layout, + MTK_ROUNDING_STRATEGY_ROUND, + &view_layout); + // Handle all crtcs after the first by unioning them together + for (guint i = 1; i < render_target->crtcs->len; i++) + { + MetaCrtc *crtc = g_ptr_array_index (render_target->crtcs, i); + MtkRectangle other_view_layout; + crtc_config = meta_crtc_get_config (crtc); + mtk_rectangle_from_graphene_rect (&crtc_config->layout, + MTK_ROUNDING_STRATEGY_ROUND, + &other_view_layout); + mtk_rectangle_union (&view_layout, &other_view_layout, &view_layout); + } + return view_layout; +} + +MetaGpu * +meta_render_target_get_gpu (MetaRenderTarget *render_target) +{ + return meta_crtc_get_gpu (meta_render_target_get_primary_crtc (render_target)); +} + +static void +meta_render_target_dispose (GObject *object) +{ + MetaRenderTarget *render_target = META_RENDER_TARGET (object); + + g_ptr_array_foreach (render_target->crtcs, (GFunc) g_object_unref, NULL); + g_ptr_array_unref (render_target->crtcs); + g_ptr_array_foreach (render_target->outputs, (GFunc) g_object_unref, NULL); + g_ptr_array_unref (render_target->outputs); + + G_OBJECT_CLASS (meta_render_target_parent_class)->dispose (object); +} + +static void +meta_render_target_init (MetaRenderTarget *render_target) +{ + render_target->crtcs = g_ptr_array_new (); + render_target->outputs = g_ptr_array_new (); +} + +static void +meta_render_target_class_init (MetaRenderTargetClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = meta_render_target_dispose; +} diff --git a/src/backends/meta-render-target.h b/src/backends/meta-render-target.h new file mode 100644 index 00000000000..04689a181c4 --- /dev/null +++ b/src/backends/meta-render-target.h @@ -0,0 +1,43 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2025 ? + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#pragma once + +#include + +#include "backends/meta-crtc.h" +#include "backends/meta-output.h" + +#define META_TYPE_RENDER_TARGET (meta_render_target_get_type ()) +G_DECLARE_FINAL_TYPE (MetaRenderTarget, meta_render_target, META, RENDER_TARGET, GObject) + +MetaRenderTarget *meta_render_target_new (void); +void meta_render_target_add (MetaRenderTarget *render_target, + MetaCrtc *crtc, + MetaOutput *output); +META_EXPORT_TEST +MetaCrtc * meta_render_target_get_primary_crtc (MetaRenderTarget *render_target); +MetaOutput * meta_render_target_get_primary_output (MetaRenderTarget *render_target); +const char * meta_render_target_get_name (MetaRenderTarget *render_target); +gboolean meta_render_target_has_crtc (MetaRenderTarget *render_target, + MetaCrtc *crtc); +GPtrArray * meta_render_target_get_crtcs (MetaRenderTarget *render_target); +GPtrArray * meta_render_target_get_outputs (MetaRenderTarget *render_target); +MtkRectangle meta_render_target_get_view_layout (MetaRenderTarget *render_target); +MetaGpu * meta_render_target_get_gpu (MetaRenderTarget *render_target); diff --git a/src/backends/native/meta-render-target-native.c b/src/backends/native/meta-render-target-native.c new file mode 100644 index 00000000000..f38ed54d5eb --- /dev/null +++ b/src/backends/native/meta-render-target-native.c @@ -0,0 +1,48 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2025 ? + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "config.h" + +#include "backends/native/meta-render-target-native.h" +#include "backends/native/meta-crtc-kms.h" +#include "backends/native/meta-kms-crtc.h" + +GPtrArray * +meta_render_target_native_get_crtc_kmses (MetaRenderTarget *render_target) +{ + GPtrArray *crtcs = meta_render_target_get_crtcs (render_target); + GPtrArray *ret = g_ptr_array_new_full (crtcs->len, g_object_unref); + for (guint i = 0; i < crtcs->len; i++) + { + g_ptr_array_add (ret, g_object_ref (META_CRTC_KMS (g_ptr_array_index (crtcs, i)))); + } + return ret; +} + +GPtrArray * +meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target) +{ + GPtrArray *crtcs = meta_render_target_get_crtcs (render_target); + GPtrArray *ret = g_ptr_array_new_full (crtcs->len, g_object_unref); + for (guint i = 0; i < crtcs->len; i++) + { + g_ptr_array_add (ret, g_object_ref (meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (g_ptr_array_index (crtcs, i))))); + } + return ret; +} diff --git a/src/backends/native/meta-render-target-native.h b/src/backends/native/meta-render-target-native.h new file mode 100644 index 00000000000..74c792187b5 --- /dev/null +++ b/src/backends/native/meta-render-target-native.h @@ -0,0 +1,36 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2025 ? + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +/* + * This is not a subclass of MetaRenderTarget, but rather a set of + * functions that makes sense in the context of the native backend. + */ + +#pragma once + +#include + +#include "backends/meta-render-target.h" + +/* Caller takes ownership of return value */ +GPtrArray * /* of type MetaCrtcKms * */ +meta_render_target_native_get_crtc_kmses (MetaRenderTarget *render_target); + +/* Caller takes ownership of return value */ +GPtrArray * /* of type MetaKmsCrtc * */ +meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target); diff --git a/src/meson.build b/src/meson.build index a19bb08b264..8b321cd6b6f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -249,6 +249,8 @@ mutter_sources = [ 'backends/meta-remote-access-controller.c', 'backends/meta-renderdoc.c', 'backends/meta-renderdoc.h', + 'backends/meta-render-target.c', + 'backends/meta-render-target.h', 'backends/meta-renderer.c', 'backends/meta-renderer.h', 'backends/meta-renderer-view.c', @@ -793,6 +795,8 @@ if have_native_backend 'backends/native/meta-render-device-surfaceless.h', 'backends/native/meta-render-device.c', 'backends/native/meta-render-device.h', + 'backends/native/meta-render-target-native.c', + 'backends/native/meta-render-target-native.h', 'backends/native/meta-renderer-native-gles3.c', 'backends/native/meta-renderer-native-gles3.h', 'backends/native/meta-renderer-native-private.h', -- GitLab From 0e1a292ca7059ae3f2776ad0881d25b3e4404446 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Fri, 28 Nov 2025 20:07:07 -0800 Subject: [PATCH 2/9] TILETEAR: MetaRendererView: PROP_CRTC -> PROP_RENDER_TARGET --- src/backends/meta-render-target.c | 19 ++++++++++++++ src/backends/meta-render-target.h | 3 +++ src/backends/meta-renderer-view.c | 25 ++++++++++--------- src/backends/meta-renderer-view.h | 3 ++- src/backends/meta-renderer.c | 2 +- .../native/meta-cursor-renderer-native.c | 3 ++- .../native/meta-render-target-native.c | 15 +++++++++++ .../native/meta-render-target-native.h | 2 ++ src/backends/native/meta-renderer-native.c | 9 ++++--- .../native/meta-renderer-view-native.c | 9 +++---- src/backends/native/meta-stage-native.c | 5 ++-- src/compositor/meta-compositor-view-native.c | 2 +- src/tests/meta-ref-test.c | 8 +++--- src/tests/native-kms-cursor-hotplug.c | 8 +++--- src/tests/native-kms-render.c | 3 ++- src/wayland/meta-wayland-dma-buf.c | 4 ++- src/wayland/meta-wayland-presentation-time.c | 4 ++- 17 files changed, 87 insertions(+), 37 deletions(-) diff --git a/src/backends/meta-render-target.c b/src/backends/meta-render-target.c index 117e9ea0ba0..fd7c03bb507 100644 --- a/src/backends/meta-render-target.c +++ b/src/backends/meta-render-target.c @@ -44,6 +44,12 @@ struct _MetaRenderTarget G_DEFINE_TYPE (MetaRenderTarget, meta_render_target, G_TYPE_OBJECT) +MetaRenderTarget * +meta_render_target_new (void) +{ + return g_object_new (META_TYPE_RENDER_TARGET, NULL); +} + void meta_render_target_add (MetaRenderTarget *render_target, MetaCrtc *crtc, @@ -74,6 +80,13 @@ meta_render_target_get_name (MetaRenderTarget *render_target) return meta_output_get_name (primary_output); } +gboolean +meta_render_target_has_crtc (MetaRenderTarget *render_target, + MetaCrtc *crtc) +{ + return g_ptr_array_find (render_target->crtcs, crtc, NULL); +} + GPtrArray * meta_render_target_get_crtcs (MetaRenderTarget *render_target) { @@ -115,6 +128,12 @@ meta_render_target_get_gpu (MetaRenderTarget *render_target) return meta_crtc_get_gpu (meta_render_target_get_primary_crtc (render_target)); } +MetaBackend * +meta_render_target_get_backend (MetaRenderTarget *render_target) +{ + return meta_crtc_get_backend (meta_render_target_get_primary_crtc (render_target)); +} + static void meta_render_target_dispose (GObject *object) { diff --git a/src/backends/meta-render-target.h b/src/backends/meta-render-target.h index 04689a181c4..f2e0eea5e9a 100644 --- a/src/backends/meta-render-target.h +++ b/src/backends/meta-render-target.h @@ -41,3 +41,6 @@ GPtrArray * meta_render_target_get_crtcs (MetaRenderTarget *render_target); GPtrArray * meta_render_target_get_outputs (MetaRenderTarget *render_target); MtkRectangle meta_render_target_get_view_layout (MetaRenderTarget *render_target); MetaGpu * meta_render_target_get_gpu (MetaRenderTarget *render_target); + +META_EXPORT_TEST +MetaBackend * meta_render_target_get_backend (MetaRenderTarget *render_target); diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c index 113d8fbbd6e..8fdc3470c1c 100644 --- a/src/backends/meta-renderer-view.c +++ b/src/backends/meta-renderer-view.c @@ -44,7 +44,7 @@ enum PROP_0, PROP_BACKEND, - PROP_CRTC, + PROP_RENDER_TARGET, PROP_COLOR_DEVICE, PROP_LAST @@ -55,20 +55,20 @@ static GParamSpec *obj_props[PROP_LAST]; typedef struct _MetaRendererViewPrivate { MetaBackend *backend; - MetaCrtc *crtc; + MetaRenderTarget *render_target; MetaColorDevice *color_device; } MetaRendererViewPrivate; G_DEFINE_TYPE_WITH_PRIVATE (MetaRendererView, meta_renderer_view, META_TYPE_STAGE_VIEW) -MetaCrtc * -meta_renderer_view_get_crtc (MetaRendererView *view) +MetaRenderTarget * +meta_renderer_view_get_render_target (MetaRendererView *view) { MetaRendererViewPrivate *priv = meta_renderer_view_get_instance_private (view); - return priv->crtc; + return priv->render_target; } static void @@ -134,8 +134,8 @@ meta_renderer_view_get_property (GObject *object, case PROP_BACKEND: g_value_set_object (value, priv->backend); break; - case PROP_CRTC: - g_value_set_object (value, priv->crtc); + case PROP_RENDER_TARGET: + g_value_set_object (value, priv->render_target); break; case PROP_COLOR_DEVICE: g_value_set_object (value, priv->color_device); @@ -161,8 +161,8 @@ meta_renderer_view_set_property (GObject *object, case PROP_BACKEND: priv->backend = g_value_get_object (value); break; - case PROP_CRTC: - priv->crtc = g_value_get_object (value); + case PROP_RENDER_TARGET: + priv->render_target = g_object_ref (g_value_get_object (value)); break; case PROP_COLOR_DEVICE: g_set_object (&priv->color_device, g_value_get_object (value)); @@ -202,6 +202,7 @@ meta_renderer_view_dispose (GObject *object) MetaRendererViewPrivate *priv = meta_renderer_view_get_instance_private (view); + g_clear_object (&priv->render_target); g_clear_object (&priv->color_device); G_OBJECT_CLASS (meta_renderer_view_parent_class)->dispose (object); @@ -229,9 +230,9 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_props[PROP_CRTC] = - g_param_spec_object ("crtc", NULL, NULL, - META_TYPE_CRTC, + obj_props[PROP_RENDER_TARGET] = + g_param_spec_object ("render-target", NULL, NULL, + META_TYPE_RENDER_TARGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); diff --git a/src/backends/meta-renderer-view.h b/src/backends/meta-renderer-view.h index e22b50f1248..67d18756f97 100644 --- a/src/backends/meta-renderer-view.h +++ b/src/backends/meta-renderer-view.h @@ -18,6 +18,7 @@ #pragma once #include "backends/meta-monitor-manager-private.h" +#include "backends/meta-render-target.h" #include "backends/meta-stage-impl-private.h" #include "backends/meta-stage-view-private.h" @@ -33,4 +34,4 @@ struct _MetaRendererViewClass }; META_EXPORT_TEST -MetaCrtc *meta_renderer_view_get_crtc (MetaRendererView *view); +MetaRenderTarget *meta_renderer_view_get_render_target (MetaRendererView *view); diff --git a/src/backends/meta-renderer.c b/src/backends/meta-renderer.c index 3fd80df2729..1b7140bcaaa 100644 --- a/src/backends/meta-renderer.c +++ b/src/backends/meta-renderer.c @@ -203,7 +203,7 @@ meta_renderer_get_view_for_crtc (MetaRenderer *renderer, { MetaRendererView *view = l->data; - if (meta_renderer_view_get_crtc (view) == crtc) + if (meta_render_target_has_crtc (meta_renderer_view_get_render_target (view), crtc)) return view; } diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index 821d675746c..ebfebd07e48 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -347,7 +347,8 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *cursor_renderer, { MetaStageView *view = l->data; MetaRendererView *renderer_view = META_RENDERER_VIEW (view); - MetaCrtc *crtc = meta_renderer_view_get_crtc (renderer_view); + MetaRenderTarget *render_target = meta_renderer_view_get_render_target (renderer_view); + MetaCrtc *crtc = meta_render_target_get_primary_crtc (render_target); MetaCrtcNative *crtc_native = META_CRTC_NATIVE (crtc); MetaGpu *gpu = meta_crtc_get_gpu (crtc); ClutterColorState *target_color_state = diff --git a/src/backends/native/meta-render-target-native.c b/src/backends/native/meta-render-target-native.c index f38ed54d5eb..dbe80908da7 100644 --- a/src/backends/native/meta-render-target-native.c +++ b/src/backends/native/meta-render-target-native.c @@ -46,3 +46,18 @@ meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target) } return ret; } + +int64_t +meta_render_target_native_get_deadline_evasion (MetaRenderTarget *render_target) +{ + int64_t deadline_evasion_us = INT64_MIN; + GPtrArray *crtcs = meta_render_target_get_crtcs (render_target); + for (guint i = 0; i < crtcs->len; i++) + { + MetaCrtc *crtc = g_ptr_array_index (crtcs, i); + MetaCrtcNative *crtc_native = META_CRTC_NATIVE (crtc); + deadline_evasion_us = MAX (deadline_evasion_us, + meta_crtc_native_get_deadline_evasion (crtc_native)); + } + return deadline_evasion_us; +} diff --git a/src/backends/native/meta-render-target-native.h b/src/backends/native/meta-render-target-native.h index 74c792187b5..0cea046837f 100644 --- a/src/backends/native/meta-render-target-native.h +++ b/src/backends/native/meta-render-target-native.h @@ -34,3 +34,5 @@ meta_render_target_native_get_crtc_kmses (MetaRenderTarget *render_target); /* Caller takes ownership of return value */ GPtrArray * /* of type MetaKmsCrtc * */ meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target); + +int64_t meta_render_target_native_get_deadline_evasion (MetaRenderTarget *render_target); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index bd2bd262420..9719a5e4ffc 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -843,10 +843,10 @@ free_unused_gpu_datas (MetaRendererNative *renderer_native) for (l = meta_renderer_get_views (renderer); l; l = l->next) { MetaRendererView *view = l->data; - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); + MetaRenderTarget *render_target = meta_renderer_view_get_render_target (view); MetaGpu *gpu; - gpu = meta_crtc_get_gpu (crtc); + gpu = meta_render_target_get_gpu (render_target); if (!gpu) continue; @@ -1531,6 +1531,9 @@ meta_renderer_native_create_view (MetaRenderer *renderer, MetaRendererViewNative *view_native; EGLSurface egl_surface; GError *local_error = NULL; + // ADLRTODO: don't leak render_target here. Instead, receive it as argument to this function. + MetaRenderTarget *render_target = meta_render_target_new (); + meta_render_target_add (render_target, crtc, output); crtc_config = meta_crtc_get_config (crtc); crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); @@ -1615,7 +1618,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, "color-device", color_device, "stage", meta_backend_get_stage (backend), "layout", &view_layout, - "crtc", crtc, + "render-target", render_target, "scale", scale, "framebuffer", framebuffer, "use-shadowfb", use_shadowfb, diff --git a/src/backends/native/meta-renderer-view-native.c b/src/backends/native/meta-renderer-view-native.c index 5699f9a558e..f7f30345a61 100644 --- a/src/backends/native/meta-renderer-view-native.c +++ b/src/backends/native/meta-renderer-view-native.c @@ -26,6 +26,7 @@ #include "backends/native/meta-crtc-native.h" #include "backends/native/meta-frame-native.h" +#include "backends/native/meta-render-target-native.h" struct _MetaRendererViewNative { @@ -40,15 +41,13 @@ update_frame_clock_deadline_evasion (MetaRendererView *renderer_view) { ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (renderer_view); ClutterFrameClock *frame_clock; - MetaCrtc *crtc; - MetaCrtcNative *crtc_native; + MetaRenderTarget *render_target; int64_t deadline_evasion_us; frame_clock = clutter_stage_view_get_frame_clock (stage_view); - crtc = meta_renderer_view_get_crtc (renderer_view); - crtc_native = META_CRTC_NATIVE (crtc); + render_target = meta_renderer_view_get_render_target (renderer_view); - deadline_evasion_us = meta_crtc_native_get_deadline_evasion (crtc_native); + deadline_evasion_us = meta_render_target_native_get_deadline_evasion (render_target); clutter_frame_clock_set_deadline_evasion (frame_clock, deadline_evasion_us); } diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c index 52f87b8d603..63e8458ea68 100644 --- a/src/backends/native/meta-stage-native.c +++ b/src/backends/native/meta-stage-native.c @@ -123,15 +123,16 @@ meta_stage_native_redraw_view (ClutterStageWindow *stage_window, MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); MetaBackend *backend = meta_stage_impl_get_backend (stage_impl); MetaRenderer *renderer = meta_backend_get_renderer (backend); + MetaRenderTarget *render_target = meta_renderer_view_get_render_target (META_RENDERER_VIEW (view)); MetaCrtc *crtc; meta_renderer_native_before_redraw (META_RENDERER_NATIVE (renderer), META_RENDERER_VIEW (view), frame); CLUTTER_STAGE_WINDOW_CLASS (meta_stage_native_parent_class)-> - redraw_view (stage_window, view, frame); + redraw_view (stage_window, view, frame); - crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (view)); + crtc = meta_render_target_get_primary_crtc (render_target); if (!clutter_frame_has_result (frame)) { diff --git a/src/compositor/meta-compositor-view-native.c b/src/compositor/meta-compositor-view-native.c index 580172f7382..acb163fac46 100644 --- a/src/compositor/meta-compositor-view-native.c +++ b/src/compositor/meta-compositor-view-native.c @@ -204,7 +204,7 @@ find_scanout_candidate (MetaCompositorView *compositor_view, } } - crtc = meta_renderer_view_get_crtc (renderer_view); + crtc = meta_render_target_get_primary_crtc (meta_renderer_view_get_render_target (renderer_view)); if (!META_IS_CRTC_KMS (crtc)) { meta_topic (META_DEBUG_RENDER, diff --git a/src/tests/meta-ref-test.c b/src/tests/meta-ref-test.c index 9b0a689ce92..f380c6f1eec 100644 --- a/src/tests/meta-ref-test.c +++ b/src/tests/meta-ref-test.c @@ -150,8 +150,8 @@ capture_view (ClutterStageView *stage_view, gboolean queue_damage) { MetaRendererView *view = META_RENDERER_VIEW (stage_view); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaBackend *backend = meta_crtc_get_backend (crtc); + MetaRenderTarget *render_target = meta_renderer_view_get_render_target (view); + MetaBackend *backend = meta_render_target_get_backend (render_target); MetaStage *stage = META_STAGE (meta_backend_get_stage (backend)); MetaContext *context = meta_backend_get_context (backend); MetaDisplay *display = meta_context_get_display (context); @@ -202,8 +202,8 @@ static void assert_software_rendered (ClutterStageView *stage_view) { MetaRendererView *view = META_RENDERER_VIEW (stage_view); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaBackend *backend = meta_crtc_get_backend (crtc); + MetaRenderTarget *render_target = meta_renderer_view_get_render_target (view); + MetaBackend *backend = meta_render_target_get_backend (render_target); g_assert_false (meta_backend_is_rendering_hardware_accelerated (backend)); } diff --git a/src/tests/native-kms-cursor-hotplug.c b/src/tests/native-kms-cursor-hotplug.c index 0b5b2c31ee8..3ecc4279634 100644 --- a/src/tests/native-kms-cursor-hotplug.c +++ b/src/tests/native-kms-cursor-hotplug.c @@ -181,8 +181,8 @@ meta_test_hotplug_multi_view_invalidation (void) meta_monitor_manager_reload (monitor_manager); views = meta_renderer_get_views (renderer); - g_assert_true (META_IS_CRTC_KMS (meta_renderer_view_get_crtc (views->data))); - g_assert_true (META_IS_CRTC_VIRTUAL (meta_renderer_view_get_crtc (views->next->data))); + g_assert_true (META_IS_CRTC_KMS (meta_render_target_get_primary_crtc (meta_renderer_view_get_render_target (views->data)))); + g_assert_true (META_IS_CRTC_VIRTUAL (meta_render_target_get_primary_crtc (meta_renderer_view_get_render_target (views->next->data)))); meta_wait_for_paint (test_context); @@ -200,8 +200,8 @@ meta_test_hotplug_multi_view_invalidation (void) META_MONITORS_CONFIG_FLAG_NONE); meta_monitor_manager_reload (monitor_manager); views = meta_renderer_get_views (renderer); - g_assert_true (META_IS_CRTC_KMS (meta_renderer_view_get_crtc (views->data))); - g_assert_true (META_IS_CRTC_VIRTUAL (meta_renderer_view_get_crtc (views->next->data))); + g_assert_true (META_IS_CRTC_KMS (meta_render_target_get_primary_crtc (meta_renderer_view_get_render_target (views->data)))); + g_assert_true (META_IS_CRTC_VIRTUAL (meta_render_target_get_primary_crtc (meta_renderer_view_get_render_target (views->next->data)))); g_assert_true (texture_changed); g_signal_handler_disconnect (cursor_sprite, texture_changed_handler_id); diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c index e7881c8ef6b..00309300700 100644 --- a/src/tests/native-kms-render.c +++ b/src/tests/native-kms-render.c @@ -353,7 +353,8 @@ on_scanout_fallback_before_paint (ClutterStage *stage, KmsRenderingTest *test) { MetaRendererView *view = META_RENDERER_VIEW (stage_view); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); + MetaRenderTarget *render_target = meta_renderer_view_get_render_target (view); + MetaCrtc *crtc = meta_render_target_get_primary_crtc (render_target); MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c index 13c6f9d4092..ad5f85939aa 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c @@ -655,6 +655,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandBuffer *buffer, #ifdef HAVE_NATIVE_BACKEND MetaWaylandDmaBufBuffer *dma_buf; MetaRendererView *renderer_view = META_RENDERER_VIEW (stage_view); + MetaRenderTarget *render_target; MetaCrtc *crtc; MetaCrtcKms *crtc_kms; MetaContext *context; @@ -677,7 +678,8 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandBuffer *buffer, if (!dma_buf) return NULL; - crtc = meta_renderer_view_get_crtc (renderer_view); + render_target = meta_renderer_view_get_render_target (renderer_view); + crtc = meta_render_target_get_primary_crtc (render_target); g_return_val_if_fail (META_IS_CRTC_KMS (crtc), NULL); crtc_kms = META_CRTC_KMS (crtc); diff --git a/src/wayland/meta-wayland-presentation-time.c b/src/wayland/meta-wayland-presentation-time.c index 9a5f6eb4876..df8710f4684 100644 --- a/src/wayland/meta-wayland-presentation-time.c +++ b/src/wayland/meta-wayland-presentation-time.c @@ -406,11 +406,13 @@ static MetaWaylandOutput * get_output_for_stage_view (MetaWaylandCompositor *compositor, ClutterStageView *stage_view) { + MetaRenderTarget *render_target; MetaCrtc *crtc; MetaOutput *output; MetaMonitor *monitor; - crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view)); + render_target = meta_renderer_view_get_render_target (META_RENDERER_VIEW (stage_view)); + crtc = meta_render_target_get_primary_crtc (render_target); /* * All outputs occupy the same region of the screen, as their contents are -- GitLab From 0abbc928ca3f5156b93f54f7f3021bd13b1b46a7 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Fri, 28 Nov 2025 21:02:03 -0800 Subject: [PATCH 3/9] TILETEAR: Add meta_render_target_native_foreach_crtc_kms macro Also, accessor for primary MetaCrtcKms --- src/backends/native/meta-render-target-native.c | 6 ++++++ src/backends/native/meta-render-target-native.h | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/backends/native/meta-render-target-native.c b/src/backends/native/meta-render-target-native.c index dbe80908da7..8b46f9c1be4 100644 --- a/src/backends/native/meta-render-target-native.c +++ b/src/backends/native/meta-render-target-native.c @@ -23,6 +23,12 @@ #include "backends/native/meta-crtc-kms.h" #include "backends/native/meta-kms-crtc.h" +MetaCrtcKms * +meta_render_target_native_get_primary_crtc_kms (MetaRenderTarget *render_target) +{ + return META_CRTC_KMS (meta_render_target_get_primary_crtc (render_target)); +} + GPtrArray * meta_render_target_native_get_crtc_kmses (MetaRenderTarget *render_target) { diff --git a/src/backends/native/meta-render-target-native.h b/src/backends/native/meta-render-target-native.h index 0cea046837f..174852c3f3c 100644 --- a/src/backends/native/meta-render-target-native.h +++ b/src/backends/native/meta-render-target-native.h @@ -26,6 +26,10 @@ #include #include "backends/meta-render-target.h" +#include "backends/native/meta-crtc-kms.h" + +MetaCrtcKms * +meta_render_target_native_get_primary_crtc_kms (MetaRenderTarget *render_target); /* Caller takes ownership of return value */ GPtrArray * /* of type MetaCrtcKms * */ @@ -36,3 +40,11 @@ GPtrArray * /* of type MetaKmsCrtc * */ meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target); int64_t meta_render_target_native_get_deadline_evasion (MetaRenderTarget *render_target); + +#define meta_render_target_native_foreach_crtc_kms(crtc_kms_decl, render_target) \ + for (guint keep = 1, \ + count = 0, \ + size = meta_render_target_get_crtcs (render_target)->len; \ + keep && count != size; \ + keep = !keep, count++) \ + for(crtc_kms_decl = META_CRTC_KMS (g_ptr_array_index (meta_render_target_get_crtcs (render_target), count)); keep; keep = !keep) -- GitLab From 13600f822314e3433ba940d342ccb771341e6ddb Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Fri, 28 Nov 2025 21:08:38 -0800 Subject: [PATCH 4/9] TILETEAR: MetaCursorRenderNative: Render cursor on all crtcs in render target --- .../native/meta-cursor-renderer-native.c | 60 ++++++++++++------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index ebfebd07e48..d000ec67dc1 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -48,6 +48,7 @@ #include "backends/native/meta-kms-plane.h" #include "backends/native/meta-kms-update.h" #include "backends/native/meta-kms.h" +#include "backends/native/meta-render-target-native.h" #include "backends/native/meta-renderer-native.h" #include "backends/native/meta-seat-native.h" #include "common/meta-cogl-drm-formats.h" @@ -118,10 +119,10 @@ static GQuark quark_cursor_stage_view = 0; G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); static gboolean -realize_cursor_sprite_for_crtc (MetaCursorRenderer *renderer, - MetaCrtcKms *crtc_kms, - ClutterColorState *target_color_state, - MetaCursorSprite *cursor_sprite); +realize_cursor_sprite_for_render_target (MetaCursorRenderer *renderer, + MetaRenderTarget *render_target, + ClutterColorState *target_color_state, + MetaCursorSprite *cursor_sprite); static void meta_cursor_renderer_native_invalidate_gpu_state (MetaCursorRendererNative *native); @@ -348,9 +349,9 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *cursor_renderer, MetaStageView *view = l->data; MetaRendererView *renderer_view = META_RENDERER_VIEW (view); MetaRenderTarget *render_target = meta_renderer_view_get_render_target (renderer_view); - MetaCrtc *crtc = meta_render_target_get_primary_crtc (render_target); - MetaCrtcNative *crtc_native = META_CRTC_NATIVE (crtc); - MetaGpu *gpu = meta_crtc_get_gpu (crtc); + MetaCrtc *primary_crtc = meta_render_target_get_primary_crtc (render_target); + MetaCrtcNative *primary_crtc_native = META_CRTC_NATIVE (primary_crtc); + MetaGpu *gpu = meta_render_target_get_gpu (render_target); ClutterColorState *target_color_state = clutter_stage_view_get_output_color_state (CLUTTER_STAGE_VIEW (view)); CursorStageView *cursor_stage_view = NULL; @@ -359,9 +360,9 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *cursor_renderer, cursor_stage_view = get_cursor_stage_view (view); g_assert (cursor_stage_view); - if (!META_IS_CRTC_KMS (crtc) || + if (!META_IS_CRTC_KMS (primary_crtc) || !is_hw_cursor_available_for_gpu (META_GPU_KMS (gpu)) || - !meta_crtc_native_is_hw_cursor_supported (crtc_native)) + !meta_crtc_native_is_hw_cursor_supported (primary_crtc_native)) { cursor_stage_view->is_hw_cursor_valid = TRUE; has_hw_cursor = FALSE; @@ -373,10 +374,10 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *cursor_renderer, if (cursor_changed || !cursor_stage_view->is_hw_cursor_valid) { - has_hw_cursor = realize_cursor_sprite_for_crtc (cursor_renderer, - META_CRTC_KMS (crtc), - target_color_state, - cursor_sprite); + has_hw_cursor = realize_cursor_sprite_for_render_target (cursor_renderer, + render_target, + target_color_state, + cursor_sprite); cursor_stage_view->is_hw_cursor_valid = TRUE; } @@ -407,14 +408,14 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *cursor_renderer, if (!has_hw_cursor) { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - - meta_kms_cursor_manager_update_sprite (kms_cursor_manager, - kms_crtc, - NULL, - MTK_MONITOR_TRANSFORM_NORMAL, - NULL); + meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, render_target) + { + meta_kms_cursor_manager_update_sprite (kms_cursor_manager, + kms_crtc, + NULL, + MTK_MONITOR_TRANSFORM_NORMAL, + NULL); + } } } } @@ -1253,6 +1254,23 @@ realize_cursor_sprite_for_crtc (MetaCursorRenderer *renderer, } } +static gboolean +realize_cursor_sprite_for_render_target (MetaCursorRenderer *renderer, + MetaRenderTarget *render_target, + ClutterColorState *target_color_state, + MetaCursorSprite *cursor_sprite) +{ + gboolean success = TRUE; + meta_render_target_native_foreach_crtc_kms (MetaCrtcKms * crtc_kms, render_target) + { + gboolean r = realize_cursor_sprite_for_crtc (renderer, crtc_kms, target_color_state, cursor_sprite); + if (crtc_kms != meta_render_target_native_get_primary_crtc_kms (render_target)) + g_warn_if_fail (r == success); + success = r; + } + return success; +} + static void meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) { -- GitLab From 0798f947aa1252e5134639c56d2a6caba5e78ed2 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Sat, 29 Nov 2025 21:41:58 -0800 Subject: [PATCH 5/9] TILETEAR: MetaOnscreenNative: hold a MetaRenderTarget It no longer holds one MetaCrtc and one MetaOutput. --- src/backends/meta-render-target.c | 24 ++ src/backends/meta-render-target.h | 2 + src/backends/native/meta-onscreen-native.c | 220 +++++++++++------- .../native/meta-render-target-native.c | 18 ++ .../native/meta-render-target-native.h | 36 ++- src/tests/native-kms-render.c | 4 +- 6 files changed, 213 insertions(+), 91 deletions(-) diff --git a/src/backends/meta-render-target.c b/src/backends/meta-render-target.c index fd7c03bb507..d060ca45cfa 100644 --- a/src/backends/meta-render-target.c +++ b/src/backends/meta-render-target.c @@ -128,6 +128,30 @@ meta_render_target_get_gpu (MetaRenderTarget *render_target) return meta_crtc_get_gpu (meta_render_target_get_primary_crtc (render_target)); } +MtkRectangle +meta_render_target_get_output_tile_frame (MetaRenderTarget *render_target, + MetaOutput *output) +{ + const MetaOutputInfo *output_info = meta_output_get_info (output); + MtkRectangle tile_frame = MTK_RECTANGLE_INIT (0, 0, output_info->tile_info.tile_w, output_info->tile_info.tile_h); + for (guint i = 0; i < render_target->outputs->len; i++) + { + MetaOutput *other_output = g_ptr_array_index (render_target->outputs, i); + const MetaOutputInfo *other_output_info = meta_output_get_info (other_output); + if (output_info->tile_info.loc_v_tile == other_output_info->tile_info.loc_v_tile && + output_info->tile_info.loc_h_tile > other_output_info->tile_info.loc_h_tile) + { + tile_frame.x += other_output_info->tile_info.tile_w; + } + if (output_info->tile_info.loc_h_tile == other_output_info->tile_info.loc_h_tile && + output_info->tile_info.loc_v_tile > other_output_info->tile_info.loc_v_tile) + { + tile_frame.y += other_output_info->tile_info.tile_h; + } + } + return tile_frame; +} + MetaBackend * meta_render_target_get_backend (MetaRenderTarget *render_target) { diff --git a/src/backends/meta-render-target.h b/src/backends/meta-render-target.h index f2e0eea5e9a..fd14315be04 100644 --- a/src/backends/meta-render-target.h +++ b/src/backends/meta-render-target.h @@ -41,6 +41,8 @@ GPtrArray * meta_render_target_get_crtcs (MetaRenderTarget *render_target); GPtrArray * meta_render_target_get_outputs (MetaRenderTarget *render_target); MtkRectangle meta_render_target_get_view_layout (MetaRenderTarget *render_target); MetaGpu * meta_render_target_get_gpu (MetaRenderTarget *render_target); +MtkRectangle meta_render_target_get_output_tile_frame (MetaRenderTarget *render_target, + MetaOutput *output); META_EXPORT_TEST MetaBackend * meta_render_target_get_backend (MetaRenderTarget *render_target); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 3b3080876b2..0247f48ac5c 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -48,6 +48,7 @@ #include "backends/native/meta-output-kms.h" #include "backends/native/meta-render-device-gbm.h" #include "backends/native/meta-render-device.h" +#include "backends/native/meta-render-target-native.h" #include "backends/native/meta-renderer-native-gles3.h" #include "backends/native/meta-renderer-native-private.h" #include "backends/native/meta-egl-gbm.h" @@ -119,8 +120,7 @@ struct _MetaOnscreenNative MetaRendererNative *renderer_native; MetaGpuKms *render_gpu; - MetaOutput *output; - MetaCrtc *crtc; + MetaRenderTarget *render_target; MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; @@ -597,6 +597,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, ClutterFrame *frame, MetaRendererView *view, MetaCrtc *crtc, + MtkRectangle output_frame, MetaKmsUpdate *kms_update, MetaKmsAssignPlaneFlag flags, const MtkRegion *region) @@ -638,20 +639,30 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, { cogl_scanout_get_src_rect (scanout, &src_rect); cogl_scanout_get_dst_rect (scanout, &dst_rect); + // If tiled display, get just the tile + if (dst_rect.width > output_frame.width || dst_rect.height > output_frame.height) + { + src_rect.origin.x += output_frame.x; + src_rect.origin.y += output_frame.y; + src_rect.size.width = output_frame.width; + src_rect.size.height = output_frame.height; + dst_rect.width = output_frame.width; + dst_rect.height = output_frame.height; + } } else { src_rect = (graphene_rect_t) { - .origin.x = 0, - .origin.y = 0, - .size.width = meta_drm_buffer_get_width (buffer), - .size.height = meta_drm_buffer_get_height (buffer) + .origin.x = output_frame.x, + .origin.y = output_frame.y, + .size.width = output_frame.width, + .size.height = output_frame.height }; dst_rect = (MtkRectangle) { .x = 0, .y = 0, - .width = meta_drm_buffer_get_width (buffer), - .height = meta_drm_buffer_get_height (buffer) + .width = output_frame.width, + .height = output_frame.height }; } @@ -687,6 +698,35 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, return TRUE; } +static gboolean +meta_onscreen_native_flip_render_target (CoglOnscreen *onscreen, + ClutterFrame *frame, + MetaRendererView *view, + MetaRenderTarget *render_target, + MetaKmsUpdate *kms_update, + MetaKmsAssignPlaneFlag flags, + const MtkRegion *region) +{ + MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); + MetaDrmBuffer *buffer = meta_frame_native_get_buffer (frame_native); + if (!buffer) + return FALSE; + GPtrArray *crtcs = meta_render_target_get_crtcs (render_target); + GPtrArray *outputs = meta_render_target_get_outputs (render_target); + MtkRectangle output_frame = MTK_RECTANGLE_INIT (0, 0, meta_drm_buffer_get_width (buffer), meta_drm_buffer_get_height (buffer)); + + g_assert (crtcs->len == outputs->len); + for (guint i = 0; i < crtcs->len; i++) + { + MetaCrtc *crtc = g_ptr_array_index (crtcs, i); + MetaOutput *output = g_ptr_array_index (outputs, i); + if (crtcs->len > 1) /* If we have a tiled display, get output frame */ + output_frame = meta_render_target_get_output_tile_frame (render_target, output); + meta_onscreen_native_flip_crtc (onscreen, frame, view, crtc, output_frame, kms_update, flags, region); + } + return TRUE; +} + static void set_underscan (MetaOutputKms *output_kms, MetaKmsUpdate *kms_update) @@ -808,7 +848,6 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, MetaRendererNativeGpuData *renderer_gpu_data) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes, "Meta::OnscreenNative::set_crtc_mode()"); @@ -823,6 +862,7 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: { + MetaCrtcKms *primary_crtc_kms = meta_render_target_native_get_primary_crtc_kms (onscreen_native->render_target); MetaDrmBuffer *buffer; graphene_rect_t src_rect; MtkRectangle dst_rect; @@ -843,7 +883,7 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, .height = meta_drm_buffer_get_height (buffer) }; - assign_primary_plane (crtc_kms, + assign_primary_plane (primary_crtc_kms, buffer, kms_update, META_KMS_ASSIGN_PLANE_FLAG_NONE, @@ -854,11 +894,17 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, #endif } - meta_crtc_kms_set_mode (crtc_kms, kms_update); - set_underscan (META_OUTPUT_KMS (onscreen_native->output), kms_update); - set_max_bpc (META_OUTPUT_KMS (onscreen_native->output), kms_update); - set_rgb_range (META_OUTPUT_KMS (onscreen_native->output), kms_update); - set_color_mode (META_OUTPUT_KMS (onscreen_native->output), kms_update); + meta_render_target_native_foreach_crtc_kms (MetaCrtcKms * crtc_kms, onscreen_native->render_target) + { + meta_crtc_kms_set_mode (crtc_kms, kms_update); + } + meta_render_target_native_foreach_output_kms (MetaOutputKms * meta_output_kms, onscreen_native->render_target) + { + set_underscan (meta_output_kms, kms_update); + set_max_bpc (meta_output_kms, kms_update); + set_rgb_range (meta_output_kms, kms_update); + set_color_mode (meta_output_kms, kms_update); + } } static void @@ -1755,11 +1801,11 @@ maybe_post_next_frame (CoglOnscreen *onscreen) MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOutputKms *output_kms = META_OUTPUT_KMS (onscreen_native->output); + MetaOutputKms *primary_output_kms = META_OUTPUT_KMS (meta_render_target_get_primary_output (onscreen_native->render_target)); MetaKmsConnector *kms_connector = - meta_output_kms_get_kms_connector (output_kms); + meta_output_kms_get_kms_connector (primary_output_kms); MetaPowerSave power_save_mode; - MetaKmsCrtc *kms_crtc; + MetaKmsCrtc *primary_kms_crtc; MetaKmsDevice *kms_device; MetaKmsUpdate *kms_update; g_autoptr (MetaKmsFeedback) kms_feedback = NULL; @@ -1795,8 +1841,8 @@ maybe_post_next_frame (CoglOnscreen *onscreen) clear_superseded_frame (onscreen); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); + primary_kms_crtc = meta_render_target_native_get_primary_kms_crtc (onscreen_native->render_target); + kms_device = meta_render_target_native_get_kms_device (onscreen_native->render_target); kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); @@ -1819,13 +1865,13 @@ maybe_post_next_frame (CoglOnscreen *onscreen) NULL); ensure_crtc_modes (onscreen, kms_update); - if (!meta_onscreen_native_flip_crtc (onscreen, - frame, - onscreen_native->view, - onscreen_native->crtc, - kms_update, - flip_flags, - region)) + if (!meta_onscreen_native_flip_render_target (onscreen, + frame, + onscreen_native->view, + onscreen_native->render_target, + kms_update, + flip_flags, + region)) { kms_update = meta_frame_native_steal_kms_update (frame_native); post_nonprimary_plane_update (onscreen_native, frame, kms_update); @@ -1845,7 +1891,7 @@ maybe_post_next_frame (CoglOnscreen *onscreen) { meta_topic (META_DEBUG_KMS, "Postponing primary plane composite update for CRTC %u (%s) to %s", - meta_kms_crtc_get_id (kms_crtc), + meta_kms_crtc_get_id (primary_kms_crtc), meta_kms_device_get_path (kms_device), meta_kms_connector_get_name (kms_connector)); @@ -1889,7 +1935,7 @@ maybe_post_next_frame (CoglOnscreen *onscreen) meta_topic (META_DEBUG_KMS, "Posting primary plane %s update for CRTC %u (%s) to %s", is_direct_scanout ? "direct scanout" : "composite", - meta_kms_crtc_get_id (kms_crtc), + meta_kms_crtc_get_id (primary_kms_crtc), meta_kms_device_get_path (kms_device), meta_kms_connector_get_name (kms_connector)); @@ -1908,9 +1954,7 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, CoglScanout *scanout) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtc *crtc = onscreen_native->crtc; - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - MetaGpuKms *gpu_kms; + MetaCrtcKms *crtc_kms = meta_render_target_native_get_primary_crtc_kms (onscreen_native->render_target); MetaKmsDevice *kms_device; MetaKmsCrtc *kms_crtc; MetaKmsUpdate *test_update; @@ -1920,8 +1964,7 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, graphene_rect_t src_rect; MtkRectangle dst_rect; - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); + kms_device = meta_render_target_native_get_kms_device (onscreen_native->render_target); kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); test_update = meta_kms_update_new (kms_device); @@ -2090,8 +2133,7 @@ static void maybe_update_frame_sync (MetaOnscreenNative *onscreen_native, ClutterFrame *frame) { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + MetaKmsCrtc *kms_crtc = meta_render_target_native_get_primary_kms_crtc (onscreen_native->render_target); MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); const MetaKmsCrtcState *crtc_state = meta_kms_crtc_get_current_state (kms_crtc); @@ -2103,13 +2145,13 @@ maybe_update_frame_sync (MetaOnscreenNative *onscreen_native, MetaKmsUpdate *kms_update; gboolean frame_sync_enabled = FALSE; - if (meta_output_is_vrr_enabled (onscreen_native->output)) + if (meta_output_is_vrr_enabled (meta_render_target_get_primary_output (onscreen_native->render_target))) frame_sync_enabled = onscreen_native->frame_sync_requested; if (frame_sync_enabled != onscreen_native->frame_sync_enabled) { frame_clock_mode = frame_sync_enabled ? CLUTTER_FRAME_CLOCK_MODE_VARIABLE : - CLUTTER_FRAME_CLOCK_MODE_FIXED; + CLUTTER_FRAME_CLOCK_MODE_FIXED; clutter_frame_clock_set_mode (frame_clock, frame_clock_mode); onscreen_native->frame_sync_enabled = frame_sync_enabled; } @@ -2130,8 +2172,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, if (meta_get_debug_paint_flags () & META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY) { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + MetaKmsCrtc *kms_crtc = meta_render_target_native_get_primary_kms_crtc (onscreen_native->render_target); meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), kms_crtc); } @@ -2144,10 +2185,10 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen, ClutterFrame *frame) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaOutputKms *output_kms = META_OUTPUT_KMS (onscreen_native->output); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);; + MetaCrtcKms *crtc_kms = meta_render_target_native_get_primary_crtc_kms (onscreen_native->render_target); + MetaOutputKms *output_kms = meta_render_target_native_get_primary_output_kms (onscreen_native->render_target); + MetaKmsCrtc *primary_kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (primary_kms_crtc);; MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); int64_t target_frame_counter = cogl_onscreen_get_frame_counter (onscreen); @@ -2160,7 +2201,10 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen, kms_device); gamma = meta_crtc_kms_peek_gamma_lut (crtc_kms); - meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, gamma); + meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) + { + meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, gamma); + } onscreen_native->property.gamma_lut.invalidated = FALSE; onscreen_native->property.gamma_lut.target_frame_counter = target_frame_counter; @@ -2176,7 +2220,7 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen, kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); - enabled = meta_output_is_privacy_screen_enabled (onscreen_native->output); + enabled = meta_output_is_privacy_screen_enabled (meta_render_target_get_primary_output (onscreen_native->render_target)); meta_kms_update_set_privacy_screen (kms_update, kms_connector, enabled); onscreen_native->property.privacy_screen.invalidated = FALSE; onscreen_native->property.privacy_screen.target_frame_counter = @@ -2227,14 +2271,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, ClutterFrame *frame) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtc *crtc = onscreen_native->crtc; - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + // MetaCrtc *crtc = onscreen_native->crtc; + // MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); + MetaKmsDevice *kms_device = meta_render_target_native_get_kms_device (onscreen_native->render_target); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; - onscreen_native->needs_flush |= meta_kms_device_handle_flush (kms_device, - kms_crtc); + meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) + { + onscreen_native->needs_flush |= meta_kms_device_handle_flush (kms_device, + kms_crtc); + } if (!meta_frame_native_has_kms_update (frame_native)) { @@ -2283,7 +2330,10 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, if (onscreen_native->needs_flush) { - meta_kms_update_set_flushing (kms_update, kms_crtc); + meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) + { + meta_kms_update_set_flushing (kms_update, kms_crtc); + } onscreen_native->needs_flush = FALSE; } @@ -2298,9 +2348,9 @@ post_nonprimary_plane_update (MetaOnscreenNative *onscreen_native, ClutterFrame *frame, MetaKmsUpdate *kms_update) { - MetaCrtc *crtc = onscreen_native->crtc; - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + MetaCrtc *primary_crtc = meta_render_target_get_primary_crtc (onscreen_native->render_target); + MetaKmsCrtc *primary_kms_crtc = meta_render_target_native_get_primary_kms_crtc (onscreen_native->render_target); + MetaKmsDevice *kms_device = meta_render_target_native_get_kms_device (onscreen_native->render_target); g_autoptr (MetaKmsFeedback) kms_feedback = NULL; meta_kms_update_add_result_listener (kms_update, @@ -2309,20 +2359,26 @@ post_nonprimary_plane_update (MetaOnscreenNative *onscreen_native, onscreen_native, NULL); - meta_kms_update_add_page_flip_listener (kms_update, - kms_crtc, - &page_flip_listener_vtable, - NULL, - g_object_ref (onscreen_native->view), - g_object_unref); - add_onscreen_frame_info (crtc, frame); + meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) + { + meta_kms_update_add_page_flip_listener (kms_update, + kms_crtc, + &page_flip_listener_vtable, + NULL, + g_object_ref (onscreen_native->view), + g_object_unref); + } + add_onscreen_frame_info (primary_crtc, frame); meta_topic (META_DEBUG_KMS, "Posting non-primary plane update for CRTC %u (%s)", - meta_kms_crtc_get_id (kms_crtc), + meta_kms_crtc_get_id (primary_kms_crtc), meta_kms_device_get_path (kms_device)); - meta_kms_update_set_flushing (kms_update, kms_crtc); + meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) + { + meta_kms_update_set_flushing (kms_update, kms_crtc); + } meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); } @@ -2356,7 +2412,7 @@ should_surface_be_sharable (CoglOnscreen *onscreen) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) == + if (META_GPU_KMS (meta_render_target_get_gpu (onscreen_native->render_target)) == onscreen_native->render_gpu) return FALSE; else @@ -2435,7 +2491,7 @@ get_supported_modifiers (CoglOnscreen *onscreen, uint32_t format) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); + MetaCrtcKms *crtc_kms = meta_render_target_native_get_primary_crtc_kms (onscreen_native->render_target); MetaGpu *gpu; g_autoptr (GArray) modifiers = NULL; @@ -2452,7 +2508,7 @@ static GArray * get_supported_kms_formats (CoglOnscreen *onscreen) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); + MetaCrtcKms *crtc_kms = meta_render_target_native_get_primary_crtc_kms (onscreen_native->render_target); MetaKmsPlane *plane = meta_crtc_kms_get_assigned_primary_plane (crtc_kms); return meta_kms_plane_copy_drm_format_list (plane); @@ -2471,7 +2527,7 @@ choose_onscreen_egl_config (CoglOnscreen *onscreen, CoglRendererEGL *cogl_renderer_egl = cogl_renderer_get_winsys_data (cogl_renderer); EGLDisplay egl_display = cogl_renderer_egl->edpy; MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); + MetaCrtcKms *crtc_kms = meta_render_target_native_get_primary_crtc_kms (onscreen_native->render_target); MetaKmsPlane *kms_plane = meta_crtc_kms_get_assigned_primary_plane (crtc_kms); EGLint attrs[COGL_MAX_EGL_CONFIG_ATTRIBS]; static const uint32_t alphaless_10bpc_formats[] = { @@ -2688,7 +2744,7 @@ create_surfaces_egl_device (CoglOnscreen *onscreen, return FALSE; output_attribs[0] = EGL_DRM_CRTC_EXT; - output_attribs[1] = meta_crtc_get_id (onscreen_native->crtc); + output_attribs[1] = meta_crtc_get_id (meta_render_target_get_primary_crtc (onscreen_native->render_target)); output_attribs[2] = EGL_NONE; if (!meta_egl_get_output_layers (egl, egl_display, @@ -2764,7 +2820,7 @@ meta_onscreen_native_allocate (CoglFramebuffer *framebuffer, #endif CoglFramebufferClass *parent_class; - if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) != + if (META_GPU_KMS (meta_render_target_get_gpu (onscreen_native->render_target)) != onscreen_native->render_gpu) { if (!init_secondary_gpu_state (onscreen_native->renderer_native, @@ -2890,7 +2946,7 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1); - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)); + gpu_kms = META_GPU_KMS (meta_render_target_get_gpu (onscreen_native->render_target)); secondary_gpu_state->gpu_kms = gpu_kms; secondary_gpu_state->renderer_gpu_data = renderer_gpu_data; secondary_gpu_state->gbm.surface = gbm_surface; @@ -2987,7 +3043,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat width = cogl_framebuffer_get_width (framebuffer); height = cogl_framebuffer_get_height (framebuffer); - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)); + gpu_kms = META_GPU_KMS (meta_render_target_get_gpu (onscreen_native->render_target)); render_device = renderer_gpu_data->render_device; meta_topic (META_DEBUG_KMS, "Secondary GPU %s using DRM format '%s' (0x%x) for a %dx%d output.", @@ -3036,7 +3092,7 @@ init_secondary_gpu_state (MetaRendererNative *renderer_native, GError **error) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpu *gpu = meta_crtc_get_gpu (onscreen_native->crtc); + MetaGpu *gpu = meta_render_target_get_gpu (onscreen_native->render_target); MetaRendererNativeGpuData *renderer_gpu_data; g_autoptr (GError) local_error = NULL; @@ -3084,9 +3140,9 @@ void meta_onscreen_native_invalidate (MetaOnscreenNative *onscreen_native) { const MetaOutputInfo *output_info = - meta_output_get_info (onscreen_native->output); + meta_output_get_info (meta_render_target_get_primary_output (onscreen_native->render_target)); - if (meta_crtc_get_gamma_lut_size (onscreen_native->crtc) > 0) + if (meta_crtc_get_gamma_lut_size (meta_render_target_get_primary_crtc (onscreen_native->render_target)) > 0) onscreen_native->property.gamma_lut.invalidated = TRUE; if (output_info->supports_privacy_screen) onscreen_native->property.privacy_screen.invalidated = TRUE; @@ -3139,8 +3195,8 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native, onscreen_native->renderer_native = renderer_native; onscreen_native->render_gpu = render_gpu; - g_set_object (&onscreen_native->output, output); - g_set_object (&onscreen_native->crtc, crtc); + onscreen_native->render_target = meta_render_target_new (); + meta_render_target_add (onscreen_native->render_target, crtc, output); if (meta_crtc_get_gamma_lut_size (crtc) > 0) { @@ -3167,9 +3223,9 @@ static void clear_invalidation_handlers (MetaOnscreenNative *onscreen_native) { g_clear_signal_handler (&onscreen_native->property.gamma_lut.signal_handler_id, - onscreen_native->crtc); + meta_render_target_get_primary_crtc (onscreen_native->render_target)); g_clear_signal_handler (&onscreen_native->property.privacy_screen.signal_handler_id, - onscreen_native->output); + meta_render_target_get_primary_output (onscreen_native->render_target)); } static void @@ -3224,8 +3280,7 @@ meta_onscreen_native_dispose (GObject *object) g_clear_pointer (&onscreen_native->secondary_gpu_state, secondary_gpu_state_free); - g_clear_object (&onscreen_native->output); - g_clear_object (&onscreen_native->crtc); + g_clear_pointer (&onscreen_native->render_target, g_ptr_array_unref); } static void @@ -3255,7 +3310,8 @@ meta_onscreen_native_class_init (MetaOnscreenNativeClass *klass) MetaCrtc * meta_onscreen_native_get_crtc (MetaOnscreenNative *onscreen_native) { - return onscreen_native->crtc; + // ADLRTODO: return all crtcs + return meta_render_target_get_primary_crtc (onscreen_native->render_target); } void diff --git a/src/backends/native/meta-render-target-native.c b/src/backends/native/meta-render-target-native.c index 8b46f9c1be4..da97d8de2cc 100644 --- a/src/backends/native/meta-render-target-native.c +++ b/src/backends/native/meta-render-target-native.c @@ -29,6 +29,24 @@ meta_render_target_native_get_primary_crtc_kms (MetaRenderTarget *render_target) return META_CRTC_KMS (meta_render_target_get_primary_crtc (render_target)); } +MetaKmsCrtc * +meta_render_target_native_get_primary_kms_crtc (MetaRenderTarget *render_target) +{ + return meta_crtc_kms_get_kms_crtc (meta_render_target_native_get_primary_crtc_kms (render_target)); +} + +MetaKmsDevice * +meta_render_target_native_get_kms_device (MetaRenderTarget *render_target) +{ + return meta_kms_crtc_get_device (meta_render_target_native_get_primary_kms_crtc (render_target)); +} + +MetaOutputKms * +meta_render_target_native_get_primary_output_kms (MetaRenderTarget *render_target) +{ + return META_OUTPUT_KMS (meta_render_target_get_primary_output (render_target)); +} + GPtrArray * meta_render_target_native_get_crtc_kmses (MetaRenderTarget *render_target) { diff --git a/src/backends/native/meta-render-target-native.h b/src/backends/native/meta-render-target-native.h index 174852c3f3c..993651f6347 100644 --- a/src/backends/native/meta-render-target-native.h +++ b/src/backends/native/meta-render-target-native.h @@ -27,9 +27,13 @@ #include "backends/meta-render-target.h" #include "backends/native/meta-crtc-kms.h" +#include "backends/native/meta-output-kms.h" -MetaCrtcKms * -meta_render_target_native_get_primary_crtc_kms (MetaRenderTarget *render_target); +MetaCrtcKms * meta_render_target_native_get_primary_crtc_kms (MetaRenderTarget *render_target); +MetaKmsCrtc * meta_render_target_native_get_primary_kms_crtc (MetaRenderTarget *render_target); +MetaOutputKms * meta_render_target_native_get_primary_output_kms (MetaRenderTarget *render_target); + +MetaKmsDevice * meta_render_target_native_get_kms_device (MetaRenderTarget *render_target); /* Caller takes ownership of return value */ GPtrArray * /* of type MetaCrtcKms * */ @@ -42,9 +46,25 @@ meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target); int64_t meta_render_target_native_get_deadline_evasion (MetaRenderTarget *render_target); #define meta_render_target_native_foreach_crtc_kms(crtc_kms_decl, render_target) \ - for (guint keep = 1, \ - count = 0, \ - size = meta_render_target_get_crtcs (render_target)->len; \ - keep && count != size; \ - keep = !keep, count++) \ - for(crtc_kms_decl = META_CRTC_KMS (g_ptr_array_index (meta_render_target_get_crtcs (render_target), count)); keep; keep = !keep) + for (guint toggle__ = 1, \ + count__ = 0, \ + size__ = meta_render_target_get_crtcs (render_target)->len; \ + count__ < size__; \ + toggle__ = 1, count__++) \ + for (crtc_kms_decl = META_CRTC_KMS (g_ptr_array_index (meta_render_target_get_crtcs (render_target), count__)); toggle__; toggle__ = 0) + +#define meta_render_target_native_foreach_output_kms(output_kms_decl, render_target) \ + for (guint toggle__ = 1, \ + count__ = 0, \ + size__ = meta_render_target_get_outputs (render_target)->len; \ + count__ < size__; \ + toggle__ = 1, count__++) \ + for (output_kms_decl = META_OUTPUT_KMS (g_ptr_array_index (meta_render_target_get_outputs (render_target), count__)); toggle__; toggle__ = 0) + +#define meta_render_target_native_foreach_kms_crtc(kms_crtc_decl, render_target) \ + for (guint toggle__ = 1, \ + count__ = 0, \ + size__ = meta_render_target_get_crtcs (render_target)->len; \ + count__ < size__; \ + toggle__ = 1, count__++) \ + for (kms_crtc_decl = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (g_ptr_array_index (meta_render_target_get_crtcs (render_target), count__))); toggle__; toggle__ = 0) diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c index 00309300700..b34358f3287 100644 --- a/src/tests/native-kms-render.c +++ b/src/tests/native-kms-render.c @@ -167,6 +167,7 @@ on_scanout_presented (ClutterStage *stage, MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaDevicePool *device_pool; CoglFramebuffer *fb; + MetaRenderTarget *render_target; MetaCrtc *crtc; MetaKmsCrtc *kms_crtc; MetaKmsDevice *kms_device; @@ -183,7 +184,8 @@ on_scanout_presented (ClutterStage *stage, device_pool = meta_backend_native_get_device_pool (backend_native); fb = clutter_stage_view_get_onscreen (stage_view); - crtc = meta_onscreen_native_get_crtc (META_ONSCREEN_NATIVE (fb)); + render_target = meta_onscreen_native_get_render_target (META_ONSCREEN_NATIVE (fb)); + crtc = meta_render_target_get_primary_crtc (render_target); kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); kms_device = meta_kms_crtc_get_device (kms_crtc); -- GitLab From cbdfe3e40991f85e9df4e2e67efcf19c85dc71ba Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Sun, 30 Nov 2025 11:14:57 -0800 Subject: [PATCH 6/9] TILETEAR: CrtcFrame.crtc->crtcs Also, CrtcFrame.submitted_update.latch_crtc->latch_crtcs --- src/backends/native/meta-kms-cursor-manager.c | 7 +- src/backends/native/meta-kms-device.c | 11 +- src/backends/native/meta-kms-device.h | 5 +- src/backends/native/meta-kms-impl-device.c | 190 +++++++++++------- src/backends/native/meta-kms-impl-device.h | 5 +- src/backends/native/meta-kms-update-private.h | 3 +- src/backends/native/meta-kms-update.c | 38 ++-- src/backends/native/meta-kms-update.h | 8 +- src/backends/native/meta-onscreen-native.c | 20 +- .../native/meta-render-target-native.c | 13 +- .../native/meta-render-target-native.h | 19 +- src/tests/native-kms-device.c | 3 +- 12 files changed, 203 insertions(+), 119 deletions(-) diff --git a/src/backends/native/meta-kms-cursor-manager.c b/src/backends/native/meta-kms-cursor-manager.c index 3724bac070f..ce32efaf1cd 100644 --- a/src/backends/native/meta-kms-cursor-manager.c +++ b/src/backends/native/meta-kms-cursor-manager.c @@ -700,11 +700,12 @@ position_changed_in_impl (MetaThreadImpl *thread_impl, MetaKmsDevice *device = meta_kms_crtc_get_device (crtc); MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); + g_autoptr (GPtrArray) crtcs = g_ptr_array_new_from_array ((void**) &crtc_state_impl->crtc, 1, NULL, NULL, NULL); crtc_state_impl->cursor_invalidated = TRUE; meta_kms_impl_device_schedule_process (impl_device, - crtc_state_impl->crtc); + crtcs); } } @@ -750,6 +751,7 @@ update_sprite_in_impl (MetaThreadImpl *thread_impl, meta_kms_device_get_impl_device (device); CrtcStateImpl *crtc_state_impl; MetaDrmBuffer *old_buffer; + g_autoptr (GPtrArray) crtcs = NULL; crtc_state_impl = find_crtc_state (cursor_manager_impl, crtc); g_return_val_if_fail (crtc_state_impl, NULL); @@ -759,9 +761,10 @@ update_sprite_in_impl (MetaThreadImpl *thread_impl, crtc_state_impl->transform = data->transform; crtc_state_impl->hotspot = data->hotspot; crtc_state_impl->cursor_invalidated = TRUE; + crtcs = g_ptr_array_new_from_array ((void**) &crtc_state_impl->crtc, 1, NULL, NULL, NULL); meta_kms_impl_device_schedule_process (impl_device, - crtc_state_impl->crtc); + crtcs); if (old_buffer) { diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c index 4dec048d085..f1d9fc6c3fd 100644 --- a/src/backends/native/meta-kms-device.c +++ b/src/backends/native/meta-kms-device.c @@ -411,13 +411,16 @@ meta_kms_device_set_needs_flush (MetaKmsDevice *device, } gboolean -meta_kms_device_handle_flush (MetaKmsDevice *device, - MetaKmsCrtc *crtc) +meta_kms_device_handle_flush (MetaKmsDevice *device, + MetaKmsCrtcPtrArray *crtcs) { - gboolean needs_flush; + gboolean needs_flush = false; g_mutex_lock (&device->needs_flush_mutex); - needs_flush = g_hash_table_remove (device->needs_flush_crtcs, crtc); + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * crtc, crtcs) + { + needs_flush |= g_hash_table_remove (device->needs_flush_crtcs, crtc); + } g_mutex_unlock (&device->needs_flush_mutex); return needs_flush; diff --git a/src/backends/native/meta-kms-device.h b/src/backends/native/meta-kms-device.h index 6dfa5a76ac0..c248baf7f40 100644 --- a/src/backends/native/meta-kms-device.h +++ b/src/backends/native/meta-kms-device.h @@ -20,6 +20,7 @@ #include #include "backends/native/meta-kms-types.h" +#include "backends/native/meta-render-target-native.h" #include "core/util-private.h" #define META_TYPE_KMS_DEVICE (meta_kms_device_get_type ()) @@ -80,8 +81,8 @@ META_EXPORT_TEST void meta_kms_device_await_flush (MetaKmsDevice *device, MetaKmsCrtc *crtc); -gboolean meta_kms_device_handle_flush (MetaKmsDevice *device, - MetaKmsCrtc *crtc); +gboolean meta_kms_device_handle_flush (MetaKmsDevice *device, + MetaKmsCrtcPtrArray *crtc); META_EXPORT_TEST void meta_kms_device_disable (MetaKmsDevice *device); diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index 4a53915deac..45cc44431ec 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -42,6 +42,7 @@ #include "backends/native/meta-kms-plane.h" #include "backends/native/meta-kms-private.h" #include "backends/native/meta-kms-utils.h" +#include "backends/native/meta-render-target-native.h" #include "backends/native/meta-thread-private.h" #include "meta-default-modes.h" @@ -64,10 +65,11 @@ static GParamSpec *obj_props[N_PROPS]; typedef struct _CrtcDeadline { MetaKmsImplDevice *impl_device; - MetaKmsCrtc *crtc; + MetaKmsCrtcPtrArray *crtcs; MetaKmsUpdate *pending_update; gboolean await_flush; gboolean pending_page_flip; + int refcnt; struct { int timer_fd; @@ -82,7 +84,7 @@ typedef struct _CrtcDeadline struct { MetaKmsUpdate *kms_update; MetaKmsUpdateFlag flags; - MetaKmsCrtc *latch_crtc; + MetaKmsCrtcPtrArray *latch_crtcs; GSource *source; } submitted_update; } CrtcFrame; @@ -130,8 +132,8 @@ typedef struct _MetaKmsImplDevicePrivate static void initable_iface_init (GInitableIface *iface); -static CrtcFrame * get_crtc_frame (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *latch_crtc); +static CrtcFrame * get_crtc_frame (MetaKmsImplDevice *impl_device, + MetaKmsCrtcPtrArray *latch_crtcs); G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDevice, meta_kms_impl_device, G_TYPE_OBJECT, @@ -1334,8 +1336,8 @@ disarm_crtc_frame_deadline_timer (CrtcFrame *crtc_frame) return; meta_topic (META_DEBUG_KMS, "Disarming deadline timer for crtc %u (%s)", - meta_kms_crtc_get_id (crtc_frame->crtc), - meta_kms_device_get_path (meta_kms_crtc_get_device (crtc_frame->crtc))); + meta_kms_crtc_get_id (meta_crtc_kms_ptr_array_get_primary (crtc_frame->crtcs)), + meta_kms_device_get_path (meta_crtc_kms_ptr_array_get_device (crtc_frame->crtcs))); timerfd_settime (crtc_frame->deadline.timer_fd, TFD_TIMER_ABSTIME, &its, NULL); @@ -1358,8 +1360,8 @@ arm_crtc_frame_deadline_timer (CrtcFrame *crtc_frame, return; meta_topic (META_DEBUG_KMS, "Arming deadline timer for crtc %u (%s): %ld", - meta_kms_crtc_get_id (crtc_frame->crtc), - meta_kms_device_get_path (meta_kms_crtc_get_device (crtc_frame->crtc)), + meta_kms_crtc_get_id (meta_crtc_kms_ptr_array_get_primary (crtc_frame->crtcs)), + meta_kms_device_get_path (meta_crtc_kms_ptr_array_get_device (crtc_frame->crtcs)), next_deadline_us); tv_sec = us2s (next_deadline_us); @@ -1387,10 +1389,10 @@ ensure_deadline_timer_armed (MetaKmsImplDevice *impl_device, if (crtc_frame->deadline.armed) return TRUE; - if (!meta_kms_crtc_get_current_state (crtc_frame->crtc)->is_drm_mode_valid) + if (!meta_kms_crtc_get_current_state (meta_crtc_kms_ptr_array_get_primary (crtc_frame->crtcs))->is_drm_mode_valid) return FALSE; - if (!meta_kms_crtc_determine_deadline (crtc_frame->crtc, + if (!meta_kms_crtc_determine_deadline (meta_crtc_kms_ptr_array_get_primary (crtc_frame->crtcs), &next_deadline_us, &next_presentation_us, &local_error)) @@ -1424,7 +1426,7 @@ ensure_deadline_timer_armed (MetaKmsImplDevice *impl_device, static void notify_crtc_frame_ready (CrtcFrame *crtc_frame) { - MetaKmsCrtc *crtc = crtc_frame->crtc; + MetaKmsCrtcPtrArray *crtcs = crtc_frame->crtcs; crtc_frame->pending_page_flip = FALSE; crtc_frame->deadline.is_deadline_page_flip = FALSE; @@ -1435,7 +1437,7 @@ notify_crtc_frame_ready (CrtcFrame *crtc_frame) if (crtc_frame->await_flush) return; - meta_kms_impl_device_schedule_process (crtc_frame->impl_device, crtc); + meta_kms_impl_device_schedule_process (crtc_frame->impl_device, crtcs); } static void @@ -1547,10 +1549,10 @@ queue_result_feedback (MetaKmsImplDevice *impl_device, } static MetaKmsFeedback * -do_process (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *latch_crtc, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) +do_process (MetaKmsImplDevice *impl_device, + MetaKmsCrtcPtrArray *latch_crtcs, + MetaKmsUpdate *update, + MetaKmsUpdateFlag flags) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); @@ -1565,8 +1567,13 @@ do_process (MetaKmsImplDevice *impl_device, COGL_TRACE_BEGIN_SCOPED (MetaKmsImplDeviceProcess, "Meta::KmsImplDevice::do_process()"); - update = meta_kms_impl_filter_update (impl, latch_crtc, update, flags); - + if (latch_crtcs) + { + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * latch_crtc, latch_crtcs) + { + update = meta_kms_impl_filter_update (impl, latch_crtc, update, flags); + } + } if (!update || meta_kms_update_is_empty (update)) { GError *error; @@ -1587,9 +1594,9 @@ do_process (MetaKmsImplDevice *impl_device, if (!(flags & META_KMS_UPDATE_FLAG_TEST_ONLY)) { - if (latch_crtc) + if (latch_crtcs) { - crtc_frame = get_crtc_frame (impl_device, latch_crtc); + crtc_frame = get_crtc_frame (impl_device, latch_crtcs); if (crtc_frame && crtc_frame->pending_update) { meta_kms_update_merge_from (crtc_frame->pending_update, update); @@ -1603,11 +1610,14 @@ do_process (MetaKmsImplDevice *impl_device, GMainContext *thread_context = meta_thread_impl_get_main_context (thread_impl); - meta_kms_update_add_page_flip_listener (update, - crtc_frame->crtc, - &crtc_page_flip_listener_vtable, - thread_context, - crtc_frame, NULL); + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * crtc, crtc_frame->crtcs) + { + meta_kms_update_add_page_flip_listener (update, + crtc, + &crtc_page_flip_listener_vtable, + thread_context, + crtc_frame, NULL); + } crtc_frame->pending_page_flip = TRUE; } } @@ -1641,8 +1651,8 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, GError **error) { CrtcFrame *crtc_frame = user_data; - MetaKmsCrtc *crtc = crtc_frame->crtc; - MetaKmsDevice *device = meta_kms_crtc_get_device (crtc); + MetaKmsCrtcPtrArray *crtcs = crtc_frame->crtcs; + MetaKmsDevice *device = meta_crtc_kms_ptr_array_get_device (crtcs); MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); g_autoptr (MetaKmsFeedback) feedback = NULL; uint64_t timer_value; @@ -1669,7 +1679,7 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, } feedback = do_process (impl_device, - crtc_frame->crtc, + crtc_frame->crtcs, g_steal_pointer (&crtc_frame->pending_update), META_KMS_UPDATE_FLAG_NONE); @@ -1684,7 +1694,7 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, lateness_us = dispatch_time_us - crtc_frame->deadline.expected_deadline_time_us; duration_us = update_done_time_us - dispatch_time_us; - if (meta_kms_crtc_get_current_state (crtc)->vrr.enabled) + if (meta_kms_crtc_get_current_state (meta_crtc_kms_ptr_array_get_primary (crtcs))->vrr.enabled) { meta_topic (META_DEBUG_KMS_DEADLINE, "VRR deadline dispatch started %3"G_GINT64_FORMAT "µs %s and " @@ -1697,7 +1707,7 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, { int64_t deadline_evasion_us, vblank_delta_us; - deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc); + deadline_evasion_us = meta_crtc_kms_ptr_array_get_deadline_evasion (crtcs); vblank_delta_us = deadline_evasion_us - lateness_us - duration_us; meta_topic (META_DEBUG_KMS_DEADLINE, @@ -1714,7 +1724,10 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, } } - meta_kms_crtc_update_shortterm_max_dispatch_duration (crtc, interval_us); + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * crtc, crtcs) + { + meta_kms_crtc_update_shortterm_max_dispatch_duration (crtc, interval_us); + } if (meta_kms_feedback_did_pass (feedback)) crtc_frame->deadline.is_deadline_page_flip = TRUE; @@ -1726,22 +1739,32 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, static void crtc_frame_free (CrtcFrame *crtc_frame) { + if (--crtc_frame->refcnt != 0) + return; g_clear_fd (&crtc_frame->deadline.timer_fd, NULL); + g_clear_pointer (&crtc_frame->crtcs, g_ptr_array_unref); g_clear_pointer (&crtc_frame->deadline.source, g_source_destroy); g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free); g_clear_pointer (&crtc_frame->submitted_update.kms_update, meta_kms_update_free); g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy); + g_clear_pointer (&crtc_frame->submitted_update.latch_crtcs, g_ptr_array_unref); g_free (crtc_frame); } static CrtcFrame * -get_crtc_frame (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *latch_crtc) +get_crtc_frame (MetaKmsImplDevice *impl_device, + MetaKmsCrtcPtrArray *latch_crtcs) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); - return g_hash_table_lookup (priv->crtc_frames, latch_crtc); + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * latch_crtc, latch_crtcs) + { + CrtcFrame *crtc_frame = g_hash_table_lookup (priv->crtc_frames, latch_crtc); + if (crtc_frame) + return crtc_frame; + } + return NULL; } static gboolean @@ -1773,8 +1796,8 @@ is_using_deadline_timer (MetaKmsImplDevice *impl_device) } static CrtcFrame * -ensure_crtc_frame (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *latch_crtc) +ensure_crtc_frame (MetaKmsImplDevice *impl_device, + MetaKmsCrtcPtrArray *latch_crtcs) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); @@ -1783,18 +1806,35 @@ ensure_crtc_frame (MetaKmsImplDevice *impl_device, CrtcFrame *crtc_frame; gboolean want_deadline_timer, have_deadline_timer; - crtc_frame = get_crtc_frame (impl_device, latch_crtc); + crtc_frame = get_crtc_frame (impl_device, latch_crtcs); if (!crtc_frame) { const MetaKmsCrtcState *crtc_state = - meta_kms_crtc_get_current_state (latch_crtc); + meta_kms_crtc_get_current_state (meta_crtc_kms_ptr_array_get_primary (latch_crtcs)); crtc_frame = g_new0 (CrtcFrame, 1); crtc_frame->impl_device = impl_device; - crtc_frame->crtc = latch_crtc; + crtc_frame->crtcs = g_ptr_array_copy (latch_crtcs, NULL, NULL); crtc_frame->deadline.timer_fd = -1; crtc_frame->await_flush = !crtc_state->is_active; - g_hash_table_insert (priv->crtc_frames, latch_crtc, crtc_frame); + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * latch_crtc, latch_crtcs) + { + crtc_frame->refcnt++; + g_hash_table_insert (priv->crtc_frames, latch_crtc, crtc_frame); + } + } + else + { + // Did have a frame, but make sure to add new crtcs to it. + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * latch_crtc, latch_crtcs) + { + if (!g_ptr_array_find (crtc_frame->crtcs, latch_crtc, NULL)) + { + g_ptr_array_add (crtc_frame->crtcs, latch_crtc); + crtc_frame->refcnt++; + g_hash_table_insert (priv->crtc_frames, latch_crtc, crtc_frame); + } + } } want_deadline_timer = is_using_deadline_timer (impl_device); @@ -1812,7 +1852,7 @@ ensure_crtc_frame (MetaKmsImplDevice *impl_device, crtc_frame); name = g_strdup_printf ("[mutter] KMS deadline clock (crtc: %u, %s)", - meta_kms_crtc_get_id (latch_crtc), + meta_kms_crtc_get_id (meta_crtc_kms_ptr_array_get_primary (latch_crtcs)), priv->path); g_source_set_name (source, name); g_source_set_priority (source, G_PRIORITY_HIGH + 1); @@ -1852,11 +1892,11 @@ queue_update (MetaKmsImplDevice *impl_device, } static void -meta_kms_impl_device_do_process_update (MetaKmsImplDevice *impl_device, - CrtcFrame *crtc_frame, - MetaKmsCrtc *latch_crtc, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) +meta_kms_impl_device_do_process_update (MetaKmsImplDevice *impl_device, + CrtcFrame *crtc_frame, + MetaKmsCrtcPtrArray *latch_crtcs, + MetaKmsUpdate *update, + MetaKmsUpdateFlag flags) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); @@ -1874,9 +1914,9 @@ meta_kms_impl_device_do_process_update (MetaKmsImplDevice *impl_device, disarm_crtc_frame_deadline_timer (crtc_frame); } - meta_kms_device_handle_flush (priv->device, latch_crtc); + meta_kms_device_handle_flush (priv->device, latch_crtcs); - feedback = do_process (impl_device, latch_crtc, update, flags); + feedback = do_process (impl_device, latch_crtcs, update, flags); if (meta_kms_feedback_did_pass (feedback) && crtc_frame->deadline.armed) @@ -1891,13 +1931,13 @@ meta_kms_impl_device_update_ready (MetaThreadImpl *impl, GError **error) { CrtcFrame *crtc_frame = user_data; - MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc); + MetaKmsDevice *device = meta_crtc_kms_ptr_array_get_device (crtc_frame->crtcs); MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); gboolean want_deadline_timer, vrr_enabled; MetaKmsUpdate *update; - MetaKmsCrtc *latch_crtc; + g_autoptr (GPtrArray) latch_crtcs; meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); @@ -1906,13 +1946,17 @@ meta_kms_impl_device_update_ready (MetaThreadImpl *impl, update = g_steal_pointer (&crtc_frame->submitted_update.kms_update); meta_kms_update_realize (update, impl_device); - latch_crtc = g_steal_pointer (&crtc_frame->submitted_update.latch_crtc); + latch_crtcs = g_steal_pointer (&crtc_frame->submitted_update.latch_crtcs); - vrr_enabled = meta_kms_crtc_get_current_state (crtc_frame->crtc)->vrr.enabled; + vrr_enabled = meta_kms_crtc_get_current_state (meta_crtc_kms_ptr_array_get_primary (crtc_frame->crtcs))->vrr.enabled; if (vrr_enabled) { - meta_kms_crtc_set_vrr_update_time (crtc_frame->crtc, - g_get_monotonic_time ()); + gint64 now = g_get_monotonic_time (); + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * kms_crtc, crtc_frame->crtcs) + { + meta_kms_crtc_set_vrr_update_time (kms_crtc, + now); + } } want_deadline_timer = @@ -1925,11 +1969,11 @@ meta_kms_impl_device_update_ready (MetaThreadImpl *impl, { if (crtc_frame->pending_page_flip) { - g_assert (latch_crtc); + g_assert (latch_crtcs && latch_crtcs->len > 0); meta_topic (META_DEBUG_KMS, "Queuing update on CRTC %u (%s): pending page flip", - meta_kms_crtc_get_id (latch_crtc), + meta_kms_crtc_get_id (meta_crtc_kms_ptr_array_get_primary (latch_crtcs)), priv->path); } @@ -1940,7 +1984,7 @@ meta_kms_impl_device_update_ready (MetaThreadImpl *impl, return GINT_TO_POINTER (TRUE); } - meta_kms_impl_device_do_process_update (impl_device, crtc_frame, latch_crtc, + meta_kms_impl_device_do_process_update (impl_device, crtc_frame, latch_crtcs, update, crtc_frame->submitted_update.flags); @@ -1972,7 +2016,7 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device); MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl); g_autoptr (GError) error = NULL; - MetaKmsCrtc *latch_crtc; + MetaKmsCrtcPtrArray *latch_crtcs; CrtcFrame *crtc_frame; MetaKmsFeedback *feedback; g_autoptr (GSource) source = NULL; @@ -1981,11 +2025,11 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - latch_crtc = meta_kms_update_get_latch_crtc (update); - if (!latch_crtc) + latch_crtcs = meta_kms_update_get_latch_crtcs (update); + if (!latch_crtcs) { g_set_error (&error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Only single-CRTC updates supported"); + "Only single-CRTC (or single tile group) updates supported"); goto err; } @@ -1998,7 +2042,7 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, if (!ensure_device_file (impl_device, &error)) goto err; - crtc_frame = ensure_crtc_frame (impl_device, latch_crtc); + crtc_frame = ensure_crtc_frame (impl_device, latch_crtcs); if (crtc_frame->submitted_update.kms_update) { @@ -2010,7 +2054,7 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, crtc_frame->await_flush = FALSE; crtc_frame->submitted_update.kms_update = update; crtc_frame->submitted_update.flags = flags; - crtc_frame->submitted_update.latch_crtc = latch_crtc; + crtc_frame->submitted_update.latch_crtcs = g_ptr_array_copy (latch_crtcs, NULL, NULL); if (is_using_deadline_timer (impl_device)) sync_fd = meta_kms_update_get_sync_fd (update); @@ -2042,7 +2086,7 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, crtc_frame); name = g_strdup_printf ("[mutter] KMS update sync_fd (crtc: %u, %s)", - meta_kms_crtc_get_id (latch_crtc), + meta_kms_crtc_get_id (meta_crtc_kms_ptr_array_get_primary (latch_crtcs)), priv->path); g_source_set_name (source, name); g_source_set_priority (source, G_PRIORITY_HIGH + 1); @@ -2066,12 +2110,13 @@ meta_kms_impl_device_await_flush (MetaKmsImplDevice *impl_device, MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); CrtcFrame *crtc_frame; + g_autoptr (GPtrArray) crtcs = g_ptr_array_new_from_array ((void**) &crtc, 1, NULL, NULL, NULL); meta_topic (META_DEBUG_KMS, "Awaiting flush on CRTC %u (%s)", meta_kms_crtc_get_id (crtc), priv->path); - crtc_frame = ensure_crtc_frame (impl_device, crtc); + crtc_frame = ensure_crtc_frame (impl_device, crtcs); crtc_frame->await_flush = TRUE; if (crtc_frame->deadline.armed) @@ -2079,12 +2124,12 @@ meta_kms_impl_device_await_flush (MetaKmsImplDevice *impl_device, } void -meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc) +meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device, + MetaKmsCrtcPtrArray *crtcs) { CrtcFrame *crtc_frame; - crtc_frame = ensure_crtc_frame (impl_device, crtc); + crtc_frame = ensure_crtc_frame (impl_device, crtcs); if (crtc_frame->await_flush) return; @@ -2100,7 +2145,7 @@ meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device, if (crtc_frame->pending_update) { meta_kms_impl_device_do_process_update (impl_device, crtc_frame, - crtc_frame->crtc, + crtc_frame->crtcs, crtc_frame->pending_update, META_KMS_UPDATE_FLAG_NONE); } @@ -2115,7 +2160,10 @@ meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device, crtc_frame->pending_update, priv->deadline_timer_state); } - meta_kms_device_set_needs_flush (meta_kms_crtc_get_device (crtc), crtc); + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * crtc, crtcs) + { + meta_kms_device_set_needs_flush (meta_crtc_kms_ptr_array_get_device (crtcs), crtc); + } } static void @@ -2209,7 +2257,7 @@ meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY) { return do_process (impl_device, - meta_kms_update_get_latch_crtc (update), + meta_kms_update_get_latch_crtcs (update), update, flags); } else if (flags & META_KMS_UPDATE_FLAG_MODE_SET) diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h index 22396dba680..35f4e33e3f0 100644 --- a/src/backends/native/meta-kms-impl-device.h +++ b/src/backends/native/meta-kms-impl-device.h @@ -28,6 +28,7 @@ #include "backends/native/meta-kms-types.h" #include "backends/native/meta-kms-update.h" #include "backends/native/meta-kms.h" +#include "backends/native/meta-render-target-native.h" typedef struct _MetaKmsDeviceCaps { @@ -207,8 +208,8 @@ void meta_kms_impl_device_await_flush (MetaKmsImplDevice *impl_device, MetaKmsCrtc *crtc); META_EXPORT_TEST -void meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc); +void meta_kms_impl_device_schedule_process (MetaKmsImplDevice *impl_device, + MetaKmsCrtcPtrArray *crtcs); void meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device, MetaKmsPageFlipData *page_flip_data); diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index b330ca2c65f..0fb3a1c3158 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -26,6 +26,7 @@ #include "backends/native/meta-kms-types.h" #include "backends/native/meta-kms-types-private.h" #include "backends/native/meta-kms-update.h" +#include "backends/native/meta-render-target-native.h" typedef struct _MetaKmsCrtcColorUpdate { @@ -245,7 +246,7 @@ void meta_kms_update_realize (MetaKmsUpdate *update, gboolean meta_kms_update_get_needs_modeset (MetaKmsUpdate *update); -MetaKmsCrtc * meta_kms_update_get_latch_crtc (MetaKmsUpdate *update); +MetaKmsCrtcPtrArray * meta_kms_update_get_latch_crtcs (MetaKmsUpdate *update); void meta_kms_page_flip_listener_unref (MetaKmsPageFlipListener *listener); diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c index 0dc78383971..03aa32eceff 100644 --- a/src/backends/native/meta-kms-update.c +++ b/src/backends/native/meta-kms-update.c @@ -37,7 +37,7 @@ struct _MetaKmsUpdate gboolean is_sealed; gboolean is_latchable; - MetaKmsCrtc *latch_crtc; + MetaKmsCrtcPtrArray *latch_crtcs; GList *mode_sets; GList *plane_assignments; @@ -253,17 +253,9 @@ update_latch_crtc (MetaKmsUpdate *update, { if (update->is_latchable) { - if (update->latch_crtc) + if (g_ptr_array_find (update->latch_crtcs, crtc, NULL) == FALSE) { - if (update->latch_crtc != crtc) - { - update->is_latchable = FALSE; - update->latch_crtc = NULL; - } - } - else - { - update->latch_crtc = crtc; + g_ptr_array_add (update->latch_crtcs, crtc); } } } @@ -1224,6 +1216,7 @@ meta_kms_update_new (MetaKmsDevice *device) update = g_new0 (MetaKmsUpdate, 1); update->device = device; update->is_latchable = TRUE; + update->latch_crtcs = g_ptr_array_new (); update->sync_fd = -1; return update; @@ -1235,6 +1228,7 @@ meta_kms_update_free (MetaKmsUpdate *update) if (update->impl_device) meta_kms_impl_device_unhold_fd (update->impl_device); + g_clear_pointer (&update->latch_crtcs, g_ptr_array_unref); g_list_free_full (update->result_listeners, (GDestroyNotify) meta_kms_result_listener_free); g_list_free_full (update->plane_assignments, @@ -1262,16 +1256,26 @@ meta_kms_update_realize (MetaKmsUpdate *update, } void -meta_kms_update_set_flushing (MetaKmsUpdate *update, - MetaKmsCrtc *crtc) +meta_kms_update_set_flushing_one (MetaKmsUpdate *update, + MetaKmsCrtc *kms_crtc) { - update_latch_crtc (update, crtc); + update_latch_crtc (update, kms_crtc); +} + +void +meta_kms_update_set_flushing (MetaKmsUpdate *update, + MetaRenderTarget *render_target) +{ + meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * crtc, render_target) + { + meta_kms_update_set_flushing_one (update, crtc); + } } -MetaKmsCrtc * -meta_kms_update_get_latch_crtc (MetaKmsUpdate *update) +MetaKmsCrtcPtrArray * +meta_kms_update_get_latch_crtcs (MetaKmsUpdate *update) { - return update->latch_crtc; + return update->latch_crtcs; } int diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h index 708497824c0..97d7295e397 100644 --- a/src/backends/native/meta-kms-update.h +++ b/src/backends/native/meta-kms-update.h @@ -25,6 +25,7 @@ #include "backends/meta-output.h" #include "backends/native/meta-drm-buffer.h" #include "backends/native/meta-kms-types.h" +#include "backends/meta-render-target.h" #include "meta/boxes.h" #include "mtk/mtk.h" @@ -101,8 +102,11 @@ MetaKmsUpdate * meta_kms_update_new (MetaKmsDevice *device); META_EXPORT_TEST void meta_kms_update_free (MetaKmsUpdate *update); -void meta_kms_update_set_flushing (MetaKmsUpdate *update, - MetaKmsCrtc *crtc); +void meta_kms_update_set_flushing_one (MetaKmsUpdate *update, + MetaKmsCrtc *kms_crtc); + +void meta_kms_update_set_flushing (MetaKmsUpdate *update, + MetaRenderTarget *render_target); META_EXPORT_TEST MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 0247f48ac5c..89dc38d3cdd 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -681,7 +681,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - meta_kms_update_set_flushing (kms_update, kms_crtc); + meta_kms_update_set_flushing_one (kms_update, kms_crtc); meta_kms_update_set_custom_page_flip (kms_update, custom_egl_stream_page_flip, onscreen_native); @@ -2277,11 +2277,9 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; - meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) - { - onscreen_native->needs_flush |= meta_kms_device_handle_flush (kms_device, - kms_crtc); - } + g_autoptr (GPtrArray) kms_crtcs = meta_render_target_native_get_kms_crtc_array (onscreen_native->render_target); + onscreen_native->needs_flush |= meta_kms_device_handle_flush (kms_device, + kms_crtcs); if (!meta_frame_native_has_kms_update (frame_native)) { @@ -2330,10 +2328,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, if (onscreen_native->needs_flush) { - meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) - { - meta_kms_update_set_flushing (kms_update, kms_crtc); - } + meta_kms_update_set_flushing (kms_update, onscreen_native->render_target); onscreen_native->needs_flush = FALSE; } @@ -2375,10 +2370,7 @@ post_nonprimary_plane_update (MetaOnscreenNative *onscreen_native, meta_kms_crtc_get_id (primary_kms_crtc), meta_kms_device_get_path (kms_device)); - meta_render_target_native_foreach_kms_crtc (MetaKmsCrtc * kms_crtc, onscreen_native->render_target) - { - meta_kms_update_set_flushing (kms_update, kms_crtc); - } + meta_kms_update_set_flushing (kms_update, onscreen_native->render_target); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); } diff --git a/src/backends/native/meta-render-target-native.c b/src/backends/native/meta-render-target-native.c index da97d8de2cc..eb86a768251 100644 --- a/src/backends/native/meta-render-target-native.c +++ b/src/backends/native/meta-render-target-native.c @@ -60,7 +60,7 @@ meta_render_target_native_get_crtc_kmses (MetaRenderTarget *render_target) } GPtrArray * -meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target) +meta_render_target_native_get_kms_crtc_array (MetaRenderTarget *render_target) { GPtrArray *crtcs = meta_render_target_get_crtcs (render_target); GPtrArray *ret = g_ptr_array_new_full (crtcs->len, g_object_unref); @@ -71,6 +71,17 @@ meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target) return ret; } +int64_t +meta_crtc_kms_ptr_array_get_deadline_evasion (MetaKmsCrtcPtrArray *arr) +{ + int64_t ret = INT64_MIN; + meta_kms_crtc_ptr_array_foreach (MetaKmsCrtc * kms_crtc, arr) + { + ret = MAX (ret, meta_kms_crtc_get_deadline_evasion (kms_crtc)); + } + return ret; +} + int64_t meta_render_target_native_get_deadline_evasion (MetaRenderTarget *render_target) { diff --git a/src/backends/native/meta-render-target-native.h b/src/backends/native/meta-render-target-native.h index 993651f6347..f522f50b217 100644 --- a/src/backends/native/meta-render-target-native.h +++ b/src/backends/native/meta-render-target-native.h @@ -39,9 +39,16 @@ MetaKmsDevice * meta_render_target_native_get_kms_device (MetaRenderTarget *rend GPtrArray * /* of type MetaCrtcKms * */ meta_render_target_native_get_crtc_kmses (MetaRenderTarget *render_target); +typedef GPtrArray MetaKmsCrtcPtrArray; /* GPtrArray of MetaKmsCrtc *, must have at least 1 element */ + /* Caller takes ownership of return value */ -GPtrArray * /* of type MetaKmsCrtc * */ -meta_render_target_native_get_kms_crtcs (MetaRenderTarget *render_target); +MetaKmsCrtcPtrArray * +meta_render_target_native_get_kms_crtc_array (MetaRenderTarget *render_target); +#define meta_crtc_kms_ptr_array_get_primary(arr) \ + ((MetaKmsCrtc *) g_ptr_array_index (arr, 0)) +#define meta_crtc_kms_ptr_array_get_device(arr) \ + ((MetaKmsDevice *) meta_kms_crtc_get_device (meta_crtc_kms_ptr_array_get_primary (arr))) +int64_t meta_crtc_kms_ptr_array_get_deadline_evasion (MetaKmsCrtcPtrArray *arr); int64_t meta_render_target_native_get_deadline_evasion (MetaRenderTarget *render_target); @@ -68,3 +75,11 @@ int64_t meta_render_target_native_get_deadline_evasion (MetaRenderTarget *render count__ < size__; \ toggle__ = 1, count__++) \ for (kms_crtc_decl = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (g_ptr_array_index (meta_render_target_get_crtcs (render_target), count__))); toggle__; toggle__ = 0) + +#define meta_kms_crtc_ptr_array_foreach(kms_crtc_decl, arr) \ + for (guint toggle__ = 1, \ + count__ = 0, \ + size__ = arr->len; \ + count__ < size__; \ + toggle__ = 1, count__++) \ + for (kms_crtc_decl = g_ptr_array_index (arr, count__); toggle__; toggle__ = 0) diff --git a/src/tests/native-kms-device.c b/src/tests/native-kms-device.c index f9cadf3f5b0..73f0b375c4a 100644 --- a/src/tests/native-kms-device.c +++ b/src/tests/native-kms-device.c @@ -607,8 +607,9 @@ schedule_process_in_impl (MetaThreadImpl *thread_impl, MetaKmsCrtc *crtc = META_KMS_CRTC (user_data); MetaKmsDevice *device = meta_kms_crtc_get_device (crtc); MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); + g_autoptr (GPtrArray) crtcs = g_ptr_array_new_from_array ((void**) &crtc, 1, NULL, NULL, NULL); - meta_kms_impl_device_schedule_process (impl_device, crtc); + meta_kms_impl_device_schedule_process (impl_device, crtcs); return NULL; } -- GitLab From d4e71fd7cbb0af2cb258f22bd02eea99642861fb Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Sun, 26 Oct 2025 16:09:21 -0700 Subject: [PATCH 7/9] TILETEAR: MetaFrameNative: track which crtcs have updates posted Also, MetaOnscreenNative: wait for all crtcs to flip on callback --- src/backends/native/meta-frame-native.c | 35 ++++++++++++++++++++++ src/backends/native/meta-frame-native.h | 14 ++++++++- src/backends/native/meta-onscreen-native.c | 9 +++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/backends/native/meta-frame-native.c b/src/backends/native/meta-frame-native.c index 98cd917c737..f2b55648f65 100644 --- a/src/backends/native/meta-frame-native.c +++ b/src/backends/native/meta-frame-native.c @@ -35,6 +35,10 @@ struct _MetaFrameNative MetaKmsUpdate *kms_update; MtkRegion *damage; + /* Array of crtcs that we have requested page flips from. + * Will be > 1 in case of tiled display. + * When all are complete, the full frame was flipped including all tiles. */ + GPtrArray *posted_crtcs; /* of type MetaCrtc * */ int sync_fd; }; @@ -43,6 +47,7 @@ meta_frame_native_release (ClutterFrame *frame) { MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); + g_clear_pointer (&frame_native->posted_crtcs, g_ptr_array_unref); g_clear_fd (&frame_native->sync_fd, NULL); g_clear_pointer (&frame_native->damage, mtk_region_unref); g_clear_object (&frame_native->buffer); @@ -57,6 +62,7 @@ meta_frame_native_new (void) MetaFrameNative *frame_native = clutter_frame_new (MetaFrameNative, meta_frame_native_release); + frame_native->posted_crtcs = g_ptr_array_new (); frame_native->sync_fd = -1; return frame_native; @@ -148,3 +154,32 @@ meta_frame_native_steal_sync_fd (MetaFrameNative *frame_native) { return g_steal_fd (&frame_native->sync_fd); } + +void +meta_frame_native_add_posted_crtc (MetaFrameNative *frame_native, + MetaCrtc *crtc) +{ + if (g_ptr_array_find (frame_native->posted_crtcs, crtc, NULL)) { + g_warning ("FrameNative already has posted crtc!"); + return; + } + g_ptr_array_add (frame_native->posted_crtcs, crtc); +} + +void +meta_frame_native_remove_posted_crtc (MetaFrameNative *frame_native, + MetaCrtc *crtc) +{ + guint index = 0; + if (!g_ptr_array_find (frame_native->posted_crtcs, crtc, &index)) { + g_warning ("FrameNative can't remove non-posted crtc!"); + return; + } + g_ptr_array_remove_index_fast (frame_native->posted_crtcs, index); +} + +gboolean +meta_frame_native_has_posted_crtcs (MetaFrameNative *frame_native) +{ + return frame_native->posted_crtcs->len > 0; +} diff --git a/src/backends/native/meta-frame-native.h b/src/backends/native/meta-frame-native.h index 38547ebc1c0..1c07e632370 100644 --- a/src/backends/native/meta-frame-native.h +++ b/src/backends/native/meta-frame-native.h @@ -17,6 +17,7 @@ #pragma once +#include "backends/meta-crtc.h" #include "backends/native/meta-backend-native-types.h" #include "backends/native/meta-kms-types.h" #include "clutter/clutter.h" @@ -60,4 +61,15 @@ meta_frame_native_set_sync_fd (MetaFrameNative *frame_native, int sync_fd); int -meta_frame_native_steal_sync_fd (MetaFrameNative *frame_native); +meta_frame_native_steal_sync_fd (MetaFrameNative * frame_native); + +void +meta_frame_native_add_posted_crtc (MetaFrameNative *frame_native, + MetaCrtc *crtc); + +void +meta_frame_native_remove_posted_crtc (MetaFrameNative *frame_native, + MetaCrtc *crtc); + +gboolean +meta_frame_native_has_posted_crtcs (MetaFrameNative *frame_native); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 89dc38d3cdd..830e6623fb6 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -280,6 +280,11 @@ notify_view_crtc_presented (MetaRendererView *view, crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc)); maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence); + MetaFrameNative *frame_native = meta_frame_native_from_frame (onscreen_native->posted_frame); + meta_frame_native_remove_posted_crtc (frame_native, crtc); + if (meta_frame_native_has_posted_crtcs (frame_native)) + return; + meta_onscreen_native_notify_frame_complete (onscreen); meta_onscreen_native_promote_posted_frame (onscreen); maybe_post_next_frame (onscreen); @@ -604,7 +609,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaFrameNative *frame_native; + MetaFrameNative *frame_native = NULL; MetaGpuKms *render_gpu = onscreen_native->render_gpu; MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); @@ -695,6 +700,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, NULL, g_object_ref (view), g_object_unref); + if (frame_native) + meta_frame_native_add_posted_crtc (frame_native, crtc); return TRUE; } -- GitLab From c2fdbfffeaa7e0cf5a3dffbad72eb625741ac898 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Mon, 1 Dec 2025 20:09:58 -0800 Subject: [PATCH 8/9] TILETEAR: Create RendererViews with RenderTarget --- src/backends/meta-logical-monitor-private.h | 3 +- src/backends/meta-logical-monitor.c | 39 ++++++++++++++++----- src/backends/meta-monitor-private.h | 13 +++++++ src/backends/meta-monitor.c | 32 +++++++++++++++++ src/backends/meta-render-target.c | 29 ++++++++++++++- src/backends/meta-render-target.h | 3 +- src/backends/meta-renderer.c | 14 +++----- src/backends/meta-renderer.h | 4 +-- src/backends/native/meta-onscreen-native.c | 10 +++--- src/backends/native/meta-onscreen-native.h | 4 +-- src/backends/native/meta-renderer-native.c | 32 +++++++---------- src/tests/meta-monitor-test-utils.c | 7 ++++ 12 files changed, 140 insertions(+), 50 deletions(-) diff --git a/src/backends/meta-logical-monitor-private.h b/src/backends/meta-logical-monitor-private.h index 93e1d090812..0eea703f0e3 100644 --- a/src/backends/meta-logical-monitor-private.h +++ b/src/backends/meta-logical-monitor-private.h @@ -50,8 +50,7 @@ typedef struct _MetaLogicalMonitorId MetaLogicalMonitorId; typedef void (* MetaLogicalMonitorCrtcFunc) (MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, + MetaRenderTarget *render_target, gpointer user_data); MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitorManager *monitor_manager, diff --git a/src/backends/meta-logical-monitor.c b/src/backends/meta-logical-monitor.c index 7c848100872..305288a3d0d 100644 --- a/src/backends/meta-logical-monitor.c +++ b/src/backends/meta-logical-monitor.c @@ -280,23 +280,42 @@ typedef struct _ForeachCrtcData } ForeachCrtcData; static gboolean -foreach_crtc (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error) +foreach_crtc_group (MetaMonitor *monitor, + MetaMonitorMode *mode, + GPtrArray *monitor_crtc_modes, /* of type MetaMonitorCrtcMode * */ + gpointer user_data, + GError **error) { ForeachCrtcData *data = user_data; + g_autoptr (MetaRenderTarget) render_target = meta_render_target_new (); + for (guint i = 0; i < monitor_crtc_modes->len; i++) + { + MetaMonitorCrtcMode *monitor_crtc_mode = g_ptr_array_index (monitor_crtc_modes, i); + MetaOutput *output = monitor_crtc_mode->output; + MetaCrtc *crtc = meta_output_get_assigned_crtc (output); + meta_render_target_add (render_target, crtc, output); + } data->func (data->logical_monitor, monitor, - monitor_crtc_mode->output, - meta_output_get_assigned_crtc (monitor_crtc_mode->output), + render_target, data->user_data); return TRUE; } +static gboolean +foreach_crtc (MetaMonitor *monitor, + MetaMonitorMode *mode, + MetaMonitorCrtcMode *monitor_crtc_mode, + gpointer user_data, + GError **error) +{ + g_autoptr (GPtrArray) monitor_crtc_modes = g_ptr_array_new_full (1, NULL); + g_ptr_array_add (monitor_crtc_modes, monitor_crtc_mode); + return foreach_crtc_group (monitor, mode, monitor_crtc_modes, user_data, error); +} + void meta_logical_monitor_foreach_crtc (MetaLogicalMonitor *logical_monitor, MetaLogicalMonitorCrtcFunc func, @@ -315,7 +334,11 @@ meta_logical_monitor_foreach_crtc (MetaLogicalMonitor *logical_monitor, }; mode = meta_monitor_get_current_mode (monitor); - meta_monitor_mode_foreach_crtc (monitor, mode, foreach_crtc, &data, NULL); + const char *tile_en = g_getenv ("TILE_EN"); + if (tile_en && !strcmp (tile_en, "1")) + meta_monitor_mode_foreach_crtc_group (monitor, mode, foreach_crtc_group, &data, NULL); + else + meta_monitor_mode_foreach_crtc (monitor, mode, foreach_crtc, &data, NULL); } } diff --git a/src/backends/meta-monitor-private.h b/src/backends/meta-monitor-private.h index fe976067b07..e9bd22877a3 100644 --- a/src/backends/meta-monitor-private.h +++ b/src/backends/meta-monitor-private.h @@ -58,6 +58,12 @@ typedef gboolean (* MetaMonitorModeFunc) (MetaMonitor *monitor, gpointer user_data, GError **error); +typedef gboolean (* MetaMonitorModeGroupFunc) (MetaMonitor *monitor, + MetaMonitorMode *mode, + GPtrArray *monitor_crtc_modes, + gpointer user_data, + GError **error); + typedef enum _MetaMonitorScalesConstraint { META_MONITOR_SCALES_CONSTRAINT_NONE = 0, @@ -258,6 +264,13 @@ gboolean meta_monitor_mode_foreach_crtc (MetaMonitor *monitor, gpointer user_data, GError **error); +META_EXPORT_TEST +gboolean meta_monitor_mode_foreach_crtc_group (MetaMonitor *monitor, + MetaMonitorMode *mode, + MetaMonitorModeGroupFunc func, + gpointer user_data, + GError **error); + META_EXPORT_TEST gboolean meta_monitor_mode_foreach_output (MetaMonitor *monitor, MetaMonitorMode *mode, diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index d0114dc6cc5..c292a2d18ed 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -2656,6 +2656,38 @@ meta_monitor_mode_foreach_crtc (MetaMonitor *monitor, return TRUE; } +gboolean +meta_monitor_mode_foreach_crtc_group (MetaMonitor *monitor, + MetaMonitorMode *mode, + MetaMonitorModeGroupFunc func, + gpointer user_data, + GError **error) +{ + MetaMonitorPrivate *monitor_priv = + meta_monitor_get_instance_private (monitor); + MetaMonitorModePrivate *mode_priv = + meta_monitor_mode_get_instance_private (mode); + GList *l; + g_autoptr (GPtrArray) monitor_crtc_modes = g_ptr_array_new (); + int i; + + for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++) + { + MetaMonitorCrtcMode *monitor_crtc_mode = &mode_priv->crtc_modes[i]; + + if (!monitor_crtc_mode->crtc_mode) + continue; + + g_ptr_array_add (monitor_crtc_modes, monitor_crtc_mode); + } + + if (!func (monitor, mode, monitor_crtc_modes, user_data, error)) + return FALSE; + + return TRUE; +} + + gboolean meta_monitor_mode_foreach_output (MetaMonitor *monitor, MetaMonitorMode *mode, diff --git a/src/backends/meta-render-target.c b/src/backends/meta-render-target.c index d060ca45cfa..e60283ca9bf 100644 --- a/src/backends/meta-render-target.c +++ b/src/backends/meta-render-target.c @@ -99,11 +99,38 @@ meta_render_target_get_outputs (MetaRenderTarget *render_target) return render_target->outputs; } +MtkRectangle +meta_render_target_get_output_frame (MetaRenderTarget *render_target) +{ + MtkRectangle output_frame; + const MetaCrtcConfig *crtc_config = meta_crtc_get_config (g_ptr_array_index (render_target->crtcs, 0)); + const MetaCrtcModeInfo *crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); + // If only one, just use that size + if (render_target->crtcs->len == 1) + { + output_frame = MTK_RECTANGLE_INIT (0, 0, crtc_mode_info->width, crtc_mode_info->height); + return output_frame; + } + // Else get full size from tile info + int width = 0; + int height = 0; + for (guint i = 0; i < render_target->outputs->len; i++) + { + MetaOutput *output = g_ptr_array_index (render_target->outputs, i); + const MetaOutputInfo *output_info = meta_output_get_info (output); + if (output_info->tile_info.loc_h_tile == 0) + height += output_info->tile_info.tile_h; + if (output_info->tile_info.loc_v_tile == 0) + width += output_info->tile_info.tile_w; + } + output_frame = MTK_RECTANGLE_INIT (0, 0, width, height); + return output_frame; +} + MtkRectangle meta_render_target_get_view_layout (MetaRenderTarget *render_target) { MtkRectangle view_layout; - g_warn_if_fail (render_target->crtcs->len > 0); const MetaCrtcConfig *crtc_config = meta_crtc_get_config (g_ptr_array_index (render_target->crtcs, 0)); mtk_rectangle_from_graphene_rect (&crtc_config->layout, MTK_ROUNDING_STRATEGY_ROUND, diff --git a/src/backends/meta-render-target.h b/src/backends/meta-render-target.h index fd14315be04..7e7a2851a68 100644 --- a/src/backends/meta-render-target.h +++ b/src/backends/meta-render-target.h @@ -39,8 +39,9 @@ gboolean meta_render_target_has_crtc (MetaRenderTarget *render_target, MetaCrtc *crtc); GPtrArray * meta_render_target_get_crtcs (MetaRenderTarget *render_target); GPtrArray * meta_render_target_get_outputs (MetaRenderTarget *render_target); -MtkRectangle meta_render_target_get_view_layout (MetaRenderTarget *render_target); MetaGpu * meta_render_target_get_gpu (MetaRenderTarget *render_target); +MtkRectangle meta_render_target_get_output_frame (MetaRenderTarget *render_target); +MtkRectangle meta_render_target_get_view_layout (MetaRenderTarget *render_target); MtkRectangle meta_render_target_get_output_tile_frame (MetaRenderTarget *render_target, MetaOutput *output); diff --git a/src/backends/meta-renderer.c b/src/backends/meta-renderer.c index 1b7140bcaaa..f7358136e86 100644 --- a/src/backends/meta-renderer.c +++ b/src/backends/meta-renderer.c @@ -95,8 +95,7 @@ static MetaRendererView * meta_renderer_create_view (MetaRenderer *renderer, MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, + MetaRenderTarget *render_target, GError **error) { MetaRendererView *view; @@ -104,8 +103,7 @@ meta_renderer_create_view (MetaRenderer *renderer, view = META_RENDERER_GET_CLASS (renderer)->create_view (renderer, logical_monitor, monitor, - output, - crtc, + render_target, error); if (view) @@ -132,8 +130,7 @@ meta_renderer_rebuild_views (MetaRenderer *renderer) static void create_crtc_view (MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, + MetaRenderTarget *render_target, gpointer user_data) { MetaRenderer *renderer = user_data; @@ -143,14 +140,13 @@ create_crtc_view (MetaLogicalMonitor *logical_monitor, view = meta_renderer_create_view (renderer, logical_monitor, monitor, - output, - crtc, + render_target, &error); if (!view) { g_warning ("Failed to create view for %s on %s: %s", meta_monitor_get_display_name (monitor), - meta_output_get_name (output), + meta_output_get_name (meta_render_target_get_primary_output (render_target)), error->message); } } diff --git a/src/backends/meta-renderer.h b/src/backends/meta-renderer.h index 4a6e617dc52..11746731f4d 100644 --- a/src/backends/meta-renderer.h +++ b/src/backends/meta-renderer.h @@ -25,6 +25,7 @@ #include #include "backends/meta-monitor-manager-private.h" +#include "backends/meta-render-target.h" #include "backends/meta-renderer-view.h" #include "core/util-private.h" #include "clutter/clutter-mutter.h" @@ -41,8 +42,7 @@ struct _MetaRendererClass MetaRendererView * (* create_view) (MetaRenderer *renderer, MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, + MetaRenderTarget *render_target, GError **error); void (* rebuild_views) (MetaRenderer *renderer); void (* resume) (MetaRenderer *renderer); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 830e6623fb6..8f7925d9bc9 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -3171,14 +3171,15 @@ on_privacy_screen_enabled_changed (MetaOutput *output, MetaOnscreenNative * meta_onscreen_native_new (MetaRendererNative *renderer_native, MetaGpuKms *render_gpu, - MetaOutput *output, - MetaCrtc *crtc, + MetaRenderTarget *render_target, CoglContext *cogl_context, int width, int height) { MetaOnscreenNative *onscreen_native; CoglFramebufferDriverConfig driver_config; + MetaCrtc *crtc = meta_render_target_get_primary_crtc (render_target); + MetaOutput *output = meta_render_target_get_primary_output (render_target); const MetaOutputInfo *output_info = meta_output_get_info (output); driver_config = (CoglFramebufferDriverConfig) { @@ -3194,8 +3195,7 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native, onscreen_native->renderer_native = renderer_native; onscreen_native->render_gpu = render_gpu; - onscreen_native->render_target = meta_render_target_new (); - meta_render_target_add (onscreen_native->render_target, crtc, output); + onscreen_native->render_target = g_object_ref (render_target); if (meta_crtc_get_gamma_lut_size (crtc) > 0) { @@ -3279,7 +3279,7 @@ meta_onscreen_native_dispose (GObject *object) g_clear_pointer (&onscreen_native->secondary_gpu_state, secondary_gpu_state_free); - g_clear_pointer (&onscreen_native->render_target, g_ptr_array_unref); + g_clear_pointer (&onscreen_native->render_target, g_object_unref); } static void diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h index e30357d19d1..545deb61947 100644 --- a/src/backends/native/meta-onscreen-native.h +++ b/src/backends/native/meta-onscreen-native.h @@ -21,6 +21,7 @@ #include #include "backends/meta-backend-types.h" +#include "backends/meta-render-target.h" #include "backends/native/meta-backend-native-types.h" #include "clutter/clutter.h" #include "cogl/cogl.h" @@ -55,8 +56,7 @@ void meta_onscreen_native_set_view (CoglOnscreen *onscreen, MetaOnscreenNative * meta_onscreen_native_new (MetaRendererNative *renderer_native, MetaGpuKms *render_gpu, - MetaOutput *output, - MetaCrtc *crtc, + MetaRenderTarget *render_target, CoglContext *cogl_context, int width, int height); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 9719a5e4ffc..bee9706f773 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -1505,8 +1505,7 @@ static MetaRendererView * meta_renderer_native_create_view (MetaRenderer *renderer, MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, + MetaRenderTarget *render_target, GError **error) { MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); @@ -1527,22 +1526,20 @@ meta_renderer_native_create_view (MetaRenderer *renderer, float scale; int onscreen_width; int onscreen_height; - MtkRectangle view_layout; + MtkRectangle view_layout = meta_render_target_get_view_layout (render_target); + MtkRectangle output_frame = meta_render_target_get_output_frame (render_target); MetaRendererViewNative *view_native; EGLSurface egl_surface; GError *local_error = NULL; - // ADLRTODO: don't leak render_target here. Instead, receive it as argument to this function. - MetaRenderTarget *render_target = meta_render_target_new (); - meta_render_target_add (render_target, crtc, output); - crtc_config = meta_crtc_get_config (crtc); + crtc_config = meta_crtc_get_config (meta_render_target_get_primary_crtc (render_target)); crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - onscreen_width = crtc_mode_info->width; - onscreen_height = crtc_mode_info->height; + onscreen_width = output_frame.width; + onscreen_height = output_frame.height; - if (META_IS_CRTC_KMS (crtc)) + if (META_IS_CRTC_KMS (meta_render_target_get_primary_crtc (render_target))) { - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); + MetaGpuKms *gpu_kms = META_GPU_KMS (meta_render_target_get_gpu (render_target)); g_autoptr (MetaOnscreenNative) onscreen_native = NULL; if (!meta_renderer_native_ensure_gpu_data (renderer_native, @@ -1561,8 +1558,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, onscreen_native = meta_onscreen_native_new (renderer_native, primary_gpu_kms, - output, - crtc, + render_target, cogl_context, onscreen_width, onscreen_height); @@ -1600,20 +1596,16 @@ meta_renderer_native_create_view (MetaRenderer *renderer, view_transform = calculate_view_transform (monitor_manager, logical_monitor, - output, - crtc); + meta_render_target_get_primary_output (render_target), + meta_render_target_get_primary_crtc (render_target)); if (meta_backend_is_stage_views_scaled (backend)) scale = meta_logical_monitor_get_scale (logical_monitor); else scale = 1.0; - mtk_rectangle_from_graphene_rect (&crtc_config->layout, - MTK_ROUNDING_STRATEGY_ROUND, - &view_layout); - view_native = g_object_new (META_TYPE_RENDERER_VIEW_NATIVE, - "name", meta_output_get_name (output), + "name", meta_output_get_name (meta_render_target_get_primary_output (render_target)), "backend", backend, "color-device", color_device, "stage", meta_backend_get_stage (backend), diff --git a/src/tests/meta-monitor-test-utils.c b/src/tests/meta-monitor-test-utils.c index 31133e09d2c..cbf0f769262 100644 --- a/src/tests/meta-monitor-test-utils.c +++ b/src/tests/meta-monitor-test-utils.c @@ -630,6 +630,13 @@ meta_check_monitor_configuration (MetaContext *context, g_assert_nonnull (view); clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); + if (expect->n_tiled_monitors > 0) + { + // In a tiled setup, view_layout may include all tiles for the given monitor. + MtkRectangle crtc_tile; + mtk_rectangle_from_graphene_rect (&crtc_config->layout, MTK_ROUNDING_STRATEGY_ROUND, &crtc_tile); + mtk_rectangle_intersect (&view_layout, &crtc_tile, &view_layout); + } g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x, view_layout.x, FLT_EPSILON); -- GitLab From e3ce3f16f1dd8ea1a8000be46c6dc45f0e0ce929 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Mon, 1 Dec 2025 22:15:13 -0800 Subject: [PATCH 9/9] TILETEAR: MetaRendererNative: properly init modesets --- src/backends/meta-render-target.h | 9 +++ src/backends/native/meta-onscreen-native.c | 7 +-- src/backends/native/meta-onscreen-native.h | 2 +- src/backends/native/meta-renderer-native.c | 64 ++++++++++++---------- 4 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/backends/meta-render-target.h b/src/backends/meta-render-target.h index 7e7a2851a68..2aa7e54d698 100644 --- a/src/backends/meta-render-target.h +++ b/src/backends/meta-render-target.h @@ -47,3 +47,12 @@ MtkRectangle meta_render_target_get_output_tile_frame (MetaRenderTarget *render_ META_EXPORT_TEST MetaBackend * meta_render_target_get_backend (MetaRenderTarget *render_target); + +#define meta_render_target_foreach_crtc_output(crtc_decl, output_decl, render_target) \ + for (guint toggle__ = 1, \ + count__ = 0, \ + size__ = meta_render_target_get_crtcs (render_target)->len; \ + count__ < size__; \ + toggle__ = 1, count__++) \ + for (crtc_decl = g_ptr_array_index (meta_render_target_get_crtcs (render_target), count__); toggle__; ) \ + for (output_decl = g_ptr_array_index (meta_render_target_get_outputs (render_target), count__); toggle__; toggle__ = 0) diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 8f7925d9bc9..772b403f3b2 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -3306,11 +3306,10 @@ meta_onscreen_native_class_init (MetaOnscreenNativeClass *klass) blit_source_quark = g_quark_from_static_string ("Blit source"); } -MetaCrtc * -meta_onscreen_native_get_crtc (MetaOnscreenNative *onscreen_native) +MetaRenderTarget * +meta_onscreen_native_get_render_target (MetaOnscreenNative *onscreen_native) { - // ADLRTODO: return all crtcs - return meta_render_target_get_primary_crtc (onscreen_native->render_target); + return onscreen_native->render_target; } void diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h index 545deb61947..25791e929d5 100644 --- a/src/backends/native/meta-onscreen-native.h +++ b/src/backends/native/meta-onscreen-native.h @@ -62,7 +62,7 @@ MetaOnscreenNative * meta_onscreen_native_new (MetaRendererNative *renderer_nati int height); META_EXPORT_TEST -MetaCrtc * meta_onscreen_native_get_crtc (MetaOnscreenNative *onscreen_native); +MetaRenderTarget * meta_onscreen_native_get_render_target (MetaOnscreenNative *onscreen_native); void meta_onscreen_native_invalidate (MetaOnscreenNative *onscreen_native); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index bee9706f773..90382c08598 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -856,9 +856,9 @@ free_unused_gpu_datas (MetaRendererNative *renderer_native) for (l = renderer_native->lingering_onscreens; l; l = l->next) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (l->data); - MetaCrtc *crtc = meta_onscreen_native_get_crtc (onscreen_native); + MetaRenderTarget *render_target = meta_onscreen_native_get_render_target (onscreen_native); - g_hash_table_add (used_gpus, meta_crtc_get_gpu (crtc)); + g_hash_table_add (used_gpus, meta_render_target_get_gpu (render_target)); } g_hash_table_foreach_remove (renderer_native->gpu_datas, @@ -1332,34 +1332,40 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (framebuffer); - MetaCrtc *crtc; - MetaCrtcKms *crtc_kms; - MetaKmsCrtc *kms_crtc; - MetaKmsPlane *kms_plane; - MtkRectangle view_layout; - float view_scale; - MetaKmsCrtcLayout crtc_layout; - - crtc = meta_onscreen_native_get_crtc (onscreen_native); - crtc_kms = META_CRTC_KMS (crtc); - - kms_plane = meta_crtc_kms_get_assigned_cursor_plane (crtc_kms); - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - - clutter_stage_view_get_layout (stage_view, &view_layout); - view_scale = clutter_stage_view_get_scale (stage_view); - - crtc_layout = (MetaKmsCrtcLayout) { - .crtc = kms_crtc, - .cursor_plane = kms_plane, - .layout = GRAPHENE_RECT_INIT (view_layout.x, - view_layout.y, - view_layout.width, - view_layout.height), - .scale = view_scale, - }; - g_array_append_val (crtc_layouts, crtc_layout); + MetaRenderTarget *render_target = meta_onscreen_native_get_render_target (onscreen_native); + meta_render_target_foreach_crtc_output (MetaCrtc * crtc, MetaOutput * output, render_target) + { + MetaCrtcKms *crtc_kms; + MetaKmsCrtc *kms_crtc; + MetaKmsPlane *kms_plane; + MtkRectangle view_layout; + MtkRectangle output_layout = meta_render_target_get_output_tile_frame (render_target, output); + float view_scale; + MetaKmsCrtcLayout crtc_layout; + + crtc_kms = META_CRTC_KMS (crtc); + + kms_plane = meta_crtc_kms_get_assigned_cursor_plane (crtc_kms); + kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + + clutter_stage_view_get_layout (stage_view, &view_layout); + view_scale = clutter_stage_view_get_scale (stage_view); + + graphene_rect_t output_layout_gr = mtk_rectangle_to_graphene_rect (&output_layout); + graphene_rect_scale (&output_layout_gr, 1 / view_scale, 1 / view_scale, &output_layout_gr); + + crtc_layout = (MetaKmsCrtcLayout) { + .crtc = kms_crtc, + .cursor_plane = kms_plane, + .layout = GRAPHENE_RECT_INIT (view_layout.x + output_layout_gr.origin.x, + view_layout.y + output_layout_gr.origin.y, + output_layout_gr.size.width ?: view_layout.width, + output_layout_gr.size.height ?: view_layout.height), + .scale = view_scale, + }; + g_array_append_val (crtc_layouts, crtc_layout); + } meta_onscreen_native_invalidate (onscreen_native); renderer_native->pending_mode_set_views = g_list_prepend (renderer_native->pending_mode_set_views, -- GitLab