From 859ea1457d77582ab6c0d0776e2b3402856f3e72 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Thu, 30 Aug 2012 01:45:17 +0200 Subject: [PATCH] Add the ability to add shader hooks to MetaBackgroundActor Using ClutterEffect is not pratical on MetaBackgroundActor, as the FBO redirection has a noticeable performance impact. Instead, allow adding GLSL code directly to the pipeline used to draw the background texture. At the same time, port MetaBackgroundActor to modern Cogl API. https://bugzilla.gnome.org/show_bug.cgi?id=669798 --- src/Makefile.am | 2 +- src/compositor/meta-background-actor.c | 69 +++++++++++++++++++++----- src/meta/meta-background-actor.h | 28 +++++++++++ 3 files changed, 85 insertions(+), 14 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index d5b398c08..e9038a616 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -221,7 +221,7 @@ typelib_DATA = Meta-$(api_version).typelib INTROSPECTION_GIRS = Meta-$(api_version).gir Meta-$(api_version).gir: libmutter.la -@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 +@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0 @META_GIR@_EXPORT_PACKAGES = libmutter @META_GIR@_CFLAGS = $(INCLUDES) @META_GIR@_LIBS = libmutter.la diff --git a/src/compositor/meta-background-actor.c b/src/compositor/meta-background-actor.c index d70ae1b6b..ea2bf388b 100644 --- a/src/compositor/meta-background-actor.c +++ b/src/compositor/meta-background-actor.c @@ -55,7 +55,7 @@ struct _MetaScreenBackground float texture_width; float texture_height; - CoglHandle texture; + CoglTexture *texture; CoglMaterialWrapMode wrap_mode; guint have_pixmap : 1; }; @@ -63,7 +63,8 @@ struct _MetaScreenBackground struct _MetaBackgroundActorPrivate { MetaScreenBackground *background; - CoglHandle material; + CoglPipeline *pipeline; + cairo_region_t *visible_region; float dim_factor; }; @@ -140,7 +141,7 @@ update_wrap_mode_of_actor (MetaBackgroundActor *self) { MetaBackgroundActorPrivate *priv = self->priv; - cogl_material_set_layer_wrap_mode (priv->material, 0, priv->background->wrap_mode); + cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, priv->background->wrap_mode); } static void @@ -174,7 +175,7 @@ set_texture_on_actor (MetaBackgroundActor *self) * the underlying X pixmap is already gone has the tendency to trigger * X errors inside DRI. For safety, trap errors */ meta_error_trap_push (display); - cogl_material_set_layer (priv->material, 0, priv->background->texture); + cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->texture); meta_error_trap_pop (display); clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); @@ -210,7 +211,7 @@ set_texture (MetaScreenBackground *background, update_wrap_mode (background); } -/* Sets our material to paint with a 1x1 texture of the stage's background +/* Sets our pipeline to paint with a 1x1 texture of the stage's background * color; doing this when we have no pixmap allows the application to turn * off painting the stage. There might be a performance benefit to * painting in this case with a solid color, but the normal solid color @@ -250,11 +251,7 @@ meta_background_actor_dispose (GObject *object) priv->background = NULL; } - if (priv->material != COGL_INVALID_HANDLE) - { - cogl_handle_unref (priv->material); - priv->material = COGL_INVALID_HANDLE; - } + g_clear_pointer(&priv->pipeline, cogl_object_unref); G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object); } @@ -309,13 +306,13 @@ meta_background_actor_paint (ClutterActor *actor) color_component = (int)(0.5 + opacity * priv->dim_factor); - cogl_material_set_color4ub (priv->material, + cogl_pipeline_set_color4ub (priv->pipeline, color_component, color_component, color_component, opacity); - cogl_set_source (priv->material); + cogl_set_source (priv->pipeline); if (priv->visible_region) { @@ -483,7 +480,8 @@ meta_background_actor_new_for_screen (MetaScreen *screen) priv->background = meta_screen_background_get (screen); priv->background->actors = g_slist_prepend (priv->background->actors, self); - priv->material = meta_create_texture_material (NULL); + /* A CoglMaterial and a CoglPipeline are the same thing */ + priv->pipeline = (CoglPipeline*) meta_create_texture_material (NULL); set_texture_on_actor (self); update_wrap_mode_of_actor (self); @@ -625,3 +623,48 @@ meta_background_actor_screen_size_changed (MetaScreen *screen) for (l = background->actors; l; l = l->next) clutter_actor_queue_relayout (l->data); } + +/** + * meta_background_actor_add_glsl_snippet: + * @actor: a #MetaBackgroundActor + * @hook: where to insert the code + * @declarations: GLSL declarations + * @code: GLSL code + * @is_replace: wheter Cogl code should be replaced by the custom shader + * + * Adds a GLSL snippet to the pipeline used for drawing the background. + * See #CoglSnippet for details. + */ +void +meta_background_actor_add_glsl_snippet (MetaBackgroundActor *actor, + MetaSnippetHook hook, + const char *declarations, + const char *code, + gboolean is_replace) +{ + MetaBackgroundActorPrivate *priv; + CoglSnippet *snippet; + + g_return_if_fail (META_IS_BACKGROUND_ACTOR (actor)); + + priv = actor->priv; + + if (is_replace) + { + snippet = cogl_snippet_new (hook, declarations, NULL); + cogl_snippet_set_replace (snippet, code); + } + else + { + snippet = cogl_snippet_new (hook, declarations, code); + } + + if (hook == COGL_SNIPPET_HOOK_VERTEX || + hook == COGL_SNIPPET_HOOK_FRAGMENT) + cogl_pipeline_add_snippet (priv->pipeline, snippet); + else + cogl_pipeline_add_layer_snippet (priv->pipeline, 0, snippet); + + cogl_object_unref (snippet); +} + diff --git a/src/meta/meta-background-actor.h b/src/meta/meta-background-actor.h index 74f83db23..6efcc2529 100644 --- a/src/meta/meta-background-actor.h +++ b/src/meta/meta-background-actor.h @@ -62,4 +62,32 @@ GType meta_background_actor_get_type (void); ClutterActor *meta_background_actor_new_for_screen (MetaScreen *screen); +/** + * MetaSnippetHook: + * Temporary hack to work around Cogl not exporting CoglSnippetHook in + * the 1.0 API. Don't use. + */ +typedef enum { + /* Per pipeline vertex hooks */ + META_SNIPPET_HOOK_VERTEX = 0, + META_SNIPPET_HOOK_VERTEX_TRANSFORM, + + /* Per pipeline fragment hooks */ + META_SNIPPET_HOOK_FRAGMENT = 2048, + + /* Per layer vertex hooks */ + META_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM = 4096, + + /* Per layer fragment hooks */ + META_SNIPPET_HOOK_LAYER_FRAGMENT = 6144, + META_SNIPPET_HOOK_TEXTURE_LOOKUP +} MetaSnippetHook; + + +void meta_background_actor_add_glsl_snippet (MetaBackgroundActor *actor, + MetaSnippetHook hook, + const char *declarations, + const char *code, + gboolean is_replace); + #endif /* META_BACKGROUND_ACTOR_H */