[mutter/wip/garnacho/wayland-emulated-output-transform: 4/13] clutter: Add infrastructure to render ClutterStageViews to an intermediate texture
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/garnacho/wayland-emulated-output-transform: 4/13] clutter: Add infrastructure to render ClutterStageViews to an intermediate texture
- Date: Mon, 1 Aug 2016 11:35:44 +0000 (UTC)
commit f3d1ef6df78adc53bd3804188bca2d49dc0a565f
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon Aug 1 02:44:57 2016 +0200
clutter: Add infrastructure to render ClutterStageViews to an intermediate texture
The texture is given through the ::back-texture property, the ClutterStageView
sets up the CoglOffscreen necessary to render into it, and the CoglPipeline used
to render it back to the framebuffer.
The pipeline can be altered through the setup_pipeline() vfunc, so ClutterStageView
implementations can alter the default behavior of rendering the texture onto the
framebuffer with no transformations.
clutter/clutter/clutter-stage-view.c | 151 +++++++++++++++++++++++++++++++++-
clutter/clutter/clutter-stage-view.h | 18 ++++
2 files changed, 168 insertions(+), 1 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index 87d6102..25a231a 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_BACK_TEXTURE,
PROP_LAST
};
@@ -37,6 +38,11 @@ typedef struct _ClutterStageViewPrivate
{
cairo_rectangle_int_t layout;
CoglFramebuffer *framebuffer;
+
+ CoglFramebuffer *back_buffer;
+ CoglTexture *back_texture;
+ CoglPipeline *pipeline;
+
guint dirty_viewport : 1;
guint dirty_projection : 1;
} ClutterStageViewPrivate;
@@ -62,6 +68,111 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
return priv->framebuffer;
}
+static void
+clutter_stage_view_ensure_pipeline (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+ ClutterStageViewClass *view_class =
+ CLUTTER_STAGE_VIEW_GET_CLASS (view);
+
+ g_clear_pointer (&priv->pipeline, cogl_object_unref);
+
+ if (!priv->back_texture)
+ return;
+
+ priv->pipeline =
+ cogl_pipeline_new (cogl_framebuffer_get_context (priv->back_buffer));
+ cogl_pipeline_set_layer_filters (priv->pipeline, 0,
+ COGL_PIPELINE_FILTER_NEAREST,
+ COGL_PIPELINE_FILTER_NEAREST);
+ cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->back_texture);
+ cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0,
+ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+
+ if (view_class->setup_pipeline)
+ view_class->setup_pipeline (view, priv->pipeline);
+}
+
+void
+clutter_stage_view_invalidate_pipeline (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ g_clear_pointer (&priv->pipeline, cogl_object_unref);
+}
+
+void
+clutter_stage_view_set_back_texture (ClutterStageView *view,
+ CoglTexture2D *texture)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+ GError *error = NULL;
+
+ g_clear_pointer (&priv->pipeline, cogl_object_unref);
+ g_clear_pointer (&priv->back_buffer, cogl_object_unref);
+ g_clear_pointer (&priv->back_texture, cogl_object_unref);
+
+ priv->back_texture = texture;
+
+ if (priv->back_texture)
+ {
+ cogl_object_ref (priv->back_texture);
+ priv->back_buffer = cogl_offscreen_new_with_texture (priv->back_texture);
+
+ if (priv->back_buffer &&
+ !cogl_framebuffer_allocate (priv->back_buffer, &error))
+ {
+ g_critical ("Failed to allocate back buffer: %s\n", error->message);
+ g_error_free (error);
+ g_clear_pointer (&priv->back_texture, cogl_object_unref);
+ g_clear_pointer (&priv->back_buffer, cogl_object_unref);
+ }
+ }
+
+ clutter_stage_view_invalidate_pipeline (view);
+}
+
+CoglTexture2D *
+clutter_stage_view_get_back_texture (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ return priv->back_texture;
+}
+
+CoglFramebuffer *
+clutter_stage_view_get_back_buffer (ClutterStageView *view)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ if (!priv->back_buffer)
+ {
+ /* There's no back buffer, use the framebuffer directly */
+ return priv->framebuffer;
+ }
+
+ return priv->back_buffer;
+}
+
+void
+clutter_stage_view_blit_back_buffer (ClutterStageView *view,
+ const cairo_rectangle_int_t *rect)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ if (!priv->back_buffer)
+ return;
+
+ clutter_stage_view_ensure_pipeline (view);
+ CLUTTER_STAGE_VIEW_GET_CLASS (view)->blit_back_buffer (view, rect);
+}
+
gboolean
clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
{
@@ -101,6 +212,19 @@ clutter_stage_view_set_dirty_projection (ClutterStageView *view,
}
static void
+clutter_stage_view_default_blit_back_buffer (ClutterStageView *view,
+ const cairo_rectangle_int_t *rect)
+{
+ ClutterStageViewPrivate *priv =
+ clutter_stage_view_get_instance_private (view);
+
+ /* FIXME: Use rect */
+ cogl_framebuffer_draw_rectangle (priv->framebuffer,
+ priv->pipeline,
+ -1, 1, 1, -1);
+}
+
+static void
clutter_stage_view_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -118,6 +242,11 @@ clutter_stage_view_get_property (GObject *object,
case PROP_FRAMEBUFFER:
g_value_set_boxed (value, priv->framebuffer);
break;
+ case PROP_BACK_TEXTURE:
+ g_value_set_boxed (value, priv->back_texture);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
@@ -141,6 +270,11 @@ clutter_stage_view_set_property (GObject *object,
case PROP_FRAMEBUFFER:
priv->framebuffer = g_value_dup_boxed (value);
break;
+ case PROP_BACK_TEXTURE:
+ clutter_stage_view_set_back_texture (view, g_value_get_boxed (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
@@ -152,6 +286,11 @@ 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->back_buffer, cogl_object_unref);
+ g_clear_pointer (&priv->back_texture, cogl_object_unref);
+ g_clear_pointer (&priv->pipeline, cogl_object_unref);
+
+ G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
}
static void
@@ -164,6 +303,8 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ klass->blit_back_buffer = clutter_stage_view_default_blit_back_buffer;
+
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;
@@ -179,7 +320,15 @@ 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_BACK_TEXTURE] =
+ g_param_spec_boxed ("back-texture",
+ "Back texture",
+ "Texture used as back buffer",
COGL_TYPE_HANDLE,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h
index e9fe3a0..2fdc7e1 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_pipeline) (ClutterStageView *view,
+ CoglPipeline *pipeline);
+
+ void (* blit_back_buffer) (ClutterStageView *view,
+ const cairo_rectangle_int_t *rect);
};
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_back_buffer (ClutterStageView *view);
+CLUTTER_AVAILABLE_IN_MUTTER
+CoglTexture2D *clutter_stage_view_get_back_texture (ClutterStageView *view);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_stage_view_set_back_texture (ClutterStageView *view,
+ CoglTexture2D *texture);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_stage_view_invalidate_pipeline (ClutterStageView *view);
+
+void clutter_stage_view_blit_back_buffer (ClutterStageView *view,
+ const cairo_rectangle_int_t *rect);
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]