Compare commits
	
		
			3 Commits
		
	
	
		
			gbsneto/co
			...
			wip/backgr
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					3c2284e69a | ||
| 
						 | 
					c632dcdd98 | ||
| 
						 | 
					786f358888 | 
@@ -100,8 +100,10 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	compositor/compositor.c			\
 | 
			
		||||
	compositor/compositor-private.h		\
 | 
			
		||||
	compositor/meta-background.c		\
 | 
			
		||||
	compositor/meta-background-private.h	\
 | 
			
		||||
	compositor/meta-background-actor.c	\
 | 
			
		||||
	compositor/meta-background-actor-private.h	\
 | 
			
		||||
	compositor/meta-background-image.c	\
 | 
			
		||||
	compositor/meta-background-group.c	\
 | 
			
		||||
	compositor/meta-cullable.c		\
 | 
			
		||||
	compositor/meta-cullable.h		\
 | 
			
		||||
@@ -133,6 +135,7 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	meta/compositor.h			\
 | 
			
		||||
	meta/meta-background.h			\
 | 
			
		||||
	meta/meta-background-actor.h		\
 | 
			
		||||
	meta/meta-background-image.h		\
 | 
			
		||||
	meta/meta-background-group.h		\
 | 
			
		||||
	meta/meta-plugin.h			\
 | 
			
		||||
	meta/meta-shadow-factory.h		\
 | 
			
		||||
@@ -282,9 +285,10 @@ libmutterinclude_headers =			\
 | 
			
		||||
	meta/keybindings.h			\
 | 
			
		||||
	meta/main.h				\
 | 
			
		||||
	meta/meta-backend.h			\
 | 
			
		||||
	meta/meta-background-actor.h		\
 | 
			
		||||
	meta/meta-background-group.h		\
 | 
			
		||||
	meta/meta-background.h			\
 | 
			
		||||
	meta/meta-background-actor.h		\
 | 
			
		||||
	meta/meta-background-image.h		\
 | 
			
		||||
	meta/meta-background-group.h		\
 | 
			
		||||
	meta/meta-cursor-tracker.h		\
 | 
			
		||||
	meta/meta-idle-monitor.h		\
 | 
			
		||||
	meta/meta-plugin.h			\
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,12 @@ round_to_fixed (float x)
 | 
			
		||||
  return roundf (x * 256);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Help macros to scale from OpenGL <-1,1> coordinates system to
 | 
			
		||||
 * window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c
 | 
			
		||||
 */
 | 
			
		||||
#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
 | 
			
		||||
#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
 | 
			
		||||
 | 
			
		||||
