5978 lines
216 KiB
Diff
5978 lines
216 KiB
Diff
From ac409e38b820ebf07a5677a3b393933dd3cf668d Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 18:24:02 -0300
|
|
Subject: [PATCH 01/49] clutter/stage-view: Move unexported functions to
|
|
private header
|
|
|
|
Next commits will expose ClutterStageView as a public class, so
|
|
move the functions private to Clutter to a private header.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
clutter/clutter/clutter-stage-view-private.h | 37 ++++++++++++++++++++
|
|
clutter/clutter/clutter-stage-view.c | 1 +
|
|
clutter/clutter/clutter-stage-view.h | 13 -------
|
|
clutter/clutter/clutter-stage.c | 1 +
|
|
clutter/clutter/cogl/clutter-stage-cogl.c | 1 +
|
|
clutter/clutter/meson.build | 1 +
|
|
6 files changed, 41 insertions(+), 13 deletions(-)
|
|
create mode 100644 clutter/clutter/clutter-stage-view-private.h
|
|
|
|
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
|
|
new file mode 100644
|
|
index 000000000..89c42599f
|
|
--- /dev/null
|
|
+++ b/clutter/clutter/clutter-stage-view-private.h
|
|
@@ -0,0 +1,37 @@
|
|
+/*
|
|
+ * Copyright (C) 2019 Red Hat Inc.
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library 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
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+
|
|
+#ifndef __CLUTTER_STAGE_VIEW_PRIVATE_H__
|
|
+#define __CLUTTER_STAGE_VIEW_PRIVATE_H__
|
|
+
|
|
+#include "clutter/clutter-stage-view.h"
|
|
+
|
|
+void clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
|
+ const cairo_rectangle_int_t *clip);
|
|
+
|
|
+gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
|
|
+
|
|
+void clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
|
|
+ gboolean dirty);
|
|
+
|
|
+gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
|
|
+
|
|
+void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
|
|
+ gboolean dirty);
|
|
+
|
|
+
|
|
+#endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
|
|
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
|
|
index c536ac720..e26e2fc07 100644
|
|
--- a/clutter/clutter/clutter-stage-view.c
|
|
+++ b/clutter/clutter/clutter-stage-view.c
|
|
@@ -18,6 +18,7 @@
|
|
#include "clutter-build-config.h"
|
|
|
|
#include "clutter/clutter-stage-view.h"
|
|
+#include "clutter/clutter-stage-view-private.h"
|
|
|
|
#include <cairo-gobject.h>
|
|
#include <math.h>
|
|
diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h
|
|
index 126498625..0c3448511 100644
|
|
--- a/clutter/clutter/clutter-stage-view.h
|
|
+++ b/clutter/clutter/clutter-stage-view.h
|
|
@@ -57,22 +57,9 @@ void clutter_stage_view_transform_to_onscreen (ClutterStageView *vie
|
|
gfloat *x,
|
|
gfloat *y);
|
|
|
|
-void clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
|
- const cairo_rectangle_int_t *clip);
|
|
-
|
|
CLUTTER_EXPORT
|
|
float clutter_stage_view_get_scale (ClutterStageView *view);
|
|
|
|
-gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
|
|
-
|
|
-void clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
|
|
- gboolean dirty);
|
|
-
|
|
-gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
|
|
-
|
|
-void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
|
|
- gboolean dirty);
|
|
-
|
|
CLUTTER_EXPORT
|
|
void clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
|
|
CoglMatrix *matrix);
|
|
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
|
|
index 1eea5b305..f254b5d49 100644
|
|
--- a/clutter/clutter/clutter-stage.c
|
|
+++ b/clutter/clutter/clutter-stage.c
|
|
@@ -72,6 +72,7 @@
|
|
#include "clutter-private.h"
|
|
#include "clutter-stage-manager-private.h"
|
|
#include "clutter-stage-private.h"
|
|
+#include "clutter-stage-view-private.h"
|
|
#include "clutter-private.h"
|
|
|
|
#include "cogl/cogl.h"
|
|
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
index eab76e52f..d942d9d41 100644
|
|
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
@@ -45,6 +45,7 @@
|
|
#include "clutter-main.h"
|
|
#include "clutter-private.h"
|
|
#include "clutter-stage-private.h"
|
|
+#include "clutter-stage-view-private.h"
|
|
|
|
typedef struct _ClutterStageViewCoglPrivate
|
|
{
|
|
diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build
|
|
index 671d790df..7feed24aa 100644
|
|
--- a/clutter/clutter/meson.build
|
|
+++ b/clutter/clutter/meson.build
|
|
@@ -206,6 +206,7 @@ clutter_private_headers = [
|
|
'clutter-stage-manager-private.h',
|
|
'clutter-stage-private.h',
|
|
'clutter-stage-view.h',
|
|
+ 'clutter-stage-view-private.h',
|
|
'clutter-stage-window.h',
|
|
]
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From cc2cf250f91d4b4c939aa1c6f8dd9dad4d77d975 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 18:32:12 -0300
|
|
Subject: [PATCH 02/49] clutter/stage-view: Annotate some functions
|
|
|
|
The GIR parser cannot figure out the ownership model of
|
|
ClutterStageView.get_framebuffer() and .get_offscreen()
|
|
without them, and throws us a couple of warnings.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
clutter/clutter/clutter-stage-view.c | 16 ++++++++++++++++
|
|
1 file changed, 16 insertions(+)
|
|
|
|
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
|
|
index e26e2fc07..0fad6fc44 100644
|
|
--- a/clutter/clutter/clutter-stage-view.c
|
|
+++ b/clutter/clutter/clutter-stage-view.c
|
|
@@ -66,6 +66,14 @@ clutter_stage_view_get_layout (ClutterStageView *view,
|
|
*rect = priv->layout;
|
|
}
|
|
|
|
+/**
|
|
+ * clutter_stage_view_get_framebuffer:
|
|
+ * @view: a #ClutterStageView
|
|
+ *
|
|
+ * Retrieves the framebuffer of @view to draw to.
|
|
+ *
|
|
+ * Returns: (transfer none): a #CoglFramebuffer
|
|
+ */
|
|
CoglFramebuffer *
|
|
clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
|
{
|
|
@@ -80,6 +88,14 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
|
return priv->framebuffer;
|
|
}
|
|
|
|
+/**
|
|
+ * clutter_stage_view_get_onscreen:
|
|
+ * @view: a #ClutterStageView
|
|
+ *
|
|
+ * Retrieves the onscreen framebuffer of @view if available.
|
|
+ *
|
|
+ * Returns: (transfer none): a #CoglFramebuffer
|
|
+ */
|
|
CoglFramebuffer *
|
|
clutter_stage_view_get_onscreen (ClutterStageView *view)
|
|
{
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From c21e563398edccbd210defe367d89920b2d3f3d1 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 18:33:17 -0300
|
|
Subject: [PATCH 03/49] clutter: Make ClutterStageView a public class
|
|
|
|
As a compositor toolkit, it makes sense to allow consumers
|
|
of Clutter interact with the stage views themselves. As such,
|
|
ClutterStageView should be a public class.
|
|
|
|
As such, it is now included in clutter.h and should not be
|
|
included directly.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
clutter/clutter/clutter-stage-view.h | 4 ++++
|
|
clutter/clutter/clutter.h | 1 +
|
|
clutter/clutter/meson.build | 4 ++--
|
|
3 files changed, 7 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h
|
|
index 0c3448511..26bf10e79 100644
|
|
--- a/clutter/clutter/clutter-stage-view.h
|
|
+++ b/clutter/clutter/clutter-stage-view.h
|
|
@@ -18,6 +18,10 @@
|
|
#ifndef __CLUTTER_STAGE_VIEW_H__
|
|
#define __CLUTTER_STAGE_VIEW_H__
|
|
|
|
+#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
|
+#error "Only <clutter/clutter.h> can be included directly."
|
|
+#endif
|
|
+
|
|
#include <cairo.h>
|
|
#include <glib-object.h>
|
|
#include <cogl/cogl.h>
|
|
diff --git a/clutter/clutter/clutter.h b/clutter/clutter/clutter.h
|
|
index 231d8cd1b..ec846910f 100644
|
|
--- a/clutter/clutter/clutter.h
|
|
+++ b/clutter/clutter/clutter.h
|
|
@@ -101,6 +101,7 @@
|
|
#include "clutter-snap-constraint.h"
|
|
#include "clutter-stage.h"
|
|
#include "clutter-stage-manager.h"
|
|
+#include "clutter-stage-view.h"
|
|
#include "clutter-tap-action.h"
|
|
#include "clutter-test-utils.h"
|
|
#include "clutter-texture.h"
|
|
diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build
|
|
index 7feed24aa..8e0484453 100644
|
|
--- a/clutter/clutter/meson.build
|
|
+++ b/clutter/clutter/meson.build
|
|
@@ -75,6 +75,7 @@ clutter_headers = [
|
|
'clutter-snap-constraint.h',
|
|
'clutter-stage.h',
|
|
'clutter-stage-manager.h',
|
|
+ 'clutter-stage-view.h',
|
|
'clutter-tap-action.h',
|
|
'clutter-test-utils.h',
|
|
'clutter-texture.h',
|
|
@@ -163,6 +164,7 @@ clutter_sources = [
|
|
'clutter-snap-constraint.c',
|
|
'clutter-stage.c',
|
|
'clutter-stage-manager.c',
|
|
+ 'clutter-stage-view.c',
|
|
'clutter-stage-window.c',
|
|
'clutter-tap-action.c',
|
|
'clutter-test-utils.c',
|
|
@@ -205,7 +207,6 @@ clutter_private_headers = [
|
|
'clutter-settings-private.h',
|
|
'clutter-stage-manager-private.h',
|
|
'clutter-stage-private.h',
|
|
- 'clutter-stage-view.h',
|
|
'clutter-stage-view-private.h',
|
|
'clutter-stage-window.h',
|
|
]
|
|
@@ -214,7 +215,6 @@ clutter_nonintrospected_sources = [
|
|
'clutter-easing.c',
|
|
'clutter-event-translator.c',
|
|
'clutter-id-pool.c',
|
|
- 'clutter-stage-view.c',
|
|
]
|
|
|
|
clutter_deprecated_headers = [
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From dfb1b9a61f2909be14be5a152f5eacb93cddafa2 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 18:39:34 -0300
|
|
Subject: [PATCH 04/49] clutter/stage: Own clutter_stage_get_view_at()
|
|
|
|
This function is exported as a Mutter-specific function,
|
|
but now that ClutterStageView is part of the public API,
|
|
ClutterStage can own this function.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
clutter/clutter/clutter-stage.h | 5 +++++
|
|
1 file changed, 5 insertions(+)
|
|
|
|
diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h
|
|
index 5730af7bd..9d0fdd362 100644
|
|
--- a/clutter/clutter/clutter-stage.h
|
|
+++ b/clutter/clutter/clutter-stage.h
|
|
@@ -30,6 +30,7 @@
|
|
|
|
#include <clutter/clutter-types.h>
|
|
#include <clutter/clutter-group.h>
|
|
+#include <clutter/clutter-stage-view.h>
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
@@ -274,6 +275,10 @@ gboolean clutter_stage_capture (ClutterStage *stage,
|
|
cairo_rectangle_int_t *rect,
|
|
ClutterCapture **captures,
|
|
int *n_captures);
|
|
+CLUTTER_EXPORT
|
|
+ClutterStageView * clutter_stage_get_view_at (ClutterStage *stage,
|
|
+ float x,
|
|
+ float y);
|
|
|
|
G_END_DECLS
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 29cd64c50a054384bf737ff12ee62770ae20b305 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 19:16:47 -0300
|
|
Subject: [PATCH 05/49] clutter/stage: Emit after-paint after painting
|
|
|
|
ClutterStage:after-paint is supposed to be emitted after all
|
|
painting is done, but before the frame is finished. However,
|
|
as it is right now, it is being emitted after each view is
|
|
painted -- on multi-monitor setups, after-frame is being
|
|
emitted multiple times.
|
|
|
|
Send after-paint only once, after all views are painted and
|
|
before finishing the frame.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
clutter/clutter/clutter-stage-private.h | 1 +
|
|
clutter/clutter/clutter-stage.c | 5 +++++
|
|
clutter/clutter/cogl/clutter-stage-cogl.c | 2 ++
|
|
3 files changed, 8 insertions(+)
|
|
|
|
diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h
|
|
index 4799c29e1..df0bf642b 100644
|
|
--- a/clutter/clutter/clutter-stage-private.h
|
|
+++ b/clutter/clutter/clutter-stage-private.h
|
|
@@ -40,6 +40,7 @@ void _clutter_stage_paint_view (ClutterStage
|
|
ClutterStageView *view,
|
|
const cairo_rectangle_int_t *clip);
|
|
|
|
+void _clutter_stage_emit_after_paint (ClutterStage *stage);
|
|
void _clutter_stage_set_window (ClutterStage *stage,
|
|
ClutterStageWindow *stage_window);
|
|
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
|
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
|
|
index f254b5d49..2b437e1f6 100644
|
|
--- a/clutter/clutter/clutter-stage.c
|
|
+++ b/clutter/clutter/clutter-stage.c
|
|
@@ -690,6 +690,11 @@ _clutter_stage_paint_view (ClutterStage *stage,
|
|
return;
|
|
|
|
clutter_stage_do_paint_view (stage, view, clip);
|
|
+}
|
|
+
|
|
+void
|
|
+_clutter_stage_emit_after_paint (ClutterStage *stage)
|
|
+{
|
|
g_signal_emit (stage, stage_signals[AFTER_PAINT], 0);
|
|
}
|
|
|
|
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
index d942d9d41..005c6f692 100644
|
|
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
@@ -936,6 +936,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
|
clutter_stage_cogl_redraw_view (stage_window, view) || swap_event;
|
|
}
|
|
|
|
+ _clutter_stage_emit_after_paint (stage_cogl->wrapper);
|
|
+
|
|
_clutter_stage_window_finish_frame (stage_window);
|
|
|
|
if (swap_event)
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 152945e1061d37d8e5899d2df9a24c25f46096ed Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 21:33:42 -0300
|
|
Subject: [PATCH 06/49] clutter/stage: Add ClutterStage:paint-view
|
|
|
|
Now that ClutterStageView is embraced as part of the public
|
|
set of Clutter classes, is it possible to give consumers
|
|
of this API more information and control over the drawing
|
|
routines of ClutterStage.
|
|
|
|
Introduce ClutterStage:paint-view, a signal that is emitted
|
|
for painting a specific view. It's defined as a RUN_LAST
|
|
signal to give anyone connecting to it the ability to run
|
|
before the view is actually painted, or after (using the
|
|
G_CONNECT_AFTER flag, or g_signal_connect_after).
|
|
|
|
This signal has a corresponding class handler, which allows
|
|
Mutter to have much finer control over the painting routines.
|
|
In fact, this will allow us to implement a "paint phase watcher"
|
|
mechanism in the following patches.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
clutter/clutter/clutter-stage.c | 47 ++++++++++++++++++++++++++++++++-
|
|
clutter/clutter/clutter-stage.h | 5 +++-
|
|
2 files changed, 50 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
|
|
index 2b437e1f6..34c4e0119 100644
|
|
--- a/clutter/clutter/clutter-stage.c
|
|
+++ b/clutter/clutter/clutter-stage.c
|
|
@@ -148,6 +148,8 @@ struct _ClutterStagePrivate
|
|
gpointer paint_data;
|
|
GDestroyNotify paint_notify;
|
|
|
|
+ cairo_rectangle_int_t view_clip;
|
|
+
|
|
int update_freeze_count;
|
|
|
|
guint relayout_pending : 1;
|
|
@@ -192,6 +194,7 @@ enum
|
|
DEACTIVATE,
|
|
DELETE_EVENT,
|
|
AFTER_PAINT,
|
|
+ PAINT_VIEW,
|
|
PRESENTED,
|
|
|
|
LAST_SIGNAL
|
|
@@ -689,7 +692,15 @@ _clutter_stage_paint_view (ClutterStage *stage,
|
|
if (!priv->impl)
|
|
return;
|
|
|
|
- clutter_stage_do_paint_view (stage, view, clip);
|
|
+ priv->view_clip = *clip;
|
|
+
|
|
+ if (g_signal_has_handler_pending (stage, stage_signals[PAINT_VIEW],
|
|
+ 0, TRUE))
|
|
+ g_signal_emit (stage, stage_signals[PAINT_VIEW], 0, view);
|
|
+ else
|
|
+ CLUTTER_STAGE_GET_CLASS (stage)->paint_view (stage, view);
|
|
+
|
|
+ priv->view_clip = (cairo_rectangle_int_t) { 0 };
|
|
}
|
|
|
|
void
|
|
@@ -1901,6 +1912,16 @@ clutter_stage_finalize (GObject *object)
|
|
G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object);
|
|
}
|
|
|
|
+static void
|
|
+clutter_stage_real_paint_view (ClutterStage *stage,
|
|
+ ClutterStageView *view)
|
|
+{
|
|
+ ClutterStagePrivate *priv = stage->priv;
|
|
+ const cairo_rectangle_int_t *clip = &priv->view_clip;
|
|
+
|
|
+ clutter_stage_do_paint_view (stage, view, clip);
|
|
+}
|
|
+
|
|
static void
|
|
clutter_stage_class_init (ClutterStageClass *klass)
|
|
{
|
|
@@ -1930,6 +1951,8 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
|
actor_class->queue_redraw = clutter_stage_real_queue_redraw;
|
|
actor_class->apply_transform = clutter_stage_real_apply_transform;
|
|
|
|
+ klass->paint_view = clutter_stage_real_paint_view;
|
|
+
|
|
/**
|
|
* ClutterStage:fullscreen:
|
|
*
|
|
@@ -2257,6 +2280,28 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
|
|
+ /**
|
|
+ * ClutterStage::paint-view:
|
|
+ * @stage: the stage that received the event
|
|
+ * @view: a #ClutterStageView
|
|
+ *
|
|
+ * The ::paint-view signal is emitted before a #ClutterStageView is being
|
|
+ * painted.
|
|
+ *
|
|
+ * The view is painted in the default handler. Hence, if you want to perform
|
|
+ * some action after the view is painted, like reading the contents of the
|
|
+ * framebuffer, use g_signal_connect_after() or pass %G_CONNECT_AFTER.
|
|
+ */
|
|
+ stage_signals[PAINT_VIEW] =
|
|
+ g_signal_new (I_("paint-view"),
|
|
+ G_TYPE_FROM_CLASS (gobject_class),
|
|
+ G_SIGNAL_RUN_LAST,
|
|
+ G_STRUCT_OFFSET (ClutterStageClass, paint_view),
|
|
+ NULL, NULL,
|
|
+ _clutter_marshal_VOID__OBJECT,
|
|
+ G_TYPE_NONE, 1,
|
|
+ CLUTTER_TYPE_STAGE_VIEW);
|
|
+
|
|
/**
|
|
* ClutterStage::presented: (skip)
|
|
* @stage: the stage that received the event
|
|
diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h
|
|
index 9d0fdd362..9da63d211 100644
|
|
--- a/clutter/clutter/clutter-stage.h
|
|
+++ b/clutter/clutter/clutter-stage.h
|
|
@@ -88,9 +88,12 @@ struct _ClutterStageClass
|
|
gboolean (* delete_event) (ClutterStage *stage,
|
|
ClutterEvent *event);
|
|
|
|
+ void (* paint_view) (ClutterStage *stage,
|
|
+ ClutterStageView *view);
|
|
+
|
|
/*< private >*/
|
|
/* padding for future expansion */
|
|
- gpointer _padding_dummy[31];
|
|
+ gpointer _padding_dummy[30];
|
|
};
|
|
|
|
/**
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 2da9db1546f025aa02e23136b40e96a8ba99d1c5 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 23:32:00 -0300
|
|
Subject: [PATCH 07/49] clutter/tests: Connect to ClutterStage:paint-view
|
|
|
|
ClutterStage:after-paint now does not guarantee a valid
|
|
implicit framebuffer pushed to the stack. Instead, use
|
|
the new 'paint-view' signal, that is emitted at a point
|
|
in the drawing routine where a framebuffer is pushed.
|
|
|
|
In addition to that, stop using the implicit framebuffer
|
|
API and port the actor-shader-effect test to read from
|
|
the view's framebuffer directly.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
clutter/tests/conform/actor-shader-effect.c | 32 ++++++++++++---------
|
|
1 file changed, 18 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/clutter/tests/conform/actor-shader-effect.c b/clutter/tests/conform/actor-shader-effect.c
|
|
index 93a43ea8b..ac99c5b40 100644
|
|
--- a/clutter/tests/conform/actor-shader-effect.c
|
|
+++ b/clutter/tests/conform/actor-shader-effect.c
|
|
@@ -209,14 +209,16 @@ make_actor (GType shader_type)
|
|
}
|
|
|
|
static guint32
|
|
-get_pixel (int x, int y)
|
|
+get_pixel (CoglFramebuffer *fb,
|
|
+ int x,
|
|
+ int y)
|
|
{
|
|
guint8 data[4];
|
|
|
|
- cogl_read_pixels (x, y, 1, 1,
|
|
- COGL_READ_PIXELS_COLOR_BUFFER,
|
|
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
|
- data);
|
|
+ cogl_framebuffer_read_pixels (fb,
|
|
+ x, y, 1, 1,
|
|
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
|
+ data);
|
|
|
|
return (((guint32) data[0] << 16) |
|
|
((guint32) data[1] << 8) |
|
|
@@ -224,19 +226,21 @@ get_pixel (int x, int y)
|
|
}
|
|
|
|
static void
|
|
-paint_cb (ClutterStage *stage,
|
|
- gpointer data)
|
|
+view_painted_cb (ClutterStage *stage,
|
|
+ ClutterStageView *view,
|
|
+ gpointer data)
|
|
{
|
|
+ CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view);
|
|
gboolean *was_painted = data;
|
|
|
|
/* old shader effect */
|
|
- g_assert_cmpint (get_pixel (0, 25), ==, 0xff0000);
|
|
+ g_assert_cmpint (get_pixel (fb, 0, 25), ==, 0xff0000);
|
|
/* new shader effect */
|
|
- g_assert_cmpint (get_pixel (100, 25), ==, 0x00ffff);
|
|
+ g_assert_cmpint (get_pixel (fb, 100, 25), ==, 0x00ffff);
|
|
/* another new shader effect */
|
|
- g_assert_cmpint (get_pixel (200, 25), ==, 0xff00ff);
|
|
+ g_assert_cmpint (get_pixel (fb, 200, 25), ==, 0xff00ff);
|
|
/* new shader effect */
|
|
- g_assert_cmpint (get_pixel (300, 25), ==, 0x00ffff);
|
|
+ g_assert_cmpint (get_pixel (fb, 300, 25), ==, 0x00ffff);
|
|
|
|
*was_painted = TRUE;
|
|
}
|
|
@@ -271,9 +275,9 @@ actor_shader_effect (void)
|
|
clutter_actor_show (stage);
|
|
|
|
was_painted = FALSE;
|
|
- g_signal_connect (stage, "after-paint",
|
|
- G_CALLBACK (paint_cb),
|
|
- &was_painted);
|
|
+ g_signal_connect_after (stage, "paint-view",
|
|
+ G_CALLBACK (view_painted_cb),
|
|
+ &was_painted);
|
|
|
|
while (!was_painted)
|
|
g_main_context_iteration (NULL, FALSE);
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 50271dfbdbb8926474a5cf3019c8552afd40f0da Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 21:43:05 -0300
|
|
Subject: [PATCH 08/49] stage: Introduce MetaStageWatch and family
|
|
|
|
MetaStageWatch, watch modes and the watch function are part
|
|
of the new stage view watching API. It's design does not
|
|
rely on signals on purpose; the number of signals that would
|
|
be emitted would be too high, and would impact performance.
|
|
|
|
MetaStageWatch is an opaque structure outside of MetaStage.
|
|
|
|
This will be used by the screencast code to monitor a single
|
|
view, which has a one-to-one relatioship to logical monitors.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
src/backends/meta-stage-private.h | 22 +++++++
|
|
src/backends/meta-stage.c | 104 ++++++++++++++++++++++++++++++
|
|
2 files changed, 126 insertions(+)
|
|
|
|
diff --git a/src/backends/meta-stage-private.h b/src/backends/meta-stage-private.h
|
|
index 639d2372c..963017688 100644
|
|
--- a/src/backends/meta-stage-private.h
|
|
+++ b/src/backends/meta-stage-private.h
|
|
@@ -27,8 +27,21 @@
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
+typedef struct _MetaStageWatch MetaStageWatch;
|
|
typedef struct _MetaOverlay MetaOverlay;
|
|
|
|
+typedef enum
|
|
+{
|
|
+ META_STAGE_WATCH_BEFORE_PAINT,
|
|
+ META_STAGE_WATCH_AFTER_ACTOR_PAINT,
|
|
+ META_STAGE_WATCH_AFTER_OVERLAY_PAINT,
|
|
+ META_STAGE_WATCH_AFTER_PAINT,
|
|
+} MetaStageWatchPhase;
|
|
+
|
|
+typedef void (* MetaStageWatchFunc) (MetaStage *stage,
|
|
+ ClutterStageView *view,
|
|
+ gpointer user_data);
|
|
+
|
|
ClutterActor *meta_stage_new (MetaBackend *backend);
|
|
|
|
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
|
|
@@ -43,6 +56,15 @@ void meta_stage_update_cursor_overlay (MetaStage *stage,
|
|
void meta_stage_set_active (MetaStage *stage,
|
|
gboolean is_active);
|
|
|
|
+MetaStageWatch * meta_stage_watch_view (MetaStage *stage,
|
|
+ ClutterStageView *view,
|
|
+ MetaStageWatchPhase watch_mode,
|
|
+ MetaStageWatchFunc callback,
|
|
+ gpointer user_data);
|
|
+
|
|
+void meta_stage_remove_watch (MetaStage *stage,
|
|
+ MetaStageWatch *watch);
|
|
+
|
|
G_END_DECLS
|
|
|
|
#endif /* META_STAGE_PRIVATE_H */
|
|
diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c
|
|
index 47a00e51a..8809035d1 100644
|
|
--- a/src/backends/meta-stage.c
|
|
+++ b/src/backends/meta-stage.c
|
|
@@ -30,6 +30,8 @@
|
|
#include "meta/meta-monitor-manager.h"
|
|
#include "meta/util.h"
|
|
|
|
+#define N_WATCH_MODES 4
|
|
+
|
|
enum
|
|
{
|
|
ACTORS_PAINTED,
|
|
@@ -39,6 +41,13 @@ enum
|
|
|
|
static guint signals[N_SIGNALS];
|
|
|
|
+struct _MetaStageWatch
|
|
+{
|
|
+ ClutterStageView *view;
|
|
+ MetaStageWatchFunc callback;
|
|
+ gpointer user_data;
|
|
+};
|
|
+
|
|
struct _MetaOverlay
|
|
{
|
|
gboolean enabled;
|
|
@@ -55,6 +64,9 @@ struct _MetaStage
|
|
{
|
|
ClutterStage parent;
|
|
|
|
+ GPtrArray *watchers[N_WATCH_MODES];
|
|
+ ClutterStageView *current_view;
|
|
+
|
|
GList *overlays;
|
|
gboolean is_active;
|
|
};
|
|
@@ -135,6 +147,7 @@ meta_stage_finalize (GObject *object)
|
|
{
|
|
MetaStage *stage = META_STAGE (object);
|
|
GList *l;
|
|
+ int i;
|
|
|
|
l = stage->overlays;
|
|
while (l)
|
|
@@ -143,9 +156,33 @@ meta_stage_finalize (GObject *object)
|
|
l = g_list_delete_link (l, l);
|
|
}
|
|
|
|
+ for (i = 0; i < N_WATCH_MODES; i++)
|
|
+ g_clear_pointer (&stage->watchers[i], g_ptr_array_unref);
|
|
+
|
|
G_OBJECT_CLASS (meta_stage_parent_class)->finalize (object);
|
|
}
|
|
|
|
+static void
|
|
+notify_watchers_for_mode (MetaStage *stage,
|
|
+ ClutterStageView *view,
|
|
+ MetaStageWatchPhase watch_phase)
|
|
+{
|
|
+ GPtrArray *watchers;
|
|
+ int i;
|
|
+
|
|
+ watchers = stage->watchers[watch_phase];
|
|
+
|
|
+ for (i = 0; i < watchers->len; i++)
|
|
+ {
|
|
+ MetaStageWatch *watch = g_ptr_array_index (watchers, i);
|
|
+
|
|
+ if (watch->view && view != watch->view)
|
|
+ continue;
|
|
+
|
|
+ watch->callback (stage, view, watch->user_data);
|
|
+ }
|
|
+}
|
|
+
|
|
static void
|
|
meta_stage_paint (ClutterActor *actor)
|
|
{
|
|
@@ -154,10 +191,30 @@ meta_stage_paint (ClutterActor *actor)
|
|
|
|
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
|
|
|
+ notify_watchers_for_mode (stage, stage->current_view,
|
|
+ META_STAGE_WATCH_AFTER_ACTOR_PAINT);
|
|
+
|
|
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
|
|
|
|
for (l = stage->overlays; l; l = l->next)
|
|
meta_overlay_paint (l->data);
|
|
+
|
|
+ notify_watchers_for_mode (stage, stage->current_view,
|
|
+ META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
|
|
+}
|
|
+
|
|
+static void
|
|
+meta_stage_paint_view (ClutterStage *stage,
|
|
+ ClutterStageView *view)
|
|
+{
|
|
+ MetaStage *meta_stage = META_STAGE (stage);
|
|
+
|
|
+ notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT);
|
|
+
|
|
+ meta_stage->current_view = view;
|
|
+ CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view);
|
|
+
|
|
+ notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT);
|
|
}
|
|
|
|
static void
|
|
@@ -202,6 +259,7 @@ meta_stage_class_init (MetaStageClass *klass)
|
|
|
|
stage_class->activate = meta_stage_activate;
|
|
stage_class->deactivate = meta_stage_deactivate;
|
|
+ stage_class->paint_view = meta_stage_paint_view;
|
|
|
|
signals[ACTORS_PAINTED] = g_signal_new ("actors-painted",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
@@ -214,7 +272,12 @@ meta_stage_class_init (MetaStageClass *klass)
|
|
static void
|
|
meta_stage_init (MetaStage *stage)
|
|
{
|
|
+ int i;
|
|
+
|
|
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
|
+
|
|
+ for (i = 0; i < N_WATCH_MODES; i++)
|
|
+ stage->watchers[i] = g_ptr_array_new_with_free_func (g_free);
|
|
}
|
|
|
|
ClutterActor *
|
|
@@ -346,3 +409,44 @@ meta_stage_set_active (MetaStage *stage,
|
|
*/
|
|
clutter_stage_event (CLUTTER_STAGE (stage), &event);
|
|
}
|
|
+
|
|
+MetaStageWatch *
|
|
+meta_stage_watch_view (MetaStage *stage,
|
|
+ ClutterStageView *view,
|
|
+ MetaStageWatchPhase watch_phase,
|
|
+ MetaStageWatchFunc callback,
|
|
+ gpointer user_data)
|
|
+{
|
|
+ MetaStageWatch *watch;
|
|
+ GPtrArray *watchers;
|
|
+
|
|
+ watch = g_new0 (MetaStageWatch, 1);
|
|
+ watch->view = view;
|
|
+ watch->callback = callback;
|
|
+ watch->user_data = user_data;
|
|
+
|
|
+ watchers = stage->watchers[watch_phase];
|
|
+ g_ptr_array_add (watchers, watch);
|
|
+
|
|
+ return watch;
|
|
+}
|
|
+
|
|
+void
|
|
+meta_stage_remove_watch (MetaStage *stage,
|
|
+ MetaStageWatch *watch)
|
|
+{
|
|
+ GPtrArray *watchers;
|
|
+ gboolean removed = FALSE;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < N_WATCH_MODES; i++)
|
|
+ {
|
|
+ watchers = stage->watchers[i];
|
|
+ removed = g_ptr_array_remove_fast (watchers, watch);
|
|
+
|
|
+ if (removed)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ g_assert (removed);
|
|
+}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 8c509454f193945f09ef7afb5a397df266d2fffd Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 17 Jun 2019 21:49:45 -0300
|
|
Subject: [PATCH 09/49] screen-cast-monitor-stream-src: Watch monitors using
|
|
MetaStageWatch
|
|
|
|
This uses the API introduced by the previous commit. By watching specific
|
|
monitors directly, and not whole stage views, we avoid showing artifacts
|
|
on multi-monitor setups.
|
|
|
|
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/424
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/623
|
|
---
|
|
.../meta-screen-cast-monitor-stream-src.c | 65 +++++++++++++------
|
|
1 file changed, 44 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
index cb9823148..f582217e5 100644
|
|
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
@@ -32,6 +32,7 @@
|
|
#include "backends/meta-monitor.h"
|
|
#include "backends/meta-screen-cast-monitor-stream.h"
|
|
#include "backends/meta-screen-cast-session.h"
|
|
+#include "backends/meta-stage-private.h"
|
|
#include "clutter/clutter.h"
|
|
#include "clutter/clutter-mutter.h"
|
|
#include "core/boxes-private.h"
|
|
@@ -42,8 +43,9 @@ struct _MetaScreenCastMonitorStreamSrc
|
|
|
|
gboolean cursor_bitmap_invalid;
|
|
|
|
- gulong actors_painted_handler_id;
|
|
- gulong paint_handler_id;
|
|
+ MetaStageWatch *paint_watch;
|
|
+ MetaStageWatch *after_paint_watch;
|
|
+
|
|
gulong cursor_moved_handler_id;
|
|
gulong cursor_changed_handler_id;
|
|
};
|
|
@@ -113,10 +115,11 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
|
}
|
|
|
|
static void
|
|
-stage_painted (ClutterActor *actor,
|
|
- MetaScreenCastMonitorStreamSrc *monitor_src)
|
|
+stage_painted (MetaStage *stage,
|
|
+ ClutterStageView *view,
|
|
+ gpointer user_data)
|
|
{
|
|
- MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
|
+ MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
|
|
|
|
meta_screen_cast_stream_src_maybe_record_frame (src);
|
|
}
|
|
@@ -245,12 +248,28 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
|
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
|
MetaBackend *backend = get_backend (monitor_src);
|
|
+ MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
|
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
|
+ MetaRendererView *view;
|
|
+ MetaMonitor *monitor;
|
|
+ MetaLogicalMonitor *logical_monitor;
|
|
+ MetaStage *meta_stage;
|
|
+ ClutterStageView *stage_view;
|
|
ClutterStage *stage;
|
|
MetaScreenCastStream *stream;
|
|
|
|
stream = meta_screen_cast_stream_src_get_stream (src);
|
|
stage = get_stage (monitor_src);
|
|
+ meta_stage = META_STAGE (stage);
|
|
+ monitor = get_monitor (monitor_src);
|
|
+ logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
|
+ view = meta_renderer_get_view_from_logical_monitor (renderer,
|
|
+ logical_monitor);
|
|
+
|
|
+ if (view)
|
|
+ stage_view = CLUTTER_STAGE_VIEW (view);
|
|
+ else
|
|
+ stage_view = NULL;
|
|
|
|
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
|
{
|
|
@@ -265,17 +284,21 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
|
|
monitor_src);
|
|
/* Intentional fall-through */
|
|
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
|
- monitor_src->actors_painted_handler_id =
|
|
- g_signal_connect (stage, "actors-painted",
|
|
- G_CALLBACK (stage_painted),
|
|
- monitor_src);
|
|
+ monitor_src->paint_watch =
|
|
+ meta_stage_watch_view (meta_stage,
|
|
+ stage_view,
|
|
+ META_STAGE_WATCH_AFTER_ACTOR_PAINT,
|
|
+ stage_painted,
|
|
+ monitor_src);
|
|
break;
|
|
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
|
|
inhibit_hw_cursor (monitor_src);
|
|
- monitor_src->paint_handler_id =
|
|
- g_signal_connect_after (stage, "paint",
|
|
- G_CALLBACK (stage_painted),
|
|
- monitor_src);
|
|
+ monitor_src->after_paint_watch =
|
|
+ meta_stage_watch_view (meta_stage,
|
|
+ stage_view,
|
|
+ META_STAGE_WATCH_AFTER_PAINT,
|
|
+ stage_painted,
|
|
+ monitor_src);
|
|
break;
|
|
}
|
|
|
|
@@ -290,21 +313,21 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|
MetaBackend *backend = get_backend (monitor_src);
|
|
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
|
ClutterStage *stage;
|
|
+ MetaStage *meta_stage;
|
|
|
|
stage = get_stage (monitor_src);
|
|
+ meta_stage = META_STAGE (stage);
|
|
|
|
- if (monitor_src->actors_painted_handler_id)
|
|
+ if (monitor_src->paint_watch)
|
|
{
|
|
- g_signal_handler_disconnect (stage,
|
|
- monitor_src->actors_painted_handler_id);
|
|
- monitor_src->actors_painted_handler_id = 0;
|
|
+ meta_stage_remove_watch (meta_stage, monitor_src->paint_watch);
|
|
+ monitor_src->paint_watch = NULL;
|
|
}
|
|
|
|
- if (monitor_src->paint_handler_id)
|
|
+ if (monitor_src->after_paint_watch)
|
|
{
|
|
- g_signal_handler_disconnect (stage,
|
|
- monitor_src->paint_handler_id);
|
|
- monitor_src->paint_handler_id = 0;
|
|
+ meta_stage_remove_watch (meta_stage, monitor_src->after_paint_watch);
|
|
+ monitor_src->after_paint_watch = NULL;
|
|
uninhibit_hw_cursor (monitor_src);
|
|
}
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 547e3f004f9d9235efc5dfd816f4a1214cf44616 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Mon, 26 Aug 2019 16:09:53 +0300
|
|
Subject: [PATCH 10/49] window-actor: Add 'damaged' signal
|
|
|
|
Make it possible to listen for damage on a window actor. For X11, the
|
|
signal is emitted when damage is reported; for Wayland, it is emitted
|
|
when any of the surfaces associated with the window is damaged.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/752
|
|
---
|
|
src/compositor/meta-window-actor-private.h | 2 ++
|
|
src/compositor/meta-window-actor.c | 23 ++++++++++++++++++
|
|
src/wayland/meta-wayland-surface.c | 27 +++++++++++++++++++---
|
|
3 files changed, 49 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
|
|
index 9c1c12d09..3df520ac5 100644
|
|
--- a/src/compositor/meta-window-actor-private.h
|
|
+++ b/src/compositor/meta-window-actor-private.h
|
|
@@ -81,4 +81,6 @@ void meta_window_actor_stereo_notify (MetaWindowActor *actor,
|
|
|
|
gboolean meta_window_actor_is_stereo (MetaWindowActor *actor);
|
|
|
|
+void meta_window_actor_notify_damaged (MetaWindowActor *window_actor);
|
|
+
|
|
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index 11686d00b..f4eba6d42 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -116,6 +116,7 @@ enum
|
|
{
|
|
FIRST_FRAME,
|
|
EFFECTS_COMPLETED,
|
|
+ DAMAGED,
|
|
|
|
LAST_SIGNAL
|
|
};
|
|
@@ -226,6 +227,20 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 0);
|
|
|
|
+ /**
|
|
+ * MetaWindowActor::damaged:
|
|
+ * @actor: the #MetaWindowActor instance
|
|
+ *
|
|
+ * Notify that one or more of the surfaces of the window have been damaged.
|
|
+ */
|
|
+ signals[DAMAGED] =
|
|
+ g_signal_new ("damaged",
|
|
+ G_TYPE_FROM_CLASS (object_class),
|
|
+ G_SIGNAL_RUN_LAST,
|
|
+ 0,
|
|
+ NULL, NULL, NULL,
|
|
+ G_TYPE_NONE, 0);
|
|
+
|
|
pspec = g_param_spec_object ("meta-window",
|
|
"MetaWindow",
|
|
"The displayed MetaWindow",
|
|
@@ -1445,6 +1460,8 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
|
|
event->area.y,
|
|
event->area.width,
|
|
event->area.height);
|
|
+
|
|
+ meta_window_actor_notify_damaged (self);
|
|
}
|
|
|
|
void
|
|
@@ -2053,3 +2070,9 @@ meta_window_actor_is_stereo (MetaWindowActor *self)
|
|
else
|
|
return FALSE;
|
|
}
|
|
+
|
|
+void
|
|
+meta_window_actor_notify_damaged (MetaWindowActor *window_actor)
|
|
+{
|
|
+ g_signal_emit (window_actor, signals[DAMAGED], 0);
|
|
+}
|
|
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
|
|
index ddad1a45c..6ffcd6a7f 100644
|
|
--- a/src/wayland/meta-wayland-surface.c
|
|
+++ b/src/wayland/meta-wayland-surface.c
|
|
@@ -669,6 +669,8 @@ void
|
|
meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
|
MetaWaylandPendingState *pending)
|
|
{
|
|
+ gboolean had_damage = FALSE;
|
|
+
|
|
if (surface->role)
|
|
{
|
|
meta_wayland_surface_role_pre_commit (surface->role, pending);
|
|
@@ -771,9 +773,12 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
|
|
|
if (!cairo_region_is_empty (pending->surface_damage) ||
|
|
!cairo_region_is_empty (pending->buffer_damage))
|
|
- surface_process_damage (surface,
|
|
- pending->surface_damage,
|
|
- pending->buffer_damage);
|
|
+ {
|
|
+ surface_process_damage (surface,
|
|
+ pending->surface_damage,
|
|
+ pending->buffer_damage);
|
|
+ had_damage = TRUE;
|
|
+ }
|
|
|
|
surface->offset_x += pending->dx;
|
|
surface->offset_y += pending->dy;
|
|
@@ -834,6 +839,22 @@ cleanup:
|
|
pending_state_reset (pending);
|
|
|
|
g_list_foreach (surface->subsurfaces, parent_surface_state_applied, NULL);
|
|
+
|
|
+ if (had_damage)
|
|
+ {
|
|
+ MetaWindow *toplevel_window;
|
|
+
|
|
+ toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
|
|
+ if (toplevel_window)
|
|
+ {
|
|
+ MetaWindowActor *toplevel_window_actor;
|
|
+
|
|
+ toplevel_window_actor =
|
|
+ meta_window_actor_from_window (toplevel_window);
|
|
+ if (toplevel_window_actor)
|
|
+ meta_window_actor_notify_damaged (toplevel_window_actor);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
static void
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 27ada1ee57ac85d77cea9a1aee71b77f4939439f Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Mon, 26 Aug 2019 16:12:30 +0300
|
|
Subject: [PATCH 11/49] screen-cast/window: Use window actor damaged signal
|
|
instead of paint
|
|
|
|
We are really more interested in when a window is damaged, rather than
|
|
when it's painted, for screen casting windows. This also has the benefit
|
|
of not listening on the "paint" signal of the actor, meaning it'll open
|
|
doors for hacks currently necessary for taking a screenshot of a window
|
|
consisting of multiple surfaces.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/752
|
|
---
|
|
.../meta-screen-cast-window-stream-src.c | 45 +++++--------------
|
|
1 file changed, 11 insertions(+), 34 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
|
|
index dbf330420..c31830b03 100644
|
|
--- a/src/backends/meta-screen-cast-window-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-window-stream-src.c
|
|
@@ -34,13 +34,11 @@ struct _MetaScreenCastWindowStreamSrc
|
|
|
|
MetaScreenCastWindow *screen_cast_window;
|
|
|
|
- unsigned long screen_cast_window_before_paint_handler_id;
|
|
- unsigned long screen_cast_window_after_paint_handler_id;
|
|
+ unsigned long screen_cast_window_damaged_handler_id;
|
|
unsigned long screen_cast_window_destroyed_handler_id;
|
|
unsigned long cursor_moved_handler_id;
|
|
unsigned long cursor_changed_handler_id;
|
|
|
|
- gboolean actor_was_dirty;
|
|
gboolean cursor_bitmap_invalid;
|
|
};
|
|
|
|
@@ -255,15 +253,10 @@ meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_s
|
|
if (!window_src->screen_cast_window)
|
|
return;
|
|
|
|
- if (window_src->screen_cast_window_before_paint_handler_id)
|
|
+ if (window_src->screen_cast_window_damaged_handler_id)
|
|
g_signal_handler_disconnect (window_src->screen_cast_window,
|
|
- window_src->screen_cast_window_before_paint_handler_id);
|
|
- window_src->screen_cast_window_before_paint_handler_id = 0;
|
|
-
|
|
- if (window_src->screen_cast_window_after_paint_handler_id)
|
|
- g_signal_handler_disconnect (window_src->screen_cast_window,
|
|
- window_src->screen_cast_window_after_paint_handler_id);
|
|
- window_src->screen_cast_window_after_paint_handler_id = 0;
|
|
+ window_src->screen_cast_window_damaged_handler_id);
|
|
+ window_src->screen_cast_window_damaged_handler_id = 0;
|
|
|
|
if (window_src->screen_cast_window_destroyed_handler_id)
|
|
g_signal_handler_disconnect (window_src->screen_cast_window,
|
|
@@ -282,23 +275,12 @@ meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_s
|
|
}
|
|
|
|
static void
|
|
-screen_cast_window_before_paint (MetaScreenCastWindow *screen_cast_window,
|
|
- MetaScreenCastWindowStreamSrc *window_src)
|
|
-{
|
|
- window_src->actor_was_dirty =
|
|
- meta_screen_cast_window_has_damage (screen_cast_window);
|
|
-}
|
|
-
|
|
-static void
|
|
-screen_cast_window_after_paint (MetaWindowActor *actor,
|
|
- MetaScreenCastWindowStreamSrc *window_src)
|
|
+screen_cast_window_damaged (MetaWindowActor *actor,
|
|
+ MetaScreenCastWindowStreamSrc *window_src)
|
|
{
|
|
- if (window_src->actor_was_dirty)
|
|
- {
|
|
- MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
|
+ MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
|
|
|
- meta_screen_cast_stream_src_maybe_record_frame (src);
|
|
- }
|
|
+ meta_screen_cast_stream_src_maybe_record_frame (src);
|
|
}
|
|
|
|
static void
|
|
@@ -378,16 +360,11 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
|
|
|
window_src->screen_cast_window = META_SCREEN_CAST_WINDOW (window_actor);
|
|
|
|
- window_src->screen_cast_window_before_paint_handler_id =
|
|
+ window_src->screen_cast_window_damaged_handler_id =
|
|
g_signal_connect (window_src->screen_cast_window,
|
|
- "paint",
|
|
- G_CALLBACK (screen_cast_window_before_paint),
|
|
+ "damaged",
|
|
+ G_CALLBACK (screen_cast_window_damaged),
|
|
window_src);
|
|
- window_src->screen_cast_window_after_paint_handler_id =
|
|
- g_signal_connect_after (window_src->screen_cast_window,
|
|
- "paint",
|
|
- G_CALLBACK (screen_cast_window_after_paint),
|
|
- window_src);
|
|
|
|
window_src->screen_cast_window_destroyed_handler_id =
|
|
g_signal_connect (window_src->screen_cast_window,
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 2bf9b015901aa58826ebf96d941f9dbf803ec6b3 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Mon, 26 Aug 2019 16:29:33 +0300
|
|
Subject: [PATCH 12/49] window-actor: Add API to get a cairo surface of the
|
|
window
|
|
|
|
This currently uses a hack where it pushes a CoglFramebuffer backed by a
|
|
texture to the framebuffer stack, then calls clutter_actor_paint() on
|
|
the window actor causing it to render into the framebuffer. This has the
|
|
effect that all subsurfaces of a window will be drawn as part of the
|
|
window.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/752
|
|
---
|
|
src/compositor/meta-window-actor.c | 113 +++++++++++++++++++++++++++++
|
|
src/meta/meta-window-actor.h | 4 +
|
|
2 files changed, 117 insertions(+)
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index f4eba6d42..9d215c745 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -2076,3 +2076,116 @@ meta_window_actor_notify_damaged (MetaWindowActor *window_actor)
|
|
{
|
|
g_signal_emit (window_actor, signals[DAMAGED], 0);
|
|
}
|
|
+
|
|
+cairo_surface_t *
|
|
+meta_window_actor_get_image (MetaWindowActor *self,
|
|
+ MetaRectangle *clip)
|
|
+{
|
|
+ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self);
|
|
+ ClutterActor *actor = CLUTTER_ACTOR (self);
|
|
+ MetaBackend *backend = meta_get_backend ();
|
|
+ ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
|
+ CoglContext *cogl_context =
|
|
+ clutter_backend_get_cogl_context (clutter_backend);
|
|
+ float resource_scale;
|
|
+ float width, height;
|
|
+ CoglTexture2D *texture;
|
|
+ g_autoptr (GError) error = NULL;
|
|
+ CoglOffscreen *offscreen;
|
|
+ CoglFramebuffer *framebuffer;
|
|
+ CoglColor clear_color;
|
|
+ float x, y;
|
|
+ MetaRectangle scaled_clip;
|
|
+ cairo_surface_t *surface;
|
|
+
|
|
+ if (!priv->surface)
|
|
+ return NULL;
|
|
+
|
|
+ if (clutter_actor_get_n_children (actor) == 1)
|
|
+ {
|
|
+ MetaShapedTexture *stex;
|
|
+
|
|
+ stex = meta_surface_actor_get_texture (priv->surface);
|
|
+ return meta_shaped_texture_get_image (stex, clip);
|
|
+ }
|
|
+
|
|
+ clutter_actor_get_size (actor, &width, &height);
|
|
+
|
|
+ if (width == 0 || height == 0)
|
|
+ return NULL;
|
|
+
|
|
+ if (!clutter_actor_get_resource_scale (actor, &resource_scale))
|
|
+ return NULL;
|
|
+
|
|
+ width = ceilf (width * resource_scale);
|
|
+ height = ceilf (height * resource_scale);
|
|
+
|
|
+ texture = cogl_texture_2d_new_with_size (cogl_context, width, height);
|
|
+ if (!texture)
|
|
+ return NULL;
|
|
+
|
|
+ cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture),
|
|
+ FALSE);
|
|
+
|
|
+ offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
|
|
+ framebuffer = COGL_FRAMEBUFFER (offscreen);
|
|
+
|
|
+ cogl_object_unref (texture);
|
|
+
|
|
+ if (!cogl_framebuffer_allocate (framebuffer, &error))
|
|
+ {
|
|
+ g_warning ("Failed to allocate framebuffer for screenshot: %s",
|
|
+ error->message);
|
|
+ cogl_object_unref (framebuffer);
|
|
+ cogl_object_unref (texture);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
|
+ clutter_actor_get_position (actor, &x, &y);
|
|
+
|
|
+ cogl_push_framebuffer (framebuffer);
|
|
+
|
|
+ cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
|
|
+ cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0);
|
|
+ cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
|
|
+ cogl_framebuffer_translate (framebuffer, -x, -y, 0);
|
|
+
|
|
+ clutter_actor_paint (actor);
|
|
+
|
|
+ cogl_pop_framebuffer ();
|
|
+
|
|
+ if (clip)
|
|
+ {
|
|
+ meta_rectangle_scale_double (clip, resource_scale,
|
|
+ META_ROUNDING_STRATEGY_GROW,
|
|
+ &scaled_clip);
|
|
+ meta_rectangle_intersect (&scaled_clip,
|
|
+ &(MetaRectangle) {
|
|
+ .width = width,
|
|
+ .height = height,
|
|
+ },
|
|
+ &scaled_clip);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ scaled_clip = (MetaRectangle) {
|
|
+ .width = width,
|
|
+ .height = height,
|
|
+ };
|
|
+ }
|
|
+
|
|
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
|
+ scaled_clip.width, scaled_clip.height);
|
|
+ cogl_framebuffer_read_pixels (framebuffer,
|
|
+ scaled_clip.x, scaled_clip.y,
|
|
+ scaled_clip.width, scaled_clip.height,
|
|
+ CLUTTER_CAIRO_FORMAT_ARGB32,
|
|
+ cairo_image_surface_get_data (surface));
|
|
+
|
|
+ cogl_object_unref (framebuffer);
|
|
+
|
|
+ cairo_surface_mark_dirty (surface);
|
|
+
|
|
+ return surface;
|
|
+}
|
|
diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h
|
|
index 9ba164910..30a17c56b 100644
|
|
--- a/src/meta/meta-window-actor.h
|
|
+++ b/src/meta/meta-window-actor.h
|
|
@@ -46,6 +46,10 @@ void meta_window_actor_sync_visibility (MetaWindowActor *self
|
|
META_EXPORT
|
|
gboolean meta_window_actor_is_destroyed (MetaWindowActor *self);
|
|
|
|
+META_EXPORT
|
|
+cairo_surface_t * meta_window_actor_get_image (MetaWindowActor *self,
|
|
+ cairo_rectangle_int_t *clip);
|
|
+
|
|
typedef enum
|
|
{
|
|
META_SHADOW_MODE_AUTO,
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 2aea9fb5c0b37f764911654e90d7d1917bf3aa0b Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Mon, 26 Aug 2019 16:31:06 +0300
|
|
Subject: [PATCH 13/49] window-actor: Use new get_image() API to screen casting
|
|
window content
|
|
|
|
This fixes screen casting of windows consisting of multiple surfaces to
|
|
work.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/752
|
|
---
|
|
src/compositor/meta-window-actor.c | 4 +---
|
|
1 file changed, 1 insertion(+), 3 deletions(-)
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index 9d215c745..b82326600 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -1985,8 +1985,6 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window,
|
|
uint8_t *data)
|
|
{
|
|
MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
|
|
- MetaWindowActorPrivate *priv =
|
|
- meta_window_actor_get_instance_private (window_actor);
|
|
cairo_surface_t *image;
|
|
uint8_t *cr_data;
|
|
int cr_stride;
|
|
@@ -1997,7 +1995,7 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window,
|
|
if (meta_window_actor_is_destroyed (window_actor))
|
|
return;
|
|
|
|
- image = meta_surface_actor_get_image (priv->surface, bounds);
|
|
+ image = meta_window_actor_get_image (window_actor, bounds);
|
|
cr_data = cairo_image_surface_get_data (image);
|
|
cr_width = cairo_image_surface_get_width (image);
|
|
cr_height = cairo_image_surface_get_height (image);
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 6edebf1a7beed7162f9a69270338010a77088b75 Mon Sep 17 00:00:00 2001
|
|
From: Pascal Nowack <Pascal.Nowack@gmx.de>
|
|
Date: Mon, 16 Dec 2019 19:00:19 +0100
|
|
Subject: [PATCH 14/49] screen-cast: Fix window recording on HiDPI
|
|
|
|
Using the same scale for the window as the
|
|
logical monitor only works correctly when having
|
|
the experimental 'scale-monitor-framebuffer'
|
|
feature enabled.
|
|
Without this experimental feature, the stream
|
|
will contain a black screen, where the actual
|
|
window only takes a small part of it.
|
|
|
|
Therefore, use a scale of 1 for the non-
|
|
experimental case.
|
|
|
|
Patch is based on commit 3fa6a92cc5dda6ab3939c3e982185f6caf453360.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/976
|
|
---
|
|
src/backends/meta-screen-cast-window-stream.c | 6 +++++-
|
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-window-stream.c b/src/backends/meta-screen-cast-window-stream.c
|
|
index 50d1806cd..b9a732cba 100644
|
|
--- a/src/backends/meta-screen-cast-window-stream.c
|
|
+++ b/src/backends/meta-screen-cast-window-stream.c
|
|
@@ -226,11 +226,15 @@ meta_screen_cast_window_stream_initable_init (GInitable *initable,
|
|
G_CALLBACK (on_window_unmanaged),
|
|
window_stream);
|
|
|
|
+ if (meta_is_stage_views_scaled ())
|
|
+ scale = (int) ceilf (meta_logical_monitor_get_scale (logical_monitor));
|
|
+ else
|
|
+ scale = 1;
|
|
+
|
|
/* We cannot set the stream size to the exact size of the window, because
|
|
* windows can be resized, whereas streams cannot.
|
|
* So we set a size equals to the size of the logical monitor for the window.
|
|
*/
|
|
- scale = (int) ceil (meta_logical_monitor_get_scale (logical_monitor));
|
|
window_stream->logical_width = logical_monitor->rect.width;
|
|
window_stream->logical_height = logical_monitor->rect.height;
|
|
window_stream->stream_width = logical_monitor->rect.width * scale;
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 077217b337f18619d3b3b878c5faae488cbafd15 Mon Sep 17 00:00:00 2001
|
|
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
Date: Tue, 4 Feb 2020 14:58:30 +0100
|
|
Subject: [PATCH 15/49] window-actor: Ensure clipping in `capture_into()`
|
|
|
|
The clip bounds passed in `meta_window_actor_capture_into()` represent
|
|
the actual allocated buffer size where the window actor image will be
|
|
eventually copied.
|
|
|
|
As such, it is completely agnostic to the scaling factors that might
|
|
affect the different surface actors which compose the window actor.
|
|
|
|
So instead of trying to compute the scale factor by which the given
|
|
clipping bounds need to be adjusted, simply clip the resulting image
|
|
based on the given bounds to make sure we never overflow the destination
|
|
buffer.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1022
|
|
---
|
|
src/compositor/meta-window-actor.c | 24 ++++++++++++++----------
|
|
1 file changed, 14 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index b82326600..6d4aa6c1b 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -2001,32 +2001,36 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window,
|
|
cr_height = cairo_image_surface_get_height (image);
|
|
cr_stride = cairo_image_surface_get_stride (image);
|
|
|
|
- if (cr_width < bounds->width || cr_height < bounds->height)
|
|
+ if (cr_width == bounds->width && cr_height == bounds->height)
|
|
{
|
|
+ memcpy (data, cr_data, cr_height * cr_stride);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ int width = MIN (bounds->width, cr_width);
|
|
+ int height = MIN (bounds->height, cr_height);
|
|
+ int stride = width * bpp;
|
|
uint8_t *src, *dst;
|
|
+
|
|
src = cr_data;
|
|
dst = data;
|
|
|
|
- for (int i = 0; i < cr_height; i++)
|
|
+ for (int i = 0; i < height; i++)
|
|
{
|
|
- memcpy (dst, src, cr_stride);
|
|
- if (cr_width < bounds->width)
|
|
- memset (dst + cr_stride, 0, (bounds->width * bpp) - cr_stride);
|
|
+ memcpy (dst, src, stride);
|
|
+ if (width < bounds->width)
|
|
+ memset (dst + stride, 0, (bounds->width * bpp) - stride);
|
|
|
|
src += cr_stride;
|
|
dst += bounds->width * bpp;
|
|
}
|
|
|
|
- for (int i = cr_height; i < bounds->height; i++)
|
|
+ for (int i = height; i < bounds->height; i++)
|
|
{
|
|
memset (dst, 0, bounds->width * bpp);
|
|
dst += bounds->width * bpp;
|
|
}
|
|
}
|
|
- else
|
|
- {
|
|
- memcpy (data, cr_data, cr_height * cr_stride);
|
|
- }
|
|
|
|
cairo_surface_destroy (image);
|
|
}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 06dcbe104c58e1efd1d99fc7d4761698f9d32824 Mon Sep 17 00:00:00 2001
|
|
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
Date: Mon, 3 Feb 2020 14:18:57 +0100
|
|
Subject: [PATCH 16/49] shaped-texture: Add `get_width()`/`get_height()` API
|
|
|
|
Add an API to retrieve the content size of a shaped texture.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1022
|
|
---
|
|
src/compositor/meta-shaped-texture-private.h | 3 +++
|
|
src/compositor/meta-shaped-texture.c | 20 ++++++++++++++++++++
|
|
2 files changed, 23 insertions(+)
|
|
|
|
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
|
|
index d0efdd4dc..362bbb93f 100644
|
|
--- a/src/compositor/meta-shaped-texture-private.h
|
|
+++ b/src/compositor/meta-shaped-texture-private.h
|
|
@@ -53,4 +53,7 @@ void meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex,
|
|
int dst_height);
|
|
void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex);
|
|
|
|
+int meta_shaped_texture_get_width (MetaShapedTexture *stex);
|
|
+int meta_shaped_texture_get_height (MetaShapedTexture *stex);
|
|
+
|
|
#endif
|
|
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
|
|
index e77a32109..6ef2125c3 100644
|
|
--- a/src/compositor/meta-shaped-texture.c
|
|
+++ b/src/compositor/meta-shaped-texture.c
|
|
@@ -1585,3 +1585,23 @@ meta_shaped_texture_new (void)
|
|
{
|
|
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
|
|
}
|
|
+
|
|
+int
|
|
+meta_shaped_texture_get_width (MetaShapedTexture *stex)
|
|
+{
|
|
+ g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 0);
|
|
+
|
|
+ ensure_size_valid (stex);
|
|
+
|
|
+ return stex->dst_width;
|
|
+}
|
|
+
|
|
+int
|
|
+meta_shaped_texture_get_height (MetaShapedTexture *stex)
|
|
+{
|
|
+ g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 0);
|
|
+
|
|
+ ensure_size_valid (stex);
|
|
+
|
|
+ return stex->dst_height;
|
|
+}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 9a9a4466e79d61996304ca0c3e9b327c9b3abc25 Mon Sep 17 00:00:00 2001
|
|
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
Date: Tue, 28 Jan 2020 11:13:41 +0100
|
|
Subject: [PATCH 17/49] screen-cast-window: Use buffer bounds in place of frame
|
|
bounds
|
|
|
|
The frame bounds as returned by `meta_window_actor_get_frame_bounds()`
|
|
would be used as cropping values when streaming a window content.
|
|
|
|
But, as its name implies, it returns the actual frame bounds, whereas we
|
|
may want to include the whole buffer, to include client side shadows for
|
|
example.
|
|
|
|
Rename the `get_frame_bounds()` API to `get_buffer_bounds()` (which was
|
|
previously partly removed with commit 11bd84789) and return the actual
|
|
buffer bounds to use as the cropping area when streaming a window.
|
|
|
|
Fixes: 931934511 - "Implement MetaScreenCastWindow interface"
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1022
|
|
Closes: https://gitlab.gnome.org/GNOME/mutter/issues/1018
|
|
---
|
|
.../meta-screen-cast-window-stream-src.c | 4 +--
|
|
src/backends/meta-screen-cast-window.c | 8 +++---
|
|
src/backends/meta-screen-cast-window.h | 8 +++---
|
|
src/compositor/meta-window-actor.c | 26 ++++++-------------
|
|
4 files changed, 18 insertions(+), 28 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
|
|
index c31830b03..210ea0807 100644
|
|
--- a/src/backends/meta-screen-cast-window-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-window-stream-src.c
|
|
@@ -230,8 +230,8 @@ meta_screen_cast_window_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
|
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
|
MetaRectangle stream_rect;
|
|
|
|
- meta_screen_cast_window_get_frame_bounds (window_src->screen_cast_window,
|
|
- crop_rect);
|
|
+ meta_screen_cast_window_get_buffer_bounds (window_src->screen_cast_window,
|
|
+ crop_rect);
|
|
|
|
stream_rect.x = 0;
|
|
stream_rect.y = 0;
|
|
diff --git a/src/backends/meta-screen-cast-window.c b/src/backends/meta-screen-cast-window.c
|
|
index ce2bf82c9..91515ded8 100644
|
|
--- a/src/backends/meta-screen-cast-window.c
|
|
+++ b/src/backends/meta-screen-cast-window.c
|
|
@@ -30,11 +30,11 @@ meta_screen_cast_window_default_init (MetaScreenCastWindowInterface *iface)
|
|
}
|
|
|
|
void
|
|
-meta_screen_cast_window_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
|
|
- MetaRectangle *bounds)
|
|
+meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds)
|
|
{
|
|
- META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->get_frame_bounds (screen_cast_window,
|
|
- bounds);
|
|
+ META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->get_buffer_bounds (screen_cast_window,
|
|
+ bounds);
|
|
}
|
|
|
|
void
|
|
diff --git a/src/backends/meta-screen-cast-window.h b/src/backends/meta-screen-cast-window.h
|
|
index badd88224..69e5a34dc 100644
|
|
--- a/src/backends/meta-screen-cast-window.h
|
|
+++ b/src/backends/meta-screen-cast-window.h
|
|
@@ -37,8 +37,8 @@ struct _MetaScreenCastWindowInterface
|
|
{
|
|
GTypeInterface parent_iface;
|
|
|
|
- void (*get_frame_bounds) (MetaScreenCastWindow *screen_cast_window,
|
|
- MetaRectangle *bounds);
|
|
+ void (*get_buffer_bounds) (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds);
|
|
|
|
void (*transform_relative_position) (MetaScreenCastWindow *screen_cast_window,
|
|
double x,
|
|
@@ -59,8 +59,8 @@ struct _MetaScreenCastWindowInterface
|
|
gboolean (*has_damage) (MetaScreenCastWindow *screen_cast_window);
|
|
};
|
|
|
|
-void meta_screen_cast_window_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
|
|
- MetaRectangle *bounds);
|
|
+void meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds);
|
|
|
|
void meta_screen_cast_window_transform_relative_position (MetaScreenCastWindow *screen_cast_window,
|
|
double x,
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index 6d4aa6c1b..81eb04c84 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -1877,29 +1877,19 @@ meta_window_actor_from_window (MetaWindow *window)
|
|
}
|
|
|
|
static void
|
|
-meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
|
|
- MetaRectangle *bounds)
|
|
+meta_window_actor_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds)
|
|
{
|
|
MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
|
|
MetaWindowActorPrivate *priv =
|
|
meta_window_actor_get_instance_private (window_actor);
|
|
- MetaWindow *window;
|
|
MetaShapedTexture *stex;
|
|
- MetaRectangle buffer_rect;
|
|
- MetaRectangle frame_rect;
|
|
- double scale_x, scale_y;
|
|
|
|
stex = meta_surface_actor_get_texture (priv->surface);
|
|
- clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale_x, &scale_y);
|
|
-
|
|
- window = priv->window;
|
|
- meta_window_get_buffer_rect (window, &buffer_rect);
|
|
- meta_window_get_frame_rect (window, &frame_rect);
|
|
-
|
|
- bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale_x);
|
|
- bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale_y);
|
|
- bounds->width = (int) ceil (frame_rect.width / scale_x);
|
|
- bounds->height = (int) ceil (frame_rect.height / scale_y);
|
|
+ *bounds = (MetaRectangle) {
|
|
+ .width = meta_shaped_texture_get_width (stex),
|
|
+ .height = meta_shaped_texture_get_height (stex)
|
|
+ };
|
|
}
|
|
|
|
static void
|
|
@@ -1917,7 +1907,7 @@ meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast
|
|
MetaRectangle bounds;
|
|
ClutterVertex v1 = { 0.f, }, v2 = { 0.f, };
|
|
|
|
- meta_window_actor_get_frame_bounds (screen_cast_window, &bounds);
|
|
+ meta_window_actor_get_buffer_bounds (screen_cast_window, &bounds);
|
|
|
|
v1.x = CLAMP ((float) x,
|
|
bounds.x,
|
|
@@ -2044,7 +2034,7 @@ meta_window_actor_has_damage (MetaScreenCastWindow *screen_cast_window)
|
|
static void
|
|
screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface)
|
|
{
|
|
- iface->get_frame_bounds = meta_window_actor_get_frame_bounds;
|
|
+ iface->get_buffer_bounds = meta_window_actor_get_buffer_bounds;
|
|
iface->transform_relative_position = meta_window_actor_transform_relative_position;
|
|
iface->transform_cursor_position = meta_window_actor_transform_cursor_position;
|
|
iface->capture_into = meta_window_actor_capture_into;
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From c6f68fe763e736c5fd84913407427254c5dc7dea Mon Sep 17 00:00:00 2001
|
|
From: Wim Taymans <wtaymans@redhat.com>
|
|
Date: Tue, 14 Jan 2020 09:44:45 +0100
|
|
Subject: [PATCH 18/49] screen-cast: Update to PipeWire 0.3 API
|
|
|
|
Update to 0.3 API
|
|
|
|
[jadahl: update Dockerfile to include new enough pipewire]
|
|
[jadahl: dropped Dockerfile changes for backport]
|
|
|
|
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/1051
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1062
|
|
---
|
|
meson.build | 4 +-
|
|
src/backends/meta-screen-cast-stream-src.c | 255 ++++++++-------------
|
|
2 files changed, 101 insertions(+), 158 deletions(-)
|
|
|
|
diff --git a/meson.build b/meson.build
|
|
index b2239ed81..8ef592bc5 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -43,7 +43,7 @@ libinput_req = '>= 1.4'
|
|
gbm_req = '>= 10.3'
|
|
|
|
# screen cast version requirements
|
|
-libpipewire_req = '>= 0.2.5'
|
|
+libpipewire_req = '>= 0.3.0'
|
|
|
|
gnome = import('gnome')
|
|
pkg = import('pkgconfig')
|
|
@@ -233,7 +233,7 @@ endif
|
|
|
|
have_remote_desktop = get_option('remote_desktop')
|
|
if have_remote_desktop
|
|
- libpipewire_dep = dependency('libpipewire-0.2', version: libpipewire_req)
|
|
+ libpipewire_dep = dependency('libpipewire-0.3', version: libpipewire_req)
|
|
endif
|
|
|
|
have_introspection = get_option('introspection')
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index 82c5cba43..ba1ce94a7 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -29,6 +29,7 @@
|
|
#include <spa/param/props.h>
|
|
#include <spa/param/format-utils.h>
|
|
#include <spa/param/video/format-utils.h>
|
|
+#include <spa/utils/result.h>
|
|
#include <stdint.h>
|
|
#include <sys/mman.h>
|
|
|
|
@@ -62,15 +63,6 @@ enum
|
|
|
|
static guint signals[N_SIGNALS];
|
|
|
|
-typedef struct _MetaSpaType
|
|
-{
|
|
- struct spa_type_media_type media_type;
|
|
- struct spa_type_media_subtype media_subtype;
|
|
- struct spa_type_format_video format_video;
|
|
- struct spa_type_video_format video_format;
|
|
- uint32_t meta_cursor;
|
|
-} MetaSpaType;
|
|
-
|
|
typedef struct _MetaPipeWireSource
|
|
{
|
|
GSource base;
|
|
@@ -82,19 +74,19 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|
{
|
|
MetaScreenCastStream *stream;
|
|
|
|
+ struct pw_context *pipewire_context;
|
|
struct pw_core *pipewire_core;
|
|
- struct pw_remote *pipewire_remote;
|
|
- struct pw_type *pipewire_type;
|
|
MetaPipeWireSource *pipewire_source;
|
|
- struct spa_hook pipewire_remote_listener;
|
|
+ struct spa_hook pipewire_core_listener;
|
|
|
|
gboolean is_enabled;
|
|
|
|
struct pw_stream *pipewire_stream;
|
|
struct spa_hook pipewire_stream_listener;
|
|
+ uint32_t node_id;
|
|
|
|
- MetaSpaType spa_type;
|
|
struct spa_video_info_raw video_format;
|
|
+ int video_stride;
|
|
|
|
uint64_t last_frame_timestamp_us;
|
|
|
|
@@ -112,8 +104,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStreamSrc,
|
|
meta_screen_cast_stream_src_init_initable_iface)
|
|
G_ADD_PRIVATE (MetaScreenCastStreamSrc))
|
|
|
|
-#define PROP_RANGE(min, max) 2, (min), (max)
|
|
-
|
|
static void
|
|
meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
|
int *width,
|
|
@@ -286,9 +276,6 @@ meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStre
|
|
int x,
|
|
int y)
|
|
{
|
|
- MetaScreenCastStreamSrcPrivate *priv =
|
|
- meta_screen_cast_stream_src_get_instance_private (src);
|
|
- MetaSpaType *spa_type = &priv->spa_type;
|
|
struct spa_meta_bitmap *spa_meta_bitmap;
|
|
|
|
spa_meta_cursor->id = 1;
|
|
@@ -300,7 +287,7 @@ meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStre
|
|
spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
|
|
spa_meta_cursor->bitmap_offset,
|
|
struct spa_meta_bitmap);
|
|
- spa_meta_bitmap->format = spa_type->video_format.RGBA;
|
|
+ spa_meta_bitmap->format = SPA_VIDEO_FORMAT_RGBA;
|
|
spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap);
|
|
|
|
spa_meta_cursor->hotspot.x = 0;
|
|
@@ -317,9 +304,6 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc
|
|
int y,
|
|
float scale)
|
|
{
|
|
- MetaScreenCastStreamSrcPrivate *priv =
|
|
- meta_screen_cast_stream_src_get_instance_private (src);
|
|
- MetaSpaType *spa_type = &priv->spa_type;
|
|
CoglTexture *cursor_texture;
|
|
struct spa_meta_bitmap *spa_meta_bitmap;
|
|
int hotspot_x, hotspot_y;
|
|
@@ -346,7 +330,7 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc
|
|
spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
|
|
spa_meta_cursor->bitmap_offset,
|
|
struct spa_meta_bitmap);
|
|
- spa_meta_bitmap->format = spa_type->video_format.RGBA;
|
|
+ spa_meta_bitmap->format = SPA_VIDEO_FORMAT_RGBA;
|
|
spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap);
|
|
|
|
meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y);
|
|
@@ -382,12 +366,10 @@ static void
|
|
add_cursor_metadata (MetaScreenCastStreamSrc *src,
|
|
struct spa_buffer *spa_buffer)
|
|
{
|
|
- MetaScreenCastStreamSrcPrivate *priv =
|
|
- meta_screen_cast_stream_src_get_instance_private (src);
|
|
- MetaSpaType *spa_type = &priv->spa_type;
|
|
struct spa_meta_cursor *spa_meta_cursor;
|
|
|
|
- spa_meta_cursor = spa_buffer_find_meta (spa_buffer, spa_type->meta_cursor);
|
|
+ spa_meta_cursor = spa_buffer_find_meta_data (spa_buffer, SPA_META_Cursor,
|
|
+ sizeof (*spa_meta_cursor));
|
|
if (spa_meta_cursor)
|
|
meta_screen_cast_stream_src_set_cursor_metadata (src, spa_meta_cursor);
|
|
}
|
|
@@ -447,14 +429,14 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
{
|
|
data = spa_buffer->datas[0].data;
|
|
}
|
|
- else if (spa_buffer->datas[0].type == priv->pipewire_type->data.MemFd)
|
|
+ else if (spa_buffer->datas[0].type == SPA_DATA_MemFd)
|
|
{
|
|
map = mmap (NULL, spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
|
|
PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
spa_buffer->datas[0].fd, 0);
|
|
if (map == MAP_FAILED)
|
|
{
|
|
- g_warning ("Failed to mmap pipewire stream buffer: %s\n",
|
|
+ g_warning ("Failed to mmap pipewire stream buffer: %s",
|
|
strerror (errno));
|
|
return;
|
|
}
|
|
@@ -469,28 +451,30 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
|
|
if (meta_screen_cast_stream_src_record_frame (src, data))
|
|
{
|
|
- struct spa_meta_video_crop *spa_meta_video_crop;
|
|
+ struct spa_meta_region *spa_meta_video_crop;
|
|
|
|
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
|
|
+ spa_buffer->datas[0].chunk->stride = priv->video_stride;
|
|
|
|
/* Update VideoCrop if needed */
|
|
spa_meta_video_crop =
|
|
- spa_buffer_find_meta (spa_buffer, priv->pipewire_type->meta.VideoCrop);
|
|
+ spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
|
|
+ sizeof (*spa_meta_video_crop));
|
|
if (spa_meta_video_crop)
|
|
{
|
|
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
|
{
|
|
- spa_meta_video_crop->x = crop_rect.x;
|
|
- spa_meta_video_crop->y = crop_rect.y;
|
|
- spa_meta_video_crop->width = crop_rect.width;
|
|
- spa_meta_video_crop->height = crop_rect.height;
|
|
+ spa_meta_video_crop->region.position.x = crop_rect.x;
|
|
+ spa_meta_video_crop->region.position.y = crop_rect.y;
|
|
+ spa_meta_video_crop->region.size.width = crop_rect.width;
|
|
+ spa_meta_video_crop->region.size.height = crop_rect.height;
|
|
}
|
|
else
|
|
{
|
|
- spa_meta_video_crop->x = 0;
|
|
- spa_meta_video_crop->y = 0;
|
|
- spa_meta_video_crop->width = priv->stream_width;
|
|
- spa_meta_video_crop->height = priv->stream_height;
|
|
+ spa_meta_video_crop->region.position.x = 0;
|
|
+ spa_meta_video_crop->region.position.y = 0;
|
|
+ spa_meta_video_crop->region.size.width = priv->stream_width;
|
|
+ spa_meta_video_crop->region.size.height = priv->stream_height;
|
|
}
|
|
}
|
|
}
|
|
@@ -555,7 +539,6 @@ on_stream_state_changed (void *data,
|
|
MetaScreenCastStreamSrc *src = data;
|
|
MetaScreenCastStreamSrcPrivate *priv =
|
|
meta_screen_cast_stream_src_get_instance_private (src);
|
|
- uint32_t node_id;
|
|
|
|
switch (state)
|
|
{
|
|
@@ -563,14 +546,12 @@ on_stream_state_changed (void *data,
|
|
g_warning ("pipewire stream error: %s", error_message);
|
|
meta_screen_cast_stream_src_notify_closed (src);
|
|
break;
|
|
- case PW_STREAM_STATE_CONFIGURE:
|
|
- node_id = pw_stream_get_node_id (priv->pipewire_stream);
|
|
- g_signal_emit (src, signals[READY], 0, (unsigned int) node_id);
|
|
- break;
|
|
- case PW_STREAM_STATE_UNCONNECTED:
|
|
- case PW_STREAM_STATE_CONNECTING:
|
|
- case PW_STREAM_STATE_READY:
|
|
case PW_STREAM_STATE_PAUSED:
|
|
+ if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
|
|
+ {
|
|
+ priv->node_id = pw_stream_get_node_id (priv->pipewire_stream);
|
|
+ g_signal_emit (src, signals[READY], 0, (unsigned int) priv->node_id);
|
|
+ }
|
|
if (meta_screen_cast_stream_src_is_enabled (src))
|
|
meta_screen_cast_stream_src_disable (src);
|
|
break;
|
|
@@ -578,68 +559,69 @@ on_stream_state_changed (void *data,
|
|
if (!meta_screen_cast_stream_src_is_enabled (src))
|
|
meta_screen_cast_stream_src_enable (src);
|
|
break;
|
|
+ case PW_STREAM_STATE_UNCONNECTED:
|
|
+ case PW_STREAM_STATE_CONNECTING:
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
-on_stream_format_changed (void *data,
|
|
- const struct spa_pod *format)
|
|
+on_stream_param_changed (void *data,
|
|
+ uint32_t id,
|
|
+ const struct spa_pod *format)
|
|
{
|
|
MetaScreenCastStreamSrc *src = data;
|
|
MetaScreenCastStreamSrcPrivate *priv =
|
|
meta_screen_cast_stream_src_get_instance_private (src);
|
|
- struct pw_type *pipewire_type = priv->pipewire_type;
|
|
uint8_t params_buffer[1024];
|
|
int32_t width, height, stride, size;
|
|
struct spa_pod_builder pod_builder;
|
|
const struct spa_pod *params[3];
|
|
const int bpp = 4;
|
|
|
|
- if (!format)
|
|
- {
|
|
- pw_stream_finish_format (priv->pipewire_stream, 0, NULL, 0);
|
|
- return;
|
|
- }
|
|
+ if (!format || id != SPA_PARAM_Format)
|
|
+ return;
|
|
|
|
spa_format_video_raw_parse (format,
|
|
- &priv->video_format,
|
|
- &priv->spa_type.format_video);
|
|
+ &priv->video_format);
|
|
|
|
width = priv->video_format.size.width;
|
|
height = priv->video_format.size.height;
|
|
stride = SPA_ROUND_UP_N (width * bpp, 4);
|
|
size = height * stride;
|
|
|
|
+ priv->video_stride = stride;
|
|
+
|
|
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
|
|
|
|
- params[0] = spa_pod_builder_object (
|
|
+ params[0] = spa_pod_builder_add_object (
|
|
&pod_builder,
|
|
- pipewire_type->param.idBuffers, pipewire_type->param_buffers.Buffers,
|
|
- ":", pipewire_type->param_buffers.size, "i", size,
|
|
- ":", pipewire_type->param_buffers.stride, "i", stride,
|
|
- ":", pipewire_type->param_buffers.buffers, "iru", 16, PROP_RANGE (2, 16),
|
|
- ":", pipewire_type->param_buffers.align, "i", 16);
|
|
-
|
|
- params[1] = spa_pod_builder_object (
|
|
+ SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
|
|
+ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (16, 2, 16),
|
|
+ SPA_PARAM_BUFFERS_blocks, SPA_POD_Int (1),
|
|
+ SPA_PARAM_BUFFERS_size, SPA_POD_Int (size),
|
|
+ SPA_PARAM_BUFFERS_stride, SPA_POD_Int (stride),
|
|
+ SPA_PARAM_BUFFERS_align, SPA_POD_Int (16));
|
|
+
|
|
+ params[1] = spa_pod_builder_add_object (
|
|
&pod_builder,
|
|
- pipewire_type->param.idMeta, pipewire_type->param_meta.Meta,
|
|
- ":", pipewire_type->param_meta.type, "I", pipewire_type->meta.VideoCrop,
|
|
- ":", pipewire_type->param_meta.size, "i", sizeof (struct spa_meta_video_crop));
|
|
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
|
+ SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop),
|
|
+ SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_region)));
|
|
|
|
- params[2] = spa_pod_builder_object (
|
|
+ params[2] = spa_pod_builder_add_object (
|
|
&pod_builder,
|
|
- pipewire_type->param.idMeta, pipewire_type->param_meta.Meta,
|
|
- ":", pipewire_type->param_meta.type, "I", priv->spa_type.meta_cursor,
|
|
- ":", pipewire_type->param_meta.size, "i", CURSOR_META_SIZE (64, 64));
|
|
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
|
+ SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor),
|
|
+ SPA_PARAM_META_size, SPA_POD_Int (CURSOR_META_SIZE (64, 64)));
|
|
|
|
- pw_stream_finish_format (priv->pipewire_stream, 0,
|
|
- params, G_N_ELEMENTS (params));
|
|
+ pw_stream_update_params (priv->pipewire_stream, params, G_N_ELEMENTS (params));
|
|
}
|
|
|
|
static const struct pw_stream_events stream_events = {
|
|
PW_VERSION_STREAM_EVENTS,
|
|
.state_changed = on_stream_state_changed,
|
|
- .format_changed = on_stream_format_changed,
|
|
+ .param_changed = on_stream_param_changed,
|
|
};
|
|
|
|
static struct pw_stream *
|
|
@@ -652,8 +634,6 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|
uint8_t buffer[1024];
|
|
struct spa_pod_builder pod_builder =
|
|
SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
|
- MetaSpaType *spa_type = &priv->spa_type;
|
|
- struct pw_type *pipewire_type = priv->pipewire_type;
|
|
float frame_rate;
|
|
MetaFraction frame_rate_fraction;
|
|
struct spa_fraction max_framerate;
|
|
@@ -661,7 +641,9 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|
const struct spa_pod *params[1];
|
|
int result;
|
|
|
|
- pipewire_stream = pw_stream_new (priv->pipewire_remote,
|
|
+ priv->node_id = SPA_ID_INVALID;
|
|
+
|
|
+ pipewire_stream = pw_stream_new (priv->pipewire_core,
|
|
"meta-screen-cast-src",
|
|
NULL);
|
|
if (!pipewire_stream)
|
|
@@ -682,17 +664,17 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|
max_framerate = SPA_FRACTION (frame_rate_fraction.num,
|
|
frame_rate_fraction.denom);
|
|
|
|
- params[0] = spa_pod_builder_object (
|
|
+ params[0] = spa_pod_builder_add_object (
|
|
&pod_builder,
|
|
- pipewire_type->param.idEnumFormat, pipewire_type->spa_format,
|
|
- "I", spa_type->media_type.video,
|
|
- "I", spa_type->media_subtype.raw,
|
|
- ":", spa_type->format_video.format, "I", spa_type->video_format.BGRx,
|
|
- ":", spa_type->format_video.size, "R", &SPA_RECTANGLE (priv->stream_width,
|
|
- priv->stream_height),
|
|
- ":", spa_type->format_video.framerate, "F", &SPA_FRACTION (0, 1),
|
|
- ":", spa_type->format_video.max_framerate, "Fru", &max_framerate,
|
|
- PROP_RANGE (&min_framerate,
|
|
+ SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
|
+ SPA_FORMAT_mediaType, SPA_POD_Id (SPA_MEDIA_TYPE_video),
|
|
+ SPA_FORMAT_mediaSubtype, SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw),
|
|
+ SPA_FORMAT_VIDEO_format, SPA_POD_Id (SPA_VIDEO_FORMAT_BGRx),
|
|
+ SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle (&SPA_RECTANGLE (priv->stream_width,
|
|
+ priv->stream_height)),
|
|
+ SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION (0, 1)),
|
|
+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_CHOICE_RANGE_Fraction (&max_framerate,
|
|
+ &min_framerate,
|
|
&max_framerate));
|
|
|
|
pw_stream_add_listener (pipewire_stream,
|
|
@@ -702,7 +684,7 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|
|
|
result = pw_stream_connect (pipewire_stream,
|
|
PW_DIRECTION_OUTPUT,
|
|
- NULL,
|
|
+ SPA_ID_INVALID,
|
|
(PW_STREAM_FLAG_DRIVER |
|
|
PW_STREAM_FLAG_MAP_BUFFERS),
|
|
params, G_N_ELEMENTS (params));
|
|
@@ -717,40 +699,18 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|
}
|
|
|
|
static void
|
|
-on_state_changed (void *data,
|
|
- enum pw_remote_state old,
|
|
- enum pw_remote_state state,
|
|
- const char *error_message)
|
|
+on_core_error (void *data,
|
|
+ uint32_t id,
|
|
+ int seq,
|
|
+ int res,
|
|
+ const char *message)
|
|
{
|
|
MetaScreenCastStreamSrc *src = data;
|
|
- MetaScreenCastStreamSrcPrivate *priv =
|
|
- meta_screen_cast_stream_src_get_instance_private (src);
|
|
- struct pw_stream *pipewire_stream;
|
|
- GError *error = NULL;
|
|
|
|
- switch (state)
|
|
- {
|
|
- case PW_REMOTE_STATE_ERROR:
|
|
- g_warning ("pipewire remote error: %s\n", error_message);
|
|
- meta_screen_cast_stream_src_notify_closed (src);
|
|
- break;
|
|
- case PW_REMOTE_STATE_CONNECTED:
|
|
- pipewire_stream = create_pipewire_stream (src, &error);
|
|
- if (!pipewire_stream)
|
|
- {
|
|
- g_warning ("Could not create pipewire stream: %s", error->message);
|
|
- g_error_free (error);
|
|
- meta_screen_cast_stream_src_notify_closed (src);
|
|
- }
|
|
- else
|
|
- {
|
|
- priv->pipewire_stream = pipewire_stream;
|
|
- }
|
|
- break;
|
|
- case PW_REMOTE_STATE_UNCONNECTED:
|
|
- case PW_REMOTE_STATE_CONNECTING:
|
|
- break;
|
|
- }
|
|
+ g_warning ("pipewire remote error: id:%u %s", id, message);
|
|
+
|
|
+ if (id == PW_ID_CORE && res == -EPIPE)
|
|
+ meta_screen_cast_stream_src_notify_closed (src);
|
|
}
|
|
|
|
static gboolean
|
|
@@ -793,17 +753,6 @@ static GSourceFuncs pipewire_source_funcs =
|
|
pipewire_loop_source_finalize
|
|
};
|
|
|
|
-static void
|
|
-init_spa_type (MetaSpaType *type,
|
|
- struct spa_type_map *map)
|
|
-{
|
|
- spa_type_media_type_map (map, &type->media_type);
|
|
- spa_type_media_subtype_map (map, &type->media_subtype);
|
|
- spa_type_format_video_map (map, &type->format_video);
|
|
- spa_type_video_format_map (map, &type->video_format);
|
|
- type->meta_cursor = spa_type_map_get_id(map, SPA_TYPE_META__Cursor);
|
|
-}
|
|
-
|
|
static MetaPipeWireSource *
|
|
create_pipewire_source (void)
|
|
{
|
|
@@ -829,9 +778,9 @@ create_pipewire_source (void)
|
|
return pipewire_source;
|
|
}
|
|
|
|
-static const struct pw_remote_events remote_events = {
|
|
- PW_VERSION_REMOTE_EVENTS,
|
|
- .state_changed = on_state_changed,
|
|
+static const struct pw_core_events core_events = {
|
|
+ PW_VERSION_CORE_EVENTS,
|
|
+ .error = on_core_error,
|
|
};
|
|
|
|
static gboolean
|
|
@@ -851,37 +800,31 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
|
|
return FALSE;
|
|
}
|
|
|
|
- priv->pipewire_core = pw_core_new (priv->pipewire_source->pipewire_loop,
|
|
- NULL);
|
|
- if (!priv->pipewire_core)
|
|
+ priv->pipewire_context = pw_context_new (priv->pipewire_source->pipewire_loop,
|
|
+ NULL, 0);
|
|
+ if (!priv->pipewire_context)
|
|
{
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
- "Failed to create pipewire core");
|
|
+ "Failed to create pipewire context");
|
|
return FALSE;
|
|
}
|
|
|
|
- priv->pipewire_remote = pw_remote_new (priv->pipewire_core, NULL, 0);
|
|
- if (!priv->pipewire_remote)
|
|
+ priv->pipewire_core = pw_context_connect (priv->pipewire_context, NULL, 0);
|
|
+ if (!priv->pipewire_core)
|
|
{
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
- "Couldn't creat pipewire remote");
|
|
+ "Couldn't connect pipewire context");
|
|
return FALSE;
|
|
}
|
|
|
|
- pw_remote_add_listener (priv->pipewire_remote,
|
|
- &priv->pipewire_remote_listener,
|
|
- &remote_events,
|
|
- src);
|
|
+ pw_core_add_listener (priv->pipewire_core,
|
|
+ &priv->pipewire_core_listener,
|
|
+ &core_events,
|
|
+ src);
|
|
|
|
- priv->pipewire_type = pw_core_get_type (priv->pipewire_core);
|
|
- init_spa_type (&priv->spa_type, priv->pipewire_type->map);
|
|
-
|
|
- if (pw_remote_connect (priv->pipewire_remote) != 0)
|
|
- {
|
|
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
- "Couldn't connect pipewire remote");
|
|
- return FALSE;
|
|
- }
|
|
+ priv->pipewire_stream = create_pipewire_stream (src, error);
|
|
+ if (!priv->pipewire_stream)
|
|
+ return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
@@ -912,8 +855,8 @@ meta_screen_cast_stream_src_finalize (GObject *object)
|
|
meta_screen_cast_stream_src_disable (src);
|
|
|
|
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
|
|
- g_clear_pointer (&priv->pipewire_remote, pw_remote_destroy);
|
|
- g_clear_pointer (&priv->pipewire_core, pw_core_destroy);
|
|
+ g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
|
|
+ g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
|
|
g_source_destroy (&priv->pipewire_source->base);
|
|
|
|
G_OBJECT_CLASS (meta_screen_cast_stream_src_parent_class)->finalize (object);
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From b29e2f833357a0b29bb42999b4d6be725be067d1 Mon Sep 17 00:00:00 2001
|
|
From: Pekka Paalanen <pekka.paalanen@collabora.com>
|
|
Date: Mon, 10 Jun 2019 17:07:55 +0300
|
|
Subject: [PATCH 19/49] egl: Introduce meta_egl_create_dmabuf_image
|
|
|
|
This bit of code was more or less duplicated in meta-renderer-native-gles3.c
|
|
and meta-wayland-dma-buf.c. Start consolidating the two implementations by
|
|
moving the *-gles3.c function into meta-egl.c and generalizing it so it could
|
|
also accommodate the meta-wayland-dma-buf.c usage.
|
|
|
|
The workaround in the *-gles3.c implementation is moved to the caller. It is
|
|
the caller's responsibility to check for the existence of the appropriate EGL
|
|
extensions.
|
|
|
|
Commit 6f59e4858e24c828e3ab0e611d36dfaaded1b272 worked around the lack of
|
|
EGL_EXT_image_dma_buf_import_modifiers with the assumption that if the modifier
|
|
is linear, there is no need to pass it into EGL. The problem is that not
|
|
passing a modifier explicitly to EGL invokes implementation-defined behaviour,
|
|
so we should not have that workaround in meta-egl.c.
|
|
|
|
This patch intends to be pure refactoring, no behavioral changes. The one
|
|
change is the addition of g_assert to catch overwriting arbitrary memory.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
|
|
---
|
|
src/backends/meta-egl.c | 94 ++++++++++++-
|
|
src/backends/meta-egl.h | 13 ++
|
|
.../native/meta-renderer-native-gles3.c | 125 +++---------------
|
|
3 files changed, 127 insertions(+), 105 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c
|
|
index a28eef4ca..fdeff4f77 100644
|
|
--- a/src/backends/meta-egl.c
|
|
+++ b/src/backends/meta-egl.c
|
|
@@ -1,7 +1,8 @@
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
- * Copyright (C) 2016 Red Hat Inc.
|
|
+ * Copyright (C) 2016, 2017 Red Hat Inc.
|
|
+ * Copyright (C) 2018, 2019 DisplayLink (UK) Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
@@ -575,6 +576,97 @@ meta_egl_destroy_image (MetaEgl *egl,
|
|
return TRUE;
|
|
}
|
|
|
|
+EGLImageKHR
|
|
+meta_egl_create_dmabuf_image (MetaEgl *egl,
|
|
+ EGLDisplay egl_display,
|
|
+ unsigned int width,
|
|
+ unsigned int height,
|
|
+ uint32_t drm_format,
|
|
+ uint32_t n_planes,
|
|
+ const int *fds,
|
|
+ const uint32_t *strides,
|
|
+ const uint32_t *offsets,
|
|
+ const uint64_t *modifiers,
|
|
+ GError **error)
|
|
+{
|
|
+ EGLint attribs[37];
|
|
+ int atti = 0;
|
|
+
|
|
+ /* This requires the Mesa commit in
|
|
+ * Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or
|
|
+ * Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652).
|
|
+ * Otherwise Mesa closes the fd behind our back and re-importing
|
|
+ * will fail.
|
|
+ * https://bugs.freedesktop.org/show_bug.cgi?id=76188
|
|
+ */
|
|
+
|
|
+ attribs[atti++] = EGL_WIDTH;
|
|
+ attribs[atti++] = width;
|
|
+ attribs[atti++] = EGL_HEIGHT;
|
|
+ attribs[atti++] = height;
|
|
+ attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
|
|
+ attribs[atti++] = drm_format;
|
|
+
|
|
+ if (n_planes > 0)
|
|
+ {
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
|
+ attribs[atti++] = fds[0];
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
|
+ attribs[atti++] = offsets[0];
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
|
+ attribs[atti++] = strides[0];
|
|
+ if (modifiers)
|
|
+ {
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
|
+ attribs[atti++] = modifiers[0] & 0xFFFFFFFF;
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
|
+ attribs[atti++] = modifiers[0] >> 32;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (n_planes > 1)
|
|
+ {
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
|
+ attribs[atti++] = fds[1];
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
|
+ attribs[atti++] = offsets[1];
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
|
+ attribs[atti++] = strides[1];
|
|
+ if (modifiers)
|
|
+ {
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
|
+ attribs[atti++] = modifiers[1] & 0xFFFFFFFF;
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
|
+ attribs[atti++] = modifiers[1] >> 32;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (n_planes > 2)
|
|
+ {
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
|
+ attribs[atti++] = fds[2];
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
|
+ attribs[atti++] = offsets[2];
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
|
+ attribs[atti++] = strides[2];
|
|
+ if (modifiers)
|
|
+ {
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
|
+ attribs[atti++] = modifiers[2] & 0xFFFFFFFF;
|
|
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
|
+ attribs[atti++] = modifiers[2] >> 32;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ attribs[atti++] = EGL_NONE;
|
|
+ g_assert (atti <= G_N_ELEMENTS (attribs));
|
|
+
|
|
+ return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
|
|
+ EGL_LINUX_DMA_BUF_EXT, NULL,
|
|
+ attribs,
|
|
+ error);
|
|
+}
|
|
+
|
|
gboolean
|
|
meta_egl_make_current (MetaEgl *egl,
|
|
EGLDisplay display,
|
|
diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h
|
|
index 81b53b32d..4591e7d85 100644
|
|
--- a/src/backends/meta-egl.h
|
|
+++ b/src/backends/meta-egl.h
|
|
@@ -2,6 +2,7 @@
|
|
|
|
/*
|
|
* Copyright (C) 2016 Red Hat Inc.
|
|
+ * Copyright (C) 2019 DisplayLink (UK) Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
@@ -101,6 +102,18 @@ gboolean meta_egl_destroy_image (MetaEgl *egl,
|
|
EGLImageKHR image,
|
|
GError **error);
|
|
|
|
+EGLImageKHR meta_egl_create_dmabuf_image (MetaEgl *egl,
|
|
+ EGLDisplay egl_display,
|
|
+ unsigned int width,
|
|
+ unsigned int height,
|
|
+ uint32_t drm_format,
|
|
+ uint32_t n_planes,
|
|
+ const int *fds,
|
|
+ const uint32_t *strides,
|
|
+ const uint32_t *offsets,
|
|
+ const uint64_t *modifiers,
|
|
+ GError **error);
|
|
+
|
|
EGLSurface meta_egl_create_window_surface (MetaEgl *egl,
|
|
EGLDisplay display,
|
|
EGLConfig config,
|
|
diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c
|
|
index 7afea8648..740b52ef6 100644
|
|
--- a/src/backends/native/meta-renderer-native-gles3.c
|
|
+++ b/src/backends/native/meta-renderer-native-gles3.c
|
|
@@ -45,101 +45,6 @@
|
|
#error "Somehow included OpenGL headers when we shouldn't have"
|
|
#endif
|
|
|
|
-static EGLImageKHR
|
|
-create_egl_image (MetaEgl *egl,
|
|
- EGLDisplay egl_display,
|
|
- EGLContext egl_context,
|
|
- unsigned int width,
|
|
- unsigned int height,
|
|
- uint32_t n_planes,
|
|
- uint32_t *strides,
|
|
- uint32_t *offsets,
|
|
- uint64_t *modifiers,
|
|
- uint32_t format,
|
|
- int fd,
|
|
- GError **error)
|
|
-{
|
|
- EGLint attribs[37];
|
|
- int atti = 0;
|
|
- gboolean has_modifier;
|
|
-
|
|
- /* This requires the Mesa commit in
|
|
- * Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or
|
|
- * Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652).
|
|
- * Otherwise Mesa closes the fd behind our back and re-importing
|
|
- * will fail.
|
|
- * https://bugs.freedesktop.org/show_bug.cgi?id=76188
|
|
- */
|
|
-
|
|
- attribs[atti++] = EGL_WIDTH;
|
|
- attribs[atti++] = width;
|
|
- attribs[atti++] = EGL_HEIGHT;
|
|
- attribs[atti++] = height;
|
|
- attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
|
|
- attribs[atti++] = format;
|
|
-
|
|
- has_modifier = (modifiers[0] != DRM_FORMAT_MOD_INVALID &&
|
|
- modifiers[0] != DRM_FORMAT_MOD_LINEAR);
|
|
-
|
|
- if (n_planes > 0)
|
|
- {
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
|
- attribs[atti++] = fd;
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
|
- attribs[atti++] = offsets[0];
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
|
- attribs[atti++] = strides[0];
|
|
- if (has_modifier)
|
|
- {
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
|
- attribs[atti++] = modifiers[0] & 0xFFFFFFFF;
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
|
- attribs[atti++] = modifiers[0] >> 32;
|
|
- }
|
|
- }
|
|
-
|
|
- if (n_planes > 1)
|
|
- {
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
|
- attribs[atti++] = fd;
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
|
- attribs[atti++] = offsets[1];
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
|
- attribs[atti++] = strides[1];
|
|
- if (has_modifier)
|
|
- {
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
|
- attribs[atti++] = modifiers[1] & 0xFFFFFFFF;
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
|
- attribs[atti++] = modifiers[1] >> 32;
|
|
- }
|
|
- }
|
|
-
|
|
- if (n_planes > 2)
|
|
- {
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
|
- attribs[atti++] = fd;
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
|
- attribs[atti++] = offsets[2];
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
|
- attribs[atti++] = strides[2];
|
|
- if (has_modifier)
|
|
- {
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
|
- attribs[atti++] = modifiers[2] & 0xFFFFFFFF;
|
|
- attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
|
- attribs[atti++] = modifiers[2] >> 32;
|
|
- }
|
|
- }
|
|
-
|
|
- attribs[atti++] = EGL_NONE;
|
|
-
|
|
- return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
|
|
- EGL_LINUX_DMA_BUF_EXT, NULL,
|
|
- attribs,
|
|
- error);
|
|
-}
|
|
-
|
|
static void
|
|
paint_egl_image (MetaGles3 *gles3,
|
|
EGLImageKHR egl_image,
|
|
@@ -195,8 +100,10 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
|
|
uint32_t strides[4] = { 0 };
|
|
uint32_t offsets[4] = { 0 };
|
|
uint64_t modifiers[4] = { 0 };
|
|
+ int fds[4] = { -1, -1, -1, -1 };
|
|
uint32_t format;
|
|
EGLImageKHR egl_image;
|
|
+ gboolean use_modifiers;
|
|
|
|
shared_bo_fd = gbm_bo_get_fd (shared_bo);
|
|
if (shared_bo_fd < 0)
|
|
@@ -216,17 +123,27 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
|
|
strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i);
|
|
offsets[i] = gbm_bo_get_offset (shared_bo, i);
|
|
modifiers[i] = gbm_bo_get_modifier (shared_bo);
|
|
+ fds[i] = shared_bo_fd;
|
|
}
|
|
|
|
- egl_image = create_egl_image (egl,
|
|
- egl_display,
|
|
- egl_context,
|
|
- width, height,
|
|
- n_planes,
|
|
- strides, offsets,
|
|
- modifiers, format,
|
|
- shared_bo_fd,
|
|
- error);
|
|
+ /* Workaround for https://gitlab.gnome.org/GNOME/mutter/issues/18 */
|
|
+ if (modifiers[0] == DRM_FORMAT_MOD_LINEAR ||
|
|
+ modifiers[0] == DRM_FORMAT_MOD_INVALID)
|
|
+ use_modifiers = FALSE;
|
|
+ else
|
|
+ use_modifiers = TRUE;
|
|
+
|
|
+ egl_image = meta_egl_create_dmabuf_image (egl,
|
|
+ egl_display,
|
|
+ width,
|
|
+ height,
|
|
+ format,
|
|
+ n_planes,
|
|
+ fds,
|
|
+ strides,
|
|
+ offsets,
|
|
+ use_modifiers ? modifiers : NULL,
|
|
+ error);
|
|
close (shared_bo_fd);
|
|
|
|
if (!egl_image)
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 5af71a6c4a723951b26597ee710462b18867d113 Mon Sep 17 00:00:00 2001
|
|
From: Pekka Paalanen <pekka.paalanen@collabora.com>
|
|
Date: Thu, 29 Nov 2018 13:37:16 +0200
|
|
Subject: [PATCH 20/49] renderer/native: Add meta_dumb_buffer_ensure_dmabuf_fd
|
|
|
|
Follow-up work will use this in an attempt to use the primary GPU to
|
|
copy into secondary GPU dumb buffers.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
|
|
---
|
|
src/backends/native/meta-renderer-native.c | 36 ++++++++++++++++++++++
|
|
1 file changed, 36 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
|
index ffb64a6bd..76cc79e23 100644
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
@@ -133,6 +133,7 @@ typedef struct _MetaDumbBuffer
|
|
int height;
|
|
int stride_bytes;
|
|
uint32_t drm_format;
|
|
+ int dmabuf_fd;
|
|
} MetaDumbBuffer;
|
|
|
|
typedef struct _MetaOnscreenNativeSecondaryGpuState
|
|
@@ -242,6 +243,10 @@ init_dumb_fb (MetaDumbBuffer *dumb_fb,
|
|
uint32_t format,
|
|
GError **error);
|
|
|
|
+static int
|
|
+meta_dumb_buffer_ensure_dmabuf_fd (MetaDumbBuffer *dumb_fb,
|
|
+ MetaGpuKms *gpu_kms);
|
|
+
|
|
static MetaEgl *
|
|
meta_renderer_native_get_egl (MetaRendererNative *renderer_native);
|
|
|
|
@@ -2892,6 +2897,7 @@ init_dumb_fb (MetaDumbBuffer *dumb_fb,
|
|
dumb_fb->height = height;
|
|
dumb_fb->stride_bytes = create_arg.pitch;
|
|
dumb_fb->drm_format = format;
|
|
+ dumb_fb->dmabuf_fd = -1;
|
|
|
|
return TRUE;
|
|
|
|
@@ -2909,6 +2915,33 @@ err_ioctl:
|
|
return FALSE;
|
|
}
|
|
|
|
+static int
|
|
+meta_dumb_buffer_ensure_dmabuf_fd (MetaDumbBuffer *dumb_fb,
|
|
+ MetaGpuKms *gpu_kms)
|
|
+{
|
|
+ int ret;
|
|
+ int kms_fd;
|
|
+ int dmabuf_fd;
|
|
+
|
|
+ if (dumb_fb->dmabuf_fd != -1)
|
|
+ return dumb_fb->dmabuf_fd;
|
|
+
|
|
+ kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
|
+
|
|
+ ret = drmPrimeHandleToFD (kms_fd, dumb_fb->handle, DRM_CLOEXEC,
|
|
+ &dmabuf_fd);
|
|
+ if (ret)
|
|
+ {
|
|
+ g_debug ("Failed to export dumb drm buffer: %s",
|
|
+ g_strerror (errno));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ dumb_fb->dmabuf_fd = dmabuf_fd;
|
|
+
|
|
+ return dumb_fb->dmabuf_fd;
|
|
+}
|
|
+
|
|
static void
|
|
release_dumb_fb (MetaDumbBuffer *dumb_fb,
|
|
MetaGpuKms *gpu_kms)
|
|
@@ -2919,6 +2952,9 @@ release_dumb_fb (MetaDumbBuffer *dumb_fb,
|
|
if (!dumb_fb->map)
|
|
return;
|
|
|
|
+ if (dumb_fb->dmabuf_fd != -1)
|
|
+ close (dumb_fb->dmabuf_fd);
|
|
+
|
|
munmap (dumb_fb->map, dumb_fb->map_size);
|
|
dumb_fb->map = NULL;
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From a6e2e1cb5fd25e152bbc3347078b0e9261a94ceb Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 16 Jul 2019 18:27:38 +0200
|
|
Subject: [PATCH 21/49] cogl/texture: Make is_get_data_supported() a bool on
|
|
the texture
|
|
|
|
Comparing the gl target is not enough. More on that later.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/687
|
|
---
|
|
cogl/cogl/cogl-texture-2d-private.h | 1 +
|
|
cogl/cogl/cogl-texture-2d.c | 1 +
|
|
cogl/cogl/driver/gl/cogl-texture-2d-gl.c | 6 ++----
|
|
3 files changed, 4 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/cogl/cogl/cogl-texture-2d-private.h b/cogl/cogl/cogl-texture-2d-private.h
|
|
index 450d156f1..c1e6dff50 100644
|
|
--- a/cogl/cogl/cogl-texture-2d-private.h
|
|
+++ b/cogl/cogl/cogl-texture-2d-private.h
|
|
@@ -47,6 +47,7 @@ struct _CoglTexture2D
|
|
gboolean auto_mipmap;
|
|
gboolean mipmaps_dirty;
|
|
gboolean is_foreign;
|
|
+ gboolean is_get_data_supported;
|
|
|
|
/* TODO: factor out these OpenGL specific members into some form
|
|
* of driver private state. */
|
|
diff --git a/cogl/cogl/cogl-texture-2d.c b/cogl/cogl/cogl-texture-2d.c
|
|
index 76f0e3a87..76cb75a5c 100644
|
|
--- a/cogl/cogl/cogl-texture-2d.c
|
|
+++ b/cogl/cogl/cogl-texture-2d.c
|
|
@@ -107,6 +107,7 @@ _cogl_texture_2d_create_base (CoglContext *ctx,
|
|
|
|
tex_2d->mipmaps_dirty = TRUE;
|
|
tex_2d->auto_mipmap = TRUE;
|
|
+ tex_2d->is_get_data_supported = TRUE;
|
|
|
|
tex_2d->gl_target = GL_TEXTURE_2D;
|
|
|
|
diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
|
|
index e36c3523e..a9329ad50 100644
|
|
--- a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
|
|
+++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
|
|
@@ -514,6 +514,7 @@ allocate_custom_egl_image_external (CoglTexture2D *tex_2d,
|
|
|
|
tex_2d->internal_format = internal_format;
|
|
tex_2d->gl_target = GL_TEXTURE_EXTERNAL_OES;
|
|
+ tex_2d->is_get_data_supported = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
@@ -840,10 +841,7 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
|
|
gboolean
|
|
_cogl_texture_2d_gl_is_get_data_supported (CoglTexture2D *tex_2d)
|
|
{
|
|
- if (tex_2d->gl_target == GL_TEXTURE_EXTERNAL_OES)
|
|
- return FALSE;
|
|
- else
|
|
- return TRUE;
|
|
+ return tex_2d->is_get_data_supported;
|
|
}
|
|
|
|
void
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 50108eca1503c8883370f0f877cab8d25f89ad2e Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 16 Jul 2019 18:29:29 +0200
|
|
Subject: [PATCH 22/49] cogl/texture: Add EGLImage texture import flags
|
|
|
|
The flags are 'none', and 'no-get-data' meaning get_data() is not
|
|
supported.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/687
|
|
---
|
|
cogl/cogl/cogl-texture-2d.c | 3 +++
|
|
cogl/cogl/cogl-texture-2d.h | 7 +++++++
|
|
cogl/cogl/cogl-texture-private.h | 1 +
|
|
cogl/cogl/driver/gl/cogl-texture-2d-gl.c | 2 ++
|
|
cogl/cogl/winsys/cogl-winsys-egl-x11.c | 1 +
|
|
src/wayland/meta-wayland-buffer.c | 3 +++
|
|
src/wayland/meta-wayland-dma-buf.c | 3 +++
|
|
7 files changed, 20 insertions(+)
|
|
|
|
diff --git a/cogl/cogl/cogl-texture-2d.c b/cogl/cogl/cogl-texture-2d.c
|
|
index 76cb75a5c..6544f8a62 100644
|
|
--- a/cogl/cogl/cogl-texture-2d.c
|
|
+++ b/cogl/cogl/cogl-texture-2d.c
|
|
@@ -242,6 +242,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
|
int height,
|
|
CoglPixelFormat format,
|
|
EGLImageKHR image,
|
|
+ CoglEglImageFlags flags,
|
|
CoglError **error)
|
|
{
|
|
CoglTextureLoader *loader;
|
|
@@ -262,6 +263,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
|
loader->src.egl_image.width = width;
|
|
loader->src.egl_image.height = height;
|
|
loader->src.egl_image.format = format;
|
|
+ loader->src.egl_image.flags = flags;
|
|
|
|
tex = _cogl_texture_2d_create_base (ctx, width, height, format, loader);
|
|
|
|
@@ -436,6 +438,7 @@ cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx,
|
|
width, height,
|
|
internal_format,
|
|
image,
|
|
+ COGL_EGL_IMAGE_FLAG_NONE,
|
|
error);
|
|
_cogl_egl_destroy_image (ctx, image);
|
|
return tex;
|
|
diff --git a/cogl/cogl/cogl-texture-2d.h b/cogl/cogl/cogl-texture-2d.h
|
|
index 29b8b2d6b..44b9d4636 100644
|
|
--- a/cogl/cogl/cogl-texture-2d.h
|
|
+++ b/cogl/cogl/cogl-texture-2d.h
|
|
@@ -65,6 +65,12 @@ G_BEGIN_DECLS
|
|
typedef struct _CoglTexture2D CoglTexture2D;
|
|
#define COGL_TEXTURE_2D(X) ((CoglTexture2D *)X)
|
|
|
|
+typedef enum _CoglEglImageFlags
|
|
+{
|
|
+ COGL_EGL_IMAGE_FLAG_NONE = 0,
|
|
+ COGL_EGL_IMAGE_FLAG_NO_GET_DATA = 1 << 0,
|
|
+} CoglEglImageFlags;
|
|
+
|
|
/**
|
|
* cogl_texture_2d_get_gtype:
|
|
*
|
|
@@ -244,6 +250,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
|
int height,
|
|
CoglPixelFormat format,
|
|
EGLImageKHR image,
|
|
+ CoglEglImageFlags flags,
|
|
CoglError **error);
|
|
|
|
typedef gboolean (*CoglTexture2DEGLImageExternalAlloc) (CoglTexture2D *tex_2d,
|
|
diff --git a/cogl/cogl/cogl-texture-private.h b/cogl/cogl/cogl-texture-private.h
|
|
index 05a0045f8..794d0d7e7 100644
|
|
--- a/cogl/cogl/cogl-texture-private.h
|
|
+++ b/cogl/cogl/cogl-texture-private.h
|
|
@@ -184,6 +184,7 @@ typedef struct _CoglTextureLoader
|
|
int width;
|
|
int height;
|
|
CoglPixelFormat format;
|
|
+ CoglEglImageFlags flags;
|
|
} egl_image;
|
|
#endif
|
|
#if defined (COGL_HAS_EGL_SUPPORT)
|
|
diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
|
|
index a9329ad50..34432ccba 100644
|
|
--- a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
|
|
+++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
|
|
@@ -328,6 +328,8 @@ allocate_from_egl_image (CoglTexture2D *tex_2d,
|
|
}
|
|
|
|
tex_2d->internal_format = internal_format;
|
|
+ tex_2d->is_get_data_supported =
|
|
+ !(loader->src.egl_image.flags & COGL_EGL_IMAGE_FLAG_NO_GET_DATA);
|
|
|
|
_cogl_texture_set_allocated (tex,
|
|
internal_format,
|
|
diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/cogl/winsys/cogl-winsys-egl-x11.c
|
|
index 4f0a12543..6a89206a1 100644
|
|
--- a/cogl/cogl/winsys/cogl-winsys-egl-x11.c
|
|
+++ b/cogl/cogl/winsys/cogl-winsys-egl-x11.c
|
|
@@ -802,6 +802,7 @@ _cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
|
|
tex->height,
|
|
texture_format,
|
|
egl_tex_pixmap->image,
|
|
+ COGL_EGL_IMAGE_FLAG_NONE,
|
|
NULL));
|
|
|
|
tex_pixmap->winsys = egl_tex_pixmap;
|
|
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
|
|
index f45679d3a..cdaad26eb 100644
|
|
--- a/src/wayland/meta-wayland-buffer.c
|
|
+++ b/src/wayland/meta-wayland-buffer.c
|
|
@@ -289,6 +289,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
|
int format, width, height, y_inverted;
|
|
CoglPixelFormat cogl_format;
|
|
EGLImageKHR egl_image;
|
|
+ CoglEglImageFlags flags;
|
|
CoglTexture2D *texture_2d;
|
|
|
|
if (buffer->egl_image.texture)
|
|
@@ -343,10 +344,12 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
|
if (egl_image == EGL_NO_IMAGE_KHR)
|
|
return FALSE;
|
|
|
|
+ flags = COGL_EGL_IMAGE_FLAG_NONE;
|
|
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
|
|
width, height,
|
|
cogl_format,
|
|
egl_image,
|
|
+ flags,
|
|
error);
|
|
|
|
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
|
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
|
|
index e49fba9cf..786b88304 100644
|
|
--- a/src/wayland/meta-wayland-dma-buf.c
|
|
+++ b/src/wayland/meta-wayland-dma-buf.c
|
|
@@ -77,6 +77,7 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
|
MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf;
|
|
CoglPixelFormat cogl_format;
|
|
EGLImageKHR egl_image;
|
|
+ CoglEglImageFlags flags;
|
|
CoglTexture2D *texture;
|
|
EGLint attribs[64];
|
|
int attr_idx = 0;
|
|
@@ -184,11 +185,13 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
|
if (egl_image == EGL_NO_IMAGE_KHR)
|
|
return FALSE;
|
|
|
|
+ flags = COGL_EGL_IMAGE_FLAG_NONE;
|
|
texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
|
dma_buf->width,
|
|
dma_buf->height,
|
|
cogl_format,
|
|
egl_image,
|
|
+ flags,
|
|
error);
|
|
|
|
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From cca085b00c029debaed80c070e316a3a7ff7e44d Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 16 Jul 2019 18:30:12 +0200
|
|
Subject: [PATCH 23/49] dma-buf: Mark DMA-BUF textures as paint-only
|
|
|
|
Reading pixels directly from a texture imported from a DMA-BUF EGLImage
|
|
may result compressed textures to be transferred into non-compressed
|
|
texture. This may have side effects causing it to be rendered
|
|
incorrectly in subsequent paints.
|
|
|
|
Avoid this by passing the no-get-data flag to the texture creator
|
|
function, eventually causing mutter to use an intermediate offscreen
|
|
framebuffer when reading pixels from such textures.
|
|
|
|
https://bugs.freedesktop.org/show_bug.cgi?id=111140
|
|
https://gitlab.freedesktop.org/xorg/xserver/issues/545
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/687
|
|
---
|
|
src/wayland/meta-wayland-dma-buf.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
|
|
index 786b88304..5661fb6ff 100644
|
|
--- a/src/wayland/meta-wayland-dma-buf.c
|
|
+++ b/src/wayland/meta-wayland-dma-buf.c
|
|
@@ -185,7 +185,7 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
|
if (egl_image == EGL_NO_IMAGE_KHR)
|
|
return FALSE;
|
|
|
|
- flags = COGL_EGL_IMAGE_FLAG_NONE;
|
|
+ flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA;
|
|
texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
|
dma_buf->width,
|
|
dma_buf->height,
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 8e25a750e9084cbc4f7e7048453ef33dfa9ea314 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 24 Feb 2020 12:44:52 -0300
|
|
Subject: [PATCH 24/49] cogl/framebuffer: Add cogl_framebuffer_flush
|
|
|
|
In future patches, we'll create additional CoglFramebuffers that
|
|
will be shared via DMA-Buf with PipeWire. When recording frames,
|
|
we'll blit the current onscreen framebuffer into the shared one.
|
|
|
|
However, that presents a problem: cogl_framebuffer_blit() mimics
|
|
glBlitFramebuffer() semantics, and doesn't do an implicit flush
|
|
of the GPU command stream. As a consequence, clients may receive
|
|
unblitted or incomplete framebuffers.
|
|
|
|
We could use cogl_framebuffer_finish() to ensure the commands were
|
|
submitted to the GPU, but it is too harsh -- it blocks the CPU
|
|
completely until the commands are finished!
|
|
|
|
Add cogl_framebuffer_flush(), which ensures the command stream is
|
|
submitted to the GPU without blocking the CPU. Even though we don't
|
|
use the framebuffer specifically, it may be useful in the future
|
|
for e.g. a potential Vulkan backend to have access to the framebuffer.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
cogl/cogl/cogl-driver.h | 3 +++
|
|
cogl/cogl/cogl-framebuffer.c | 11 +++++++++++
|
|
cogl/cogl/cogl-framebuffer.h | 12 ++++++++++++
|
|
cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h | 3 +++
|
|
cogl/cogl/driver/gl/cogl-framebuffer-gl.c | 6 ++++++
|
|
cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 1 +
|
|
cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 1 +
|
|
cogl/cogl/driver/nop/cogl-driver-nop.c | 1 +
|
|
cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h | 3 +++
|
|
cogl/cogl/driver/nop/cogl-framebuffer-nop.c | 5 +++++
|
|
10 files changed, 46 insertions(+)
|
|
|
|
diff --git a/cogl/cogl/cogl-driver.h b/cogl/cogl/cogl-driver.h
|
|
index 86682d8a7..af92146d0 100644
|
|
--- a/cogl/cogl/cogl-driver.h
|
|
+++ b/cogl/cogl/cogl-driver.h
|
|
@@ -87,6 +87,9 @@ struct _CoglDriverVtable
|
|
void
|
|
(* framebuffer_finish) (CoglFramebuffer *framebuffer);
|
|
|
|
+ void
|
|
+ (* framebuffer_flush) (CoglFramebuffer *framebuffer);
|
|
+
|
|
void
|
|
(* framebuffer_discard_buffers) (CoglFramebuffer *framebuffer,
|
|
unsigned long buffers);
|
|
diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
|
|
index 948cd112d..d64fc89fb 100644
|
|
--- a/cogl/cogl/cogl-framebuffer.c
|
|
+++ b/cogl/cogl/cogl-framebuffer.c
|
|
@@ -1568,6 +1568,17 @@ cogl_framebuffer_finish (CoglFramebuffer *framebuffer)
|
|
ctx->driver_vtable->framebuffer_finish (framebuffer);
|
|
}
|
|
|
|
+void
|
|
+cogl_framebuffer_flush (CoglFramebuffer *framebuffer)
|
|
+{
|
|
+
|
|
+ CoglContext *ctx = framebuffer->context;
|
|
+
|
|
+ _cogl_framebuffer_flush_journal (framebuffer);
|
|
+
|
|
+ ctx->driver_vtable->framebuffer_flush (framebuffer);
|
|
+}
|
|
+
|
|
void
|
|
cogl_framebuffer_push_matrix (CoglFramebuffer *framebuffer)
|
|
{
|
|
diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h
|
|
index 230a78627..38ada9feb 100644
|
|
--- a/cogl/cogl/cogl-framebuffer.h
|
|
+++ b/cogl/cogl/cogl-framebuffer.h
|
|
@@ -1910,6 +1910,18 @@ cogl_blit_framebuffer (CoglFramebuffer *src,
|
|
int height,
|
|
GError **error);
|
|
|
|
+/**
|
|
+ * cogl_framebuffer_flush:
|
|
+ * @framebuffer: A #CoglFramebuffer pointer
|
|
+ *
|
|
+ * Flushes @framebuffer to ensure the current batch of commands is
|
|
+ * submitted to the GPU.
|
|
+ *
|
|
+ * Unlike cogl_framebuffer_finish(), this does not block the CPU.
|
|
+ */
|
|
+void
|
|
+cogl_framebuffer_flush (CoglFramebuffer *framebuffer);
|
|
+
|
|
G_END_DECLS
|
|
|
|
#endif /* __COGL_FRAMEBUFFER_H */
|
|
diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h b/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h
|
|
index 214f45f0f..bbd7b0e99 100644
|
|
--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h
|
|
+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h
|
|
@@ -61,6 +61,9 @@ _cogl_framebuffer_gl_query_bits (CoglFramebuffer *framebuffer,
|
|
void
|
|
_cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer);
|
|
|
|
+void
|
|
+_cogl_framebuffer_gl_flush (CoglFramebuffer *framebuffer);
|
|
+
|
|
void
|
|
_cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer,
|
|
unsigned long buffers);
|
|
diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
|
|
index 90d08954d..6466fd6bc 100644
|
|
--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
|
|
+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
|
|
@@ -1115,6 +1115,12 @@ _cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer)
|
|
GE (framebuffer->context, glFinish ());
|
|
}
|
|
|
|
+void
|
|
+_cogl_framebuffer_gl_flush (CoglFramebuffer *framebuffer)
|
|
+{
|
|
+ GE (framebuffer->context, glFlush ());
|
|
+}
|
|
+
|
|
void
|
|
_cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer,
|
|
unsigned long buffers)
|
|
diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
|
|
index e06e27961..716617b54 100644
|
|
--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
|
|
+++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
|
|
@@ -668,6 +668,7 @@ _cogl_driver_gl =
|
|
_cogl_framebuffer_gl_clear,
|
|
_cogl_framebuffer_gl_query_bits,
|
|
_cogl_framebuffer_gl_finish,
|
|
+ _cogl_framebuffer_gl_flush,
|
|
_cogl_framebuffer_gl_discard_buffers,
|
|
_cogl_framebuffer_gl_draw_attributes,
|
|
_cogl_framebuffer_gl_draw_indexed_attributes,
|
|
diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
|
|
index bcb0bdf07..902bd0bd3 100644
|
|
--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
|
|
+++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
|
|
@@ -447,6 +447,7 @@ _cogl_driver_gles =
|
|
_cogl_framebuffer_gl_clear,
|
|
_cogl_framebuffer_gl_query_bits,
|
|
_cogl_framebuffer_gl_finish,
|
|
+ _cogl_framebuffer_gl_flush,
|
|
_cogl_framebuffer_gl_discard_buffers,
|
|
_cogl_framebuffer_gl_draw_attributes,
|
|
_cogl_framebuffer_gl_draw_indexed_attributes,
|
|
diff --git a/cogl/cogl/driver/nop/cogl-driver-nop.c b/cogl/cogl/driver/nop/cogl-driver-nop.c
|
|
index b41a2bcc5..8cab69afa 100644
|
|
--- a/cogl/cogl/driver/nop/cogl-driver-nop.c
|
|
+++ b/cogl/cogl/driver/nop/cogl-driver-nop.c
|
|
@@ -66,6 +66,7 @@ _cogl_driver_nop =
|
|
_cogl_framebuffer_nop_clear,
|
|
_cogl_framebuffer_nop_query_bits,
|
|
_cogl_framebuffer_nop_finish,
|
|
+ _cogl_framebuffer_nop_flush,
|
|
_cogl_framebuffer_nop_discard_buffers,
|
|
_cogl_framebuffer_nop_draw_attributes,
|
|
_cogl_framebuffer_nop_draw_indexed_attributes,
|
|
diff --git a/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h b/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h
|
|
index 05bbde6b4..810b98413 100644
|
|
--- a/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h
|
|
+++ b/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h
|
|
@@ -64,6 +64,9 @@ _cogl_framebuffer_nop_query_bits (CoglFramebuffer *framebuffer,
|
|
void
|
|
_cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer);
|
|
|
|
+void
|
|
+_cogl_framebuffer_nop_flush (CoglFramebuffer *framebuffer);
|
|
+
|
|
void
|
|
_cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer,
|
|
unsigned long buffers);
|
|
diff --git a/cogl/cogl/driver/nop/cogl-framebuffer-nop.c b/cogl/cogl/driver/nop/cogl-framebuffer-nop.c
|
|
index 643e304ea..db9819524 100644
|
|
--- a/cogl/cogl/driver/nop/cogl-framebuffer-nop.c
|
|
+++ b/cogl/cogl/driver/nop/cogl-framebuffer-nop.c
|
|
@@ -76,6 +76,11 @@ _cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer)
|
|
{
|
|
}
|
|
|
|
+void
|
|
+_cogl_framebuffer_nop_flush (CoglFramebuffer *framebuffer)
|
|
+{
|
|
+}
|
|
+
|
|
void
|
|
_cogl_framebuffer_nop_discard_buffers (CoglFramebuffer *framebuffer,
|
|
unsigned long buffers)
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 80affcf2cd04a0a05dd6cb45ea7475b12d9f6841 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 9 Dec 2019 10:03:07 -0300
|
|
Subject: [PATCH 25/49] cogl/context: Add cogl_renderer_create_dma_buf() and
|
|
family
|
|
|
|
This is a winsys-specific API that allows exporting a DMA buffer fd.
|
|
The CoglDmaBufHandle structure allows passing the ownership of the
|
|
DMA buffer to whoever is using it, so the winsys doesn't need to
|
|
manually track it.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
cogl/cogl/cogl-dma-buf-handle.c | 94 ++++++++++++++++++++++++++
|
|
cogl/cogl/cogl-dma-buf-handle.h | 83 +++++++++++++++++++++++
|
|
cogl/cogl/cogl-renderer.c | 14 ++++
|
|
cogl/cogl/cogl-renderer.h | 21 ++++++
|
|
cogl/cogl/cogl-types.h | 8 +++
|
|
cogl/cogl/cogl.h | 1 +
|
|
cogl/cogl/meson.build | 2 +
|
|
cogl/cogl/winsys/cogl-winsys-private.h | 6 ++
|
|
8 files changed, 229 insertions(+)
|
|
create mode 100644 cogl/cogl/cogl-dma-buf-handle.c
|
|
create mode 100644 cogl/cogl/cogl-dma-buf-handle.h
|
|
|
|
diff --git a/cogl/cogl/cogl-dma-buf-handle.c b/cogl/cogl/cogl-dma-buf-handle.c
|
|
new file mode 100644
|
|
index 000000000..4a8f709f2
|
|
--- /dev/null
|
|
+++ b/cogl/cogl/cogl-dma-buf-handle.c
|
|
@@ -0,0 +1,94 @@
|
|
+/*
|
|
+ * Cogl
|
|
+ *
|
|
+ * A Low Level GPU Graphics and Utilities API
|
|
+ *
|
|
+ * Copyright (C) 2020 Endless, Inc.
|
|
+ *
|
|
+ * Permission is hereby granted, free of charge, to any person
|
|
+ * obtaining a copy of this software and associated documentation
|
|
+ * files (the "Software"), to deal in the Software without
|
|
+ * restriction, including without limitation the rights to use, copy,
|
|
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
+ * of the Software, and to permit persons to whom the Software is
|
|
+ * furnished to do so, subject to the following conditions:
|
|
+ *
|
|
+ * The above copyright notice and this permission notice shall be
|
|
+ * included in all copies or substantial portions of the Software.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
+ * SOFTWARE.
|
|
+ *
|
|
+ * Authors:
|
|
+ * Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
+ */
|
|
+
|
|
+#include "cogl-config.h"
|
|
+
|
|
+#include "cogl-dma-buf-handle.h"
|
|
+#include "cogl-object.h"
|
|
+
|
|
+#include <unistd.h>
|
|
+
|
|
+struct _CoglDmaBufHandle
|
|
+{
|
|
+ CoglFramebuffer *framebuffer;
|
|
+ int dmabuf_fd;
|
|
+ gpointer user_data;
|
|
+ GDestroyNotify destroy_func;
|
|
+};
|
|
+
|
|
+CoglDmaBufHandle *
|
|
+cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
|
|
+ int dmabuf_fd,
|
|
+ gpointer user_data,
|
|
+ GDestroyNotify destroy_func)
|
|
+{
|
|
+ CoglDmaBufHandle *dmabuf_handle;
|
|
+
|
|
+ g_assert (framebuffer);
|
|
+ g_assert (dmabuf_fd != -1);
|
|
+
|
|
+ dmabuf_handle = g_new0 (CoglDmaBufHandle, 1);
|
|
+ dmabuf_handle->framebuffer = cogl_object_ref (framebuffer);
|
|
+ dmabuf_handle->dmabuf_fd = dmabuf_fd;
|
|
+ dmabuf_handle->user_data = user_data;
|
|
+ dmabuf_handle->destroy_func = destroy_func;
|
|
+
|
|
+ return dmabuf_handle;
|
|
+}
|
|
+
|
|
+void
|
|
+cogl_dma_buf_handle_free (CoglDmaBufHandle *dmabuf_handle)
|
|
+{
|
|
+ g_return_if_fail (dmabuf_handle != NULL);
|
|
+
|
|
+ g_clear_pointer (&dmabuf_handle->framebuffer, cogl_object_unref);
|
|
+
|
|
+ if (dmabuf_handle->destroy_func)
|
|
+ g_clear_pointer (&dmabuf_handle->user_data, dmabuf_handle->destroy_func);
|
|
+
|
|
+ if (dmabuf_handle->dmabuf_fd != -1)
|
|
+ close (dmabuf_handle->dmabuf_fd);
|
|
+
|
|
+ g_free (dmabuf_handle);
|
|
+}
|
|
+
|
|
+CoglFramebuffer *
|
|
+cogl_dma_buf_handle_get_framebuffer (CoglDmaBufHandle *dmabuf_handle)
|
|
+{
|
|
+ return dmabuf_handle->framebuffer;
|
|
+}
|
|
+
|
|
+int
|
|
+cogl_dma_buf_handle_get_fd (CoglDmaBufHandle *dmabuf_handle)
|
|
+{
|
|
+ return dmabuf_handle->dmabuf_fd;
|
|
+}
|
|
+
|
|
diff --git a/cogl/cogl/cogl-dma-buf-handle.h b/cogl/cogl/cogl-dma-buf-handle.h
|
|
new file mode 100644
|
|
index 000000000..25b9b0ccb
|
|
--- /dev/null
|
|
+++ b/cogl/cogl/cogl-dma-buf-handle.h
|
|
@@ -0,0 +1,83 @@
|
|
+/*
|
|
+ * Cogl
|
|
+ *
|
|
+ * A Low Level GPU Graphics and Utilities API
|
|
+ *
|
|
+ * Copyright (C) 2020 Endless, Inc.
|
|
+ *
|
|
+ * Permission is hereby granted, free of charge, to any person
|
|
+ * obtaining a copy of this software and associated documentation
|
|
+ * files (the "Software"), to deal in the Software without
|
|
+ * restriction, including without limitation the rights to use, copy,
|
|
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
+ * of the Software, and to permit persons to whom the Software is
|
|
+ * furnished to do so, subject to the following conditions:
|
|
+ *
|
|
+ * The above copyright notice and this permission notice shall be
|
|
+ * included in all copies or substantial portions of the Software.
|
|
+ *
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
+ * SOFTWARE.
|
|
+ *
|
|
+ * Authors:
|
|
+ * Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
+ */
|
|
+
|
|
+
|
|
+#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION)
|
|
+#error "Only <cogl/cogl.h> can be included directly."
|
|
+#endif
|
|
+
|
|
+#ifndef __COGL_DMA_BUF_HANDLE_H__
|
|
+#define __COGL_DMA_BUF_HANDLE_H__
|
|
+
|
|
+#include <cogl/cogl-types.h>
|
|
+#include <cogl/cogl-framebuffer.h>
|
|
+
|
|
+/**
|
|
+ * cogl_dma_buf_handle_new: (skip)
|
|
+ */
|
|
+CoglDmaBufHandle *
|
|
+cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
|
|
+ int dmabuf_fd,
|
|
+ gpointer data,
|
|
+ GDestroyNotify destroy_func);
|
|
+
|
|
+/**
|
|
+ * cogl_dma_buf_handle_free: (skip)
|
|
+ *
|
|
+ * Releases @dmabuf_handle; it is a programming error to release
|
|
+ * an already released handle.
|
|
+ */
|
|
+void
|
|
+cogl_dma_buf_handle_free (CoglDmaBufHandle *dmabuf_handle);
|
|
+
|
|
+/**
|
|
+ * cogl_dma_buf_handle_get_framebuffer: (skip)
|
|
+ *
|
|
+ * Retrieves the #CoglFramebuffer, backed by an exported DMABuf buffer,
|
|
+ * of @dmabuf_handle.
|
|
+ *
|
|
+ * Returns: (transfer none): a #CoglFramebuffer
|
|
+ */
|
|
+CoglFramebuffer *
|
|
+cogl_dma_buf_handle_get_framebuffer (CoglDmaBufHandle *dmabuf_handle);
|
|
+
|
|
+/**
|
|
+ * cogl_dma_buf_handle_get_fd: (skip)
|
|
+ *
|
|
+ * Retrieves the file descriptor of @dmabuf_handle.
|
|
+ *
|
|
+ * Returns: a valid file descriptor
|
|
+ */
|
|
+int
|
|
+cogl_dma_buf_handle_get_fd (CoglDmaBufHandle *dmabuf_handle);
|
|
+
|
|
+
|
|
+#endif /* __COGL_DMA_BUF_HANDLE_H__ */
|
|
diff --git a/cogl/cogl/cogl-renderer.c b/cogl/cogl/cogl-renderer.c
|
|
index 854aa1fdd..8c2ff0702 100644
|
|
--- a/cogl/cogl/cogl-renderer.c
|
|
+++ b/cogl/cogl/cogl-renderer.c
|
|
@@ -838,3 +838,17 @@ cogl_renderer_foreach_output (CoglRenderer *renderer,
|
|
for (l = renderer->outputs; l; l = l->next)
|
|
callback (l->data, user_data);
|
|
}
|
|
+
|
|
+CoglDmaBufHandle *
|
|
+cogl_renderer_create_dma_buf (CoglRenderer *renderer,
|
|
+ int width,
|
|
+ int height,
|
|
+ GError **error)
|
|
+{
|
|
+ const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
|
|
+
|
|
+ if (winsys->renderer_create_dma_buf)
|
|
+ return winsys->renderer_create_dma_buf (renderer, width, height, error);
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
diff --git a/cogl/cogl/cogl-renderer.h b/cogl/cogl/cogl-renderer.h
|
|
index 0b3ddb8f2..c5e904106 100644
|
|
--- a/cogl/cogl/cogl-renderer.h
|
|
+++ b/cogl/cogl/cogl-renderer.h
|
|
@@ -418,6 +418,27 @@ cogl_renderer_foreach_output (CoglRenderer *renderer,
|
|
CoglOutputCallback callback,
|
|
void *user_data);
|
|
|
|
+/**
|
|
+ * cogl_renderer_create_dma_buf: (skip)
|
|
+ * @renderer: A #CoglRenderer
|
|
+ * @width: width of the new
|
|
+ * @height: height of the new
|
|
+ * @error: (nullable): return location for a #GError
|
|
+ *
|
|
+ * Creates a new #CoglFramebuffer with @width x @height, and format
|
|
+ * hardcoded to XRGB, and exports the new framebuffer's DMA buffer
|
|
+ * handle.
|
|
+ *
|
|
+ * Returns: (nullable)(transfer full): a #CoglDmaBufHandle. The
|
|
+ * return result must be released with cogl_dma_buf_handle_free()
|
|
+ * after use.
|
|
+ */
|
|
+CoglDmaBufHandle *
|
|
+cogl_renderer_create_dma_buf (CoglRenderer *renderer,
|
|
+ int width,
|
|
+ int height,
|
|
+ GError **error);
|
|
+
|
|
G_END_DECLS
|
|
|
|
#endif /* __COGL_RENDERER_H__ */
|
|
diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h
|
|
index 69d304cf0..1d420dc2c 100644
|
|
--- a/cogl/cogl/cogl-types.h
|
|
+++ b/cogl/cogl/cogl-types.h
|
|
@@ -138,6 +138,14 @@ typedef int32_t CoglAngle;
|
|
typedef struct _CoglColor CoglColor;
|
|
typedef struct _CoglTextureVertex CoglTextureVertex;
|
|
|
|
+/**
|
|
+ * CoglDmaBufHandle: (skip)
|
|
+ *
|
|
+ * An opaque type that tracks the lifetime of a DMA buffer fd. Release
|
|
+ * with cogl_dma_buf_handle_free().
|
|
+ */
|
|
+typedef struct _CoglDmaBufHandle CoglDmaBufHandle;
|
|
+
|
|
/* Enum declarations */
|
|
|
|
#define COGL_A_BIT (1 << 4)
|
|
diff --git a/cogl/cogl/cogl.h b/cogl/cogl/cogl.h
|
|
index 565ea289a..065278d36 100644
|
|
--- a/cogl/cogl/cogl.h
|
|
+++ b/cogl/cogl/cogl.h
|
|
@@ -61,6 +61,7 @@
|
|
#include <cogl/cogl1-context.h>
|
|
#include <cogl/cogl-bitmap.h>
|
|
#include <cogl/cogl-color.h>
|
|
+#include <cogl/cogl-dma-buf-handle.h>
|
|
#include <cogl/cogl-matrix.h>
|
|
#include <cogl/cogl-matrix-stack.h>
|
|
#include <cogl/cogl-offscreen.h>
|
|
diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build
|
|
index 8032669e4..1934e7574 100644
|
|
--- a/cogl/cogl/meson.build
|
|
+++ b/cogl/cogl/meson.build
|
|
@@ -102,6 +102,7 @@ cogl_nonintrospected_headers = [
|
|
'cogl-renderer.h',
|
|
'cogl-swap-chain.h',
|
|
'cogl-onscreen-template.h',
|
|
+ 'cogl-dma-buf-handle.h',
|
|
'cogl-display.h',
|
|
'cogl-context.h',
|
|
'cogl-snippet.h',
|
|
@@ -217,6 +218,7 @@ cogl_sources = [
|
|
'cogl-i18n-private.h',
|
|
'cogl-debug.h',
|
|
'cogl-debug-options.h',
|
|
+ 'cogl-dma-buf-handle.c',
|
|
'cogl-gpu-info.c',
|
|
'cogl-gpu-info-private.h',
|
|
'cogl-context-private.h',
|
|
diff --git a/cogl/cogl/winsys/cogl-winsys-private.h b/cogl/cogl/winsys/cogl-winsys-private.h
|
|
index c6b2f3579..59c8945ce 100644
|
|
--- a/cogl/cogl/winsys/cogl-winsys-private.h
|
|
+++ b/cogl/cogl/winsys/cogl-winsys-private.h
|
|
@@ -100,6 +100,12 @@ typedef struct _CoglWinsysVtable
|
|
void
|
|
(*display_destroy) (CoglDisplay *display);
|
|
|
|
+ CoglDmaBufHandle *
|
|
+ (*renderer_create_dma_buf) (CoglRenderer *renderer,
|
|
+ int width,
|
|
+ int height,
|
|
+ GError **error);
|
|
+
|
|
gboolean
|
|
(*context_init) (CoglContext *context, CoglError **error);
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From aee3b6d1933375b9b8fb144c523a6227cd935142 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 9 Dec 2019 10:04:56 -0300
|
|
Subject: [PATCH 26/49] renderer-native: Move DMA buffer creation to an
|
|
auxiliary function
|
|
|
|
This will be reused by the DMA buffer exporting function.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
src/backends/native/meta-renderer-native.c | 92 +++++++++++++++++++---
|
|
1 file changed, 83 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
|
index 76cc79e23..75d6ec4c2 100644
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
@@ -2214,6 +2214,89 @@ wait_for_pending_flips (CoglOnscreen *onscreen)
|
|
meta_gpu_kms_wait_for_flip (onscreen_native->render_gpu, NULL);
|
|
}
|
|
|
|
+static CoglContext *
|
|
+cogl_context_from_renderer_native (MetaRendererNative *renderer_native)
|
|
+{
|
|
+ MetaBackend *backend = backend_from_renderer_native (renderer_native);
|
|
+ ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
|
+
|
|
+ return clutter_backend_get_cogl_context (clutter_backend);
|
|
+}
|
|
+
|
|
+static CoglFramebuffer *
|
|
+create_dma_buf_framebuffer (MetaRendererNative *renderer_native,
|
|
+ int dmabuf_fd,
|
|
+ uint32_t width,
|
|
+ uint32_t height,
|
|
+ uint32_t stride,
|
|
+ uint32_t offset,
|
|
+ uint64_t modifier,
|
|
+ uint32_t drm_format,
|
|
+ GError **error)
|
|
+{
|
|
+ CoglContext *cogl_context =
|
|
+ cogl_context_from_renderer_native (renderer_native);
|
|
+ CoglDisplay *cogl_display = cogl_context->display;
|
|
+ CoglRenderer *cogl_renderer = cogl_display->renderer;
|
|
+ CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
|
+ EGLDisplay egl_display = cogl_renderer_egl->edpy;
|
|
+ MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
|
|
+ EGLImageKHR egl_image;
|
|
+ uint32_t strides[1];
|
|
+ uint32_t offsets[1];
|
|
+ uint64_t modifiers[1];
|
|
+ CoglPixelFormat cogl_format;
|
|
+ CoglEglImageFlags flags;
|
|
+ CoglTexture2D *cogl_tex;
|
|
+ CoglOffscreen *cogl_fbo;
|
|
+ int ret;
|
|
+
|
|
+ ret = cogl_pixel_format_from_drm_format (drm_format, &cogl_format, NULL);
|
|
+ g_assert (ret);
|
|
+
|
|
+ strides[0] = stride;
|
|
+ offsets[0] = offset;
|
|
+ modifiers[0] = modifier;
|
|
+ egl_image = meta_egl_create_dmabuf_image (egl,
|
|
+ egl_display,
|
|
+ width,
|
|
+ height,
|
|
+ drm_format,
|
|
+ 1 /* n_planes */,
|
|
+ &dmabuf_fd,
|
|
+ strides,
|
|
+ offsets,
|
|
+ modifiers,
|
|
+ error);
|
|
+ if (egl_image == EGL_NO_IMAGE_KHR)
|
|
+ return NULL;
|
|
+
|
|
+ flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA;
|
|
+ cogl_tex = cogl_egl_texture_2d_new_from_image (cogl_context,
|
|
+ width,
|
|
+ height,
|
|
+ cogl_format,
|
|
+ egl_image,
|
|
+ flags,
|
|
+ error);
|
|
+
|
|
+ meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
|
+
|
|
+ if (!cogl_tex)
|
|
+ return NULL;
|
|
+
|
|
+ cogl_fbo = cogl_offscreen_new_with_texture (COGL_TEXTURE (cogl_tex));
|
|
+ cogl_object_unref (cogl_tex);
|
|
+
|
|
+ if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (cogl_fbo), error))
|
|
+ {
|
|
+ cogl_object_unref (cogl_fbo);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return COGL_FRAMEBUFFER (cogl_fbo);
|
|
+}
|
|
+
|
|
static void
|
|
copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
@@ -3457,15 +3540,6 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
|
return crtc_transform;
|
|
}
|
|
|
|
-static CoglContext *
|
|
-cogl_context_from_renderer_native (MetaRendererNative *renderer_native)
|
|
-{
|
|
- MetaBackend *backend = backend_from_renderer_native (renderer_native);
|
|
- ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
|
-
|
|
- return clutter_backend_get_cogl_context (clutter_backend);
|
|
-}
|
|
-
|
|
static gboolean
|
|
should_force_shadow_fb (MetaRendererNative *renderer_native,
|
|
MetaGpuKms *primary_gpu)
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 1eab96d6e3813ec5745e882d9a195adf4a226ff6 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 9 Dec 2019 10:05:37 -0300
|
|
Subject: [PATCH 27/49] renderer-native: Implement DMA buffer creation
|
|
|
|
Create a new gbm_bo using the same given geometry, and export the new
|
|
bo's DMA buffer fd. The new bo lives as long as necessary to be used,
|
|
and reused, by PipeWire.
|
|
|
|
Unfortunately, PipeWire doesn't support modifiers properly, so use the
|
|
linear format for now. For now, a hardcoded format of DRM_FORMAT_XRGB8888
|
|
is set, so we don't need to negotiate the format with PipeWire early.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
src/backends/native/meta-renderer-native.c | 68 ++++++++++++++++++++++
|
|
1 file changed, 68 insertions(+)
|
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
|
index 75d6ec4c2..ba98de650 100644
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
@@ -2618,6 +2618,73 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
_cogl_winsys_egl_ensure_current (cogl_display);
|
|
}
|
|
|
|
+static CoglDmaBufHandle *
|
|
+meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
|
|
+ int width,
|
|
+ int height,
|
|
+ GError **error)
|
|
+{
|
|
+ CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
|
+ MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
|
|
+ MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
|
+
|
|
+ switch (renderer_gpu_data->mode)
|
|
+ {
|
|
+ case META_RENDERER_NATIVE_MODE_GBM:
|
|
+ {
|
|
+ CoglFramebuffer *dmabuf_fb;
|
|
+ struct gbm_bo *new_bo;
|
|
+ int dmabuf_fd = -1;
|
|
+
|
|
+ new_bo = gbm_bo_create (renderer_gpu_data->gbm.device,
|
|
+ width, height, DRM_FORMAT_XRGB8888,
|
|
+ GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
|
|
+
|
|
+ if (!new_bo)
|
|
+ {
|
|
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
+ "Failed to allocate buffer");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ dmabuf_fd = gbm_bo_get_fd (new_bo);
|
|
+
|
|
+ if (dmabuf_fd == -1)
|
|
+ {
|
|
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
|
|
+ "Failed to export buffer's DMA fd: %s",
|
|
+ g_strerror (errno));
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ dmabuf_fb = create_dma_buf_framebuffer (renderer_native,
|
|
+ dmabuf_fd,
|
|
+ width, height,
|
|
+ gbm_bo_get_stride (new_bo),
|
|
+ gbm_bo_get_offset (new_bo, 0),
|
|
+ DRM_FORMAT_MOD_LINEAR,
|
|
+ DRM_FORMAT_XRGB8888,
|
|
+ error);
|
|
+
|
|
+ if (!dmabuf_fb)
|
|
+ return NULL;
|
|
+
|
|
+ return cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo,
|
|
+ (GDestroyNotify) gbm_bo_destroy);
|
|
+ }
|
|
+ break;
|
|
+#ifdef HAVE_EGL_DEVICE
|
|
+ case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
|
+ break;
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN,
|
|
+ "Current mode does not support exporting DMA buffers");
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
static gboolean
|
|
meta_renderer_native_init_egl_context (CoglContext *cogl_context,
|
|
GError **error)
|
|
@@ -3461,6 +3528,7 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
|
|
|
|
vtable.renderer_connect = meta_renderer_native_connect;
|
|
vtable.renderer_disconnect = meta_renderer_native_disconnect;
|
|
+ vtable.renderer_create_dma_buf = meta_renderer_native_create_dma_buf;
|
|
|
|
vtable.onscreen_init = meta_renderer_native_init_onscreen;
|
|
vtable.onscreen_deinit = meta_renderer_native_release_onscreen;
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From a8503b2e8b5573f9decf97264a26877adf65c4c0 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 9 Dec 2019 10:07:29 -0300
|
|
Subject: [PATCH 28/49] screen-cast-stream-src: Support DMA buffer sharing
|
|
|
|
Implement PipeWire's add_buffer and remove buffer, try and export
|
|
a DMA buffer first and, on failure, fallback to memfd.
|
|
|
|
When DMA buffers are successfully created and shared, blit the
|
|
framebuffer contents when drawing instead of downloading the pixels.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
src/backends/meta-screen-cast-stream-src.c | 189 ++++++++++++++++++---
|
|
src/backends/meta-screen-cast-stream-src.h | 2 +
|
|
2 files changed, 164 insertions(+), 27 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index ba1ce94a7..0eb9f4d8c 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -25,6 +25,7 @@
|
|
#include "backends/meta-screen-cast-stream-src.h"
|
|
|
|
#include <errno.h>
|
|
+#include <fcntl.h>
|
|
#include <pipewire/pipewire.h>
|
|
#include <spa/param/props.h>
|
|
#include <spa/param/format-utils.h>
|
|
@@ -90,6 +91,8 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|
|
|
uint64_t last_frame_timestamp_us;
|
|
|
|
+ GHashTable *dmabuf_handles;
|
|
+
|
|
int stream_width;
|
|
int stream_height;
|
|
} MetaScreenCastStreamSrcPrivate;
|
|
@@ -139,6 +142,19 @@ meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
|
return klass->record_frame (src, data);
|
|
}
|
|
|
|
+static gboolean
|
|
+meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
|
+ CoglFramebuffer *framebuffer)
|
|
+{
|
|
+ MetaScreenCastStreamSrcClass *klass =
|
|
+ META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
|
+
|
|
+ if (klass->blit_to_framebuffer)
|
|
+ return klass->blit_to_framebuffer (src, framebuffer);
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
static void
|
|
meta_screen_cast_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
|
struct spa_meta_cursor *spa_meta_cursor)
|
|
@@ -394,6 +410,33 @@ maybe_record_cursor (MetaScreenCastStreamSrc *src,
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
+static gboolean
|
|
+do_record_frame (MetaScreenCastStreamSrc *src,
|
|
+ struct spa_buffer *spa_buffer,
|
|
+ uint8_t *data)
|
|
+{
|
|
+ MetaScreenCastStreamSrcPrivate *priv =
|
|
+ meta_screen_cast_stream_src_get_instance_private (src);
|
|
+
|
|
+ if (spa_buffer->datas[0].data ||
|
|
+ spa_buffer->datas[0].type == SPA_DATA_MemFd)
|
|
+ {
|
|
+ return meta_screen_cast_stream_src_record_frame (src, data);
|
|
+ }
|
|
+ else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf)
|
|
+ {
|
|
+ CoglDmaBufHandle *dmabuf_handle =
|
|
+ g_hash_table_lookup (priv->dmabuf_handles,
|
|
+ GINT_TO_POINTER (spa_buffer->datas[0].fd));
|
|
+ CoglFramebuffer *dmabuf_fbo =
|
|
+ cogl_dma_buf_handle_get_framebuffer (dmabuf_handle);
|
|
+
|
|
+ return meta_screen_cast_stream_src_blit_to_framebuffer (src, dmabuf_fbo);
|
|
+ }
|
|
+
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
void
|
|
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
{
|
|
@@ -402,8 +445,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
MetaRectangle crop_rect;
|
|
struct pw_buffer *buffer;
|
|
struct spa_buffer *spa_buffer;
|
|
- uint8_t *map = NULL;
|
|
- uint8_t *data;
|
|
+ uint8_t *data = NULL;
|
|
uint64_t now_us;
|
|
|
|
now_us = g_get_monotonic_time ();
|
|
@@ -424,32 +466,15 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
}
|
|
|
|
spa_buffer = buffer->buffer;
|
|
+ data = spa_buffer->datas[0].data;
|
|
|
|
- if (spa_buffer->datas[0].data)
|
|
- {
|
|
- data = spa_buffer->datas[0].data;
|
|
- }
|
|
- else if (spa_buffer->datas[0].type == SPA_DATA_MemFd)
|
|
+ if (spa_buffer->datas[0].type != SPA_DATA_DmaBuf && !data)
|
|
{
|
|
- map = mmap (NULL, spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
|
|
- PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
- spa_buffer->datas[0].fd, 0);
|
|
- if (map == MAP_FAILED)
|
|
- {
|
|
- g_warning ("Failed to mmap pipewire stream buffer: %s",
|
|
- strerror (errno));
|
|
- return;
|
|
- }
|
|
-
|
|
- data = SPA_MEMBER (map, spa_buffer->datas[0].mapoffset, uint8_t);
|
|
- }
|
|
- else
|
|
- {
|
|
- g_warning ("Unhandled spa buffer type: %d", spa_buffer->datas[0].type);
|
|
+ g_critical ("Invalid buffer data");
|
|
return;
|
|
}
|
|
|
|
- if (meta_screen_cast_stream_src_record_frame (src, data))
|
|
+ if (do_record_frame (src, spa_buffer, data))
|
|
{
|
|
struct spa_meta_region *spa_meta_video_crop;
|
|
|
|
@@ -487,9 +512,6 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
|
|
priv->last_frame_timestamp_us = now_us;
|
|
|
|
- if (map)
|
|
- munmap (map, spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset);
|
|
-
|
|
pw_stream_queue_buffer (priv->pipewire_stream, buffer);
|
|
}
|
|
|
|
@@ -618,10 +640,116 @@ on_stream_param_changed (void *data,
|
|
pw_stream_update_params (priv->pipewire_stream, params, G_N_ELEMENTS (params));
|
|
}
|
|
|
|
+static void
|
|
+on_stream_add_buffer (void *data,
|
|
+ struct pw_buffer *buffer)
|
|
+{
|
|
+ MetaScreenCastStreamSrc *src = data;
|
|
+ MetaScreenCastStreamSrcPrivate *priv =
|
|
+ meta_screen_cast_stream_src_get_instance_private (src);
|
|
+ CoglContext *context =
|
|
+ clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
+ CoglRenderer *renderer = cogl_context_get_renderer (context);
|
|
+ g_autoptr (GError) error = NULL;
|
|
+ CoglDmaBufHandle *dmabuf_handle;
|
|
+ struct spa_buffer *spa_buffer = buffer->buffer;
|
|
+ struct spa_data *spa_data = spa_buffer->datas;
|
|
+ const int bpp = 4;
|
|
+ int stride;
|
|
+
|
|
+ stride = SPA_ROUND_UP_N (priv->video_format.size.width * bpp, 4);
|
|
+
|
|
+ spa_data[0].mapoffset = 0;
|
|
+ spa_data[0].maxsize = stride * priv->video_format.size.height;
|
|
+
|
|
+ dmabuf_handle = cogl_renderer_create_dma_buf (renderer,
|
|
+ priv->stream_width,
|
|
+ priv->stream_height,
|
|
+ &error);
|
|
+
|
|
+ if (error)
|
|
+ g_debug ("Error exporting DMA buffer handle: %s", error->message);
|
|
+
|
|
+ if (dmabuf_handle)
|
|
+ {
|
|
+ spa_data[0].type = SPA_DATA_DmaBuf;
|
|
+ spa_data[0].flags = SPA_DATA_FLAG_READWRITE;
|
|
+ spa_data[0].fd = cogl_dma_buf_handle_get_fd (dmabuf_handle);
|
|
+ spa_data[0].data = NULL;
|
|
+
|
|
+ g_hash_table_insert (priv->dmabuf_handles,
|
|
+ GINT_TO_POINTER (spa_data[0].fd),
|
|
+ dmabuf_handle);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ unsigned int seals;
|
|
+
|
|
+ /* Fallback to a memfd buffer */
|
|
+ spa_data[0].type = SPA_DATA_MemFd;
|
|
+ spa_data[0].flags = SPA_DATA_FLAG_READWRITE;
|
|
+ spa_data[0].fd = memfd_create ("mutter-screen-cast-memfd",
|
|
+ MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
|
+ if (spa_data[0].fd == -1)
|
|
+ {
|
|
+ g_critical ("Can't create memfd: %m");
|
|
+ return;
|
|
+ }
|
|
+ spa_data[0].mapoffset = 0;
|
|
+ spa_data[0].maxsize = stride * priv->video_format.size.height;
|
|
+
|
|
+ if (ftruncate (spa_data[0].fd, spa_data[0].maxsize) < 0)
|
|
+ {
|
|
+ g_critical ("Can't truncate to %d: %m", spa_data[0].maxsize);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
|
|
+ if (fcntl (spa_data[0].fd, F_ADD_SEALS, seals) == -1)
|
|
+ g_warning ("Failed to add seals: %m");
|
|
+
|
|
+ spa_data[0].data = mmap (NULL,
|
|
+ spa_data[0].maxsize,
|
|
+ PROT_READ | PROT_WRITE,
|
|
+ MAP_SHARED,
|
|
+ spa_data[0].fd,
|
|
+ spa_data[0].mapoffset);
|
|
+ if (spa_data[0].data == MAP_FAILED)
|
|
+ {
|
|
+ g_critical ("Failed to mmap memory: %m");
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+on_stream_remove_buffer (void *data,
|
|
+ struct pw_buffer *buffer)
|
|
+{
|
|
+ MetaScreenCastStreamSrc *src = data;
|
|
+ MetaScreenCastStreamSrcPrivate *priv =
|
|
+ meta_screen_cast_stream_src_get_instance_private (src);
|
|
+ struct spa_buffer *spa_buffer = buffer->buffer;
|
|
+ struct spa_data *spa_data = spa_buffer->datas;
|
|
+
|
|
+ if (spa_data[0].type == SPA_DATA_DmaBuf)
|
|
+ {
|
|
+ if (!g_hash_table_remove (priv->dmabuf_handles, GINT_TO_POINTER (spa_data[0].fd)))
|
|
+ g_critical ("Failed to remove non-exported DMA buffer");
|
|
+ }
|
|
+ else if (spa_data[0].type == SPA_DATA_MemFd)
|
|
+ {
|
|
+ munmap (spa_data[0].data, spa_data[0].maxsize);
|
|
+ close (spa_data[0].fd);
|
|
+ }
|
|
+}
|
|
+
|
|
static const struct pw_stream_events stream_events = {
|
|
PW_VERSION_STREAM_EVENTS,
|
|
.state_changed = on_stream_state_changed,
|
|
.param_changed = on_stream_param_changed,
|
|
+ .add_buffer = on_stream_add_buffer,
|
|
+ .remove_buffer = on_stream_remove_buffer,
|
|
};
|
|
|
|
static struct pw_stream *
|
|
@@ -686,7 +814,7 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|
PW_DIRECTION_OUTPUT,
|
|
SPA_ID_INVALID,
|
|
(PW_STREAM_FLAG_DRIVER |
|
|
- PW_STREAM_FLAG_MAP_BUFFERS),
|
|
+ PW_STREAM_FLAG_ALLOC_BUFFERS),
|
|
params, G_N_ELEMENTS (params));
|
|
if (result != 0)
|
|
{
|
|
@@ -854,6 +982,7 @@ meta_screen_cast_stream_src_finalize (GObject *object)
|
|
if (meta_screen_cast_stream_src_is_enabled (src))
|
|
meta_screen_cast_stream_src_disable (src);
|
|
|
|
+ g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
|
|
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
|
|
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
|
|
g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
|
|
@@ -905,6 +1034,12 @@ meta_screen_cast_stream_src_get_property (GObject *object,
|
|
static void
|
|
meta_screen_cast_stream_src_init (MetaScreenCastStreamSrc *src)
|
|
{
|
|
+ MetaScreenCastStreamSrcPrivate *priv =
|
|
+ meta_screen_cast_stream_src_get_instance_private (src);
|
|
+
|
|
+ priv->dmabuf_handles =
|
|
+ g_hash_table_new_full (NULL, NULL, NULL,
|
|
+ (GDestroyNotify) cogl_dma_buf_handle_free);
|
|
}
|
|
|
|
static void
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h
|
|
index fc0e5bc77..3f6a1af2b 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.h
|
|
+++ b/src/backends/meta-screen-cast-stream-src.h
|
|
@@ -55,6 +55,8 @@ struct _MetaScreenCastStreamSrcClass
|
|
void (* disable) (MetaScreenCastStreamSrc *src);
|
|
gboolean (* record_frame) (MetaScreenCastStreamSrc *src,
|
|
uint8_t *data);
|
|
+ gboolean (* blit_to_framebuffer) (MetaScreenCastStreamSrc *src,
|
|
+ CoglFramebuffer *framebuffer);
|
|
gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
|
|
MetaRectangle *crop_rect);
|
|
void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From b25135cdeda1ee1aa26bb645ba981478c823d413 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 9 Dec 2019 10:11:51 -0300
|
|
Subject: [PATCH 29/49] monitor-stream-src: Implement blitting view
|
|
framebuffers
|
|
|
|
Add the vfunc override that actually consume the new Cogl API. Every
|
|
view that fits into the logical monitor is rendered.
|
|
|
|
Fixes https://gitlab.gnome.org/GNOME/mutter/issues/639
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
.../meta-screen-cast-monitor-stream-src.c | 62 +++++++++++++++++++
|
|
1 file changed, 62 insertions(+)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
index f582217e5..0c7d8ec17 100644
|
|
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
@@ -367,6 +367,66 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
|
return TRUE;
|
|
}
|
|
|
|
+static gboolean
|
|
+meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
|
+ CoglFramebuffer *framebuffer)
|
|
+{
|
|
+ MetaScreenCastMonitorStreamSrc *monitor_src =
|
|
+ META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
|
+ MetaBackend *backend = get_backend (monitor_src);
|
|
+ MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
|
+ MetaMonitor *monitor;
|
|
+ MetaLogicalMonitor *logical_monitor;
|
|
+ MetaRectangle logical_monitor_layout;
|
|
+ GList *l;
|
|
+ float view_scale;
|
|
+
|
|
+ monitor = get_monitor (monitor_src);
|
|
+ logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
|
+ logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
|
|
+
|
|
+ if (meta_is_stage_views_scaled ())
|
|
+ view_scale = meta_logical_monitor_get_scale (logical_monitor);
|
|
+ else
|
|
+ view_scale = 1.0;
|
|
+
|
|
+ for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
|
+ {
|
|
+ ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data);
|
|
+ g_autoptr (GError) error = NULL;
|
|
+ CoglFramebuffer *view_framebuffer;
|
|
+ MetaRectangle view_layout;
|
|
+ int x, y;
|
|
+
|
|
+ clutter_stage_view_get_layout (view, &view_layout);
|
|
+
|
|
+ if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout))
|
|
+ continue;
|
|
+
|
|
+ view_framebuffer = clutter_stage_view_get_framebuffer (view);
|
|
+
|
|
+ x = (int) roundf ((view_layout.x - logical_monitor_layout.x) * view_scale);
|
|
+ y = (int) roundf ((view_layout.y - logical_monitor_layout.y) * view_scale);
|
|
+
|
|
+ if (!cogl_blit_framebuffer (view_framebuffer,
|
|
+ framebuffer,
|
|
+ 0, 0,
|
|
+ x, y,
|
|
+ cogl_framebuffer_get_width (view_framebuffer),
|
|
+ cogl_framebuffer_get_height (view_framebuffer),
|
|
+ &error))
|
|
+ {
|
|
+ g_warning ("Error blitting view into DMABuf framebuffer: %s",
|
|
+ error->message);
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ cogl_framebuffer_flush (framebuffer);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static void
|
|
meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
|
struct spa_meta_cursor *spa_meta_cursor)
|
|
@@ -492,6 +552,8 @@ meta_screen_cast_monitor_stream_src_class_init (MetaScreenCastMonitorStreamSrcCl
|
|
src_class->enable = meta_screen_cast_monitor_stream_src_enable;
|
|
src_class->disable = meta_screen_cast_monitor_stream_src_disable;
|
|
src_class->record_frame = meta_screen_cast_monitor_stream_src_record_frame;
|
|
+ src_class->blit_to_framebuffer =
|
|
+ meta_screen_cast_monitor_stream_src_blit_to_framebuffer;
|
|
src_class->set_cursor_metadata =
|
|
meta_screen_cast_monitor_stream_src_set_cursor_metadata;
|
|
}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 7806ab62bbf51e2ca884b17a314c74b38f3ae9c5 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Fri, 28 Feb 2020 12:23:15 -0300
|
|
Subject: [PATCH 30/49] window-stream-source: Draw into DMA buffer image
|
|
|
|
Much like monitor streaming, implement window streaming by
|
|
making the window actor draw itself with a paint context
|
|
that used the passed framebuffer.
|
|
|
|
Now that all MetaScreenCastStreamSrc subclasses implement
|
|
blit_to_framebuffer, remove the conditional check from
|
|
meta_screen_cast_stream_src_blit_to_framebuffer().
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
src/backends/meta-screen-cast-stream-src.c | 5 +-
|
|
.../meta-screen-cast-window-stream-src.c | 21 +++++++
|
|
src/backends/meta-screen-cast-window.c | 11 ++++
|
|
src/backends/meta-screen-cast-window.h | 8 +++
|
|
src/compositor/meta-window-actor.c | 63 +++++++++++++++++++
|
|
5 files changed, 104 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index 0eb9f4d8c..6f7551ad4 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -149,10 +149,7 @@ meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
|
MetaScreenCastStreamSrcClass *klass =
|
|
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
|
|
|
- if (klass->blit_to_framebuffer)
|
|
- return klass->blit_to_framebuffer (src, framebuffer);
|
|
-
|
|
- return FALSE;
|
|
+ return klass->blit_to_framebuffer (src, framebuffer);
|
|
}
|
|
|
|
static void
|
|
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
|
|
index 210ea0807..3f9cab694 100644
|
|
--- a/src/backends/meta-screen-cast-window-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-window-stream-src.c
|
|
@@ -412,6 +412,25 @@ meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
|
return TRUE;
|
|
}
|
|
|
|
+static gboolean
|
|
+meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
|
+ CoglFramebuffer *framebuffer)
|
|
+{
|
|
+ MetaScreenCastWindowStreamSrc *window_src =
|
|
+ META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
|
+ MetaRectangle stream_rect;
|
|
+
|
|
+ stream_rect.x = 0;
|
|
+ stream_rect.y = 0;
|
|
+ stream_rect.width = get_stream_width (window_src);
|
|
+ stream_rect.height = get_stream_height (window_src);
|
|
+
|
|
+ return
|
|
+ meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
|
|
+ &stream_rect,
|
|
+ framebuffer);
|
|
+}
|
|
+
|
|
static void
|
|
meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
|
struct spa_meta_cursor *spa_meta_cursor)
|
|
@@ -496,6 +515,8 @@ meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClas
|
|
src_class->enable = meta_screen_cast_window_stream_src_enable;
|
|
src_class->disable = meta_screen_cast_window_stream_src_disable;
|
|
src_class->record_frame = meta_screen_cast_window_stream_src_record_frame;
|
|
+ src_class->blit_to_framebuffer =
|
|
+ meta_screen_cast_window_stream_src_blit_to_framebuffer;
|
|
src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop;
|
|
src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata;
|
|
}
|
|
diff --git a/src/backends/meta-screen-cast-window.c b/src/backends/meta-screen-cast-window.c
|
|
index 91515ded8..50b65a5df 100644
|
|
--- a/src/backends/meta-screen-cast-window.c
|
|
+++ b/src/backends/meta-screen-cast-window.c
|
|
@@ -78,6 +78,17 @@ meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window,
|
|
data);
|
|
}
|
|
|
|
+gboolean
|
|
+meta_screen_cast_window_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds,
|
|
+ CoglFramebuffer *framebuffer)
|
|
+{
|
|
+ MetaScreenCastWindowInterface *iface =
|
|
+ META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window);
|
|
+
|
|
+ return iface->blit_to_framebuffer (screen_cast_window, bounds, framebuffer);
|
|
+}
|
|
+
|
|
gboolean
|
|
meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window)
|
|
{
|
|
diff --git a/src/backends/meta-screen-cast-window.h b/src/backends/meta-screen-cast-window.h
|
|
index 69e5a34dc..45b681292 100644
|
|
--- a/src/backends/meta-screen-cast-window.h
|
|
+++ b/src/backends/meta-screen-cast-window.h
|
|
@@ -56,6 +56,10 @@ struct _MetaScreenCastWindowInterface
|
|
MetaRectangle *bounds,
|
|
uint8_t *data);
|
|
|
|
+ gboolean (*blit_to_framebuffer) (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds,
|
|
+ CoglFramebuffer *framebuffer);
|
|
+
|
|
gboolean (*has_damage) (MetaScreenCastWindow *screen_cast_window);
|
|
};
|
|
|
|
@@ -78,6 +82,10 @@ void meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_win
|
|
MetaRectangle *bounds,
|
|
uint8_t *data);
|
|
|
|
+gboolean meta_screen_cast_window_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds,
|
|
+ CoglFramebuffer *framebuffer);
|
|
+
|
|
gboolean meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window);
|
|
|
|
G_END_DECLS
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index 81eb04c84..a7dc25004 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -2025,6 +2025,68 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window,
|
|
cairo_surface_destroy (image);
|
|
}
|
|
|
|
+static gboolean
|
|
+meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
+ MetaRectangle *bounds,
|
|
+ CoglFramebuffer *framebuffer)
|
|
+{
|
|
+ MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
|
|
+ ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
|
+ MetaRectangle scaled_clip;
|
|
+ CoglColor clear_color;
|
|
+ float resource_scale;
|
|
+ float width, height;
|
|
+ float x, y;
|
|
+
|
|
+ if (meta_window_actor_is_destroyed (window_actor))
|
|
+ return FALSE;
|
|
+
|
|
+ clutter_actor_get_size (actor, &width, &height);
|
|
+
|
|
+ if (width == 0 || height == 0)
|
|
+ return FALSE;
|
|
+
|
|
+ if (!clutter_actor_get_resource_scale (actor, &resource_scale))
|
|
+ return FALSE;
|
|
+
|
|
+ width = ceilf (width * resource_scale);
|
|
+ height = ceilf (height * resource_scale);
|
|
+
|
|
+ cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
|
+ clutter_actor_get_position (actor, &x, &y);
|
|
+
|
|
+ cogl_framebuffer_push_matrix (framebuffer);
|
|
+
|
|
+ cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
|
|
+ cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0);
|
|
+ cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
|
|
+ cogl_framebuffer_translate (framebuffer, -x, -y, 0);
|
|
+
|
|
+ meta_rectangle_scale_double (bounds, resource_scale,
|
|
+ META_ROUNDING_STRATEGY_GROW,
|
|
+ &scaled_clip);
|
|
+ meta_rectangle_intersect (&scaled_clip,
|
|
+ &(MetaRectangle) {
|
|
+ .width = width,
|
|
+ .height = height,
|
|
+ },
|
|
+ &scaled_clip);
|
|
+
|
|
+ cogl_framebuffer_push_rectangle_clip (framebuffer,
|
|
+ scaled_clip.x, scaled_clip.y,
|
|
+ scaled_clip.x + scaled_clip.width,
|
|
+ scaled_clip.y + scaled_clip.height);
|
|
+
|
|
+ cogl_push_framebuffer (framebuffer);
|
|
+ clutter_actor_paint (actor);
|
|
+ cogl_pop_framebuffer ();
|
|
+
|
|
+ cogl_framebuffer_pop_clip (framebuffer);
|
|
+ cogl_framebuffer_pop_matrix (framebuffer);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static gboolean
|
|
meta_window_actor_has_damage (MetaScreenCastWindow *screen_cast_window)
|
|
{
|
|
@@ -2038,6 +2100,7 @@ screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface)
|
|
iface->transform_relative_position = meta_window_actor_transform_relative_position;
|
|
iface->transform_cursor_position = meta_window_actor_transform_cursor_position;
|
|
iface->capture_into = meta_window_actor_capture_into;
|
|
+ iface->blit_to_framebuffer = meta_window_actor_blit_to_framebuffer;
|
|
iface->has_damage = meta_window_actor_has_damage;
|
|
}
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From d005b89e4846aeaca01568865dd7d440f036c783 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 24 Feb 2020 14:14:07 -0300
|
|
Subject: [PATCH 31/49] screen-cast-stream-src: Remove unused parameter
|
|
|
|
The 'data' parameter is not used in maybe_record_cursor(), so remove
|
|
it.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
src/backends/meta-screen-cast-stream-src.c | 5 ++---
|
|
1 file changed, 2 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index 6f7551ad4..9c3657c75 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -389,8 +389,7 @@ add_cursor_metadata (MetaScreenCastStreamSrc *src,
|
|
|
|
static void
|
|
maybe_record_cursor (MetaScreenCastStreamSrc *src,
|
|
- struct spa_buffer *spa_buffer,
|
|
- uint8_t *data)
|
|
+ struct spa_buffer *spa_buffer)
|
|
{
|
|
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
|
|
|
@@ -505,7 +504,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
spa_buffer->datas[0].chunk->size = 0;
|
|
}
|
|
|
|
- maybe_record_cursor (src, spa_buffer, data);
|
|
+ maybe_record_cursor (src, spa_buffer);
|
|
|
|
priv->last_frame_timestamp_us = now_us;
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 0b8f27b4adf72ade1c8f5e958d9fcf31a9063d94 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Fri, 28 Feb 2020 15:47:23 -0300
|
|
Subject: [PATCH 32/49] monitor-stream-src: Use cogl_framebuffer_finish()
|
|
|
|
Even though cogl_framebuffer_flush() was supposed to be enough,
|
|
it ends up creating streams with odd visual glitches that look
|
|
very much like unfinished frames.
|
|
|
|
Switch back to cogl_framebuffer_finish(), which is admittedly
|
|
an overkill, but it's what works for now. There is anedoctal
|
|
evidence showing it doesn't incur in worse performance.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1086
|
|
---
|
|
src/backends/meta-screen-cast-monitor-stream-src.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
index 0c7d8ec17..af763dc09 100644
|
|
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
@@ -422,7 +422,7 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|
}
|
|
}
|
|
|
|
- cogl_framebuffer_flush (framebuffer);
|
|
+ cogl_framebuffer_finish (framebuffer);
|
|
|
|
return TRUE;
|
|
}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 1b9704405568f1a52168ce8c5267fe9a5ab1f789 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Mon, 9 Mar 2020 17:43:54 +0100
|
|
Subject: [PATCH 33/49] screen-cast-stream-src: Don't complain when we can't
|
|
dequeue buffer
|
|
|
|
PipeWire will be unable to dequeue a buffer if all are already busy.
|
|
This can happen for valid reasons, e.g. the stream consumer not being
|
|
fast enough, so don't complain in the journal if it happens.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1115
|
|
---
|
|
src/backends/meta-screen-cast-stream-src.c | 5 +----
|
|
1 file changed, 1 insertion(+), 4 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index 9c3657c75..170f34043 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -456,10 +456,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
|
|
buffer = pw_stream_dequeue_buffer (priv->pipewire_stream);
|
|
if (!buffer)
|
|
- {
|
|
- g_warning ("Failed to dequeue at PipeWire buffer");
|
|
- return;
|
|
- }
|
|
+ return;
|
|
|
|
spa_buffer = buffer->buffer;
|
|
data = spa_buffer->datas[0].data;
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 99a671e71cedcb3ef3093d0afcc823bfdd8eaf79 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 5 Mar 2020 23:29:26 +0100
|
|
Subject: [PATCH 34/49] screen-cast-stream-src: Don't leak GSource
|
|
|
|
For every stream src, we created and attached a GSource. Upon stream
|
|
src destruction, we g_source_destroy():ed the GSource. What
|
|
g_source_destroy() does, hawever, is not really "destroy" it but only
|
|
detaches it from the main context removing the reference the context had
|
|
added for it via g_source_attach(). This caused the GSource to leak,
|
|
although in a detached state, as the reference taken on creation was
|
|
still held.
|
|
|
|
Fix this by also removing our own reference to it when finalizing.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1106
|
|
---
|
|
src/backends/meta-screen-cast-stream-src.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index 170f34043..4f3d821ef 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -885,7 +885,7 @@ create_pipewire_source (void)
|
|
pipewire_source->pipewire_loop = pw_loop_new (NULL);
|
|
if (!pipewire_source->pipewire_loop)
|
|
{
|
|
- g_source_destroy ((GSource *) pipewire_source);
|
|
+ g_source_unref ((GSource *) pipewire_source);
|
|
return NULL;
|
|
}
|
|
|
|
@@ -980,6 +980,7 @@ meta_screen_cast_stream_src_finalize (GObject *object)
|
|
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
|
|
g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
|
|
g_source_destroy (&priv->pipewire_source->base);
|
|
+ g_source_unref (&priv->pipewire_source->base);
|
|
|
|
G_OBJECT_CLASS (meta_screen_cast_stream_src_parent_class)->finalize (object);
|
|
}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 6af35cad8bc09c291c29fffb08fe8ba3b76b779e Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 16 Mar 2020 19:47:30 -0300
|
|
Subject: [PATCH 35/49] window-actor: Shuffle some lines around
|
|
|
|
Move the CoglColor assignment right above the cogl_framebuffer_clear() call,
|
|
and let these wonderful partners together to delight us with an easier to
|
|
read code.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1129
|
|
---
|
|
src/compositor/meta-window-actor.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index a7dc25004..f90d2b0af 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -2052,11 +2052,11 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
width = ceilf (width * resource_scale);
|
|
height = ceilf (height * resource_scale);
|
|
|
|
- cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
|
clutter_actor_get_position (actor, &x, &y);
|
|
|
|
cogl_framebuffer_push_matrix (framebuffer);
|
|
|
|
+ cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
|
cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
|
|
cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0);
|
|
cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 4ecb19fffd37786d6b8efc3b05e7239bee49e763 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 16 Mar 2020 19:55:16 -0300
|
|
Subject: [PATCH 36/49] window-actor: Clip before translate when blitting
|
|
|
|
cogl_framebuffer_push_rectangle_clip() acts on the current modelview
|
|
matrix. That means the result of clipping then translating will be
|
|
different of the result of translating then clipping.
|
|
|
|
What we want for window screencasting is the former, not the latter.
|
|
Move the translation code (and associated) to after clipping.
|
|
|
|
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/1097
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1129
|
|
---
|
|
src/compositor/meta-window-actor.c | 10 +++++-----
|
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index f90d2b0af..c9ef5846a 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -2054,13 +2054,9 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
|
|
clutter_actor_get_position (actor, &x, &y);
|
|
|
|
- cogl_framebuffer_push_matrix (framebuffer);
|
|
-
|
|
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
|
cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
|
|
cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0);
|
|
- cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
|
|
- cogl_framebuffer_translate (framebuffer, -x, -y, 0);
|
|
|
|
meta_rectangle_scale_double (bounds, resource_scale,
|
|
META_ROUNDING_STRATEGY_GROW,
|
|
@@ -2077,12 +2073,16 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
scaled_clip.x + scaled_clip.width,
|
|
scaled_clip.y + scaled_clip.height);
|
|
|
|
+ cogl_framebuffer_push_matrix (framebuffer);
|
|
+ cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
|
|
+ cogl_framebuffer_translate (framebuffer, -x, -y, 0);
|
|
+
|
|
cogl_push_framebuffer (framebuffer);
|
|
clutter_actor_paint (actor);
|
|
cogl_pop_framebuffer ();
|
|
|
|
- cogl_framebuffer_pop_clip (framebuffer);
|
|
cogl_framebuffer_pop_matrix (framebuffer);
|
|
+ cogl_framebuffer_pop_clip (framebuffer);
|
|
|
|
return TRUE;
|
|
}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 14f76043aa912b186ecbce0e5dae46f521fec10f Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Tue, 17 Mar 2020 16:55:39 -0300
|
|
Subject: [PATCH 37/49] window-stream-src: Ensure initial frame is recorded
|
|
|
|
MetaScreenCastWindowStreamSrc connects to the "damaged" signal of
|
|
MetaWindowActor. This signal is not exactly tied to the paint cycle
|
|
of the stage, and a damage may take quite a while to arrive when
|
|
a client doesn't want to draw anything. For that reason, the window
|
|
screencast can start empty, waiting for a damage to arrive.
|
|
|
|
Ensure at least one frame is recorded when enabling the window stream.
|
|
|
|
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/1097
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1129
|
|
---
|
|
src/backends/meta-screen-cast-window-stream-src.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
|
|
index 3f9cab694..0e0907e82 100644
|
|
--- a/src/backends/meta-screen-cast-window-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-window-stream-src.c
|
|
@@ -389,6 +389,8 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
|
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
|
break;
|
|
}
|
|
+
|
|
+ meta_screen_cast_stream_src_maybe_record_frame (src);
|
|
}
|
|
|
|
static void
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 4c4324e21cc3739c6d0a384519f8b8a47d9d8216 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Tue, 17 Mar 2020 18:22:29 -0300
|
|
Subject: [PATCH 38/49] window-stream-src: Implement cursor blitting
|
|
|
|
A regression compared to the old code, we're not drawing the cursor
|
|
when on EMBEDDED mode.
|
|
|
|
Blit the cursor to the screencast framebuffer when on EMBEDDED mode.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1129
|
|
---
|
|
.../meta-screen-cast-window-stream-src.c | 81 ++++++++++++++++++-
|
|
1 file changed, 77 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
|
|
index 0e0907e82..87505b793 100644
|
|
--- a/src/backends/meta-screen-cast-window-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-window-stream-src.c
|
|
@@ -178,6 +178,65 @@ maybe_draw_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src,
|
|
cairo_surface_destroy (cursor_surface);
|
|
}
|
|
|
|
+static void
|
|
+maybe_blit_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src,
|
|
+ CoglFramebuffer *framebuffer,
|
|
+ MetaRectangle *stream_rect)
|
|
+{
|
|
+ MetaBackend *backend = get_backend (window_src);
|
|
+ CoglContext *cogl_context =
|
|
+ clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
+ MetaCursorRenderer *cursor_renderer =
|
|
+ meta_backend_get_cursor_renderer (backend);
|
|
+ MetaScreenCastWindow *screen_cast_window;
|
|
+ MetaCursorSprite *cursor_sprite;
|
|
+ ClutterPoint relative_cursor_position;
|
|
+ ClutterPoint cursor_position;
|
|
+ CoglTexture *cursor_texture;
|
|
+ CoglPipeline *pipeline;
|
|
+ int width, height;
|
|
+ float scale;
|
|
+ int hotspot_x, hotspot_y;
|
|
+ float x, y;
|
|
+
|
|
+ cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
|
|
+ if (!cursor_sprite)
|
|
+ return;
|
|
+
|
|
+ cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
|
+ if (!cursor_texture)
|
|
+ return;
|
|
+
|
|
+ screen_cast_window = window_src->screen_cast_window;
|
|
+ cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
|
+ if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window,
|
|
+ cursor_sprite,
|
|
+ &cursor_position,
|
|
+ &scale,
|
|
+ &relative_cursor_position))
|
|
+ return;
|
|
+
|
|
+ meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y);
|
|
+
|
|
+ x = (relative_cursor_position.x - hotspot_x) * scale;
|
|
+ y = (relative_cursor_position.y - hotspot_y) * scale;
|
|
+ width = cogl_texture_get_width (cursor_texture);
|
|
+ height = cogl_texture_get_height (cursor_texture);
|
|
+
|
|
+ pipeline = cogl_pipeline_new (cogl_context);
|
|
+ cogl_pipeline_set_layer_texture (pipeline, 0, cursor_texture);
|
|
+ cogl_pipeline_set_layer_filters (pipeline, 0,
|
|
+ COGL_PIPELINE_FILTER_LINEAR,
|
|
+ COGL_PIPELINE_FILTER_LINEAR);
|
|
+
|
|
+ cogl_framebuffer_draw_rectangle (framebuffer,
|
|
+ pipeline,
|
|
+ x, y,
|
|
+ x + width, y + height);
|
|
+
|
|
+ cogl_object_unref (pipeline);
|
|
+}
|
|
+
|
|
static gboolean
|
|
capture_into (MetaScreenCastWindowStreamSrc *window_src,
|
|
uint8_t *data)
|
|
@@ -420,6 +479,7 @@ meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|
{
|
|
MetaScreenCastWindowStreamSrc *window_src =
|
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
|
+ MetaScreenCastStream *stream;
|
|
MetaRectangle stream_rect;
|
|
|
|
stream_rect.x = 0;
|
|
@@ -427,10 +487,23 @@ meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|
stream_rect.width = get_stream_width (window_src);
|
|
stream_rect.height = get_stream_height (window_src);
|
|
|
|
- return
|
|
- meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
|
|
- &stream_rect,
|
|
- framebuffer);
|
|
+ if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
|
|
+ &stream_rect,
|
|
+ framebuffer))
|
|
+ return FALSE;
|
|
+
|
|
+ stream = meta_screen_cast_stream_src_get_stream (src);
|
|
+ switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
|
+ {
|
|
+ case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
|
|
+ maybe_blit_cursor_sprite (window_src, framebuffer, &stream_rect);
|
|
+ break;
|
|
+ case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
|
+ case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
}
|
|
|
|
static void
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From f454e95162dd44feb1581b52521c637b378aa3bd Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Mon, 16 Mar 2020 19:31:25 -0300
|
|
Subject: [PATCH 39/49] window-stream-src: Finish framebuffer after blitting
|
|
|
|
Just like what's done for monitor screencasting. Unfortunately, there's
|
|
no mechanism to share fences with PipeWire clients yet, which forces
|
|
us to guarantee that a frame is completed after blitting.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1129
|
|
---
|
|
src/backends/meta-screen-cast-window-stream-src.c | 2 ++
|
|
1 file changed, 2 insertions(+)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
|
|
index 87505b793..c252b4356 100644
|
|
--- a/src/backends/meta-screen-cast-window-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-window-stream-src.c
|
|
@@ -503,6 +503,8 @@ meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|
break;
|
|
}
|
|
|
|
+ cogl_framebuffer_finish (framebuffer);
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 3658b9f61921b6568913966be5bd28ceb111c23b Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Wed, 18 Mar 2020 21:12:26 -0300
|
|
Subject: [PATCH 40/49] clutter/actor: Add culling inhibiting API
|
|
|
|
This will allow us to continue painting actors that are
|
|
outside the visible boundaries of the stage view.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1129
|
|
---
|
|
clutter/clutter/clutter-actor.c | 64 ++++++++++++++++++++++++++++++++-
|
|
clutter/clutter/clutter-actor.h | 5 +++
|
|
2 files changed, 68 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
|
|
index 803f76aae..77a61ae1a 100644
|
|
--- a/clutter/clutter/clutter-actor.c
|
|
+++ b/clutter/clutter/clutter-actor.c
|
|
@@ -703,6 +703,7 @@ struct _ClutterActorPrivate
|
|
|
|
guint8 opacity;
|
|
gint opacity_override;
|
|
+ unsigned int inhibit_culling_counter;
|
|
|
|
ClutterOffscreenRedirect offscreen_redirect;
|
|
|
|
@@ -3824,6 +3825,7 @@ clutter_actor_paint (ClutterActor *self)
|
|
{
|
|
ClutterActorPrivate *priv;
|
|
ClutterPickMode pick_mode;
|
|
+ gboolean culling_inhibited;
|
|
gboolean clip_set = FALSE;
|
|
ClutterStage *stage;
|
|
|
|
@@ -3973,7 +3975,10 @@ clutter_actor_paint (ClutterActor *self)
|
|
* paint then the last-paint-volume would likely represent the new
|
|
* actor position not the old.
|
|
*/
|
|
- if (!in_clone_paint () && pick_mode == CLUTTER_PICK_NONE)
|
|
+ culling_inhibited = priv->inhibit_culling_counter > 0;
|
|
+ if (!culling_inhibited &&
|
|
+ !in_clone_paint () &&
|
|
+ pick_mode == CLUTTER_PICK_NONE)
|
|
{
|
|
gboolean success;
|
|
/* annoyingly gcc warns if uninitialized even though
|
|
@@ -16014,6 +16019,63 @@ clutter_actor_get_opacity_override (ClutterActor *self)
|
|
return self->priv->opacity_override;
|
|
}
|
|
|
|
+/**
|
|
+ * clutter_actor_inhibit_culling:
|
|
+ * @actor: a #ClutterActor
|
|
+ *
|
|
+ * Increases the culling inhibitor counter. Inhibiting culling
|
|
+ * forces the actor to be painted even when outside the visible
|
|
+ * bounds of the stage view.
|
|
+ *
|
|
+ * This is usually necessary when an actor is being painted on
|
|
+ * another paint context.
|
|
+ *
|
|
+ * Pair with clutter_actor_uninhibit_culling() when the actor doesn't
|
|
+ * need to be painted anymore.
|
|
+ */
|
|
+void
|
|
+clutter_actor_inhibit_culling (ClutterActor *actor)
|
|
+{
|
|
+ ClutterActorPrivate *priv;
|
|
+
|
|
+ g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
|
+
|
|
+ priv = actor->priv;
|
|
+
|
|
+ priv->inhibit_culling_counter++;
|
|
+ _clutter_actor_set_enable_paint_unmapped (actor, TRUE);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * clutter_actor_uninhibit_culling:
|
|
+ * @actor: a #ClutterActor
|
|
+ *
|
|
+ * Decreases the culling inhibitor counter. See clutter_actor_inhibit_culling()
|
|
+ * for when inhibit culling is necessary.
|
|
+ *
|
|
+ * Calling this function without a matching call to
|
|
+ * clutter_actor_inhibit_culling() is a programming error.
|
|
+ */
|
|
+void
|
|
+clutter_actor_uninhibit_culling (ClutterActor *actor)
|
|
+{
|
|
+ ClutterActorPrivate *priv;
|
|
+
|
|
+ g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
|
+
|
|
+ priv = actor->priv;
|
|
+
|
|
+ if (priv->inhibit_culling_counter == 0)
|
|
+ {
|
|
+ g_critical ("Unpaired call to clutter_actor_uninhibit_culling");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ priv->inhibit_culling_counter--;
|
|
+ if (priv->inhibit_culling_counter == 0)
|
|
+ _clutter_actor_set_enable_paint_unmapped (actor, FALSE);
|
|
+}
|
|
+
|
|
/* Allows you to disable applying the actors model view transform during
|
|
* a paint. Used by ClutterClone. */
|
|
void
|
|
diff --git a/clutter/clutter/clutter-actor.h b/clutter/clutter/clutter-actor.h
|
|
index 7d2168af1..f6e0acbb2 100644
|
|
--- a/clutter/clutter/clutter-actor.h
|
|
+++ b/clutter/clutter/clutter-actor.h
|
|
@@ -870,6 +870,11 @@ void clutter_actor_set_opacity_override
|
|
CLUTTER_EXPORT
|
|
gint clutter_actor_get_opacity_override (ClutterActor *self);
|
|
|
|
+CLUTTER_EXPORT
|
|
+void clutter_actor_inhibit_culling (ClutterActor *actor);
|
|
+CLUTTER_EXPORT
|
|
+void clutter_actor_uninhibit_culling (ClutterActor *actor);
|
|
+
|
|
/**
|
|
* ClutterActorCreateChildFunc:
|
|
* @item: (type GObject): the item in the model
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 471c6d372bd9e1a79cf10e46fb8cbc4c110d1da6 Mon Sep 17 00:00:00 2001
|
|
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
Date: Wed, 18 Mar 2020 21:14:58 -0300
|
|
Subject: [PATCH 41/49] window-actor: Inhibit culling when blitting to
|
|
screencast
|
|
|
|
This allows us to screencast any window continuously, even
|
|
without it being visible. Because it's still being painted,
|
|
clients continue to receive frame callbacks, and people
|
|
are happy again.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/merge_requests/1129
|
|
---
|
|
src/compositor/meta-window-actor.c | 21 +++++++++++++++------
|
|
1 file changed, 15 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index c9ef5846a..08d1b0a87 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -2049,6 +2049,8 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
if (!clutter_actor_get_resource_scale (actor, &resource_scale))
|
|
return FALSE;
|
|
|
|
+ clutter_actor_inhibit_culling (actor);
|
|
+
|
|
width = ceilf (width * resource_scale);
|
|
height = ceilf (height * resource_scale);
|
|
|
|
@@ -2084,6 +2086,8 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
cogl_framebuffer_pop_matrix (framebuffer);
|
|
cogl_framebuffer_pop_clip (framebuffer);
|
|
|
|
+ clutter_actor_uninhibit_culling (actor);
|
|
+
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -2151,33 +2155,36 @@ meta_window_actor_get_image (MetaWindowActor *self,
|
|
CoglColor clear_color;
|
|
float x, y;
|
|
MetaRectangle scaled_clip;
|
|
- cairo_surface_t *surface;
|
|
+ cairo_surface_t *surface = NULL;
|
|
|
|
if (!priv->surface)
|
|
return NULL;
|
|
|
|
+ clutter_actor_inhibit_culling (actor);
|
|
+
|
|
if (clutter_actor_get_n_children (actor) == 1)
|
|
{
|
|
MetaShapedTexture *stex;
|
|
|
|
stex = meta_surface_actor_get_texture (priv->surface);
|
|
- return meta_shaped_texture_get_image (stex, clip);
|
|
+ surface = meta_shaped_texture_get_image (stex, clip);
|
|
+ goto out;
|
|
}
|
|
|
|
clutter_actor_get_size (actor, &width, &height);
|
|
|
|
if (width == 0 || height == 0)
|
|
- return NULL;
|
|
+ goto out;
|
|
|
|
if (!clutter_actor_get_resource_scale (actor, &resource_scale))
|
|
- return NULL;
|
|
+ goto out;
|
|
|
|
width = ceilf (width * resource_scale);
|
|
height = ceilf (height * resource_scale);
|
|
|
|
texture = cogl_texture_2d_new_with_size (cogl_context, width, height);
|
|
if (!texture)
|
|
- return NULL;
|
|
+ goto out;
|
|
|
|
cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture),
|
|
FALSE);
|
|
@@ -2193,7 +2200,7 @@ meta_window_actor_get_image (MetaWindowActor *self,
|
|
error->message);
|
|
cogl_object_unref (framebuffer);
|
|
cogl_object_unref (texture);
|
|
- return NULL;
|
|
+ goto out;
|
|
}
|
|
|
|
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
|
@@ -2242,5 +2249,7 @@ meta_window_actor_get_image (MetaWindowActor *self,
|
|
|
|
cairo_surface_mark_dirty (surface);
|
|
|
|
+out:
|
|
+ clutter_actor_uninhibit_culling (actor);
|
|
return surface;
|
|
}
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From f29763e93ddf7933bd5ea3d2cd5769683b9e312b Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Mon, 18 May 2020 17:52:09 +0200
|
|
Subject: [PATCH 42/49] screen-cast/monitor-src: Get views from the stage
|
|
|
|
Otherwise we don't get the views when in the X11 session.
|
|
---
|
|
clutter/clutter/clutter-mutter.h | 3 +++
|
|
clutter/clutter/clutter-stage-private.h | 2 --
|
|
src/backends/meta-screen-cast-monitor-stream-src.c | 4 ++--
|
|
3 files changed, 5 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h
|
|
index a53080457..6137605d4 100644
|
|
--- a/clutter/clutter/clutter-mutter.h
|
|
+++ b/clutter/clutter/clutter-mutter.h
|
|
@@ -55,6 +55,9 @@ void clutter_stage_update_resource_scales (ClutterStage *stage);
|
|
CLUTTER_EXPORT
|
|
gboolean clutter_actor_has_damage (ClutterActor *actor);
|
|
|
|
+CLUTTER_EXPORT
|
|
+GList *_clutter_stage_peek_stage_views (ClutterStage *stage);
|
|
+
|
|
#undef __CLUTTER_H_INSIDE__
|
|
|
|
#endif /* __CLUTTER_MUTTER_H__ */
|
|
diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h
|
|
index df0bf642b..42474687a 100644
|
|
--- a/clutter/clutter/clutter-stage-private.h
|
|
+++ b/clutter/clutter/clutter-stage-private.h
|
|
@@ -133,8 +133,6 @@ void _clutter_stage_presented (ClutterStage *stag
|
|
CoglFrameEvent frame_event,
|
|
ClutterFrameInfo *frame_info);
|
|
|
|
-GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
|
|
-
|
|
G_END_DECLS
|
|
|
|
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|
|
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
index af763dc09..655b68261 100644
|
|
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
|
|
@@ -374,7 +374,7 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
|
MetaBackend *backend = get_backend (monitor_src);
|
|
- MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
|
+ ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
|
MetaMonitor *monitor;
|
|
MetaLogicalMonitor *logical_monitor;
|
|
MetaRectangle logical_monitor_layout;
|
|
@@ -390,7 +390,7 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|
else
|
|
view_scale = 1.0;
|
|
|
|
- for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
|
+ for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
|
|
{
|
|
ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data);
|
|
g_autoptr (GError) error = NULL;
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From d6d401f74452e7eb2f2ac0272b30603782ea95c8 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 12 May 2020 08:52:01 +0200
|
|
Subject: [PATCH 43/49] screen-cast-stream-src: Don't throttle if max framerate
|
|
is 1/0
|
|
|
|
The max framerate 1/0 means variable without any particular max, so
|
|
don't throttle if that was set.
|
|
|
|
Not doing this would end up with a floating point exception.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1251
|
|
---
|
|
src/backends/meta-screen-cast-stream-src.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index 4f3d821ef..ad0d9ed79 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -445,7 +445,8 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|
uint64_t now_us;
|
|
|
|
now_us = g_get_monotonic_time ();
|
|
- if (priv->last_frame_timestamp_us != 0 &&
|
|
+ if (priv->video_format.max_framerate.num > 0 &&
|
|
+ priv->last_frame_timestamp_us != 0 &&
|
|
(now_us - priv->last_frame_timestamp_us <
|
|
((1000000 * priv->video_format.max_framerate.denom) /
|
|
priv->video_format.max_framerate.num)))
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 0e00b9b3516362009c671cfd62dd32dc9691e647 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 12 May 2020 16:14:00 +0200
|
|
Subject: [PATCH 44/49] screen-cast-src: Notify that about the stream being
|
|
closed on idle
|
|
|
|
We're iterating inside the PipeWire loop when detecting PipeWire errors,
|
|
and shouldn't destroy the PipeWire objects mid-iteration. Avoid this by
|
|
first disabling the stream src (effectively stopping the recording),
|
|
then notifying about it being closed in an idle callback. The
|
|
notification eventually makes the rest of the screen cast code clean up
|
|
the objects, including the src and the associated PipeWire objects, but
|
|
will do so outside the PipeWire loop iteration.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1251
|
|
---
|
|
src/backends/meta-screen-cast-stream-src.c | 20 ++++++++++++++++----
|
|
1 file changed, 16 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
|
|
index ad0d9ed79..0500bfec5 100644
|
|
--- a/src/backends/meta-screen-cast-stream-src.c
|
|
+++ b/src/backends/meta-screen-cast-stream-src.c
|
|
@@ -540,10 +540,16 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|
priv->is_enabled = FALSE;
|
|
}
|
|
|
|
-static void
|
|
-meta_screen_cast_stream_src_notify_closed (MetaScreenCastStreamSrc *src)
|
|
+static gboolean
|
|
+notify_stream_src_closed_idle (gpointer user_data)
|
|
{
|
|
+ MetaScreenCastStreamSrc *src = user_data;
|
|
+
|
|
g_signal_emit (src, signals[CLOSED], 0);
|
|
+
|
|
+ g_object_unref (src);
|
|
+
|
|
+ return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static void
|
|
@@ -560,7 +566,9 @@ on_stream_state_changed (void *data,
|
|
{
|
|
case PW_STREAM_STATE_ERROR:
|
|
g_warning ("pipewire stream error: %s", error_message);
|
|
- meta_screen_cast_stream_src_notify_closed (src);
|
|
+ if (meta_screen_cast_stream_src_is_enabled (src))
|
|
+ meta_screen_cast_stream_src_disable (src);
|
|
+ g_idle_add (notify_stream_src_closed_idle, g_object_ref (src));
|
|
break;
|
|
case PW_STREAM_STATE_PAUSED:
|
|
if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
|
|
@@ -832,7 +840,11 @@ on_core_error (void *data,
|
|
g_warning ("pipewire remote error: id:%u %s", id, message);
|
|
|
|
if (id == PW_ID_CORE && res == -EPIPE)
|
|
- meta_screen_cast_stream_src_notify_closed (src);
|
|
+ {
|
|
+ if (meta_screen_cast_stream_src_is_enabled (src))
|
|
+ meta_screen_cast_stream_src_disable (src);
|
|
+ g_idle_add (notify_stream_src_closed_idle, g_object_ref (src));
|
|
+ }
|
|
}
|
|
|
|
static gboolean
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 788a6f4adea0f976598014744149fb78feac145d Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Mon, 18 May 2020 19:10:49 +0200
|
|
Subject: [PATCH 45/49] compositor: Only check for stereo when using GLX
|
|
|
|
If EGL Xlib is used, we'll get bogus return value and crash.
|
|
---
|
|
src/compositor/compositor.c | 8 ++++++++
|
|
1 file changed, 8 insertions(+)
|
|
|
|
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
|
|
index 6c08c8fe4..a6ae55abb 100644
|
|
--- a/src/compositor/compositor.c
|
|
+++ b/src/compositor/compositor.c
|
|
@@ -534,9 +534,17 @@ typedef struct {
|
|
static gboolean
|
|
display_has_stereo_tree_ext (MetaX11Display *x11_display)
|
|
{
|
|
+ MetaBackend *backend = meta_get_backend ();
|
|
+ ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
|
+ CoglContext *cogl_context =
|
|
+ clutter_backend_get_cogl_context (clutter_backend);
|
|
+ CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context);
|
|
Display *xdisplay = x11_display->xdisplay;
|
|
const char *extensions_string;
|
|
|
|
+ if (cogl_renderer_get_winsys_id (cogl_renderer) != COGL_WINSYS_ID_GLX)
|
|
+ return FALSE;
|
|
+
|
|
static const char * (*query_extensions_string) (Display *display,
|
|
int screen);
|
|
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 1aa9d081b69dc8ce7948a2189bd6ca0dd4c9611b Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Fri, 3 Apr 2020 17:12:58 +0200
|
|
Subject: [PATCH 46/49] window-actor: Set viewport when blitting to screencast
|
|
fb
|
|
|
|
This fixes an issue where a non-maximized screen casted window would be
|
|
stretched to fill the whole screen cast stream, instead of just the crop
|
|
that corresponds to the current window size.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1174
|
|
---
|
|
src/compositor/meta-window-actor.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
|
|
index 08d1b0a87..1167acfa5 100644
|
|
--- a/src/compositor/meta-window-actor.c
|
|
+++ b/src/compositor/meta-window-actor.c
|
|
@@ -2059,6 +2059,7 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
|
cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
|
|
cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0);
|
|
+ cogl_framebuffer_set_viewport (framebuffer, 0, 0, width, height);
|
|
|
|
meta_rectangle_scale_double (bounds, resource_scale,
|
|
META_ROUNDING_STRATEGY_GROW,
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 289cad91ac820b7280485603865d3060b5f84cf8 Mon Sep 17 00:00:00 2001
|
|
From: Carlos Garnacho <carlosg@gnome.org>
|
|
Date: Sat, 16 May 2020 10:44:04 +0200
|
|
Subject: [PATCH 47/49] backends: Ensure remote desktop dbus interface state
|
|
|
|
Ensure that it does receive Start and Stop orderly, and error out
|
|
otherwise.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1258
|
|
---
|
|
src/backends/meta-remote-desktop-session.c | 22 +++++++++++++++++++++-
|
|
1 file changed, 21 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/backends/meta-remote-desktop-session.c b/src/backends/meta-remote-desktop-session.c
|
|
index f069cba2f..8d53dc41c 100644
|
|
--- a/src/backends/meta-remote-desktop-session.c
|
|
+++ b/src/backends/meta-remote-desktop-session.c
|
|
@@ -56,6 +56,7 @@ struct _MetaRemoteDesktopSession
|
|
|
|
MetaScreenCastSession *screen_cast_session;
|
|
gulong screen_cast_session_closed_handler_id;
|
|
+ guint started : 1;
|
|
|
|
ClutterVirtualInputDevice *virtual_pointer;
|
|
ClutterVirtualInputDevice *virtual_keyboard;
|
|
@@ -120,7 +121,7 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
|
ClutterDeviceManager *device_manager =
|
|
clutter_device_manager_get_default ();
|
|
|
|
- g_assert (!session->virtual_pointer && !session->virtual_keyboard);
|
|
+ g_assert (!session->started);
|
|
|
|
if (session->screen_cast_session)
|
|
{
|
|
@@ -140,6 +141,7 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
|
CLUTTER_TOUCHSCREEN_DEVICE);
|
|
|
|
init_remote_access_handle (session);
|
|
+ session->started = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
@@ -150,6 +152,8 @@ meta_remote_desktop_session_close (MetaRemoteDesktopSession *session)
|
|
MetaDBusRemoteDesktopSession *skeleton =
|
|
META_DBUS_REMOTE_DESKTOP_SESSION (session);
|
|
|
|
+ session->started = FALSE;
|
|
+
|
|
if (session->screen_cast_session)
|
|
{
|
|
g_signal_handler_disconnect (session->screen_cast_session,
|
|
@@ -261,6 +265,14 @@ handle_start (MetaDBusRemoteDesktopSession *skeleton,
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
GError *error = NULL;
|
|
|
|
+ if (session->started)
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_FAILED,
|
|
+ "Already started");
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
if (!check_permission (session, invocation))
|
|
{
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
@@ -293,6 +305,14 @@ handle_stop (MetaDBusRemoteDesktopSession *skeleton,
|
|
{
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
+ if (!session->started)
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_FAILED,
|
|
+ "Session not started");
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
if (!check_permission (session, invocation))
|
|
{
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From ccbfc529a11e52a27e8d6751753e82e55319e3c8 Mon Sep 17 00:00:00 2001
|
|
From: Carlos Garnacho <carlosg@gnome.org>
|
|
Date: Sat, 16 May 2020 10:46:57 +0200
|
|
Subject: [PATCH 48/49] backends: Make uniform checks on remote desktop input
|
|
dbus methods
|
|
|
|
They all checked that the remote session service talked with the
|
|
correct peer, and some of them did check that there is an associated
|
|
screencast session.
|
|
|
|
Add a new check for the session being started (as it's state is
|
|
decoupled with screencast session availability) and move all checks
|
|
to a function that is called from all input-oriented DBus methods.
|
|
|
|
Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1254
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1258
|
|
---
|
|
src/backends/meta-remote-desktop-session.c | 145 ++++++++-------------
|
|
1 file changed, 51 insertions(+), 94 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-remote-desktop-session.c b/src/backends/meta-remote-desktop-session.c
|
|
index 8d53dc41c..59057fc70 100644
|
|
--- a/src/backends/meta-remote-desktop-session.c
|
|
+++ b/src/backends/meta-remote-desktop-session.c
|
|
@@ -258,6 +258,37 @@ check_permission (MetaRemoteDesktopSession *session,
|
|
g_dbus_method_invocation_get_sender (invocation)) == 0;
|
|
}
|
|
|
|
+static gboolean
|
|
+meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
|
|
+ GDBusMethodInvocation *invocation)
|
|
+{
|
|
+ if (!session->started)
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_FAILED,
|
|
+ "Session not started");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ if (!check_permission (session, invocation))
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_ACCESS_DENIED,
|
|
+ "Permission denied");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ if (!session->screen_cast_session)
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_FAILED,
|
|
+ "No screen cast active");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static gboolean
|
|
handle_start (MetaDBusRemoteDesktopSession *skeleton,
|
|
GDBusMethodInvocation *invocation)
|
|
@@ -337,13 +368,8 @@ handle_notify_keyboard_keycode (MetaDBusRemoteDesktopSession *skeleton,
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
ClutterKeyState state;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
if (pressed)
|
|
state = CLUTTER_KEY_STATE_PRESSED;
|
|
@@ -369,13 +395,8 @@ handle_notify_keyboard_keysym (MetaDBusRemoteDesktopSession *skeleton,
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
ClutterKeyState state;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
if (pressed)
|
|
state = CLUTTER_KEY_STATE_PRESSED;
|
|
@@ -423,13 +444,8 @@ handle_notify_pointer_button (MetaDBusRemoteDesktopSession *skeleton,
|
|
uint32_t button;
|
|
ClutterButtonState state;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
button = translate_to_clutter_button (button_code);
|
|
|
|
@@ -459,13 +475,8 @@ handle_notify_pointer_axis (MetaDBusRemoteDesktopSession *skeleton,
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH)
|
|
{
|
|
@@ -512,13 +523,8 @@ handle_notify_pointer_axis_discrete (MetaDBusRemoteDesktopSession *skeleton,
|
|
ClutterScrollDirection direction;
|
|
int step_count;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
if (axis > 1)
|
|
{
|
|
@@ -563,13 +569,8 @@ handle_notify_pointer_motion_relative (MetaDBusRemoteDesktopSession *skeleton,
|
|
{
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer,
|
|
CLUTTER_CURRENT_TIME,
|
|
@@ -592,21 +593,8 @@ handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
|
|
MetaScreenCastStream *stream;
|
|
double abs_x, abs_y;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
-
|
|
- if (!session->screen_cast_session)
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_FAILED,
|
|
- "No screen cast active");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
|
stream_path);
|
|
@@ -642,21 +630,8 @@ handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
|
|
MetaScreenCastStream *stream;
|
|
double abs_x, abs_y;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
-
|
|
- if (!session->screen_cast_session)
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_FAILED,
|
|
- "No screen cast active");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
|
stream_path);
|
|
@@ -693,21 +668,8 @@ handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
|
|
MetaScreenCastStream *stream;
|
|
double abs_x, abs_y;
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
-
|
|
- if (!session->screen_cast_session)
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_FAILED,
|
|
- "No screen cast active");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
|
stream_path);
|
|
@@ -739,13 +701,8 @@ handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton,
|
|
{
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
- if (!check_permission (session, invocation))
|
|
- {
|
|
- g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
- G_DBUS_ERROR_ACCESS_DENIED,
|
|
- "Permission denied");
|
|
- return TRUE;
|
|
- }
|
|
+ if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
+ return TRUE;
|
|
|
|
clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen,
|
|
CLUTTER_CURRENT_TIME,
|
|
--
|
|
2.26.2
|
|
|
|
|
|
From 519c86b833f57286e51f2a1514003e9e3461bd7e Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 21 Apr 2020 15:44:32 +0200
|
|
Subject: [PATCH 49/49] remote-access-controller: Allow inhibiting remote
|
|
access
|
|
|
|
Inhibiting remote access means any current remote access session is
|
|
terminated, and no new ones can be created, until remote access is
|
|
uninhibited. The inhibitation is ref counted, meaning there can be more
|
|
than one inhibitor.
|
|
|
|
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1212
|
|
(cherry picked from commit 4300f1f91d726051893146d7b294d8852782f137)
|
|
---
|
|
src/backends/meta-backend-types.h | 1 +
|
|
src/backends/meta-backend.c | 4 +-
|
|
.../meta-remote-access-controller-private.h | 4 ++
|
|
src/backends/meta-remote-access-controller.c | 49 +++++++++++++++++++
|
|
src/backends/meta-remote-desktop.c | 39 +++++++++++++++
|
|
src/backends/meta-remote-desktop.h | 4 ++
|
|
src/backends/meta-screen-cast.c | 34 +++++++++++++
|
|
src/backends/meta-screen-cast.h | 4 ++
|
|
src/meta/meta-remote-access-controller.h | 6 +++
|
|
9 files changed, 143 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/backends/meta-backend-types.h b/src/backends/meta-backend-types.h
|
|
index eb982d73e..98cac8b9e 100644
|
|
--- a/src/backends/meta-backend-types.h
|
|
+++ b/src/backends/meta-backend-types.h
|
|
@@ -49,6 +49,7 @@ typedef struct _MetaTileInfo MetaTileInfo;
|
|
typedef struct _MetaRenderer MetaRenderer;
|
|
typedef struct _MetaRendererView MetaRendererView;
|
|
|
|
+typedef struct _MetaRemoteDesktop MetaRemoteDesktop;
|
|
typedef struct _MetaScreenCast MetaScreenCast;
|
|
typedef struct _MetaScreenCastSession MetaScreenCastSession;
|
|
typedef struct _MetaScreenCastStream MetaScreenCastStream;
|
|
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
|
|
index 72cfbdaf3..750a9248a 100644
|
|
--- a/src/backends/meta-backend.c
|
|
+++ b/src/backends/meta-backend.c
|
|
@@ -501,12 +501,12 @@ meta_backend_real_post_init (MetaBackend *backend)
|
|
priv->input_settings = meta_backend_create_input_settings (backend);
|
|
|
|
#ifdef HAVE_REMOTE_DESKTOP
|
|
- priv->remote_access_controller =
|
|
- g_object_new (META_TYPE_REMOTE_ACCESS_CONTROLLER, NULL);
|
|
priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL);
|
|
priv->screen_cast = meta_screen_cast_new (backend,
|
|
priv->dbus_session_watcher);
|
|
priv->remote_desktop = meta_remote_desktop_new (priv->dbus_session_watcher);
|
|
+ priv->remote_access_controller =
|
|
+ meta_remote_access_controller_new (priv->remote_desktop, priv->screen_cast);
|
|
#endif /* HAVE_REMOTE_DESKTOP */
|
|
|
|
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
|
|
diff --git a/src/backends/meta-remote-access-controller-private.h b/src/backends/meta-remote-access-controller-private.h
|
|
index fce2082bf..444b71a77 100644
|
|
--- a/src/backends/meta-remote-access-controller-private.h
|
|
+++ b/src/backends/meta-remote-access-controller-private.h
|
|
@@ -21,8 +21,12 @@
|
|
#ifndef META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H
|
|
#define META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H
|
|
|
|
+#include "backends/meta-backend-types.h"
|
|
#include "meta/meta-remote-access-controller.h"
|
|
|
|
+MetaRemoteAccessController * meta_remote_access_controller_new (MetaRemoteDesktop *remote_desktop,
|
|
+ MetaScreenCast *screen_cast);
|
|
+
|
|
void meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *controller,
|
|
MetaRemoteAccessHandle *handle);
|
|
|
|
diff --git a/src/backends/meta-remote-access-controller.c b/src/backends/meta-remote-access-controller.c
|
|
index 0e0ebe2bd..e5ae0b5bd 100644
|
|
--- a/src/backends/meta-remote-access-controller.c
|
|
+++ b/src/backends/meta-remote-access-controller.c
|
|
@@ -22,6 +22,9 @@
|
|
|
|
#include "backends/meta-remote-access-controller-private.h"
|
|
|
|
+#include "backends/meta-remote-desktop.h"
|
|
+#include "backends/meta-screen-cast.h"
|
|
+
|
|
enum
|
|
{
|
|
HANDLE_STOPPED,
|
|
@@ -52,6 +55,9 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaRemoteAccessHandle,
|
|
struct _MetaRemoteAccessController
|
|
{
|
|
GObject parent;
|
|
+
|
|
+ MetaRemoteDesktop *remote_desktop;
|
|
+ MetaScreenCast *screen_cast;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaRemoteAccessController,
|
|
@@ -94,6 +100,49 @@ meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *con
|
|
handle);
|
|
}
|
|
|
|
+/**
|
|
+ * meta_remote_access_controller_inhibit_remote_access:
|
|
+ * @controller: a #MetaRemoteAccessController
|
|
+ *
|
|
+ * Inhibits remote access sessions from being created and running. Any active
|
|
+ * remote access session will be terminated.
|
|
+ */
|
|
+void
|
|
+meta_remote_access_controller_inhibit_remote_access (MetaRemoteAccessController *controller)
|
|
+{
|
|
+ meta_remote_desktop_inhibit (controller->remote_desktop);
|
|
+ meta_screen_cast_inhibit (controller->screen_cast);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * meta_remote_access_controller_uninhibit_remote_access:
|
|
+ * @controller: a #MetaRemoteAccessController
|
|
+ *
|
|
+ * Uninhibits remote access sessions from being created and running. If this was
|
|
+ * the last inhibitation that was inhibited, new remote access sessions can now
|
|
+ * be created.
|
|
+ */
|
|
+void
|
|
+meta_remote_access_controller_uninhibit_remote_access (MetaRemoteAccessController *controller)
|
|
+{
|
|
+ meta_screen_cast_uninhibit (controller->screen_cast);
|
|
+ meta_remote_desktop_uninhibit (controller->remote_desktop);
|
|
+}
|
|
+
|
|
+MetaRemoteAccessController *
|
|
+meta_remote_access_controller_new (MetaRemoteDesktop *remote_desktop,
|
|
+ MetaScreenCast *screen_cast)
|
|
+{
|
|
+ MetaRemoteAccessController *remote_access_controller;
|
|
+
|
|
+ remote_access_controller = g_object_new (META_TYPE_REMOTE_ACCESS_CONTROLLER,
|
|
+ NULL);
|
|
+ remote_access_controller->remote_desktop = remote_desktop;
|
|
+ remote_access_controller->screen_cast = screen_cast;
|
|
+
|
|
+ return remote_access_controller;
|
|
+}
|
|
+
|
|
static void
|
|
meta_remote_access_handle_init (MetaRemoteAccessHandle *handle)
|
|
{
|
|
diff --git a/src/backends/meta-remote-desktop.c b/src/backends/meta-remote-desktop.c
|
|
index d741dccd8..6d87d755b 100644
|
|
--- a/src/backends/meta-remote-desktop.c
|
|
+++ b/src/backends/meta-remote-desktop.c
|
|
@@ -56,6 +56,8 @@ struct _MetaRemoteDesktop
|
|
|
|
int dbus_name_id;
|
|
|
|
+ int inhibit_count;
|
|
+
|
|
GHashTable *sessions;
|
|
|
|
MetaDbusSessionWatcher *session_watcher;
|
|
@@ -70,6 +72,34 @@ G_DEFINE_TYPE_WITH_CODE (MetaRemoteDesktop,
|
|
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_REMOTE_DESKTOP,
|
|
meta_remote_desktop_init_iface));
|
|
|
|
+void
|
|
+meta_remote_desktop_inhibit (MetaRemoteDesktop *remote_desktop)
|
|
+{
|
|
+ remote_desktop->inhibit_count++;
|
|
+ if (remote_desktop->inhibit_count == 1)
|
|
+ {
|
|
+ GHashTableIter iter;
|
|
+ gpointer key, value;
|
|
+
|
|
+ g_hash_table_iter_init (&iter, remote_desktop->sessions);
|
|
+ while (g_hash_table_iter_next (&iter, &key, &value))
|
|
+ {
|
|
+ MetaRemoteDesktopSession *session = value;
|
|
+
|
|
+ g_hash_table_iter_steal (&iter);
|
|
+ meta_remote_desktop_session_close (session);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+meta_remote_desktop_uninhibit (MetaRemoteDesktop *remote_desktop)
|
|
+{
|
|
+ g_return_if_fail (remote_desktop->inhibit_count > 0);
|
|
+
|
|
+ remote_desktop->inhibit_count--;
|
|
+}
|
|
+
|
|
GDBusConnection *
|
|
meta_remote_desktop_get_connection (MetaRemoteDesktop *remote_desktop)
|
|
{
|
|
@@ -108,6 +138,15 @@ handle_create_session (MetaDBusRemoteDesktop *skeleton,
|
|
char *session_path;
|
|
const char *client_dbus_name;
|
|
|
|
+ if (remote_desktop->inhibit_count > 0)
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_ACCESS_DENIED,
|
|
+ "Session creation inhibited");
|
|
+
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
peer_name = g_dbus_method_invocation_get_sender (invocation);
|
|
session = meta_remote_desktop_session_new (remote_desktop,
|
|
peer_name,
|
|
diff --git a/src/backends/meta-remote-desktop.h b/src/backends/meta-remote-desktop.h
|
|
index 3eebc13d5..210a84a04 100644
|
|
--- a/src/backends/meta-remote-desktop.h
|
|
+++ b/src/backends/meta-remote-desktop.h
|
|
@@ -36,6 +36,10 @@ G_DECLARE_FINAL_TYPE (MetaRemoteDesktop, meta_remote_desktop,
|
|
META, REMOTE_DESKTOP,
|
|
MetaDBusRemoteDesktopSkeleton)
|
|
|
|
+void meta_remote_desktop_inhibit (MetaRemoteDesktop *remote_desktop);
|
|
+
|
|
+void meta_remote_desktop_uninhibit (MetaRemoteDesktop *remote_desktop);
|
|
+
|
|
MetaRemoteDesktopSession * meta_remote_desktop_get_session (MetaRemoteDesktop *remote_desktop,
|
|
const char *session_id);
|
|
|
|
diff --git a/src/backends/meta-screen-cast.c b/src/backends/meta-screen-cast.c
|
|
index 063fffd8e..46bc26838 100644
|
|
--- a/src/backends/meta-screen-cast.c
|
|
+++ b/src/backends/meta-screen-cast.c
|
|
@@ -40,6 +40,8 @@ struct _MetaScreenCast
|
|
|
|
int dbus_name_id;
|
|
|
|
+ int inhibit_count;
|
|
+
|
|
GList *sessions;
|
|
|
|
MetaDbusSessionWatcher *session_watcher;
|
|
@@ -54,6 +56,29 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCast, meta_screen_cast,
|
|
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SCREEN_CAST,
|
|
meta_screen_cast_init_iface))
|
|
|
|
+void
|
|
+meta_screen_cast_inhibit (MetaScreenCast *screen_cast)
|
|
+{
|
|
+ screen_cast->inhibit_count++;
|
|
+ if (screen_cast->inhibit_count == 1)
|
|
+ {
|
|
+ while (screen_cast->sessions)
|
|
+ {
|
|
+ MetaScreenCastSession *session = screen_cast->sessions->data;
|
|
+
|
|
+ meta_screen_cast_session_close (session);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+meta_screen_cast_uninhibit (MetaScreenCast *screen_cast)
|
|
+{
|
|
+ g_return_if_fail (screen_cast->inhibit_count > 0);
|
|
+
|
|
+ screen_cast->inhibit_count--;
|
|
+}
|
|
+
|
|
GDBusConnection *
|
|
meta_screen_cast_get_connection (MetaScreenCast *screen_cast)
|
|
{
|
|
@@ -118,6 +143,15 @@ handle_create_session (MetaDBusScreenCast *skeleton,
|
|
char *remote_desktop_session_id = NULL;
|
|
MetaScreenCastSessionType session_type;
|
|
|
|
+ if (screen_cast->inhibit_count > 0)
|
|
+ {
|
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
+ G_DBUS_ERROR_ACCESS_DENIED,
|
|
+ "Session creation inhibited");
|
|
+
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
g_variant_lookup (properties, "remote-desktop-session-id", "s",
|
|
&remote_desktop_session_id);
|
|
|
|
diff --git a/src/backends/meta-screen-cast.h b/src/backends/meta-screen-cast.h
|
|
index 994c40c53..a3b650cd8 100644
|
|
--- a/src/backends/meta-screen-cast.h
|
|
+++ b/src/backends/meta-screen-cast.h
|
|
@@ -42,6 +42,10 @@ G_DECLARE_FINAL_TYPE (MetaScreenCast, meta_screen_cast,
|
|
META, SCREEN_CAST,
|
|
MetaDBusScreenCastSkeleton)
|
|
|
|
+void meta_screen_cast_inhibit (MetaScreenCast *screen_cast);
|
|
+
|
|
+void meta_screen_cast_uninhibit (MetaScreenCast *screen_cast);
|
|
+
|
|
GDBusConnection * meta_screen_cast_get_connection (MetaScreenCast *screen_cast);
|
|
|
|
MetaBackend * meta_screen_cast_get_backend (MetaScreenCast *screen_cast);
|
|
diff --git a/src/meta/meta-remote-access-controller.h b/src/meta/meta-remote-access-controller.h
|
|
index e7c707bbc..56f0dcbe2 100644
|
|
--- a/src/meta/meta-remote-access-controller.h
|
|
+++ b/src/meta/meta-remote-access-controller.h
|
|
@@ -51,4 +51,10 @@ G_DECLARE_FINAL_TYPE (MetaRemoteAccessController,
|
|
META, REMOTE_ACCESS_CONTROLLER,
|
|
GObject)
|
|
|
|
+META_EXPORT
|
|
+void meta_remote_access_controller_inhibit_remote_access (MetaRemoteAccessController *controller);
|
|
+
|
|
+META_EXPORT
|
|
+void meta_remote_access_controller_uninhibit_remote_access (MetaRemoteAccessController *controller);
|
|
+
|
|
#endif /* META_REMOTE_ACCESS_CONTROLLER_H */
|
|
--
|
|
2.26.2
|
|
|