[mutter] clutter/stage-view: Separate offscreen and shadowfb
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] clutter/stage-view: Separate offscreen and shadowfb
- Date: Mon, 4 Nov 2019 09:59:15 +0000 (UTC)
commit db90c0d509f38dfd4c88b32d0cbb1ea53f399a63
Author: Olivier Fourdan <ofourdan redhat com>
Date: Tue Oct 22 17:03:03 2019 +0200
clutter/stage-view: Separate offscreen and shadowfb
Previously, we would use a single offscreen framebuffer for both
transformations and when a shadow framebuffer should be used, but that
can be dreadfully slow when using software rendering with a discrete GPU
due to bandwidth limitations.
Keep the offscreen framebuffer for transformations only and add another
intermediate shadow framebuffer used as a copy of the onscreen
framebuffer.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/877
clutter/clutter/clutter-stage-view-private.h | 4 +-
clutter/clutter/clutter-stage-view.c | 162 +++++++++++++++++++++------
clutter/clutter/cogl/clutter-stage-cogl.c | 6 +-
3 files changed, 130 insertions(+), 42 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
index 89c42599f..9fcbadba5 100644
--- a/clutter/clutter/clutter-stage-view-private.h
+++ b/clutter/clutter/clutter-stage-view-private.h
@@ -20,8 +20,8 @@
#include "clutter/clutter-stage-view.h"
-void clutter_stage_view_blit_offscreen (ClutterStageView *view,
- const cairo_rectangle_int_t *clip);
+void clutter_stage_view_after_paint (ClutterStageView *view,
+ const cairo_rectangle_int_t *clip);
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index b76bf677b..aa1cb212f 100644
--- a/clutter/clutter/clutter-stage-view.c
+++ b/clutter/clutter/clutter-stage-view.c
@@ -30,6 +30,7 @@ enum
PROP_LAYOUT,
PROP_FRAMEBUFFER,
PROP_OFFSCREEN,
+ PROP_SHADOWFB,
PROP_SCALE,
PROP_LAST
@@ -44,7 +45,10 @@ typedef struct _ClutterStageViewPrivate
CoglFramebuffer *framebuffer;
CoglOffscreen *offscreen;
- CoglPipeline *pipeline;
+ CoglPipeline *offscreen_pipeline;
+
+ CoglOffscreen *shadowfb;
+ CoglPipeline *shadowfb_pipeline;
guint dirty_viewport : 1;
guint dirty_projection : 1;
@@ -78,6 +82,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
if (priv->offscreen)
return priv->offscreen;
+ else if (priv->shadowfb)
+ return priv->shadowfb;
else
return priv->framebuffer;
}
@@ -99,6 +105,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
return priv->framebuffer;
}
+static CoglPipeline *
+clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
+{
+ CoglPipeline *pipeline;
+
+ pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
+
+ cogl_pipeline_set_layer_filters (pipeline, 0,
+ COGL_PIPELINE_FILTER_NEAREST,
+ COGL_PIPELINE_FILTER_NEAREST);
+ cogl_pipeline_set_layer_texture (pipeline, 0,
+ cogl_offscreen_get_texture (framebuffer));
+ cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
+ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+
+ return pipeline;
+}
+
static void
clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
{
@@ -109,71 +133,122 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
g_assert (priv->offscreen != NULL);
- if (priv->pipeline)
+ if (priv->offscreen_pipeline)
return;
- priv->pipeline =
- cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen));
- cogl_pipeline_set_layer_filters (priv->pipeline, 0,
- COGL_PIPELINE_FILTER_NEAREST,
- COGL_PIPELINE_FILTER_NEAREST);
- cogl_pipeline_set_layer_texture (priv->pipeline, 0,
- cogl_offscreen_get_texture (priv->offscreen));
- cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0,
- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+ priv->offscreen_pipeline =
+ clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
if (view_class->setup_offscreen_blit_pipeline)
- view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
+ view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
}
-void
-clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
+static void
+clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
- g_clear_pointer (&priv->pipeline, cogl_object_unref);
+ if (priv->shadowfb_pipeline)
+ return;
+
+ priv->shadowfb_pipeline =
+ clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
}
void
-clutter_stage_view_blit_offscreen (ClutterStageView *view,
- const cairo_rectangle_int_t *rect)
+clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
+
+ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
+}
+
+static void
+clutter_stage_view_copy_to_framebuffer (ClutterStageView *view,
+ const cairo_rectangle_int_t *rect,
+ CoglPipeline *pipeline,
+ CoglFramebuffer *src_framebuffer,
+ CoglFramebuffer *dst_framebuffer,
+ gboolean can_blit)
+{
CoglMatrix matrix;
- clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
- if (cogl_matrix_is_identity (&matrix))
+ /* First, try with blit */
+ if (can_blit)
{
- int fb_width = cogl_framebuffer_get_width (priv->framebuffer);
- int fb_height = cogl_framebuffer_get_height (priv->framebuffer);
-
- if (cogl_blit_framebuffer (priv->offscreen,
- priv->framebuffer,
+ if (cogl_blit_framebuffer (src_framebuffer,
+ dst_framebuffer,
0, 0,
0, 0,
- fb_width, fb_height,
+ cogl_framebuffer_get_width (dst_framebuffer),
+ cogl_framebuffer_get_height (dst_framebuffer),
NULL))
return;
}
- clutter_stage_view_ensure_offscreen_blit_pipeline (view);
- cogl_framebuffer_push_matrix (priv->framebuffer);
+ /* If blit fails, fallback to the slower painting method */
+ cogl_framebuffer_push_matrix (dst_framebuffer);
- /* Set transform so 0,0 is on the top left corner and 1,1 on
- * the bottom right corner.
- */
cogl_matrix_init_identity (&matrix);
cogl_matrix_translate (&matrix, -1, 1, 0);
cogl_matrix_scale (&matrix, 2, -2, 0);
- cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix);
+ cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
- cogl_framebuffer_draw_rectangle (priv->framebuffer,
- priv->pipeline,
+ cogl_framebuffer_draw_rectangle (dst_framebuffer,
+ pipeline,
0, 0, 1, 1);
- cogl_framebuffer_pop_matrix (priv->framebuffer);
+ cogl_framebuffer_pop_matrix (dst_framebuffer);
+}
+
+void
+clutter_stage_view_after_paint (ClutterStageView *view,
+ const cairo_rectangle_int_t *rect)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ if (priv->offscreen)
+ {
+ gboolean can_blit;
+ CoglMatrix matrix;
+
+ clutter_stage_view_ensure_offscreen_blit_pipeline (view);
+ clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
+ can_blit = cogl_matrix_is_identity (&matrix);
+
+ if (priv->shadowfb)
+ {
+ clutter_stage_view_copy_to_framebuffer (view,
+ rect,
+ priv->offscreen_pipeline,
+ priv->offscreen,
+ priv->shadowfb,
+ can_blit);
+ }
+ else
+ {
+ clutter_stage_view_copy_to_framebuffer (view,
+ rect,
+ priv->offscreen_pipeline,
+ priv->offscreen,
+ priv->framebuffer,
+ can_blit);
+ }
+ }
+
+ if (priv->shadowfb)
+ {
+ clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
+ clutter_stage_view_copy_to_framebuffer (view,
+ rect,
+ priv->shadowfb_pipeline,
+ priv->shadowfb,
+ priv->framebuffer,
+ TRUE);
+ }
}
float
@@ -273,6 +348,9 @@ clutter_stage_view_get_property (GObject *object,
case PROP_OFFSCREEN:
g_value_set_boxed (value, priv->offscreen);
break;
+ case PROP_SHADOWFB:
+ g_value_set_boxed (value, priv->shadowfb);
+ break;
case PROP_SCALE:
g_value_set_float (value, priv->scale);
break;
@@ -318,6 +396,9 @@ clutter_stage_view_set_property (GObject *object,
case PROP_OFFSCREEN:
priv->offscreen = g_value_dup_boxed (value);
break;
+ case PROP_SHADOWFB:
+ priv->shadowfb = g_value_dup_boxed (value);
+ break;
case PROP_SCALE:
priv->scale = g_value_get_float (value);
break;
@@ -334,8 +415,10 @@ clutter_stage_view_dispose (GObject *object)
clutter_stage_view_get_instance_private (view);
g_clear_pointer (&priv->framebuffer, cogl_object_unref);
+ g_clear_pointer (&priv->shadowfb, cogl_object_unref);
g_clear_pointer (&priv->offscreen, cogl_object_unref);
- g_clear_pointer (&priv->pipeline, cogl_object_unref);
+ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
+ g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
}
@@ -390,6 +473,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
+ obj_props[PROP_SHADOWFB] =
+ g_param_spec_boxed ("shadowfb",
+ "Shadow framebuffer",
+ "Framebuffer used as intermediate shadow buffer",
+ COGL_TYPE_HANDLE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
obj_props[PROP_SCALE] =
g_param_spec_float ("scale",
"View scale",
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index fdc22476a..6dfde0b6b 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -563,11 +563,7 @@ paint_stage (ClutterStageCogl *stage_cogl,
_clutter_stage_maybe_setup_viewport (stage, view);
_clutter_stage_paint_view (stage, view, &paint_rect);
- if (clutter_stage_view_get_onscreen (view) !=
- clutter_stage_view_get_framebuffer (view))
- {
- clutter_stage_view_blit_offscreen (view, &paint_rect);
- }
+ clutter_stage_view_after_paint (view, &paint_rect);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]