/* This helper function checks if (according to our fixed point precision)
 | 
			
		||||
 * the vertices @verts form a box of width @widthf and height @heightf
 | 
			
		||||
 * located at integral coordinates. These coordinates are returned
 | 
			
		||||
@@ -118,3 +124,67 @@ meta_actor_is_untransformed (ClutterActor *actor,
 | 
			
		||||
  return meta_actor_vertices_are_untransformed (verts, widthf, heightf, x_origin, y_origin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_actor_painting_untransformed:
 | 
			
		||||
 * @paint_width: the width of the painted area
 | 
			
		||||
 * @paint_height: the height of the painted area
 | 
			
		||||
 * @x_origin: if the transform is only an integer translation
 | 
			
		||||
 *  then the X coordinate of the location of the origin under the transformation
 | 
			
		||||
 *  from drawing space to screen pixel space is returned here.
 | 
			
		||||
 * @y_origin: if the transform is only an integer translation
 | 
			
		||||
 *  then the X coordinate of the location of the origin under the transformation
 | 
			
		||||
 *  from drawing space to screen pixel space is returned here.
 | 
			
		||||
 *
 | 
			
		||||
 * Determines if the current painting transform is an integer translation.
 | 
			
		||||
 * This can differ from the result of meta_actor_is_untransformed() when
 | 
			
		||||
 * painting an actor if we're inside a inside a clone paint. @paint_width
 | 
			
		||||
 * and @paint_height are used to determine the vertices of the rectangle
 | 
			
		||||
 * we check to see if the painted area is "close enough" to the integer
 | 
			
		||||
 * transform.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_actor_painting_untransformed (int              paint_width,
 | 
			
		||||
                                   int              paint_height,
 | 
			
		||||
                                   int             *x_origin,
 | 
			
		||||
                                   int             *y_origin)
 | 
			
		||||
{
 | 
			
		||||
  CoglMatrix modelview, projection, modelview_projection;
 | 
			
		||||
  ClutterVertex vertices[4];
 | 
			
		||||
  float viewport[4];
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  cogl_get_modelview_matrix (&modelview);
 | 
			
		||||
  cogl_get_projection_matrix (&projection);
 | 
			
		||||
 | 
			
		||||
  cogl_matrix_multiply (&modelview_projection,
 | 
			
		||||
                        &projection,
 | 
			
		||||
                        &modelview);
 | 
			
		||||
 | 
			
		||||
  vertices[0].x = 0;
 | 
			
		||||
  vertices[0].y = 0;
 | 
			
		||||
  vertices[0].z = 0;
 | 
			
		||||
  vertices[1].x = paint_width;
 | 
			
		||||
  vertices[1].y = 0;
 | 
			
		||||
  vertices[1].z = 0;
 | 
			
		||||
  vertices[2].x = 0;
 | 
			
		||||
  vertices[2].y = paint_height;
 | 
			
		||||
  vertices[2].z = 0;
 | 
			
		||||
  vertices[3].x = paint_width;
 | 
			
		||||
  vertices[3].y = paint_height;
 | 
			
		||||
  vertices[3].z = 0;
 | 
			
		||||
 | 
			
		||||
  cogl_get_viewport (viewport);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < 4; i++)
 | 
			
		||||
    {
 | 
			
		||||
      float w = 1;
 | 
			
		||||
      cogl_matrix_transform_point (&modelview_projection, &vertices[i].x, &vertices[i].y, &vertices[i].z, &w);
 | 
			
		||||
      vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w,
 | 
			
		||||
                                      viewport[2], viewport[0]);
 | 
			
		||||
      vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w,
 | 
			
		||||
                                      viewport[3], viewport[1]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return meta_actor_vertices_are_untransformed (vertices, paint_width, paint_height, x_origin, y_origin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,4 +31,9 @@ gboolean meta_actor_is_untransformed (ClutterActor *actor,
 | 
			
		||||
                                      int          *x_origin,
 | 
			
		||||
                                      int          *y_origin);
 | 
			
		||||
 | 
			
		||||
gboolean meta_actor_painting_untransformed (int         paint_width,
 | 
			
		||||
                                            int         paint_height,
 | 
			
		||||
                                            int        *x_origin,
 | 
			
		||||
                                            int        *y_origin);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_CLUTTER_UTILS_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -64,3 +64,37 @@ meta_create_texture_pipeline (CoglTexture *src_texture)
 | 
			
		||||
 | 
			
		||||
  return pipeline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean is_pot(int x)
 | 
			
		||||
{
 | 
			
		||||
  return x > 0 && (x & (x - 1)) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CoglTexture *
 | 
			
		||||
meta_create_large_texture (int                   width,
 | 
			
		||||
                           int                   height,
 | 
			
		||||
                           CoglTextureComponents components)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend = clutter_get_default_backend ();
 | 
			
		||||
  CoglContext *ctx = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
 | 
			
		||||
  gboolean should_use_rectangle = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!(is_pot (width) && is_pot (height)) &&
 | 
			
		||||
      !cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT))
 | 
			
		||||
    {
 | 
			
		||||
      if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
 | 
			
		||||
        should_use_rectangle = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (should_use_rectangle)
 | 
			
		||||
    texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (ctx,
 | 
			
		||||
                                                                  width, height));
 | 
			
		||||
  else
 | 
			
		||||
    texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
 | 
			
		||||
                                                           width, height));
 | 
			
		||||
  cogl_texture_set_components (texture, components);
 | 
			
		||||
 | 
			
		||||
  return texture;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,4 +25,8 @@
 | 
			
		||||
 | 
			
		||||
CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture);
 | 
			
		||||
 | 
			
		||||
CoglTexture *meta_create_large_texture (int                   width,
 | 
			
		||||
                                        int                   height,
 | 
			
		||||
                                        CoglTextureComponents components);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_COGL_UTILS_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2009 Sander Dijkhuis
 | 
			
		||||
 * Copyright 2010 Red Hat, Inc.
 | 
			
		||||
 * Copyright 2014 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
@@ -26,23 +26,119 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
/*
 | 
			
		||||
 * The overall model drawing model of this widget is that we have one
 | 
			
		||||
 * texture, or two interpolated textures, possibly with alpha or
 | 
			
		||||
 * margins that let the underlying background show through, blended
 | 
			
		||||
 * over a solid color or a gradient. The result of that combination
 | 
			
		||||
 * can then be affected by a "vignette" that darkens the background
 | 
			
		||||
 * away from a central point (or as a no-GLSL fallback, simply darkens
 | 
			
		||||
 * the background) and by overall opacity.
 | 
			
		||||
 *
 | 
			
		||||
 * As of GNOME 3.14, GNOME is only using a fraction of this when the
 | 
			
		||||
 * user sets the background through the control center - what can be
 | 
			
		||||
 * set is:
 | 
			
		||||
 *
 | 
			
		||||
 *  A single image without a border
 | 
			
		||||
 *  An animation of images without a border that blend together,
 | 
			
		||||
 *   with the blend changing every 4-5 minutes
 | 
			
		||||
 *  A solid color with a repeated noise texture blended over it
 | 
			
		||||
 *
 | 
			
		||||
 * This all is pretty easy to do in a fragment shader, except when:
 | 
			
		||||
 *
 | 
			
		||||
 *  A) We don't have GLSL - in this case, the operation of
 | 
			
		||||
 *     interpolating the two textures and blending the result over the
 | 
			
		||||
 *     background can't be expressed with Cogl's fixed-function layer
 | 
			
		||||
 *     combining (which is confined to what GL's texture environment
 | 
			
		||||
 *     combining can do) So we can only handle the above directly if
 | 
			
		||||
 *     there are no margins or alpha.
 | 
			
		||||
 *
 | 
			
		||||
 *  B) The image textures are sliced. Texture size limits on older
 | 
			
		||||
 *     hardware (pre-965 intel hardware, r300, etc.)  is often 2048,
 | 
			
		||||
 *     and it would be common to use a texture larger than this for a
 | 
			
		||||
 *     background and expect it to be scaled down. Cogl can compensate
 | 
			
		||||
 *     for this by breaking the texture up into multiple textures, but
 | 
			
		||||
 *     can't multitexture with sliced textures. So we can only handle
 | 
			
		||||
 *     the above if there's a single texture.
 | 
			
		||||
 *
 | 
			
		||||
 * However, even when we *can* represent everything in a single pass,
 | 
			
		||||
 * it's not necessarily efficient. If we want to draw a 1024x768
 | 
			
		||||
 * background, it's pretty inefficient to bilinearly texture from
 | 
			
		||||
 * two 2560x1440 images and mix that. So the drawing model we take
 | 
			
		||||
 * here is that MetaBackground generates a single texture (which
 | 
			
		||||
 * might be a 1x1 texture for a solid color, or a 1x2 texture for a
 | 
			
		||||
 * gradient, or a repeated texture for wallpaper, or a pre-rendered
 | 
			
		||||
 * texture the size of the screen), and we draw with that, possibly
 | 
			
		||||
 * adding the vignette and opacity.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl-texture-pixmap-x11.h>
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
 | 
			
		||||
#include "cogl-utils.h"
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "clutter-utils.h"
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include <meta/meta-background.h>
 | 
			
		||||
#include "meta-background-actor-private.h"
 | 
			
		||||
#include "meta-background-private.h"
 | 
			
		||||
#include "meta-cullable.h"
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_META_SCREEN = 1,
 | 
			
		||||
  PROP_MONITOR,
 | 
			
		||||
  PROP_BACKGROUND,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  CHANGED_BACKGROUND = 1 << 0,
 | 
			
		||||
  CHANGED_EFFECTS = 1 << 2,
 | 
			
		||||
  CHANGED_VIGNETTE_PARAMETERS = 1 << 3,
 | 
			
		||||
  CHANGED_ALL = 0xFFFF
 | 
			
		||||
} ChangedFlags;
 | 
			
		||||
 | 
			
		||||
#define VERTEX_SHADER_DECLARATIONS                                      \
 | 
			
		||||
"uniform vec2 scale;\n"                                                 \
 | 
			
		||||
"uniform vec2 offset;\n"                                                \
 | 
			
		||||
"varying vec2 position;\n"                                              \
 | 
			
		||||
 | 
			
		||||
#define VERTEX_SHADER_CODE                                              \
 | 
			
		||||
"position = cogl_tex_coord0_in.xy * scale + offset;\n"                  \
 | 
			
		||||
 | 
			
		||||
#define FRAGMENT_SHADER_DECLARATIONS                                    \
 | 
			
		||||
"uniform float vignette_sharpness;\n"                                   \
 | 
			
		||||
"varying vec2 position;\n"                                              \
 | 
			
		||||
 | 
			
		||||
#define FRAGMENT_SHADER_CODE                                                   \
 | 
			
		||||
"float t = 2.0 * length(position);\n"                                          \
 | 
			
		||||
"t = min(t, 1.0);\n"                                                           \
 | 
			
		||||
"float pixel_brightness = 1 - t * vignette_sharpness;\n"                       \
 | 
			
		||||
"cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n"                \
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaBackgroundLayer MetaBackgroundLayer;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  PIPELINE_VIGNETTE = (1 << 0),
 | 
			
		||||
  PIPELINE_BLEND = (1 << 1),
 | 
			
		||||
} PipelineFlags;
 | 
			
		||||
 | 
			
		||||
struct _MetaBackgroundActorPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  int monitor;
 | 
			
		||||
 | 
			
		||||
  MetaBackground *background;
 | 
			
		||||
 | 
			
		||||
  gboolean vignette;
 | 
			
		||||
  float brightness;
 | 
			
		||||
  float vignette_sharpness;
 | 
			
		||||
 | 
			
		||||
  ChangedFlags changed;
 | 
			
		||||
  CoglPipeline *pipeline;
 | 
			
		||||
  PipelineFlags pipeline_flags;
 | 
			
		||||
  cairo_rectangle_int_t texture_area;
 | 
			
		||||
  gboolean force_bilinear;
 | 
			
		||||
 | 
			
		||||
  cairo_region_t *clip_region;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -66,27 +162,45 @@ static void
 | 
			
		||||
meta_background_actor_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  set_clip_region (self, NULL);
 | 
			
		||||
  meta_background_actor_set_background (self, NULL);
 | 
			
		||||
  if (priv->pipeline)
 | 
			
		||||
    {
 | 
			
		||||
      cogl_object_unref (priv->pipeline);
 | 
			
		||||
      priv->pipeline = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
get_preferred_size (MetaBackgroundActor *self,
 | 
			
		||||
                    gfloat              *width,
 | 
			
		||||
                    gfloat              *height)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (self)->priv;
 | 
			
		||||
  MetaRectangle monitor_geometry;
 | 
			
		||||
 | 
			
		||||
  meta_screen_get_monitor_geometry (priv->screen, priv->monitor, &monitor_geometry);
 | 
			
		||||
 | 
			
		||||
  if (width != NULL)
 | 
			
		||||
    *width = monitor_geometry.width;
 | 
			
		||||
 | 
			
		||||
  if (height != NULL)
 | 
			
		||||
    *height = monitor_geometry.height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_actor_get_preferred_width (ClutterActor *actor,
 | 
			
		||||
                                           gfloat        for_height,
 | 
			
		||||
                                           gfloat       *min_width_p,
 | 
			
		||||
                                           gfloat       *natural_width_p)
 | 
			
		||||
{
 | 
			
		||||
  ClutterContent *content;
 | 
			
		||||
  gfloat width;
 | 
			
		||||
 | 
			
		||||
  content = clutter_actor_get_content (actor);
 | 
			
		||||
 | 
			
		||||
  if (content)
 | 
			
		||||
    clutter_content_get_preferred_size (content, &width, NULL);
 | 
			
		||||
  else
 | 
			
		||||
    width = 0;
 | 
			
		||||
  get_preferred_size (META_BACKGROUND_ACTOR (actor), &width, NULL);
 | 
			
		||||
 | 
			
		||||
  if (min_width_p)
 | 
			
		||||
    *min_width_p = width;
 | 
			
		||||
@@ -101,15 +215,9 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
 | 
			
		||||
                                            gfloat       *natural_height_p)
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
  ClutterContent *content;
 | 
			
		||||
  gfloat height;
 | 
			
		||||
 | 
			
		||||
  content = clutter_actor_get_content (actor);
 | 
			
		||||
 | 
			
		||||
  if (content)
 | 
			
		||||
    clutter_content_get_preferred_size (content, NULL, &height);
 | 
			
		||||
  else
 | 
			
		||||
    height = 0;
 | 
			
		||||
  get_preferred_size (META_BACKGROUND_ACTOR (actor), NULL, &height);
 | 
			
		||||
 | 
			
		||||
  if (min_height_p)
 | 
			
		||||
    *min_height_p = height;
 | 
			
		||||
@@ -117,18 +225,306 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
 | 
			
		||||
    *natural_height_p = height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CoglPipeline *
 | 
			
		||||
make_pipeline (PipelineFlags pipeline_flags)
 | 
			
		||||
{
 | 
			
		||||
  static CoglPipeline *templates[4];
 | 
			
		||||
  CoglPipeline **templatep;
 | 
			
		||||
 | 
			
		||||
  templatep = &templates[pipeline_flags];
 | 
			
		||||
  if (*templatep == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      /* Cogl automatically caches pipelines with no eviction policy,
 | 
			
		||||
       * so we need to prevent identical pipelines from getting cached
 | 
			
		||||
       * separately, by reusing the same shader snippets.
 | 
			
		||||
       */
 | 
			
		||||
      *templatep = COGL_PIPELINE (meta_create_texture_pipeline (NULL));
 | 
			
		||||
 | 
			
		||||
      if ((pipeline_flags & PIPELINE_VIGNETTE) != 0)
 | 
			
		||||
        {
 | 
			
		||||
          static CoglSnippet *snippet;
 | 
			
		||||
 | 
			
		||||
          if (!snippet)
 | 
			
		||||
            snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
 | 
			
		||||
                                        VERTEX_SHADER_DECLARATIONS, VERTEX_SHADER_CODE);
 | 
			
		||||
 | 
			
		||||
          cogl_pipeline_add_snippet (*templatep, snippet);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if ((pipeline_flags & PIPELINE_VIGNETTE) != 0)
 | 
			
		||||
        {
 | 
			
		||||
          static CoglSnippet *snippet;
 | 
			
		||||
 | 
			
		||||
          if (!snippet)
 | 
			
		||||
            snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
 | 
			
		||||
                                        FRAGMENT_SHADER_DECLARATIONS, FRAGMENT_SHADER_CODE);
 | 
			
		||||
 | 
			
		||||
          cogl_pipeline_add_snippet (*templatep, snippet);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if ((pipeline_flags & PIPELINE_BLEND) == 0)
 | 
			
		||||
        cogl_pipeline_set_blend (*templatep, "RGBA = ADD (SRC_COLOR, 0)", NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return cogl_pipeline_copy (*templatep);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
setup_pipeline (MetaBackgroundActor   *self,
 | 
			
		||||
                cairo_rectangle_int_t *actor_pixel_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = self->priv;
 | 
			
		||||
  PipelineFlags pipeline_flags = 0;
 | 
			
		||||
  guint8 opacity;
 | 
			
		||||
  float color_component;
 | 
			
		||||
  CoglPipelineFilter filter;
 | 
			
		||||
 | 
			
		||||
  opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self));
 | 
			
		||||
  if (opacity < 255)
 | 
			
		||||
    pipeline_flags |= PIPELINE_BLEND;
 | 
			
		||||
  if (priv->vignette && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
 | 
			
		||||
    pipeline_flags |= PIPELINE_VIGNETTE;
 | 
			
		||||
 | 
			
		||||
  if (priv->pipeline &&
 | 
			
		||||
      pipeline_flags != priv->pipeline_flags)
 | 
			
		||||
    {
 | 
			
		||||
      cogl_object_unref (priv->pipeline);
 | 
			
		||||
      priv->pipeline = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (priv->pipeline == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      priv->pipeline_flags = pipeline_flags;
 | 
			
		||||
      priv->pipeline = make_pipeline (pipeline_flags);
 | 
			
		||||
      priv->changed = CHANGED_ALL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if ((priv->changed & CHANGED_BACKGROUND) != 0)
 | 
			
		||||
    {
 | 
			
		||||
      CoglPipelineWrapMode wrap_mode;
 | 
			
		||||
      CoglTexture *texture = meta_background_get_texture (priv->background,
 | 
			
		||||
                                                          priv->monitor,
 | 
			
		||||
                                                          &priv->texture_area,
 | 
			
		||||
                                                          &wrap_mode);
 | 
			
		||||
      priv->force_bilinear = texture &&
 | 
			
		||||
        (priv->texture_area.width != (int)cogl_texture_get_width (texture) ||
 | 
			
		||||
         priv->texture_area.height != (int)cogl_texture_get_height (texture));
 | 
			
		||||
 | 
			
		||||
      cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
 | 
			
		||||
      cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, wrap_mode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if ((priv->changed & CHANGED_VIGNETTE_PARAMETERS) != 0)
 | 
			
		||||
    {
 | 
			
		||||
      cogl_pipeline_set_uniform_1f (priv->pipeline,
 | 
			
		||||
                                    cogl_pipeline_get_uniform_location (priv->pipeline,
 | 
			
		||||
                                                                        "vignette_sharpness"),
 | 
			
		||||
                                    priv->vignette_sharpness);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (priv->vignette)
 | 
			
		||||
    color_component = priv->brightness * opacity / 255.;
 | 
			
		||||
  else
 | 
			
		||||
    color_component = opacity / 255.;
 | 
			
		||||
 | 
			
		||||
  cogl_pipeline_set_color4f (priv->pipeline,
 | 
			
		||||
                             color_component,
 | 
			
		||||
                             color_component,
 | 
			
		||||
                             color_component,
 | 
			
		||||
                             opacity / 255.);
 | 
			
		||||
 | 
			
		||||
  if (!priv->force_bilinear &&
 | 
			
		||||
      meta_actor_painting_untransformed (actor_pixel_rect->width, actor_pixel_rect->height, NULL, NULL))
 | 
			
		||||
    filter = COGL_PIPELINE_FILTER_NEAREST;
 | 
			
		||||
  else
 | 
			
		||||
    filter = COGL_PIPELINE_FILTER_LINEAR;
 | 
			
		||||
 | 
			
		||||
  cogl_pipeline_set_layer_filters (priv->pipeline, 0, filter, filter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_glsl_parameters (MetaBackgroundActor   *self,
 | 
			
		||||
                     cairo_rectangle_int_t *actor_pixel_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = self->priv;
 | 
			
		||||
  float scale[2];
 | 
			
		||||
  float offset[2];
 | 
			
		||||
 | 
			
		||||
  /* Compute a scale and offset for transforming texture coordinates to the
 | 
			
		||||
   * coordinate system from [-0.5 to 0.5] across the area of the actor
 | 
			
		||||
   */
 | 
			
		||||
  scale[0] = priv->texture_area.width / (float)actor_pixel_rect->width;
 | 
			
		||||
  scale[1] = priv->texture_area.height / (float)actor_pixel_rect->height;
 | 
			
		||||
  offset[0] = priv->texture_area.x / (float)actor_pixel_rect->width - 0.5;
 | 
			
		||||
  offset[1] = priv->texture_area.y / (float)actor_pixel_rect->height - 0.5;
 | 
			
		||||
 | 
			
		||||
  cogl_pipeline_set_uniform_float (priv->pipeline,
 | 
			
		||||
                                   cogl_pipeline_get_uniform_location (priv->pipeline,
 | 
			
		||||
                                                                       "scale"),
 | 
			
		||||
                                   2, 1, scale);
 | 
			
		||||
 | 
			
		||||
  cogl_pipeline_set_uniform_float (priv->pipeline,
 | 
			
		||||
                                   cogl_pipeline_get_uniform_location (priv->pipeline,
 | 
			
		||||
                                                                       "offset"),
 | 
			
		||||
                                   2, 1, offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_actor_paint (ClutterActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = self->priv;
 | 
			
		||||
  ClutterActorBox actor_box;
 | 
			
		||||
  cairo_rectangle_int_t actor_pixel_rect;
 | 
			
		||||
  cairo_region_t *paintable_region = NULL;
 | 
			
		||||
  int n_texture_subareas;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if ((priv->clip_region && cairo_region_is_empty (priv->clip_region)))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  clutter_actor_get_content_box (actor, &actor_box);
 | 
			
		||||
  actor_pixel_rect.x = actor_box.x1;
 | 
			
		||||
  actor_pixel_rect.y = actor_box.y1;
 | 
			
		||||
  actor_pixel_rect.width = actor_box.x2 - actor_box.x1;
 | 
			
		||||
  actor_pixel_rect.height = actor_box.y2 - actor_box.y1;
 | 
			
		||||
 | 
			
		||||
  /* Now figure out what to actually paint.
 | 
			
		||||
   */
 | 
			
		||||
  paintable_region = cairo_region_create_rectangle (&actor_pixel_rect);
 | 
			
		||||
  if (priv->clip_region != NULL)
 | 
			
		||||
    cairo_region_intersect (paintable_region, priv->clip_region);
 | 
			
		||||
 | 
			
		||||
  if (cairo_region_is_empty (paintable_region))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  setup_pipeline (self, &actor_pixel_rect);
 | 
			
		||||
  set_glsl_parameters (self, &actor_pixel_rect);
 | 
			
		||||
 | 
			
		||||
  /* Finally, split the paintable region up into distinct areas
 | 
			
		||||
   * and paint each area one by one
 | 
			
		||||
   */
 | 
			
		||||
  n_texture_subareas = cairo_region_num_rectangles (paintable_region);
 | 
			
		||||
  for (i = 0; i < n_texture_subareas; i++)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t rect;
 | 
			
		||||
      float tx1, tx2, ty1, ty2;
 | 
			
		||||
 | 
			
		||||
      cairo_region_get_rectangle (paintable_region, i, &rect);
 | 
			
		||||
 | 
			
		||||
      tx1 = (rect.x - actor_pixel_rect.x - priv->texture_area.x) / (float)priv->texture_area.width;
 | 
			
		||||
      ty1 = (rect.y - actor_pixel_rect.y - priv->texture_area.y) / (float)priv->texture_area.height;
 | 
			
		||||
      tx2 = (rect.x + rect.width - actor_pixel_rect.x - priv->texture_area.x) / (float)priv->texture_area.width;
 | 
			
		||||
      ty2 = (rect.y + rect.height - actor_pixel_rect.y - priv->texture_area.y) / (float)priv->texture_area.height;
 | 
			
		||||
 | 
			
		||||
      cogl_framebuffer_draw_textured_rectangle (cogl_get_draw_framebuffer (),
 | 
			
		||||
                                                priv->pipeline,
 | 
			
		||||
                                                rect.x, rect.y,
 | 
			
		||||
                                                rect.x + rect.width, rect.y + rect.height,
 | 
			
		||||
                                                tx1, ty1, tx2, ty2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  cairo_region_destroy (paintable_region);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_actor_set_property (GObject      *object,
 | 
			
		||||
                                    guint         prop_id,
 | 
			
		||||
                                    const GValue *value,
 | 
			
		||||
                                    GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_META_SCREEN:
 | 
			
		||||
      priv->screen = g_value_get_object (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_MONITOR:
 | 
			
		||||
      priv->monitor = g_value_get_int (value);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_BACKGROUND:
 | 
			
		||||
      meta_background_actor_set_background (self, g_value_get_object (value));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_actor_get_property (GObject      *object,
 | 
			
		||||
                                    guint         prop_id,
 | 
			
		||||
                                    GValue       *value,
 | 
			
		||||
                                    GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (object)->priv;
 | 
			
		||||
 | 
			
		||||
  switch (prop_id)
 | 
			
		||||
    {
 | 
			
		||||
    case PROP_META_SCREEN:
 | 
			
		||||
      g_value_set_object (value, priv->screen);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_MONITOR:
 | 
			
		||||
      g_value_set_int (value, priv->monitor);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_BACKGROUND:
 | 
			
		||||
      g_value_set_object (value, priv->background);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
 | 
			
		||||
  GParamSpec *param_spec;
 | 
			
		||||
 | 
			
		||||
  g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate));
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_background_actor_dispose;
 | 
			
		||||
  object_class->set_property = meta_background_actor_set_property;
 | 
			
		||||
  object_class->get_property = meta_background_actor_get_property;
 | 
			
		||||
 | 
			
		||||
  actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
 | 
			
		||||
  actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
 | 
			
		||||
  actor_class->paint = meta_background_actor_paint;
 | 
			
		||||
 | 
			
		||||
  param_spec = g_param_spec_object ("meta-screen",
 | 
			
		||||
                                    "MetaScreen",
 | 
			
		||||
                                    "MetaScreen",
 | 
			
		||||
                                    META_TYPE_SCREEN,
 | 
			
		||||
                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_META_SCREEN,
 | 
			
		||||
                                   param_spec);
 | 
			
		||||
 | 
			
		||||
  param_spec = g_param_spec_int ("monitor",
 | 
			
		||||
                                 "monitor",
 | 
			
		||||
                                 "monitor",
 | 
			
		||||
                                 0, G_MAXINT, 0,
 | 
			
		||||
                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_MONITOR,
 | 
			
		||||
                                   param_spec);
 | 
			
		||||
 | 
			
		||||
  param_spec = g_param_spec_object ("background",
 | 
			
		||||
                                    "Background",
 | 
			
		||||
                                    "MetaBackground object holding background parameters",
 | 
			
		||||
                                    META_TYPE_BACKGROUND,
 | 
			
		||||
                                    G_PARAM_READWRITE);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_BACKGROUND,
 | 
			
		||||
                                   param_spec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -141,19 +537,22 @@ meta_background_actor_init (MetaBackgroundActor *self)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_actor_new:
 | 
			
		||||
 * @monitor: Index of the monitor for which to draw the background
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a new actor to draw the background for the given monitor.
 | 
			
		||||
 * This actor should be associated with a #MetaBackground using
 | 
			
		||||
 * clutter_actor_set_content()
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the newly created background actor
 | 
			
		||||
 */
 | 
			
		||||
ClutterActor *
 | 
			
		||||
meta_background_actor_new (void)
 | 
			
		||||
meta_background_actor_new (MetaScreen *screen,
 | 
			
		||||
                           int         monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActor *self;
 | 
			
		||||
 | 
			
		||||
  self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL);
 | 
			
		||||
  self = g_object_new (META_TYPE_BACKGROUND_ACTOR,
 | 
			
		||||
                       "meta-screen", screen,
 | 
			
		||||
                       "monitor", monitor,
 | 
			
		||||
                       NULL);
 | 
			
		||||
 | 
			
		||||
  return CLUTTER_ACTOR (self);
 | 
			
		||||
}
 | 
			
		||||
@@ -195,3 +594,95 @@ meta_background_actor_get_clip_region (MetaBackgroundActor *self)
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = self->priv;
 | 
			
		||||
  return priv->clip_region;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
invalidate_pipeline (MetaBackgroundActor *self,
 | 
			
		||||
                     ChangedFlags         changed)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  priv->changed |= changed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_background_changed (MetaBackground      *background,
 | 
			
		||||
                       MetaBackgroundActor *self)
 | 
			
		||||
{
 | 
			
		||||
  invalidate_pipeline (self, CHANGED_BACKGROUND);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_background_actor_set_background (MetaBackgroundActor *self,
 | 
			
		||||
                                      MetaBackground      *background)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
 | 
			
		||||
  g_return_if_fail (background == NULL || META_IS_BACKGROUND (background));
 | 
			
		||||
 | 
			
		||||
  priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (background == priv->background)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (priv->background)
 | 
			
		||||
    {
 | 
			
		||||
      g_signal_handlers_disconnect_by_func (priv->background,
 | 
			
		||||
                                            (gpointer)on_background_changed,
 | 
			
		||||
                                            self);
 | 
			
		||||
      g_object_unref (priv->background);
 | 
			
		||||
      priv->background = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (background)
 | 
			
		||||
    {
 | 
			
		||||
      priv->background = g_object_ref (background);
 | 
			
		||||
      g_signal_connect (priv->background, "changed",
 | 
			
		||||
                        G_CALLBACK (on_background_changed), self);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  invalidate_pipeline (self, CHANGED_BACKGROUND);
 | 
			
		||||
  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_background_actor_add_vignette (MetaBackgroundActor *self,
 | 
			
		||||
                                    double               brightness,
 | 
			
		||||
                                    double               sharpness)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
 | 
			
		||||
  g_return_if_fail (brightness >= 0. && brightness <= 1.);
 | 
			
		||||
  g_return_if_fail (sharpness >= 0.);
 | 
			
		||||
 | 
			
		||||
  priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (!priv->vignette)
 | 
			
		||||
    invalidate_pipeline (self, CHANGED_EFFECTS);
 | 
			
		||||
 | 
			
		||||
  priv->vignette = TRUE;
 | 
			
		||||
  priv->brightness = brightness;
 | 
			
		||||
  priv->vignette_sharpness = sharpness;
 | 
			
		||||
  invalidate_pipeline (self, CHANGED_VIGNETTE_PARAMETERS);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_background_actor_remove_vignette (MetaBackgroundActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundActorPrivate *priv;
 | 
			
		||||
  priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  if (!priv->vignette)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv->vignette = FALSE;
 | 
			
		||||
 | 
			
		||||
  invalidate_pipeline (self, CHANGED_EFFECTS);
 | 
			
		||||
  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										342
									
								
								src/compositor/meta-background-image.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								src/compositor/meta-background-image.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,342 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2014 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:meta-background-image
 | 
			
		||||
 * @title: MetaBackgroundImage
 | 
			
		||||
 * @short_description: objects holding images loaded from files, used for backgrounds
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <meta/meta-background-image.h>
 | 
			
		||||
#include "cogl-utils.h"
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  LOADED,
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0 };
 | 
			
		||||
 | 
			
		||||
struct _MetaBackgroundImageCache
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
 | 
			
		||||
  GHashTable *images;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBackgroundImageCacheClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBackgroundImage
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
  char *filename;
 | 
			
		||||
  MetaBackgroundImageCache *cache;
 | 
			
		||||
  gboolean in_cache;
 | 
			
		||||
  gboolean loaded;
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaBackgroundImageClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_image_cache_init (MetaBackgroundImageCache *cache)
 | 
			
		||||
{
 | 
			
		||||
  cache->images = g_hash_table_new (g_str_hash, g_str_equal);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_image_cache_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundImageCache *cache = META_BACKGROUND_IMAGE_CACHE (object);
 | 
			
		||||
  GHashTableIter iter;
 | 
			
		||||
  gpointer key, value;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_iter_init (&iter, cache->images);
 | 
			
		||||
  while (g_hash_table_iter_next (&iter, &key, &value))
 | 
			
		||||
    {
 | 
			
		||||
      MetaBackgroundImage *image = value;
 | 
			
		||||
      image->in_cache = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_hash_table_destroy (cache->images);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_background_image_cache_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_image_cache_class_init (MetaBackgroundImageCacheClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_background_image_cache_finalize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_cache_get_default:
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): the global singleton background cache
 | 
			
		||||
 */
 | 
			
		||||
MetaBackgroundImageCache *
 | 
			
		||||
meta_background_image_cache_get_default (void)
 | 
			
		||||
{
 | 
			
		||||
  static MetaBackgroundImageCache *cache;
 | 
			
		||||
 | 
			
		||||
  if (cache == NULL)
 | 
			
		||||
    cache = g_object_new (META_TYPE_BACKGROUND_IMAGE_CACHE, NULL);
 | 
			
		||||
 | 
			
		||||
  return cache;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
load_file (GTask               *task,
 | 
			
		||||
           MetaBackgroundImage *image,
 | 
			
		||||
           gpointer             task_data,
 | 
			
		||||
           GCancellable        *cancellable)
 | 
			
		||||
{
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  GdkPixbuf *pixbuf;
 | 
			
		||||
 | 
			
		||||
  pixbuf = gdk_pixbuf_new_from_file (image->filename,
 | 
			
		||||
                                     &error);
 | 
			
		||||
 | 
			
		||||
  if (pixbuf == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_task_return_error (task, error);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_task_return_pointer (task, pixbuf, (GDestroyNotify) g_object_unref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
file_loaded (GObject      *source_object,
 | 
			
		||||
             GAsyncResult *result,
 | 
			
		||||
             gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundImage *image = META_BACKGROUND_IMAGE (source_object);
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  GTask *task;
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
  GdkPixbuf *pixbuf;
 | 
			
		||||
  int width, height, row_stride;
 | 
			
		||||
  guchar *pixels;
 | 
			
		||||
  gboolean has_alpha;
 | 
			
		||||
 | 
			
		||||
  task = G_TASK (result);
 | 
			
		||||
  pixbuf = g_task_propagate_pointer (task, &error);
 | 
			
		||||
 | 
			
		||||
  if (pixbuf == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to load background '%s': %s",
 | 
			
		||||
                 image->filename, error->message);
 | 
			
		||||
      g_clear_error (&error);
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  width = gdk_pixbuf_get_width (pixbuf);
 | 
			
		||||
  height = gdk_pixbuf_get_height (pixbuf);
 | 
			
		||||
  row_stride = gdk_pixbuf_get_rowstride (pixbuf);
 | 
			
		||||
  pixels = gdk_pixbuf_get_pixels (pixbuf);
 | 
			
		||||
  has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
 | 
			
		||||
 | 
			
		||||
  texture = meta_create_large_texture (width, height,
 | 
			
		||||
                                       has_alpha ? COGL_TEXTURE_COMPONENTS_RGBA : COGL_TEXTURE_COMPONENTS_RGB);
 | 
			
		||||
  if (!cogl_texture_set_data (texture,
 | 
			
		||||
                              has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
 | 
			
		||||
                              row_stride,
 | 
			
		||||
                              pixels, 0,
 | 
			
		||||
                              NULL))
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to create texture for background");
 | 
			
		||||
      cogl_object_unref (texture);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  image->texture = texture;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  image->loaded = TRUE;
 | 
			
		||||
  g_signal_emit (image, signals[LOADED], 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_cache_load:
 | 
			
		||||
 * @cache: a #MetaBackgroundImageCache
 | 
			
		||||
 * @filename: filename to load
 | 
			
		||||
 *
 | 
			
		||||
 * Loads an image to use as a background, or returns a reference to an
 | 
			
		||||
 * image that is already in the process of loading or loaded. In either
 | 
			
		||||
 * case, what is returned is a #MetaBackgroundImage which can be derefenced
 | 
			
		||||
 * to get a #CoglTexture. If meta_background_image_is_loaded() returns %TRUE,
 | 
			
		||||
 * the background is loaded, otherwise the MetaBackgroundImage::loaded
 | 
			
		||||
 * signal will be emitted exactly once. The 'loaded' state means that the
 | 
			
		||||
 * loading process finished, whether it succeeded or failed.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer full): a #MetaBackgroundImage to dereference to get the loaded texture
 | 
			
		||||
 */
 | 
			
		||||
MetaBackgroundImage *
 | 
			
		||||
meta_background_image_cache_load (MetaBackgroundImageCache *cache,
 | 
			
		||||
                                  const char               *filename)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundImage *image;
 | 
			
		||||
  GTask *task;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
 | 
			
		||||
  g_return_val_if_fail (filename != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  image = g_hash_table_lookup (cache->images, filename);
 | 
			
		||||
  if (image != NULL)
 | 
			
		||||
    return g_object_ref (image);
 | 
			
		||||
 | 
			
		||||
  image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL);
 | 
			
		||||
  image->cache = cache;
 | 
			
		||||
  image->in_cache = TRUE;
 | 
			
		||||
  image->filename = g_strdup (filename);
 | 
			
		||||
  g_hash_table_insert (cache->images, image->filename, image);
 | 
			
		||||
 | 
			
		||||
  task = g_task_new (image, NULL, file_loaded, NULL);
 | 
			
		||||
 | 
			
		||||
  g_task_run_in_thread (task, (GTaskThreadFunc) load_file);
 | 
			
		||||
  g_object_unref (task);
 | 
			
		||||
 | 
			
		||||
  return image;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_cache_purge:
 | 
			
		||||
 * @cache: a #MetaBackgroundImageCache
 | 
			
		||||
 * @filename: filename to remove from the cache
 | 
			
		||||
 *
 | 
			
		||||
 * Remove an entry from the cache; this would be used if monitoring
 | 
			
		||||
 * showed that the file changed.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
 | 
			
		||||
                                   const char               *filename)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundImage *image;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
 | 
			
		||||
  g_return_val_if_fail (filename != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  image = g_hash_table_lookup (cache->images, filename);
 | 
			
		||||
  if (image == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_remove (cache->images, image->filename);
 | 
			
		||||
  image->in_cache = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaBackgroundImage, meta_background_image, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_image_init (MetaBackgroundImage *image)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_image_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object);
 | 
			
		||||
 | 
			
		||||
  if (image->in_cache)
 | 
			
		||||
    g_hash_table_remove (image->cache->images, image->filename);
 | 
			
		||||
 | 
			
		||||
  if (image->texture)
 | 
			
		||||
    cogl_object_unref (image->texture);
 | 
			
		||||
  if (image->filename)
 | 
			
		||||
    g_free (image->filename);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_background_image_class_init (MetaBackgroundImageClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_background_image_finalize;
 | 
			
		||||
 | 
			
		||||
  signals[LOADED] =
 | 
			
		||||
    g_signal_new ("loaded",
 | 
			
		||||
                  G_TYPE_FROM_CLASS (object_class),
 | 
			
		||||
                  G_SIGNAL_RUN_LAST,
 | 
			
		||||
                  0,
 | 
			
		||||
                  NULL, NULL, NULL,
 | 
			
		||||
                  G_TYPE_NONE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_is_loaded:
 | 
			
		||||
 * @image: a #MetaBackgroundImage
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: %TRUE if loading has already completed, %FALSE otherwise
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_background_image_is_loaded (MetaBackgroundImage *image)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE);
 | 
			
		||||
 | 
			
		||||
  return image->loaded;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_get_success:
 | 
			
		||||
 * @image: a #MetaBackgroundImage
 | 
			
		||||
 *
 | 
			
		||||
 * This function is a convenience function for checking for success,
 | 
			
		||||
 * without having to call meta_background_image_get_success() and
 | 
			
		||||
 * handle the return of a Cogl type.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: %TRUE if loading completed successfully, otherwise %FALSE
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_background_image_get_success (MetaBackgroundImage *image)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE);
 | 
			
		||||
 | 
			
		||||
  return image->texture != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_background_image_get_texture:
 | 
			
		||||
 * @image: a #MetaBackgroundImage
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): a #CoglTexture if loading succeeded; if
 | 
			
		||||
 *  loading failed or has not yet finished, %NULL.
 | 
			
		||||
 */
 | 
			
		||||
CoglTexture *
 | 
			
		||||
meta_background_image_get_texture (MetaBackgroundImage *image)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), NULL);
 | 
			
		||||
 | 
			
		||||
  return image->texture;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								src/compositor/meta-background-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/compositor/meta-background-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#ifndef META_BACKGROUND_PRIVATE_H
 | 
			
		||||
#define META_BACKGROUND_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-background-private.h"
 | 
			
		||||
 | 
			
		||||
CoglTexture *meta_background_get_texture (MetaBackground         *self,
 | 
			
		||||
                                          int                     monitor_index,
 | 
			
		||||
                                          cairo_rectangle_int_t  *texture_area,
 | 
			
		||||
                                          CoglPipelineWrapMode   *wrap_mode);
 | 
			
		||||
 | 
			
		||||
#endif /* META_BACKGROUND_PRIVATE_H */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -343,7 +343,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
 | 
			
		||||
  filter = COGL_PIPELINE_FILTER_LINEAR;
 | 
			
		||||
 | 
			
		||||
  if (!clutter_actor_is_in_clone_paint (actor) && meta_actor_is_untransformed (actor, NULL, NULL))
 | 
			
		||||
  if (meta_actor_painting_untransformed (tex_width, tex_height, NULL, NULL))
 | 
			
		||||
    filter = COGL_PIPELINE_FILTER_NEAREST;
 | 
			
		||||
 | 
			
		||||
  ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
 | 
			
		||||
 
 | 
			
		||||
@@ -31,64 +31,6 @@ static void cullable_iface_init (MetaCullableInterface *iface);
 | 
			
		||||
G_DEFINE_TYPE_WITH_CODE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR,
 | 
			
		||||
                         G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
 | 
			
		||||
 | 
			
		||||
/* Help macros to scale from OpenGL <-1,1> coordinates system to
 | 
			
		||||
 * window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c
 | 
			
		||||
 */
 | 
			
		||||
#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
 | 
			
		||||
#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
 | 
			
		||||
 | 
			
		||||
/* Check if we're painting the MetaWindowGroup "untransformed". This can
 | 
			
		||||
 * differ from the result of actor_is_untransformed(window_group) if we're
 | 
			
		||||
 * inside a clone paint. The integer translation, if any, is returned.
 | 
			
		||||
 */
 | 
			
		||||
static gboolean
 | 
			
		||||
painting_untransformed (MetaWindowGroup *window_group,
 | 
			
		||||
                        int             *x_origin,
 | 
			
		||||
                        int             *y_origin)
 | 
			
		||||
{
 | 
			
		||||
  CoglMatrix modelview, projection, modelview_projection;
 | 
			
		||||
  ClutterVertex vertices[4];
 | 
			
		||||
  int width, height;
 | 
			
		||||
  float viewport[4];
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  cogl_get_modelview_matrix (&modelview);
 | 
			
		||||
  cogl_get_projection_matrix (&projection);
 | 
			
		||||
 | 
			
		||||
  cogl_matrix_multiply (&modelview_projection,
 | 
			
		||||
                        &projection,
 | 
			
		||||
                        &modelview);
 | 
			
		||||
 | 
			
		||||
  meta_screen_get_size (window_group->screen, &width, &height);
 | 
			
		||||
 | 
			
		||||
  vertices[0].x = 0;
 | 
			
		||||
  vertices[0].y = 0;
 | 
			
		||||
  vertices[0].z = 0;
 | 
			
		||||
  vertices[1].x = width;
 | 
			
		||||
  vertices[1].y = 0;
 | 
			
		||||
  vertices[1].z = 0;
 | 
			
		||||
  vertices[2].x = 0;
 | 
			
		||||
  vertices[2].y = height;
 | 
			
		||||
  vertices[2].z = 0;
 | 
			
		||||
  vertices[3].x = width;
 | 
			
		||||
  vertices[3].y = height;
 | 
			
		||||
  vertices[3].z = 0;
 | 
			
		||||
 | 
			
		||||
  cogl_get_viewport (viewport);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < 4; i++)
 | 
			
		||||
    {
 | 
			
		||||
      float w = 1;
 | 
			
		||||
      cogl_matrix_transform_point (&modelview_projection, &vertices[i].x, &vertices[i].y, &vertices[i].z, &w);
 | 
			
		||||
      vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w,
 | 
			
		||||
                                      viewport[2], viewport[0]);
 | 
			
		||||
      vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w,
 | 
			
		||||
                                      viewport[3], viewport[1]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return meta_actor_vertices_are_untransformed (vertices, width, height, x_origin, y_origin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_group_cull_out (MetaCullable   *cullable,
 | 
			
		||||
                            cairo_region_t *unobscured_region,
 | 
			
		||||
@@ -119,10 +61,13 @@ meta_window_group_paint (ClutterActor *actor)
 | 
			
		||||
  int paint_x_offset, paint_y_offset;
 | 
			
		||||
  int paint_x_origin, paint_y_origin;
 | 
			
		||||
  int actor_x_origin, actor_y_origin;
 | 
			
		||||
  int screen_width, screen_height;
 | 
			
		||||
 | 
			
		||||
  MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
 | 
			
		||||
  ClutterActor *stage = clutter_actor_get_stage (actor);
 | 
			
		||||
 | 
			
		||||
  meta_screen_get_size (window_group->screen, &screen_width, &screen_height);
 | 
			
		||||
 | 
			
		||||
  /* Normally we expect an actor to be drawn at it's position on the screen.
 | 
			
		||||
   * However, if we're inside the paint of a ClutterClone, that won't be the
 | 
			
		||||
   * case and we need to compensate. We look at the position of the window
 | 
			
		||||
@@ -136,7 +81,7 @@ meta_window_group_paint (ClutterActor *actor)
 | 
			
		||||
   * painting currently, and never worry about how actors are positioned
 | 
			
		||||
   * on the stage.
 | 
			
		||||
   */
 | 
			
		||||
  if (!painting_untransformed (window_group, &paint_x_origin, &paint_y_origin) ||
 | 
			
		||||
  if (!meta_actor_painting_untransformed (screen_width, screen_height, &paint_x_origin, &paint_y_origin) ||
 | 
			
		||||
      !meta_actor_is_untransformed (actor, &actor_x_origin, &actor_y_origin))
 | 
			
		||||
    {
 | 
			
		||||
      CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
 | 
			
		||||
 
 | 
			
		||||
@@ -303,15 +303,16 @@ on_monitors_changed (MetaScreen *screen,
 | 
			
		||||
  for (i = 0; i < n; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaRectangle rect;
 | 
			
		||||
      ClutterActor *background;
 | 
			
		||||
      ClutterActor *background_actor;
 | 
			
		||||
      MetaBackground *background;
 | 
			
		||||
      ClutterColor color;
 | 
			
		||||
 | 
			
		||||
      meta_screen_get_monitor_geometry (screen, i, &rect);
 | 
			
		||||
 | 
			
		||||
      background = meta_background_actor_new ();
 | 
			
		||||
      background_actor = meta_background_actor_new (screen, i);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_set_position (background, rect.x, rect.y);
 | 
			
		||||
      clutter_actor_set_size (background, rect.width, rect.height);
 | 
			
		||||
      clutter_actor_set_position (background_actor, rect.x, rect.y);
 | 
			
		||||
      clutter_actor_set_size (background_actor, rect.width, rect.height);
 | 
			
		||||
 | 
			
		||||
      /* Don't use rand() here, mesa calls srand() internally when
 | 
			
		||||
         parsing the driconf XML, but it's nice if the colors are
 | 
			
		||||
@@ -322,9 +323,13 @@ on_monitors_changed (MetaScreen *screen,
 | 
			
		||||
                          g_rand_int_range (rand, 0, 255),
 | 
			
		||||
                          g_rand_int_range (rand, 0, 255),
 | 
			
		||||
                          255);
 | 
			
		||||
      clutter_actor_set_background_color (background, &color);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_add_child (self->priv->background_group, background);
 | 
			
		||||
      background = meta_background_new (screen);
 | 
			
		||||
      meta_background_set_color (background, &color);
 | 
			
		||||
      meta_background_actor_set_background (META_BACKGROUND_ACTOR (background_actor), background);
 | 
			
		||||
      g_object_unref (background);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_add_child (self->priv->background_group, background_actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_rand_free (rand);
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,8 @@
 | 
			
		||||
#define META_BACKGROUND_ACTOR_H
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/gradient.h>
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
#include <meta/meta-background.h>
 | 
			
		||||
 | 
			
		||||
#include <gsettings-desktop-schemas/gdesktop-enums.h>
 | 
			
		||||
 | 
			
		||||
@@ -63,6 +61,15 @@ struct _MetaBackgroundActor
 | 
			
		||||
 | 
			
		||||
GType meta_background_actor_get_type (void);
 | 
			
		||||
 | 
			
		||||
ClutterActor *meta_background_actor_new (void);
 | 
			
		||||
ClutterActor *meta_background_actor_new    (MetaScreen *screen,
 | 
			
		||||
                                            int         monitor);
 | 
			
		||||
 | 
			
		||||
void meta_background_actor_set_background  (MetaBackgroundActor *self,
 | 
			
		||||
                                            MetaBackground      *background);
 | 
			
		||||
 | 
			
		||||
void meta_background_actor_add_vignette    (MetaBackgroundActor *self,
 | 
			
		||||
                                            double               brightness,
 | 
			
		||||
                                            double               sharpness);
 | 
			
		||||
void meta_background_actor_remove_vignette (MetaBackgroundActor *self);
 | 
			
		||||
 | 
			
		||||
#endif /* META_BACKGROUND_ACTOR_H */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										76
									
								
								src/meta/meta-background-image.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/meta/meta-background-image.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaBackgroundImageCache:
 | 
			
		||||
 *
 | 
			
		||||
 * Simple cache for background textures loaded from files
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2014 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __META_BACKGROUND_IMAGE_H__
 | 
			
		||||
#define __META_BACKGROUND_IMAGE_H__
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_BACKGROUND_IMAGE            (meta_background_image_get_type ())
 | 
			
		||||
#define META_BACKGROUND_IMAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKGROUND_IMAGE, MetaBackgroundImage))
 | 
			
		||||
#define META_BACKGROUND_IMAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BACKGROUND_IMAGE, MetaBackgroundImageClass))
 | 
			
		||||
#define META_IS_BACKGROUND_IMAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKGROUND_IMAGE))
 | 
			
		||||
#define META_IS_BACKGROUND_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BACKGROUND_IMAGE))
 | 
			
		||||
#define META_BACKGROUND_IMAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BACKGROUND_IMAGE, MetaBackgroundImageClass))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaBackgroundImage:
 | 
			
		||||
 *
 | 
			
		||||
 * #MetaBackgroundImage is an object that represents a loaded or loading background image.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaBackgroundImage      MetaBackgroundImage;
 | 
			
		||||
typedef struct _MetaBackgroundImageClass MetaBackgroundImageClass;
 | 
			
		||||
 | 
			
		||||
GType meta_background_image_get_type (void);
 | 
			
		||||
 | 
			
		||||
gboolean     meta_background_image_is_loaded   (MetaBackgroundImage *image);
 | 
			
		||||
gboolean     meta_background_image_get_success (MetaBackgroundImage *image);
 | 
			
		||||
CoglTexture *meta_background_image_get_texture (MetaBackgroundImage *image);
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_BACKGROUND_IMAGE_CACHE            (meta_background_image_cache_get_type ())
 | 
			
		||||
#define META_BACKGROUND_IMAGE_CACHE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKGROUND_IMAGE_CACHE, MetaBackgroundImageCache))
 | 
			
		||||
#define META_BACKGROUND_IMAGE_CACHE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BACKGROUND_IMAGE_CACHE, MetaBackgroundImageCacheClass))
 | 
			
		||||
#define META_IS_BACKGROUND_IMAGE_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKGROUND_IMAGE_CACHE))
 | 
			
		||||
#define META_IS_BACKGROUND_IMAGE_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BACKGROUND_IMAGE_CACHE))
 | 
			
		||||
#define META_BACKGROUND_IMAGE_CACHE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BACKGROUND_IMAGE_CACHE, MetaBackgroundImageCacheClass))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaBackgroundImageCache:
 | 
			
		||||
 *
 | 
			
		||||
 * #MetaBackgroundImageCache caches loading of textures for backgrounds; there's actually
 | 
			
		||||
 * nothing background specific about it, other than it is tuned to work well for
 | 
			
		||||
 * large images as typically are used for backgrounds.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaBackgroundImageCache      MetaBackgroundImageCache;
 | 
			
		||||
typedef struct _MetaBackgroundImageCacheClass MetaBackgroundImageCacheClass;
 | 
			
		||||
 | 
			
		||||
MetaBackgroundImageCache *meta_background_image_cache_get_default (void);
 | 
			
		||||
 | 
			
		||||
GType meta_background_image_cache_get_type (void);
 | 
			
		||||
 | 
			
		||||
MetaBackgroundImage *meta_background_image_cache_load  (MetaBackgroundImageCache *cache,
 | 
			
		||||
                                                        const char               *filename);
 | 
			
		||||
void                 meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
 | 
			
		||||
                                                        const char               *filename);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_BACKGROUND_IMAGE_H__ */
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * meta-background.h: CoglTexture for paintnig the system background
 | 
			
		||||
 * meta-background-actor.h:  for painting the root window background
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2013 Red Hat, Inc.
 | 
			
		||||
 * Copyright 2010 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
@@ -21,20 +21,16 @@
 | 
			
		||||
#ifndef META_BACKGROUND_H
 | 
			
		||||
#define META_BACKGROUND_H
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/gradient.h>
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
 | 
			
		||||
#include <gsettings-desktop-schemas/gdesktop-enums.h>
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaBackground:
 | 
			
		||||
 *
 | 
			
		||||
 * This class handles loading a background from file, screenshot, or
 | 
			
		||||
 * color scheme. The resulting object can be associated with one or
 | 
			
		||||
 * more #MetaBackgroundActor objects to handle loading the background.
 | 
			
		||||
 * This class handles tracking and painting the root window background.
 | 
			
		||||
 * By integrating with #MetaWindowGroup we can avoid painting parts of
 | 
			
		||||
 * the background that are obscured by other windows.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_BACKGROUND            (meta_background_get_type ())
 | 
			
		||||
@@ -48,20 +44,6 @@ typedef struct _MetaBackground        MetaBackground;
 | 
			
		||||
typedef struct _MetaBackgroundClass   MetaBackgroundClass;
 | 
			
		||||
typedef struct _MetaBackgroundPrivate MetaBackgroundPrivate;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaBackgroundEffects:
 | 
			
		||||
 * @META_BACKGROUND_EFFECTS_NONE: No effect
 | 
			
		||||
 * @META_BACKGROUND_EFFECTS_VIGNETTE: Vignette
 | 
			
		||||
 *
 | 
			
		||||
 * Which effects to enable on the background
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_BACKGROUND_EFFECTS_NONE       = 0,
 | 
			
		||||
  META_BACKGROUND_EFFECTS_VIGNETTE   = 1 << 1,
 | 
			
		||||
} MetaBackgroundEffects;
 | 
			
		||||
 | 
			
		||||
struct _MetaBackgroundClass
 | 
			
		||||
{
 | 
			
		||||
  /*< private >*/
 | 
			
		||||
@@ -70,7 +52,6 @@ struct _MetaBackgroundClass
 | 
			
		||||
 | 
			
		||||
struct _MetaBackground
 | 
			
		||||
{
 | 
			
		||||
  /*< private >*/
 | 
			
		||||
  GObject parent;
 | 
			
		||||
 | 
			
		||||
  MetaBackgroundPrivate *priv;
 | 
			
		||||
@@ -78,33 +59,21 @@ struct _MetaBackground
 | 
			
		||||
 | 
			
		||||
GType meta_background_get_type (void);
 | 
			
		||||
 | 
			
		||||
MetaBackground *meta_background_new (MetaScreen           *screen,
 | 
			
		||||
                                     int                   monitor,
 | 
			
		||||
				     MetaBackgroundEffects effects);
 | 
			
		||||
MetaBackground *meta_background_copy (MetaBackground        *self,
 | 
			
		||||
                                      int                    monitor,
 | 
			
		||||
				      MetaBackgroundEffects  effects);
 | 
			
		||||
MetaBackground *meta_background_new  (MetaScreen *screen);
 | 
			
		||||
 | 
			
		||||
void meta_background_load_gradient (MetaBackground            *self,
 | 
			
		||||
                                    GDesktopBackgroundShading  shading_direction,
 | 
			
		||||
                                    ClutterColor              *color,
 | 
			
		||||
                                    ClutterColor              *second_color);
 | 
			
		||||
void meta_background_load_color (MetaBackground *self,
 | 
			
		||||
                                 ClutterColor   *color);
 | 
			
		||||
void meta_background_load_file_async (MetaBackground          *self,
 | 
			
		||||
                                      const char              *filename,
 | 
			
		||||
                                      GDesktopBackgroundStyle  style,
 | 
			
		||||
                                      GCancellable            *cancellable,
 | 
			
		||||
                                      GAsyncReadyCallback      callback,
 | 
			
		||||
                                      gpointer                 user_data);
 | 
			
		||||
gboolean meta_background_load_file_finish (MetaBackground       *self,
 | 
			
		||||
                                           GAsyncResult         *result,
 | 
			
		||||
                                           GError              **error);
 | 
			
		||||
 | 
			
		||||
const char *meta_background_get_filename (MetaBackground *self);
 | 
			
		||||
GDesktopBackgroundStyle meta_background_get_style (MetaBackground *self);
 | 
			
		||||
GDesktopBackgroundShading meta_background_get_shading (MetaBackground *self);
 | 
			
		||||
const ClutterColor *meta_background_get_color (MetaBackground *self);
 | 
			
		||||
const ClutterColor *meta_background_get_second_color (MetaBackground *self);
 | 
			
		||||
void meta_background_set_color    (MetaBackground            *self,
 | 
			
		||||
                                   ClutterColor              *color);
 | 
			
		||||
void meta_background_set_gradient (MetaBackground            *self,
 | 
			
		||||
                                   GDesktopBackgroundShading  shading_direction,
 | 
			
		||||
                                   ClutterColor              *color,
 | 
			
		||||
                                   ClutterColor              *second_color);
 | 
			
		||||
void meta_background_set_filename (MetaBackground            *self,
 | 
			
		||||
                                   const char                *filename,
 | 
			
		||||
                                   GDesktopBackgroundStyle    style);
 | 
			
		||||
void meta_background_set_blend    (MetaBackground            *self,
 | 
			
		||||
                                   const char                *filename1,
 | 
			
		||||
                                   const char                *filename2,
 | 
			
		||||
                                   double                     blend_factor,
 | 
			
		||||
                                   GDesktopBackgroundStyle    style);
 | 
			
		||||
 | 
			
		||||
#endif /* META_BACKGROUND_H */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user