diff --git a/src/backends/meta-logical-monitor-private.h b/src/backends/meta-logical-monitor-private.h
index 93e1d090812d7ef24151c01804e8f868ad464d95..0eea703f0e3a5610ed3411c1465070419b3345ef 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 7c84810087265ce7992a905eff6fd0c976153605..305288a3d0db7dc5f7a8573a0decfc4c8ef2d56c 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 fe976067b076c6906accfb760ddabae9a07d06ff..e9bd22877a361ca1cf5d524c8b0ba6953613d9e7 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 d0114dc6cc53f9f46386141a837b473e9f675b30..c292a2d18ed7a9e440ef01c275145807250a4e60 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
new file mode 100644
index 0000000000000000000000000000000000000000..e60283ca9bfa8f6576dab50eaebf8d6cf6225aba
--- /dev/null
+++ b/src/backends/meta-render-target.c
@@ -0,0 +1,214 @@
+/* -*- 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)
+
+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,
+ 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);
+}
+
+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)
+{
+ return render_target->crtcs;
+}
+
+GPtrArray *
+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;
+ 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));
+}
+
+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)
+{
+ return meta_crtc_get_backend (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 0000000000000000000000000000000000000000..2aa7e54d6981b8baa1441fe59e3065f6b934217e
--- /dev/null
+++ b/src/backends/meta-render-target.h
@@ -0,0 +1,58 @@
+/* -*- 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);
+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);
+
+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/meta-renderer-view.c b/src/backends/meta-renderer-view.c
index 113d8fbbd6e5e80e69e5fe30b445a04090324083..8fdc3470c1c0af758df2bea22fb48c020b8aa9f7 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 e22b50f1248e794490f5beb2c42be17881f9fe26..67d18756f9730a309c021d49505b039d7863753a 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 3fd80df2729140190db6a66eaf9b553ac2b38388..f7358136e86d2b51fea6c3e9ea4168b41212165f 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);
}
}
@@ -203,7 +199,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/meta-renderer.h b/src/backends/meta-renderer.h
index 4a6e617dc527e009889b442602101a466810f9b1..11746731f4d35cb299aac864bcb34d5b6e50653f 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-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c
index 821d675746c0d726e302bdd9494d87176e8275ec..d000ec67dc19f740d7c76934dfd92b03880cfa7e 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);
@@ -347,9 +348,10 @@ 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);
- MetaCrtcNative *crtc_native = META_CRTC_NATIVE (crtc);
- MetaGpu *gpu = meta_crtc_get_gpu (crtc);
+ MetaRenderTarget *render_target = meta_renderer_view_get_render_target (renderer_view);
+ 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;
@@ -358,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;
@@ -372,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;
}
@@ -406,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);
+ }
}
}
}
@@ -1252,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)
{
diff --git a/src/backends/native/meta-frame-native.c b/src/backends/native/meta-frame-native.c
index 98cd917c73757646d7c0037e0b6a95b4993ebbe7..f2b55648f653ec53bbefde10919754d9ac11f000 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 38547ebc1c03c33b50f6e8ba70c8bbe44b14e59e..1c07e632370aa547a7cbc7176106d6915981199c 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-kms-cursor-manager.c b/src/backends/native/meta-kms-cursor-manager.c
index 3724bac070f58e7e096a75e32c43172ee4e28974..ce32efaf1cdd6c94ab86cd7752291f2ec90abf1a 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 4dec048d08514f08ddc298b27c3cec94b83bdb90..f1d9fc6c3fd4301216ed3e5f12251a486b78a689 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 6dfa5a76ac03880a1ffe60b5c529be9c213fc2bd..c248baf7f40778e4c0896be33fa32fd203848a54 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 4a53915deac1f5759dee10c7eaaf22c7aee20c9c..45cc44431ec84d6988d17b71f814bce8dd880dde 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 22396dba680a9bd32db239749583a4a8c414a097..35f4e33e3f02378f5333689ec7294ab5711465a5 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 b330ca2c65f93505744f1744e441deebafdcc26d..0fb3a1c31588f6dce77e3021d5069ee37db314c1 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 0dc78383971492443d424a353604ed44ffdf4237..03aa32eceff0bafbaa7ad9f938c4e2dba35bd29f 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 708497824c098726d57db0472c394b093d78a5df..97d7295e3978e4b77a42a45c84901141d9943a73 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 3b3080876b28581defcbbb87a90af54db6962970..772b403f3b2b5903fa503be6ea3aaff73eaf3e39 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;
@@ -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);
@@ -597,13 +602,14 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
ClutterFrame *frame,
MetaRendererView *view,
MetaCrtc *crtc,
+ MtkRectangle output_frame,
MetaKmsUpdate *kms_update,
MetaKmsAssignPlaneFlag flags,
const MtkRegion *region)
{
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);
@@ -638,20 +644,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
};
}
@@ -670,7 +686,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);
@@ -684,6 +700,37 @@ 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;
+}
+
+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;
}
@@ -808,7 +855,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 +869,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 +890,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 +901,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 +1808,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 +1848,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 +1872,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 +1898,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 +1942,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 +1961,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 +1971,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 +2140,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 +2152,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 +2179,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 +2192,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 +2208,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 +2227,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 +2278,15 @@ 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;
+ 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_crtc);
+ kms_crtcs);
if (!meta_frame_native_has_kms_update (frame_native))
{
@@ -2283,7 +2335,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
if (onscreen_native->needs_flush)
{
- 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;
}
@@ -2298,9 +2350,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 +2361,23 @@ 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_kms_update_set_flushing (kms_update, onscreen_native->render_target);
meta_kms_device_post_update (kms_device, kms_update,
META_KMS_UPDATE_FLAG_NONE);
}
@@ -2356,7 +2411,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 +2490,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 +2507,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 +2526,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 +2743,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 +2819,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 +2945,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 +3042,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 +3091,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 +3139,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;
@@ -3116,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) {
@@ -3139,8 +3195,7 @@ 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 = g_object_ref (render_target);
if (meta_crtc_get_gamma_lut_size (crtc) > 0)
{
@@ -3167,9 +3222,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 +3279,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_object_unref);
}
static void
@@ -3252,10 +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)
{
- return onscreen_native->crtc;
+ 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 e30357d19d1fd4544026f0f7ef6dba6221d571a9..25791e929d5d613b0850d476f182d8ba7bc66121 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,14 +56,13 @@ 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);
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-render-target-native.c b/src/backends/native/meta-render-target-native.c
new file mode 100644
index 0000000000000000000000000000000000000000..eb86a7682513f79bfc87ac5b15ddfe4b2a62225b
--- /dev/null
+++ b/src/backends/native/meta-render-target-native.c
@@ -0,0 +1,98 @@
+/* -*- 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"
+
+MetaCrtcKms *
+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)
+{
+ 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_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);
+ 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;
+}
+
+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)
+{
+ 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
new file mode 100644
index 0000000000000000000000000000000000000000..f522f50b2172aa483dfbab4a4f8fd376b89de653
--- /dev/null
+++ b/src/backends/native/meta-render-target-native.h
@@ -0,0 +1,85 @@
+/* -*- 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"
+#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);
+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 * */
+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 */
+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);
+
+#define meta_render_target_native_foreach_crtc_kms(crtc_kms_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_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)
+
+#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/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index bd2bd26242086464960af9e7f1c388b1a28703e6..90382c08598a21410cecd9a0240338108018fd0b 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;
@@ -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,
@@ -1505,8 +1511,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,19 +1532,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;
- 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,
@@ -1558,8 +1564,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);
@@ -1597,25 +1602,21 @@ 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),
"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 5699f9a558e46636c7f1ba0620c8c635e9f53f81..f7f30345a61e5bc2fd4edce5996d8ac03661bb13 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 52f87b8d603d7436289307e19e4522f60e0a3a7b..63e8458ea68023fe28008574c83e635b05a408cf 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 580172f7382e60ca65696d0372bc4b767b2b81d3..acb163fac4623ea96d09b3fd8316bb39702b7291 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/meson.build b/src/meson.build
index a19bb08b2646832c422c6742b6a1a935f1920c92..8b321cd6b6f292ed0fd6b9ea2012100545fdfff9 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',
diff --git a/src/tests/meta-monitor-test-utils.c b/src/tests/meta-monitor-test-utils.c
index 31133e09d2c617165f991df9b336b85d60b3c084..cbf0f76926230a54953b7906ffedae920709db90 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);
diff --git a/src/tests/meta-ref-test.c b/src/tests/meta-ref-test.c
index 9b0a689ce92bb99bac8676dc1025e43933c521b7..f380c6f1eec84153ac6fac0229d2c0386f8c56b0 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 0b5b2c31ee879a4f9e47f48c7747f49aabb40b5c..3ecc427963468873df370094dc2a3c36ea5c0412 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-device.c b/src/tests/native-kms-device.c
index f9cadf3f5b01c9ad14f72ce517bb6ca8ea602a2e..73f0b375c4ab32e7a97d73cbb85a1a842a6af398 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;
}
diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c
index e7881c8ef6bdbd8392babd60e95c68d8c780e83b..b34358f3287ae314ff51d889d2d32de71a5e9e45 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);
@@ -353,7 +355,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 13c6f9d409289d03913852669aae082f434e5197..ad5f85939aa1b7859073c24328a070bae46b4c7a 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 9a5f6eb48766682b183c9d7f771648c975e8489d..df8710f4684b57dca4284cabc9770f8cc999beee 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