[mutter/wip/gcampax/background: 65/68] Stop using GnomeBG for drawing the background
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/gcampax/background: 65/68] Stop using GnomeBG for drawing the background
- Date: Wed, 13 Feb 2013 21:32:57 +0000 (UTC)
commit 94ac7ff02cc6d9ff71b354ed6e10b00f8511fdf7
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Mon Feb 4 18:40:58 2013 +0100
Stop using GnomeBG for drawing the background
Load the image directly with GdkPixbuf and do the drawing with Cogl.
This avoids creating a screen-sized texture (which is likely to be outside
of HW limits), and avoids doing all blending and scaling in software.
For now, only simple images are supported. The next commit will restore
support for slideshows.
configure.ac | 1 -
src/compositor/meta-background-actor-private.h | 6 +-
src/compositor/meta-background-actor.c | 574 ++++++++++++++++++------
src/compositor/meta-background.c | 80 ++--
4 files changed, 464 insertions(+), 197 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 29deae9..da68ff9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,7 +75,6 @@ MUTTER_PC_MODULES="
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.13.5
cogl-1.0 >= 1.13.3
- gnome-desktop-3.0
"
GLIB_GSETTINGS
diff --git a/src/compositor/meta-background-actor-private.h b/src/compositor/meta-background-actor-private.h
index de8f13a..7b1f8b8 100644
--- a/src/compositor/meta-background-actor-private.h
+++ b/src/compositor/meta-background-actor-private.h
@@ -3,9 +3,6 @@
#ifndef META_BACKGROUND_ACTOR_PRIVATE_H
#define META_BACKGROUND_ACTOR_PRIVATE_H
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include <libgnome-desktop/gnome-bg.h>
-
#include <meta/screen.h>
#include <meta/meta-background-actor.h>
@@ -13,12 +10,13 @@ void meta_background_actor_set_visible_region (MetaBackgroundActor *self,
cairo_region_t *visible_region);
GTask *meta_background_draw_async (MetaScreen *screen,
- GnomeBG *bg,
+ const char *picture_uri,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
CoglHandle meta_background_draw_finish (MetaScreen *screen,
GAsyncResult *result,
+ char **picture_uri,
GError **error);
diff --git a/src/compositor/meta-background-actor.c b/src/compositor/meta-background-actor.c
index 057aa12..074e146 100644
--- a/src/compositor/meta-background-actor.c
+++ b/src/compositor/meta-background-actor.c
@@ -25,13 +25,8 @@
#include <config.h>
-#include <cogl/cogl-texture-pixmap-x11.h>
-
#include <clutter/clutter.h>
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include <libgnome-desktop/gnome-bg.h>
-
#include "cogl-utils.h"
#include "compositor-private.h"
#include <meta/errors.h>
@@ -47,6 +42,19 @@
*/
typedef struct _MetaBackground MetaBackground;
+typedef struct {
+ CoglTexture *texture;
+ float texture_width;
+ float texture_height;
+
+ /* ClutterColor, not CoglColor, because
+ the latter is opaque... */
+ ClutterColor colors[2];
+ GDesktopBackgroundStyle style;
+ GDesktopBackgroundShading shading;
+ char *picture_uri;
+} MetaBackgroundState;
+
struct _MetaBackground
{
GSList *actors;
@@ -54,11 +62,9 @@ struct _MetaBackground
MetaScreen *screen;
GCancellable *cancellable;
- float texture_width;
- float texture_height;
- CoglTexture *old_texture;
- CoglTexture *texture;
- GnomeBG *bg;
+ MetaBackgroundState old_state;
+ MetaBackgroundState state;
+ GSettings *settings;
GTask *rendering_task;
};
@@ -69,8 +75,8 @@ struct _MetaBackgroundActorPrivate
MetaBackground *background;
GSettings *settings;
+ CoglPipeline *solid_pipeline;
CoglPipeline *pipeline;
- CoglMaterialWrapMode wrap_mode;
cairo_region_t *visible_region;
float dim_factor;
@@ -95,20 +101,22 @@ static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
-static void meta_background_update (GnomeBG *bg,
- MetaBackground *background);
+static void meta_background_update (MetaBackground *background,
+ const char *picture_uri);
static void meta_background_actor_screen_size_changed (MetaScreen *screen,
MetaBackgroundActor *actor);
static void meta_background_actor_constructed (GObject *object);
-static void clear_old_texture (MetaBackground *background);
-static void set_texture (MetaBackground *background,
- CoglHandle texture);
+static void clear_state (MetaBackgroundState *state);
+static void set_texture (MetaBackground *background,
+ CoglHandle texture,
+ const char *picture_uri);
static void
meta_background_free (MetaBackground *background)
{
- set_texture (background, COGL_INVALID_HANDLE);
+ clear_state (&background->old_state);
+ clear_state (&background->state);
g_cancellable_cancel (background->cancellable);
g_object_unref (background->cancellable);
@@ -119,11 +127,15 @@ meta_background_free (MetaBackground *background)
}
static void
-on_settings_changed (GSettings *settings,
- const char *key,
- GnomeBG *bg)
+on_settings_changed (GSettings *settings,
+ const char *key,
+ MetaBackground *background)
{
- gnome_bg_load_from_preferences (bg, settings);
+ char *picture_uri;
+
+ picture_uri = g_settings_get_string (settings, "picture-uri");
+ meta_background_update (background, picture_uri);
+ g_free (picture_uri);
}
static GSettings *
@@ -149,26 +161,12 @@ meta_background_get (MetaScreen *screen,
g_object_set_qdata_full (G_OBJECT (settings), background_quark,
background, (GDestroyNotify) meta_background_free);
- background->bg = gnome_bg_new ();
+ background->settings = settings;
+ background->screen = screen;
g_signal_connect (settings, "changed",
- G_CALLBACK (on_settings_changed), background->bg);
- on_settings_changed (settings, NULL, background->bg);
-
- background->screen = screen;
- background->texture_width = -1;
- background->texture_height = -1;
-
- g_signal_connect (background->bg, "transitioned",
- G_CALLBACK (meta_background_update), background);
- g_signal_connect (background->bg, "changed",
- G_CALLBACK (meta_background_update), background);
-
- /* GnomeBG has queued a changed event, but we need to start rendering now,
- or it will be too late when we paint the first frame.
- */
- g_object_set_data (G_OBJECT (background->bg), "ignore-pending-change", GINT_TO_POINTER (TRUE));
- meta_background_update (background->bg, background);
+ G_CALLBACK (on_settings_changed), background);
+ on_settings_changed (settings, NULL, background);
}
return background;
@@ -181,80 +179,79 @@ update_actor_pipeline (MetaBackgroundActor *self,
MetaBackgroundActorPrivate *priv = self->priv;
priv->is_crossfading = crossfade;
- cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, priv->wrap_mode);
-
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
+static inline void
+clear_state (MetaBackgroundState *state)
+{
+ g_clear_pointer (&state->texture, cogl_handle_unref);
+ g_free (state->picture_uri);
+ state->picture_uri = NULL;
+}
+
static void
crossfade_completed (ClutterTimeline *timeline,
MetaBackgroundActor *actor)
{
- clear_old_texture (actor->priv->background);
+ clear_state (&actor->priv->background->old_state);
update_actor_pipeline (actor, FALSE);
}
-static void
-clear_old_texture (MetaBackground *background)
+static inline gboolean
+state_is_valid (MetaBackgroundState *state)
{
- if (background->old_texture != COGL_INVALID_HANDLE)
- {
- cogl_handle_unref (background->old_texture);
- background->old_texture = COGL_INVALID_HANDLE;
- }
+ return state->texture != COGL_INVALID_HANDLE;
+}
+
+static inline void
+get_color_from_settings (GSettings *settings,
+ const char *key,
+ ClutterColor *color)
+{
+ char *str;
+
+ str = g_settings_get_string (settings, key);
+ clutter_color_from_string (color, str);
+
+ g_free (str);
}
static void
set_texture (MetaBackground *background,
- CoglHandle texture)
+ CoglHandle texture,
+ const char *picture_uri)
{
GSList *l;
gboolean crossfade;
int width, height;
- CoglMaterialWrapMode wrap_mode;
- if (background->old_texture != COGL_INVALID_HANDLE)
- {
- cogl_handle_unref (background->old_texture);
- background->old_texture = COGL_INVALID_HANDLE;
- }
+ g_assert (texture != COGL_INVALID_HANDLE);
- if (texture != COGL_INVALID_HANDLE)
- {
- background->old_texture = background->texture;
- background->texture = cogl_handle_ref (texture);
- }
- else if (background->texture != COGL_INVALID_HANDLE)
- {
- cogl_handle_unref (background->texture);
- background->texture = COGL_INVALID_HANDLE;
- }
+ clear_state (&background->old_state);
- if (texture != COGL_INVALID_HANDLE &&
- background->old_texture != COGL_INVALID_HANDLE)
- crossfade = TRUE;
- else
- crossfade = FALSE;
+ if (state_is_valid (&background->state))
+ background->old_state = background->state;
- background->texture_width = cogl_texture_get_width (background->texture);
- background->texture_height = cogl_texture_get_height (background->texture);
+ background->state.texture = cogl_handle_ref (texture);
+ get_color_from_settings (background->settings, "primary-color",
+ &background->state.colors[0]);
+ get_color_from_settings (background->settings, "secondary-color",
+ &background->state.colors[1]);
+ background->state.style = g_settings_get_enum (background->settings, "picture-options");
+ background->state.shading = g_settings_get_enum (background->settings, "color-shading-type");
+ background->state.texture_width = cogl_texture_get_width (background->state.texture);
+ background->state.texture_height = cogl_texture_get_height (background->state.texture);
+ background->state.picture_uri = g_strdup (picture_uri);
- meta_screen_get_size (background->screen, &width, &height);
+ crossfade = state_is_valid (&background->old_state);
- /* We turn off repeating when we have a full-screen pixmap to keep from
- * getting artifacts from one side of the image sneaking into the other
- * side of the image via bilinear filtering.
- */
- if (width == background->texture_width && height == background->texture_height)
- wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE;
- else
- wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
+ meta_screen_get_size (background->screen, &width, &height);
for (l = background->actors; l; l = l->next)
{
MetaBackgroundActor *actor = l->data;
- actor->priv->wrap_mode = wrap_mode;
update_actor_pipeline (actor, crossfade);
if (crossfade)
@@ -286,7 +283,7 @@ static inline void
meta_background_ensure_rendered (MetaBackground *background)
{
if (G_LIKELY (background->rendering_task == NULL ||
- background->texture != COGL_INVALID_HANDLE))
+ background->state.texture != COGL_INVALID_HANDLE))
return;
g_task_wait_sync (background->rendering_task);
@@ -306,6 +303,7 @@ meta_background_actor_dispose (GObject *object)
priv->background = NULL;
}
+ g_clear_pointer (&priv->solid_pipeline, cogl_object_unref);
g_clear_pointer (&priv->pipeline, cogl_object_unref);
g_clear_object (&priv->settings);
@@ -350,40 +348,345 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
}
static void
-paint_background (MetaBackgroundActor *self)
+paint_gradient (MetaBackgroundState *state,
+ CoglPipeline *pipeline,
+ float color_factor,
+ float alpha_factor,
+ ClutterActorBox *monitor_box,
+ float actor_width,
+ float actor_height,
+ float screen_width,
+ float screen_height)
+{
+ ClutterBackend *backend = clutter_get_default_backend ();
+ CoglContext *context = clutter_backend_get_cogl_context (backend);
+ CoglPrimitive *primitive;
+ int i;
+
+ /* Order is:
+ * 1 -- 0
+ * | |
+ * 3 -- 2
+ *
+ * (tri strip with counter-clockwise winding)
+ */
+ CoglVertexP2C4 vertices[4] = {
+ { monitor_box->x2 * (actor_width / screen_width), monitor_box->y1 * (actor_height / screen_height),
+ state->colors[0].red, state->colors[0].green, state->colors[0].blue, state->colors[0].alpha },
+
+ { monitor_box->x1 * (actor_width / screen_width), monitor_box->y1 * (actor_height / screen_height),
+ state->colors[0].red, state->colors[0].green, state->colors[0].blue, state->colors[0].alpha },
+
+ { monitor_box->x2 * (actor_width / screen_width), monitor_box->y2 * (actor_height / screen_height),
+ state->colors[0].red, state->colors[0].green, state->colors[0].blue, state->colors[0].alpha },
+
+ { monitor_box->x1 * (actor_width / screen_width), monitor_box->y2 * (actor_height / screen_height),
+ state->colors[0].red, state->colors[0].green, state->colors[0].blue, state->colors[0].alpha },
+ };
+
+ /* These styles cover the entire screen */
+ if (state->style == G_DESKTOP_BACKGROUND_STYLE_WALLPAPER ||
+ state->style == G_DESKTOP_BACKGROUND_STYLE_STRETCHED ||
+ state->style == G_DESKTOP_BACKGROUND_STYLE_ZOOM)
+ return;
+
+ if (state->shading != G_DESKTOP_BACKGROUND_SHADING_SOLID)
+ {
+ if (state->shading == G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL)
+ {
+ vertices[2].r = vertices[3].r = state->colors[1].red;
+ vertices[2].g = vertices[3].g = state->colors[1].green;
+ vertices[2].b = vertices[3].b = state->colors[1].blue;
+ vertices[2].a = vertices[3].a = state->colors[1].alpha;
+ }
+ else
+ {
+ vertices[0].r = vertices[2].r = state->colors[1].red;
+ vertices[0].g = vertices[2].g = state->colors[1].green;
+ vertices[0].b = vertices[2].b = state->colors[1].blue;
+ vertices[0].a = vertices[2].a = state->colors[1].alpha;
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ vertices[i].r *= color_factor;
+ vertices[i].g *= color_factor;
+ vertices[i].b *= color_factor;
+ vertices[i].a *= alpha_factor;
+ }
+
+ primitive = cogl_primitive_new_p2c4 (context,
+ COGL_VERTICES_MODE_TRIANGLE_STRIP,
+ 4, vertices);
+ cogl_framebuffer_draw_primitive (cogl_get_draw_framebuffer (),
+ pipeline, primitive);
+ cogl_object_unref (primitive);
+}
+
+static void
+paint_background_box (MetaBackgroundState *state,
+ CoglPipeline *pipeline,
+ float color_factor,
+ float alpha_factor,
+ ClutterActorBox *monitor_box,
+ float actor_width,
+ float actor_height,
+ float screen_width,
+ float screen_height)
+{
+ CoglPrimitive *primitive;
+ CoglPipeline *pipeline_copy;
+ ClutterBackend *backend = clutter_get_default_backend ();
+ CoglContext *context = clutter_backend_get_cogl_context (backend);
+ int i;
+ float monitor_width, monitor_height;
+ float image_width, image_height;
+
+ /* Order is:
+ * 1 -- 0
+ * | |
+ * 3 -- 2
+ *
+ * (tri strip with counter-clockwise winding)
+ */
+ CoglVertexP2T2 vertices[4];
+
+ if (state->style == G_DESKTOP_BACKGROUND_STYLE_NONE)
+ return;
+
+ vertices[0].s = 1.0;
+ vertices[0].t = 0.0;
+ vertices[1].s = 0.0;
+ vertices[1].t = 0.0;
+ vertices[2].s = 1.0;
+ vertices[2].t = 1.0;
+ vertices[3].s = 0.0;
+ vertices[3].t = 1.0;
+
+ clutter_actor_box_get_size (monitor_box, &monitor_width, &monitor_height);
+
+ switch (state->style) {
+ case G_DESKTOP_BACKGROUND_STYLE_STRETCHED:
+ /* Stretched:
+ The easy case: the image is stretched to cover the monitor fully.
+ */
+ image_width = monitor_width;
+ image_height = monitor_height;
+ break;
+
+ case G_DESKTOP_BACKGROUND_STYLE_SPANNED:
+ /* Spanned:
+ The image is scaled to fit and drawn across all monitors.
+ If this is the case, monitor_box is actually the union of all monitors,
+ and we can fall through to scaled.
+ */
+ case G_DESKTOP_BACKGROUND_STYLE_SCALED:
+ /* Scaled:
+ The image is scaled to fit (so one dimension is always covered)
+ */
+ {
+ float scaling_factor = MIN (monitor_width / state->texture_width,
+ monitor_height / state->texture_height);
+ image_width = state->texture_width * scaling_factor;
+ image_height = state->texture_height * scaling_factor;
+ }
+ break;
+
+ case G_DESKTOP_BACKGROUND_STYLE_ZOOM:
+ /* Zoom:
+ The image is zoomed to fill the screen.
+ */
+ {
+ float scaling_factor = MAX (monitor_width / state->texture_width,
+ monitor_height / state->texture_height);
+ image_width = state->texture_width * scaling_factor;
+ image_height = state->texture_height * scaling_factor;
+ }
+ break;
+
+ case G_DESKTOP_BACKGROUND_STYLE_CENTERED:
+ /* Centered:
+ The image is centered and not scaled.
+ */
+ case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER:
+ /* Wallpaper:
+ The image is not scaled but tiled.
+ */
+
+ image_width = state->texture_width;
+ image_height = state->texture_height;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ pipeline_copy = cogl_pipeline_copy (pipeline);
+ cogl_pipeline_set_color4f (pipeline_copy,
+ color_factor,
+ color_factor,
+ color_factor,
+ alpha_factor);
+
+ if (state->style == G_DESKTOP_BACKGROUND_STYLE_WALLPAPER)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ vertices[i].s *= (monitor_width / image_width);
+ vertices[i].t *= (monitor_height / image_height);
+ }
+
+ vertices[0].x = monitor_width;
+ vertices[0].y = 0;
+ vertices[1].x = 0;
+ vertices[1].y = 0;
+ vertices[2].x = monitor_width;
+ vertices[2].y = monitor_height;
+ vertices[3].x = 0;
+ vertices[3].y = monitor_height;
+
+ cogl_pipeline_set_layer_wrap_mode (pipeline_copy, 0, COGL_PIPELINE_WRAP_MODE_REPEAT);
+ }
+ else
+ {
+ /* Coordinates of the vertices, relative to the image */
+ float x0, x1, y0, y1;
+
+ x0 = (monitor_width - image_width) / 2;
+ y0 = (monitor_height - image_height) / 2;
+ x1 = x0 + image_width;
+ y1 = y0 + image_height;
+
+ vertices[0].x = x1;
+ vertices[0].y = y0;
+ vertices[1].x = x0;
+ vertices[1].y = y0;
+ vertices[2].x = x1;
+ vertices[2].y = y1;
+ vertices[3].x = x0;
+ vertices[3].y = y1;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ vertices[i].x *= (actor_width / screen_width);
+ vertices[i].y *= (actor_height / screen_height);
+ }
+
+ primitive = cogl_primitive_new_p2t2 (context,
+ COGL_VERTICES_MODE_TRIANGLE_STRIP,
+ 4, vertices);
+ cogl_framebuffer_draw_primitive (cogl_get_draw_framebuffer (),
+ pipeline_copy, primitive);
+ cogl_object_unref (primitive);
+ cogl_object_unref (pipeline_copy);
+}
+
+static void
+paint_background_unclipped (MetaBackgroundActor *self,
+ MetaBackgroundState *state,
+ float color_factor,
+ float alpha_factor)
+{
+ MetaBackgroundActorPrivate *priv;
+ int screen_width, screen_height;
+ float actor_width, actor_height;
+ ClutterActorBox monitor_box;
+
+ priv = self->priv;
+ clutter_actor_get_size (CLUTTER_ACTOR (self), &actor_width, &actor_height);
+ meta_screen_get_size (priv->screen, &screen_width, &screen_height);
+
+ if (state->style == G_DESKTOP_BACKGROUND_STYLE_SPANNED)
+ {
+ /* Prepare a box covering the screen */
+ monitor_box.x1 = 0;
+ monitor_box.y1 = 0;
+ monitor_box.x2 = screen_width;
+ monitor_box.y2 = screen_height;
+
+ paint_gradient (state, priv->solid_pipeline,
+ color_factor, alpha_factor,
+ &monitor_box,
+ actor_width, actor_height,
+ screen_width, screen_height);
+ paint_background_box (state, priv->pipeline,
+ color_factor, alpha_factor,
+ &monitor_box,
+ actor_width, actor_height,
+ screen_width, screen_height);
+ }
+ else
+ {
+ /* Iterate each monitor */
+ int i, n;
+ MetaRectangle monitor_rect;
+
+ n = meta_screen_get_n_monitors (priv->screen);
+ for (i = 0; i < n; i++)
+ {
+ meta_screen_get_monitor_geometry (priv->screen, i, &monitor_rect);
+ monitor_box.x1 = monitor_rect.x;
+ monitor_box.y1 = monitor_rect.y;
+ monitor_box.x2 = monitor_rect.x + monitor_rect.width;
+ monitor_box.y2 = monitor_rect.y + monitor_rect.height;
+
+ /* Sad truth: we need to paint twice to get the border of the image
+ right.
+
+ A similar effect could be obtained with GL_CLAMP_TO_BORDER, but
+ Cogl doesn't expose that.
+ */
+ paint_gradient (state, priv->solid_pipeline,
+ color_factor, alpha_factor,
+ &monitor_box,
+ actor_width, actor_height,
+ screen_width, screen_height);
+ paint_background_box (state, priv->pipeline,
+ color_factor, alpha_factor,
+ &monitor_box,
+ actor_width, actor_height,
+ screen_width, screen_height);
+ }
+ }
+}
+
+static void
+paint_background (MetaBackgroundActor *self,
+ MetaBackgroundState *state,
+ float color_factor,
+ float alpha_factor)
{
MetaBackgroundActorPrivate *priv = self->priv;
- float width, height;
- ClutterActorBox alloc;
- clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &alloc);
- clutter_actor_box_get_size (&alloc, &width, &height);
+ cogl_pipeline_set_layer_texture (priv->pipeline, 0, state->texture);
if (priv->visible_region)
{
int n_rectangles = cairo_region_num_rectangles (priv->visible_region);
int i;
+ cogl_path_new ();
+
for (i = 0; i < n_rectangles; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (priv->visible_region, i, &rect);
- cogl_rectangle_with_texture_coords (rect.x, rect.y,
- rect.x + rect.width, rect.y + rect.height,
- rect.x / priv->background->texture_width,
- rect.y / priv->background->texture_height,
- (rect.x + rect.width) / priv->background->texture_width,
- (rect.y + rect.height) / priv->background->texture_height);
+ cogl_path_rectangle (rect.x,
+ rect.y,
+ rect.x + rect.width,
+ rect.y + rect.height);
}
+
+ cogl_clip_push_from_path ();
+ paint_background_unclipped (self, state, color_factor, alpha_factor);
+ cogl_clip_pop ();
}
else
{
- cogl_rectangle_with_texture_coords (0.0f, 0.0f,
- width, height,
- 0.0f, 0.0f,
- width / priv->background->texture_width,
- height / priv->background->texture_height);
+ paint_background_unclipped (self, state, color_factor, alpha_factor);
}
}
@@ -409,29 +712,16 @@ meta_background_actor_paint (ClutterActor *actor)
second_color_factor = (opacity / 256.f) * priv->dim_factor * (1 - crossfade_progress);
second_alpha_factor = (opacity / 256.f) * (1 - crossfade_progress);
- cogl_set_source (priv->pipeline);
-
if (priv->is_crossfading)
{
- cogl_pipeline_set_color4f (priv->pipeline,
- second_color_factor,
- second_color_factor,
- second_color_factor,
- second_alpha_factor);
- cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->old_texture);
-
- paint_background (self);
+ paint_background (self, &priv->background->old_state,
+ second_color_factor,
+ second_alpha_factor);
}
-
- cogl_pipeline_set_color4f (priv->pipeline,
- first_color_factor,
- first_color_factor,
- first_color_factor,
- first_alpha_factor);
- cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->texture);
-
- paint_background (self);
+ paint_background (self, &priv->background->state,
+ first_color_factor,
+ first_alpha_factor);
}
static gboolean
@@ -644,12 +934,13 @@ meta_background_actor_init (MetaBackgroundActor *self)
MetaBackgroundActorPrivate);
priv->dim_factor = 1.0;
priv->crossfade_progress = 0.0;
- priv->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
}
static void
meta_background_actor_constructed (GObject *object)
{
+ ClutterBackend *backend = clutter_get_default_backend ();
+ CoglContext *context = clutter_backend_get_cogl_context (backend);
MetaBackgroundActor *self;
MetaBackgroundActorPrivate *priv;
@@ -661,10 +952,12 @@ meta_background_actor_constructed (GObject *object)
priv->background = meta_background_get (priv->screen, priv->settings);
priv->background->actors = g_slist_prepend (priv->background->actors, self);
- priv->pipeline = meta_create_texture_material (priv->background->texture);
-
- if (priv->background->texture != COGL_INVALID_HANDLE)
- update_actor_pipeline (self, FALSE);
+ priv->solid_pipeline = cogl_pipeline_new (context);
+ priv->pipeline = meta_create_texture_material (COGL_INVALID_HANDLE);
+ cogl_pipeline_set_layer_filters (priv->pipeline, 0,
+ COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR,
+ COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR);
+ update_actor_pipeline (self, FALSE);
}
/**
@@ -697,9 +990,10 @@ on_background_drawn (GObject *object,
MetaBackground *background;
CoglHandle texture;
GError *error;
+ char *picture_uri;
error = NULL;
- texture = meta_background_draw_finish (META_SCREEN (object), result, &error);
+ texture = meta_background_draw_finish (META_SCREEN (object), result, &picture_uri, &error);
/* Don't even access user_data if cancelled, it might be already
freed */
@@ -716,8 +1010,9 @@ on_background_drawn (GObject *object,
if (texture != COGL_INVALID_HANDLE)
{
- set_texture (background, texture);
+ set_texture (background, texture, picture_uri);
cogl_handle_unref (texture);
+ g_free (picture_uri);
return;
}
else
@@ -730,17 +1025,20 @@ on_background_drawn (GObject *object,
/*
* meta_background_update:
- * @bg: the #GnomeBG that triggered the update
* @background: a #MetaBackground
+ * @picture_uri: the new image URI
*
* Forces a redraw of the background. The redraw happens asynchronously in
* a thread, and the actual on screen change is therefore delayed until
* the redraw is finished.
*/
void
-meta_background_update (GnomeBG *bg,
- MetaBackground *background)
+meta_background_update (MetaBackground *background,
+ const char *picture_uri)
{
+ if (g_strcmp0 (background->state.picture_uri, picture_uri) == 0)
+ return;
+
if (background->cancellable)
{
g_cancellable_cancel (background->cancellable);
@@ -750,8 +1048,9 @@ meta_background_update (GnomeBG *bg,
g_clear_object (&background->rendering_task);
background->cancellable = g_cancellable_new ();
+
background->rendering_task = meta_background_draw_async (background->screen,
- bg,
+ picture_uri,
background->cancellable,
on_background_drawn, background);
}
@@ -799,21 +1098,6 @@ static void
meta_background_actor_screen_size_changed (MetaScreen *screen,
MetaBackgroundActor *actor)
{
- MetaBackgroundActorPrivate *priv;
- MetaBackground *background;
- int width, height;
-
- priv = actor->priv;
- background = priv->background;
-
- meta_screen_get_size (screen, &width, &height);
-
- if (width == background->texture_width && height == background->texture_height)
- priv->wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE;
- else
- priv->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
-
- update_actor_pipeline (actor, actor->priv->is_crossfading);
clutter_actor_queue_relayout (CLUTTER_ACTOR (actor));
}
diff --git a/src/compositor/meta-background.c b/src/compositor/meta-background.c
index 080dcef..d427d15 100644
--- a/src/compositor/meta-background.c
+++ b/src/compositor/meta-background.c
@@ -29,78 +29,60 @@
#include "meta-background-actor-private.h"
#include <core/screen-private.h>
-typedef struct {
- GnomeBG *bg;
- GdkPixbuf *pixbuf;
-
- GdkRectangle *monitors;
- int num_monitors;
-} TaskData;
-
-static void
-task_data_free (gpointer task_data)
-{
- TaskData *td = task_data;
-
- g_object_unref (td->bg);
- g_object_unref (td->pixbuf);
-
- g_free (td->monitors);
-
- g_slice_free (TaskData, td);
-}
-
static void
meta_background_draw_thread (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
- TaskData *td = task_data;
+ GFile *file;
+ GInputStream *stream;
+ GdkPixbuf *pixbuf;
+ GError *error;
+
+ /* TODO: handle slideshows and other complications */
- gnome_bg_draw_areas (td->bg,
- td->pixbuf,
- TRUE,
- td->monitors,
- td->num_monitors);
+ file = g_file_new_for_uri (task_data);
- g_task_return_pointer (task, g_object_ref (td->pixbuf), g_object_unref);
+ error = NULL;
+ stream = G_INPUT_STREAM (g_file_read (file, cancellable, &error));
+ if (stream == NULL)
+ {
+ g_object_unref (file);
+ g_task_return_error (task, error);
+ return;
+ }
+
+ pixbuf = gdk_pixbuf_new_from_stream (stream, cancellable, &error);
+ if (pixbuf == NULL)
+ {
+ g_object_unref (file);
+ g_object_unref (stream);
+ g_task_return_error (task, error);
+ }
+
+ g_task_return_pointer (task, pixbuf, g_object_unref);
+ g_object_unref (file);
+ g_object_unref (stream);
}
GTask *
meta_background_draw_async (MetaScreen *screen,
- GnomeBG *bg,
+ const char *picture_uri,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
- TaskData *td;
- int i;
g_return_val_if_fail (META_IS_SCREEN (screen), NULL);
- g_return_val_if_fail (GNOME_IS_BG (bg), NULL);
task = g_task_new (screen, cancellable, callback, user_data);
g_task_set_source_tag (task, meta_background_draw_async);
g_task_set_return_on_cancel (task, TRUE);
g_task_set_check_cancellable (task, TRUE);
- td = g_slice_new (TaskData);
- td->bg = g_object_ref (bg);
- td->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- FALSE, /* has alpha */
- 8, /* bits per sample */
- screen->rect.width,
- screen->rect.height);
-
- td->num_monitors = meta_screen_get_n_monitors (screen);
- td->monitors = g_new (GdkRectangle, td->num_monitors);
- for (i = 0; i < td->num_monitors; i++)
- meta_screen_get_monitor_geometry (screen, i, (MetaRectangle*)(td->monitors + i));
-
- g_task_set_task_data (task, td, task_data_free);
-
+ g_task_set_task_data (task, g_strdup (picture_uri), g_free);
g_task_run_in_thread (task, meta_background_draw_thread);
return task;
@@ -109,6 +91,7 @@ meta_background_draw_async (MetaScreen *screen,
CoglHandle
meta_background_draw_finish (MetaScreen *screen,
GAsyncResult *result,
+ char **picture_uri,
GError **error)
{
GdkPixbuf *pixbuf;
@@ -118,6 +101,9 @@ meta_background_draw_finish (MetaScreen *screen,
if (pixbuf == NULL)
return COGL_INVALID_HANDLE;
+ if (picture_uri != NULL)
+ *picture_uri = g_strdup (g_task_get_task_data (G_TASK (result)));
+
handle = cogl_texture_new_from_data (gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
COGL_TEXTURE_NO_ATLAS | COGL_TEXTURE_NO_SLICING,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]