[mutter/wip/garnacho/wayland-emulated-output-transform: 19/27] clutter: Add infrastructure to render ClutterStageViews to offscreen
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/garnacho/wayland-emulated-output-transform: 19/27] clutter: Add infrastructure to render ClutterStageViews to offscreen
- Date: Tue, 23 Aug 2016 18:05:51 +0000 (UTC)
commit 6302ffe8ac59ab4f41de74449d1c5b188c4a3126
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.
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]