|
|
1a3082 |
From cf8f1fb8478e4b76c91e825d1537396b014689a0 Mon Sep 17 00:00:00 2001
|
|
|
1a3082 |
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
|
1a3082 |
Date: Tue, 22 Oct 2019 17:03:03 +0200
|
|
|
1a3082 |
Subject: [PATCH 11/12] clutter/stage-view: Separate offscreen and shadowfb
|
|
|
1a3082 |
|
|
|
1a3082 |
Previously, we would use a single offscreen framebuffer for both
|
|
|
1a3082 |
transformations and when a shadow framebuffer should be used, but that
|
|
|
1a3082 |
can be dreadfully slow when using software rendering with a discrete GPU
|
|
|
1a3082 |
due to bandwidth limitations.
|
|
|
1a3082 |
|
|
|
1a3082 |
Keep the offscreen framebuffer for transformations only and add another
|
|
|
1a3082 |
intermediate shadow framebuffer used as a copy of the onscreen
|
|
|
1a3082 |
framebuffer.
|
|
|
1a3082 |
|
|
|
1a3082 |
https://gitlab.gnome.org/GNOME/mutter/merge_requests/917
|
|
|
1a3082 |
|
|
|
1a3082 |
(cherry picked from commit 2b8b450fe16c21f0f37a1779560c0e5da61a9b89)
|
|
|
1a3082 |
---
|
|
|
1a3082 |
clutter/clutter/clutter-stage-view.c | 162 +++++++++++++++++-----
|
|
|
1a3082 |
clutter/clutter/cogl/clutter-stage-cogl.c | 6 +-
|
|
|
1a3082 |
2 files changed, 128 insertions(+), 40 deletions(-)
|
|
|
1a3082 |
|
|
|
1a3082 |
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
|
|
|
1a3082 |
index 503c31e78..c536ac720 100644
|
|
|
1a3082 |
--- a/clutter/clutter/clutter-stage-view.c
|
|
|
1a3082 |
+++ b/clutter/clutter/clutter-stage-view.c
|
|
|
1a3082 |
@@ -29,6 +29,7 @@ enum
|
|
|
1a3082 |
PROP_LAYOUT,
|
|
|
1a3082 |
PROP_FRAMEBUFFER,
|
|
|
1a3082 |
PROP_OFFSCREEN,
|
|
|
1a3082 |
+ PROP_SHADOWFB,
|
|
|
1a3082 |
PROP_SCALE,
|
|
|
1a3082 |
|
|
|
1a3082 |
PROP_LAST
|
|
|
1a3082 |
@@ -43,7 +44,10 @@ typedef struct _ClutterStageViewPrivate
|
|
|
1a3082 |
CoglFramebuffer *framebuffer;
|
|
|
1a3082 |
|
|
|
1a3082 |
CoglOffscreen *offscreen;
|
|
|
1a3082 |
- CoglPipeline *pipeline;
|
|
|
1a3082 |
+ CoglPipeline *offscreen_pipeline;
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ CoglOffscreen *shadowfb;
|
|
|
1a3082 |
+ CoglPipeline *shadowfb_pipeline;
|
|
|
1a3082 |
|
|
|
1a3082 |
guint dirty_viewport : 1;
|
|
|
1a3082 |
guint dirty_projection : 1;
|
|
|
1a3082 |
@@ -69,6 +73,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
|
|
1a3082 |
|
|
|
1a3082 |
if (priv->offscreen)
|
|
|
1a3082 |
return priv->offscreen;
|
|
|
1a3082 |
+ else if (priv->shadowfb)
|
|
|
1a3082 |
+ return priv->shadowfb;
|
|
|
1a3082 |
else
|
|
|
1a3082 |
return priv->framebuffer;
|
|
|
1a3082 |
}
|
|
|
1a3082 |
@@ -82,6 +88,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
|
|
|
1a3082 |
return priv->framebuffer;
|
|
|
1a3082 |
}
|
|
|
1a3082 |
|
|
|
1a3082 |
+static CoglPipeline *
|
|
|
1a3082 |
+clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
|
|
|
1a3082 |
+{
|
|
|
1a3082 |
+ CoglPipeline *pipeline;
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ cogl_pipeline_set_layer_filters (pipeline, 0,
|
|
|
1a3082 |
+ COGL_PIPELINE_FILTER_NEAREST,
|
|
|
1a3082 |
+ COGL_PIPELINE_FILTER_NEAREST);
|
|
|
1a3082 |
+ cogl_pipeline_set_layer_texture (pipeline, 0,
|
|
|
1a3082 |
+ cogl_offscreen_get_texture (framebuffer));
|
|
|
1a3082 |
+ cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
|
|
|
1a3082 |
+ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ return pipeline;
|
|
|
1a3082 |
+}
|
|
|
1a3082 |
+
|
|
|
1a3082 |
static void
|
|
|
1a3082 |
clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
|
|
|
1a3082 |
{
|
|
|
1a3082 |
@@ -92,71 +116,122 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
|
|
|
1a3082 |
|
|
|
1a3082 |
g_assert (priv->offscreen != NULL);
|
|
|
1a3082 |
|
|
|
1a3082 |
- if (priv->pipeline)
|
|
|
1a3082 |
+ if (priv->offscreen_pipeline)
|
|
|
1a3082 |
return;
|
|
|
1a3082 |
|
|
|
1a3082 |
- priv->pipeline =
|
|
|
1a3082 |
- cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen));
|
|
|
1a3082 |
- cogl_pipeline_set_layer_filters (priv->pipeline, 0,
|
|
|
1a3082 |
- COGL_PIPELINE_FILTER_NEAREST,
|
|
|
1a3082 |
- COGL_PIPELINE_FILTER_NEAREST);
|
|
|
1a3082 |
- cogl_pipeline_set_layer_texture (priv->pipeline, 0,
|
|
|
1a3082 |
- cogl_offscreen_get_texture (priv->offscreen));
|
|
|
1a3082 |
- cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0,
|
|
|
1a3082 |
- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
|
|
1a3082 |
+ priv->offscreen_pipeline =
|
|
|
1a3082 |
+ clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
|
|
|
1a3082 |
|
|
|
1a3082 |
if (view_class->setup_offscreen_blit_pipeline)
|
|
|
1a3082 |
- view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
|
|
|
1a3082 |
+ view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
|
|
|
1a3082 |
}
|
|
|
1a3082 |
|
|
|
1a3082 |
-void
|
|
|
1a3082 |
-clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
|
|
|
1a3082 |
+static void
|
|
|
1a3082 |
+clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
|
|
|
1a3082 |
{
|
|
|
1a3082 |
ClutterStageViewPrivate *priv =
|
|
|
1a3082 |
clutter_stage_view_get_instance_private (view);
|
|
|
1a3082 |
|
|
|
1a3082 |
- g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
|
|
1a3082 |
+ if (priv->shadowfb_pipeline)
|
|
|
1a3082 |
+ return;
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ priv->shadowfb_pipeline =
|
|
|
1a3082 |
+ clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
|
|
|
1a3082 |
}
|
|
|
1a3082 |
|
|
|
1a3082 |
void
|
|
|
1a3082 |
-clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
|
|
1a3082 |
- const cairo_rectangle_int_t *rect)
|
|
|
1a3082 |
+clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
|
|
|
1a3082 |
{
|
|
|
1a3082 |
ClutterStageViewPrivate *priv =
|
|
|
1a3082 |
clutter_stage_view_get_instance_private (view);
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
|
|
|
1a3082 |
+}
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+static void
|
|
|
1a3082 |
+clutter_stage_view_copy_to_framebuffer (ClutterStageView *view,
|
|
|
1a3082 |
+ const cairo_rectangle_int_t *rect,
|
|
|
1a3082 |
+ CoglPipeline *pipeline,
|
|
|
1a3082 |
+ CoglFramebuffer *src_framebuffer,
|
|
|
1a3082 |
+ CoglFramebuffer *dst_framebuffer,
|
|
|
1a3082 |
+ gboolean can_blit)
|
|
|
1a3082 |
+{
|
|
|
1a3082 |
CoglMatrix matrix;
|
|
|
1a3082 |
|
|
|
1a3082 |
- clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
|
|
|
1a3082 |
- if (cogl_matrix_is_identity (&matrix))
|
|
|
1a3082 |
+ /* First, try with blit */
|
|
|
1a3082 |
+ if (can_blit)
|
|
|
1a3082 |
{
|
|
|
1a3082 |
- int fb_width = cogl_framebuffer_get_width (priv->framebuffer);
|
|
|
1a3082 |
- int fb_height = cogl_framebuffer_get_height (priv->framebuffer);
|
|
|
1a3082 |
-
|
|
|
1a3082 |
- if (cogl_blit_framebuffer (priv->offscreen,
|
|
|
1a3082 |
- priv->framebuffer,
|
|
|
1a3082 |
+ if (cogl_blit_framebuffer (src_framebuffer,
|
|
|
1a3082 |
+ dst_framebuffer,
|
|
|
1a3082 |
0, 0,
|
|
|
1a3082 |
0, 0,
|
|
|
1a3082 |
- fb_width, fb_height,
|
|
|
1a3082 |
+ cogl_framebuffer_get_width (dst_framebuffer),
|
|
|
1a3082 |
+ cogl_framebuffer_get_height (dst_framebuffer),
|
|
|
1a3082 |
NULL))
|
|
|
1a3082 |
return;
|
|
|
1a3082 |
}
|
|
|
1a3082 |
|
|
|
1a3082 |
- clutter_stage_view_ensure_offscreen_blit_pipeline (view);
|
|
|
1a3082 |
- cogl_framebuffer_push_matrix (priv->framebuffer);
|
|
|
1a3082 |
+ /* If blit fails, fallback to the slower painting method */
|
|
|
1a3082 |
+ cogl_framebuffer_push_matrix (dst_framebuffer);
|
|
|
1a3082 |
|
|
|
1a3082 |
- /* Set transform so 0,0 is on the top left corner and 1,1 on
|
|
|
1a3082 |
- * the bottom right corner.
|
|
|
1a3082 |
- */
|
|
|
1a3082 |
cogl_matrix_init_identity (&matrix);
|
|
|
1a3082 |
cogl_matrix_translate (&matrix, -1, 1, 0);
|
|
|
1a3082 |
cogl_matrix_scale (&matrix, 2, -2, 0);
|
|
|
1a3082 |
- cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix);
|
|
|
1a3082 |
+ cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
|
|
|
1a3082 |
|
|
|
1a3082 |
- cogl_framebuffer_draw_rectangle (priv->framebuffer,
|
|
|
1a3082 |
- priv->pipeline,
|
|
|
1a3082 |
+ cogl_framebuffer_draw_rectangle (dst_framebuffer,
|
|
|
1a3082 |
+ pipeline,
|
|
|
1a3082 |
0, 0, 1, 1);
|
|
|
1a3082 |
|
|
|
1a3082 |
- cogl_framebuffer_pop_matrix (priv->framebuffer);
|
|
|
1a3082 |
+ cogl_framebuffer_pop_matrix (dst_framebuffer);
|
|
|
1a3082 |
+}
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+void
|
|
|
1a3082 |
+clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
|
|
1a3082 |
+ const cairo_rectangle_int_t *rect)
|
|
|
1a3082 |
+{
|
|
|
1a3082 |
+ ClutterStageViewPrivate *priv =
|
|
|
1a3082 |
+ clutter_stage_view_get_instance_private (view);
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ if (priv->offscreen)
|
|
|
1a3082 |
+ {
|
|
|
1a3082 |
+ gboolean can_blit;
|
|
|
1a3082 |
+ CoglMatrix matrix;
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ clutter_stage_view_ensure_offscreen_blit_pipeline (view);
|
|
|
1a3082 |
+ clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
|
|
|
1a3082 |
+ can_blit = cogl_matrix_is_identity (&matrix);
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ if (priv->shadowfb)
|
|
|
1a3082 |
+ {
|
|
|
1a3082 |
+ clutter_stage_view_copy_to_framebuffer (view,
|
|
|
1a3082 |
+ rect,
|
|
|
1a3082 |
+ priv->offscreen_pipeline,
|
|
|
1a3082 |
+ priv->offscreen,
|
|
|
1a3082 |
+ priv->shadowfb,
|
|
|
1a3082 |
+ can_blit);
|
|
|
1a3082 |
+ }
|
|
|
1a3082 |
+ else
|
|
|
1a3082 |
+ {
|
|
|
1a3082 |
+ clutter_stage_view_copy_to_framebuffer (view,
|
|
|
1a3082 |
+ rect,
|
|
|
1a3082 |
+ priv->offscreen_pipeline,
|
|
|
1a3082 |
+ priv->offscreen,
|
|
|
1a3082 |
+ priv->framebuffer,
|
|
|
1a3082 |
+ can_blit);
|
|
|
1a3082 |
+ }
|
|
|
1a3082 |
+ }
|
|
|
1a3082 |
+
|
|
|
1a3082 |
+ if (priv->shadowfb)
|
|
|
1a3082 |
+ {
|
|
|
1a3082 |
+ clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
|
|
|
1a3082 |
+ clutter_stage_view_copy_to_framebuffer (view,
|
|
|
1a3082 |
+ rect,
|
|
|
1a3082 |
+ priv->shadowfb_pipeline,
|
|
|
1a3082 |
+ priv->shadowfb,
|
|
|
1a3082 |
+ priv->framebuffer,
|
|
|
1a3082 |
+ TRUE);
|
|
|
1a3082 |
+ }
|
|
|
1a3082 |
}
|
|
|
1a3082 |
|
|
|
1a3082 |
float
|
|
|
1a3082 |
@@ -256,6 +331,9 @@ clutter_stage_view_get_property (GObject *object,
|
|
|
1a3082 |
case PROP_OFFSCREEN:
|
|
|
1a3082 |
g_value_set_boxed (value, priv->offscreen);
|
|
|
1a3082 |
break;
|
|
|
1a3082 |
+ case PROP_SHADOWFB:
|
|
|
1a3082 |
+ g_value_set_boxed (value, priv->shadowfb);
|
|
|
1a3082 |
+ break;
|
|
|
1a3082 |
case PROP_SCALE:
|
|
|
1a3082 |
g_value_set_float (value, priv->scale);
|
|
|
1a3082 |
break;
|
|
|
1a3082 |
@@ -301,6 +379,9 @@ clutter_stage_view_set_property (GObject *object,
|
|
|
1a3082 |
case PROP_OFFSCREEN:
|
|
|
1a3082 |
priv->offscreen = g_value_dup_boxed (value);
|
|
|
1a3082 |
break;
|
|
|
1a3082 |
+ case PROP_SHADOWFB:
|
|
|
1a3082 |
+ priv->shadowfb = g_value_dup_boxed (value);
|
|
|
1a3082 |
+ break;
|
|
|
1a3082 |
case PROP_SCALE:
|
|
|
1a3082 |
priv->scale = g_value_get_float (value);
|
|
|
1a3082 |
break;
|
|
|
1a3082 |
@@ -317,8 +398,10 @@ clutter_stage_view_dispose (GObject *object)
|
|
|
1a3082 |
clutter_stage_view_get_instance_private (view);
|
|
|
1a3082 |
|
|
|
1a3082 |
g_clear_pointer (&priv->framebuffer, cogl_object_unref);
|
|
|
1a3082 |
+ g_clear_pointer (&priv->shadowfb, cogl_object_unref);
|
|
|
1a3082 |
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
|
|
1a3082 |
- g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
|
|
1a3082 |
+ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
|
|
|
1a3082 |
+ g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
|
|
|
1a3082 |
|
|
|
1a3082 |
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
|
|
|
1a3082 |
}
|
|
|
1a3082 |
@@ -373,6 +456,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
|
|
1a3082 |
G_PARAM_CONSTRUCT_ONLY |
|
|
|
1a3082 |
G_PARAM_STATIC_STRINGS);
|
|
|
1a3082 |
|
|
|
1a3082 |
+ obj_props[PROP_SHADOWFB] =
|
|
|
1a3082 |
+ g_param_spec_boxed ("shadowfb",
|
|
|
1a3082 |
+ "Shadow framebuffer",
|
|
|
1a3082 |
+ "Framebuffer used as intermediate shadow buffer",
|
|
|
1a3082 |
+ COGL_TYPE_HANDLE,
|
|
|
1a3082 |
+ G_PARAM_READWRITE |
|
|
|
1a3082 |
+ G_PARAM_CONSTRUCT_ONLY |
|
|
|
1a3082 |
+ G_PARAM_STATIC_STRINGS);
|
|
|
1a3082 |
+
|
|
|
1a3082 |
obj_props[PROP_SCALE] =
|
|
|
1a3082 |
g_param_spec_float ("scale",
|
|
|
1a3082 |
"View scale",
|
|
|
1a3082 |
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
|
1a3082 |
index e0c39185b..eab76e52f 100644
|
|
|
1a3082 |
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
|
1a3082 |
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
|
|
|
1a3082 |
@@ -477,11 +477,7 @@ paint_stage (ClutterStageCogl *stage_cogl,
|
|
|
1a3082 |
_clutter_stage_maybe_setup_viewport (stage, view);
|
|
|
1a3082 |
_clutter_stage_paint_view (stage, view, clip);
|
|
|
1a3082 |
|
|
|
1a3082 |
- if (clutter_stage_view_get_onscreen (view) !=
|
|
|
1a3082 |
- clutter_stage_view_get_framebuffer (view))
|
|
|
1a3082 |
- {
|
|
|
1a3082 |
- clutter_stage_view_blit_offscreen (view, clip);
|
|
|
1a3082 |
- }
|
|
|
1a3082 |
+ clutter_stage_view_blit_offscreen (view, clip);
|
|
|
1a3082 |
}
|
|
|
1a3082 |
|
|
|
1a3082 |
static void
|
|
|
1a3082 |
--
|
|
|
1a3082 |
2.21.0
|
|
|
1a3082 |
|