[mutter: 5/13] clutter: Add infrastructure to render ClutterStageViews to offscreen
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter: 5/13] clutter: Add infrastructure to render ClutterStageViews to offscreen
- Date: Wed, 24 Aug 2016 00:40:58 +0000 (UTC)
commit 54dc10f890919b7eab6fc893776fa6cef5aefdc2
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon Aug 1 02:44:57 2016 +0200
clutter: Add infrastructure to render ClutterStageViews to offscreen
The offscreen is given through the ::back-buffer property, the ClutterStageView
will set up the the CoglPipeline used to render it back to the "onscreen"
framebuffer.
The pipeline can be altered through the setup_pipeline() vfunc, so ClutterStageView
implementations can alter the default behavior of blitting from offscreen to
onscreen with no transformations.
All getters of "the framebuffer" that were expecting to get an onscreen have
been updated to call the right clutter_stage_view_get_onscreen() function.
https://bugzilla.gnome.org/show_bug.cgi?id=745079
clutter/clutter/clutter-stage-view.c | 168 +++++++++++++++++++++++++++-
clutter/clutter/clutter-stage-view.h | 18 +++
clutter/clutter/cogl/clutter-stage-cogl.c | 2 +-
src/backends/native/meta-renderer-native.c | 8 +-
src/backends/native/meta-stage-native.c | 2 +-
5 files changed, 191 insertions(+), 7 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index 8eb17b8..a8b1d09 100644
--- a/clutter/clutter/clutter-stage-view.c
+++ b/clutter/clutter/clutter-stage-view.c
@@ -27,6 +27,7 @@ enum
PROP_LAYOUT,
PROP_FRAMEBUFFER,
+ PROP_OFFSCREEN,
PROP_LAST
};
@@ -37,6 +38,10 @@ typedef struct _ClutterStageViewPrivate
{
cairo_rectangle_int_t layout;
CoglFramebuffer *framebuffer;
+
+ CoglOffscreen *offscreen;
+ CoglPipeline *pipeline;
+
guint dirty_viewport : 1;
guint dirty_projection : 1;
} ClutterStageViewPrivate;
@@ -59,9 +64,123 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
+ if (priv->offscreen)
+ return priv->offscreen;
+ else
+ return priv->framebuffer;
+}
+
+CoglFramebuffer *
+clutter_stage_view_get_onscreen (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
return priv->framebuffer;
}
+static void
+clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+ ClutterStageViewClass *view_class =
+ CLUTTER_STAGE_VIEW_GET_CLASS (view);
+
+ g_assert (priv->offscreen != NULL);
+
+ if (priv->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);
+
+ if (view_class->setup_offscreen_blit_pipeline)
+ view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
+}
+
+void
+clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ g_clear_pointer (&priv->pipeline, cogl_object_unref);
+}
+
+static void
+transform_rect_to_onscreen (ClutterStageView *view,
+ const cairo_rectangle_t *rect,
+ cairo_rectangle_t *rect_out)
+{
+ float x1, y1, x2, y2;
+
+ x1 = rect->x;
+ y1 = rect->y;
+ clutter_stage_view_transform_to_onscreen (view, &x1, &y1);
+
+ x2 = rect->x + rect->width;
+ y2 = rect->y + rect->height;
+ clutter_stage_view_transform_to_onscreen (view, &x2, &y2);
+
+ *rect_out = (cairo_rectangle_t) {
+ .x = MIN (x1, x2),
+ .y = MIN (y1, y2),
+ .width = ABS (x2 - x1),
+ .height = ABS (y2 - y1)
+ };
+}
+
+void
+clutter_stage_view_blit_offscreen (ClutterStageView *view,
+ const cairo_rectangle_int_t *rect)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+ cairo_rectangle_t texture_rect, onscreen_rect;
+ CoglMatrix matrix;
+
+ clutter_stage_view_ensure_offscreen_blit_pipeline (view);
+ cogl_framebuffer_push_matrix (priv->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);
+
+ texture_rect = (cairo_rectangle_t) {
+ .x = (double) rect->x / cogl_framebuffer_get_width (priv->offscreen),
+ .y = (double) rect->y / cogl_framebuffer_get_height (priv->offscreen),
+ .width = (double) rect->width / cogl_framebuffer_get_width (priv->offscreen),
+ .height = (double) rect->height / cogl_framebuffer_get_height (priv->offscreen)
+ };
+
+ transform_rect_to_onscreen (view, &texture_rect, &onscreen_rect);
+
+ cogl_framebuffer_draw_textured_rectangle (priv->framebuffer,
+ priv->pipeline,
+ onscreen_rect.x,
+ onscreen_rect.y,
+ onscreen_rect.x + onscreen_rect.width,
+ onscreen_rect.y + onscreen_rect.height,
+ texture_rect.x,
+ texture_rect.y,
+ texture_rect.x + texture_rect.width,
+ texture_rect.y + texture_rect.height);
+
+ cogl_framebuffer_pop_matrix (priv->framebuffer);
+}
+
gboolean
clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
{
@@ -100,6 +219,27 @@ clutter_stage_view_set_dirty_projection (ClutterStageView *view,
priv->dirty_projection = dirty;
}
+void
+clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
+ gfloat *x,
+ gfloat *y)
+{
+ ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view);
+ gfloat z = 0, w = 1;
+ CoglMatrix matrix;
+
+ view_class->get_offscreen_transformation_matrix (view, &matrix);
+ cogl_matrix_get_inverse (&matrix, &matrix);
+ cogl_matrix_transform_point (&matrix, x, y, &z, &w);
+}
+
+static void
+clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *view,
+ CoglMatrix *matrix)
+{
+ cogl_matrix_init_identity (matrix);
+}
+
static void
clutter_stage_view_get_property (GObject *object,
guint prop_id,
@@ -118,6 +258,11 @@ clutter_stage_view_get_property (GObject *object,
case PROP_FRAMEBUFFER:
g_value_set_boxed (value, priv->framebuffer);
break;
+ case PROP_OFFSCREEN:
+ g_value_set_boxed (value, priv->offscreen);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
@@ -141,6 +286,11 @@ clutter_stage_view_set_property (GObject *object,
case PROP_FRAMEBUFFER:
priv->framebuffer = g_value_dup_boxed (value);
break;
+ case PROP_OFFSCREEN:
+ priv->offscreen = g_value_dup_boxed (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
@@ -152,6 +302,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->offscreen, cogl_object_unref);
+ g_clear_pointer (&priv->pipeline, cogl_object_unref);
+
+ G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
}
static void
@@ -169,6 +323,9 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ klass->get_offscreen_transformation_matrix =
+ clutter_stage_default_get_offscreen_transformation_matrix;
+
object_class->get_property = clutter_stage_view_get_property;
object_class->set_property = clutter_stage_view_set_property;
object_class->dispose = clutter_stage_view_dispose;
@@ -184,9 +341,18 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
obj_props[PROP_FRAMEBUFFER] =
g_param_spec_boxed ("framebuffer",
"View framebuffer",
- "The framebuffer of the view",
+ "The front buffer of the view",
+ COGL_TYPE_HANDLE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ obj_props[PROP_OFFSCREEN] =
+ g_param_spec_boxed ("offscreen",
+ "Offscreen buffer",
+ "Framebuffer used as intermediate buffer",
COGL_TYPE_HANDLE,
G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h
index e9fe3a0..e820e96 100644
--- a/clutter/clutter/clutter-stage-view.h
+++ b/clutter/clutter/clutter-stage-view.h
@@ -33,6 +33,12 @@ G_DECLARE_DERIVABLE_TYPE (ClutterStageView, clutter_stage_view,
struct _ClutterStageViewClass
{
GObjectClass parent_class;
+
+ void (* setup_offscreen_blit_pipeline) (ClutterStageView *view,
+ CoglPipeline *pipeline);
+
+ void (* get_offscreen_transformation_matrix) (ClutterStageView *view,
+ CoglMatrix *matrix);
};
CLUTTER_AVAILABLE_IN_MUTTER
@@ -41,6 +47,18 @@ void clutter_stage_view_get_layout (ClutterStageView *view,
CLUTTER_AVAILABLE_IN_MUTTER
CoglFramebuffer *clutter_stage_view_get_framebuffer (ClutterStageView *view);
+CLUTTER_AVAILABLE_IN_MUTTER
+CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
+ gfloat *x,
+ gfloat *y);
+
+void clutter_stage_view_blit_offscreen (ClutterStageView *view,
+ const cairo_rectangle_int_t *clip);
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c
index 58979f1..6bf2f7b 100644
--- a/clutter/clutter/cogl/clutter-stage-cogl.c
+++ b/clutter/clutter/cogl/clutter-stage-cogl.c
@@ -357,7 +357,7 @@ swap_framebuffer (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *swap_region,
gboolean swap_with_damage)
{
- CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
+ CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
int damage[4], ndamage;
damage[0] = swap_region->x;
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 895f850..bdcfc79 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -379,7 +379,7 @@ on_crtc_flipped (GClosure *closure,
{
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
CoglFramebuffer *framebuffer =
- clutter_stage_view_get_framebuffer (stage_view);
+ clutter_stage_view_get_onscreen (stage_view);
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
@@ -397,7 +397,7 @@ flip_closure_destroyed (MetaRendererView *view)
{
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
CoglFramebuffer *framebuffer =
- clutter_stage_view_get_framebuffer (stage_view);
+ clutter_stage_view_get_onscreen (stage_view);
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
@@ -828,7 +828,7 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
{
ClutterStageView *stage_view = l->data;
CoglFramebuffer *framebuffer =
- clutter_stage_view_get_framebuffer (stage_view);
+ clutter_stage_view_get_onscreen (stage_view);
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
@@ -861,7 +861,7 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
MetaMonitorManagerKms *monitor_manager_kms =
META_MONITOR_MANAGER_KMS (monitor_manager);
CoglFramebuffer *framebuffer =
- clutter_stage_view_get_framebuffer (stage_view);
+ clutter_stage_view_get_onscreen (stage_view);
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c
index 617a707..82ede47 100644
--- a/src/backends/native/meta-stage-native.c
+++ b/src/backends/native/meta-stage-native.c
@@ -127,7 +127,7 @@ ensure_frame_callback (MetaStageNative *stage_native,
if (closure)
return;
- framebuffer = clutter_stage_view_get_framebuffer (stage_view);
+ framebuffer = clutter_stage_view_get_onscreen (stage_view);
onscreen = COGL_ONSCREEN (framebuffer);
closure = cogl_onscreen_add_frame_callback (onscreen,
frame_cb,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]