2008-04-15 Matthew Allum <mallum@openedhand.com>
authorMatthew Allum <mallum@openedhand.com>
Tue, 15 Apr 2008 21:18:13 +0000 (21:18 +0000)
committerMatthew Allum <mallum@openedhand.com>
Tue, 15 Apr 2008 21:18:13 +0000 (21:18 +0000)
        Work related to #873;

        * clutter/glx/clutter-backend-glx.c:
        * clutter/glx/clutter-backend-glx.h:
        * clutter/x11/clutter-x11-texture-pixmap.c:
        * clutter/x11/clutter-x11-texture-pixmap.h:
        General cleanup of texture pixmap code, adding;
          - Pixmap dimentions and depth now auto probed, read only props.
          - More X safety traps
          - Add support for optionally tracking damage and automatically
            updating texture.

        * clutter/glx/clutter-glx-texture-pixmap.c:
        * clutter/glx/clutter-glx-texture-pixmap.h:
        General cleanup and some safety additions. Needs more work so
        'proper' subclass - dependent on new COGL.

        * clutter/x11/clutter-backend-x11.c: (clutter_x11_remove_filter):
        Invert g_return_if check.

        * configure.ac:
        Pull in XComposite and XDamage (at least for now)

        * tests/Makefile.am:
        * tests/test-pixmap.c:
        Add a modified test from Johan for above.

ChangeLog
clutter/glx/clutter-backend-glx.c
clutter/glx/clutter-backend-glx.h
clutter/glx/clutter-glx-texture-pixmap.c
clutter/glx/clutter-glx-texture-pixmap.h
clutter/x11/clutter-backend-x11.c
clutter/x11/clutter-x11-texture-pixmap.c
clutter/x11/clutter-x11-texture-pixmap.h
configure.ac
tests/Makefile.am
tests/test-pixmap.c [new file with mode: 0644]

index 81b9484..96e4afb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2008-04-15  Matthew Allum  <mallum@openedhand.com>
+
+        Work related to #873;
+
+       * clutter/glx/clutter-backend-glx.c:
+       * clutter/glx/clutter-backend-glx.h:
+       * clutter/x11/clutter-x11-texture-pixmap.c:
+       * clutter/x11/clutter-x11-texture-pixmap.h:
+        General cleanup of texture pixmap code, adding;
+          - Pixmap dimentions and depth now auto probed, read only props.
+          - More X safety traps
+          - Add support for optionally tracking damage and automatically
+            updating texture.
+
+       * clutter/glx/clutter-glx-texture-pixmap.c:
+       * clutter/glx/clutter-glx-texture-pixmap.h:
+        General cleanup and some safety additions. Needs more work so
+        'proper' subclass - dependent on new COGL.
+
+       * clutter/x11/clutter-backend-x11.c: (clutter_x11_remove_filter):
+        Invert g_return_if check.
+
+       * configure.ac:
+        Pull in XComposite and XDamage (at least for now)
+
+       * tests/Makefile.am:
+       * tests/test-pixmap.c:
+        Add a modified test from Johan for above.
+
 2008-04-15  Neil Roberts  <neil@o-hand.com>
 
        Added support for foreign windows to the Win32 backend.
index 34b9c23..f67042e 100644 (file)
@@ -342,18 +342,6 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
         }
     }
 
-  /* Check for the texture from pixmap extension */
-  if (cogl_check_extension ("GLX_EXT_texture_from_pixmap", glx_extensions))
-    {
-      backend_glx->bind_tex_image =
-          (BindTexImage)cogl_get_proc_address ("glXBindTexImageEXT");
-      backend_glx->release_tex_image =
-          (ReleaseTexImage)cogl_get_proc_address ("glXReleaseTexImageEXT");
-
-      if (backend_glx->bind_tex_image && backend_glx->release_tex_image)
-        backend_glx->t_f_p = TRUE;
-    }
-
   CLUTTER_NOTE (MISC, "backend features checked");
 
   return flags;
index 9f0755c..fadffd3 100644 (file)
@@ -59,14 +59,6 @@ typedef int (*WaitVideoSyncProc) (int           divisor,
                                   int          remainder,
                                   unsigned int *count);
 typedef int (*SwapIntervalProc) (int interval);
-typedef void    (*BindTexImage)    (Display     *display,
-                                    GLXDrawable  drawable,
-                                    int          buffer,
-                                    int         *attribList);
-typedef void    (*ReleaseTexImage)    (Display     *display,
-                                       GLXDrawable  drawable,
-                                       int          buffer);
-
 
 struct _ClutterBackendGLX
 {
@@ -82,11 +74,6 @@ struct _ClutterBackendGLX
   gint                   dri_fd;
   ClutterGLXVBlankType   vblank_type;
 
-  /* texture from pixmap stuff */
-  gboolean              t_f_p;
-  BindTexImage          bind_tex_image;
-  ReleaseTexImage       release_tex_image;
-
   /* props */
   Atom atom_WM_STATE;
   Atom atom_WM_STATE_FULLSCREEN;
index d5b267f..420e551 100644 (file)
 
 #include "cogl.h"
 
-enum
-{
-  PROP_PIXMAP = 1,
-  PROP_PIXMAP_WIDTH,
-  PROP_PIXMAP_HEIGHT,
-  PROP_DEPTH
-};
+typedef void    (*BindTexImage) (Display     *display,
+                                 GLXDrawable  drawable,
+                                 int          buffer,
+                                 int         *attribList);
+typedef void    (*ReleaseTexImage) (Display     *display,
+                                    GLXDrawable  drawable,
+                                    int          buffer);
+
+static BindTexImage      _gl_bind_tex_image = NULL;
+static ReleaseTexImage   _gl_release_tex_image = NULL;
+static gboolean          _have_tex_from_pixmap_ext = FALSE;
+static gboolean          _ext_check_done = FALSE;
 
 struct _ClutterGLXTexturePixmapPrivate
 {
@@ -62,32 +67,44 @@ struct _ClutterGLXTexturePixmapPrivate
   guint         texture_id;
   GLXPixmap     glx_pixmap;
   gboolean      bound;
+
 };
 
-static ClutterBackendGLX *backend = NULL;
+static void 
+clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass);
+
+static void 
+clutter_glx_texture_pixmap_init       (ClutterGLXTexturePixmap *self);
+
+static void 
+clutter_glx_texture_pixmap_dispose (GObject *object);
+
+static void 
+clutter_glx_texture_pixmap_notify (GObject    *object,
+                                   GParamSpec *pspec);
 
-static void clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass);
-static void clutter_glx_texture_pixmap_init       (ClutterGLXTexturePixmap *self);
-static GObject *clutter_glx_texture_pixmap_constructor (GType                  type,
-                                                        guint                  n_construct_properties,
-                                                        GObjectConstructParam *construct_properties);
-static void clutter_glx_texture_pixmap_dispose    (GObject *object);
-static void clutter_glx_texture_pixmap_notify     (GObject    *object,
-                                                   GParamSpec *pspec);
+static void 
+clutter_glx_texture_pixmap_realize (ClutterActor *actor);
 
-static void clutter_glx_texture_pixmap_realize (ClutterActor *actor);
-static void clutter_glx_texture_pixmap_unrealize (ClutterActor *actor);
-static void clutter_glx_texture_pixmap_paint (ClutterActor *actor);
+static void 
+clutter_glx_texture_pixmap_unrealize (ClutterActor *actor);
 
-static void clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
-                                                    gint x,
-                                                    gint y,
-                                                    gint width,
-                                                    gint height);
+static void 
+clutter_glx_texture_pixmap_paint (ClutterActor *actor);
 
-static void clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture);
+static void 
+clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
+                                        gint x,
+                                        gint y,
+                                        gint width,
+                                        gint height);
+
+static void 
+clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *tex);
 
-G_DEFINE_TYPE (ClutterGLXTexturePixmap, clutter_glx_texture_pixmap, CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
+G_DEFINE_TYPE (ClutterGLXTexturePixmap,    \
+               clutter_glx_texture_pixmap, \
+               CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
 
 static void
 clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
@@ -96,11 +113,9 @@ clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
   ClutterActorClass            *actor_class = CLUTTER_ACTOR_CLASS (klass);
   ClutterX11TexturePixmapClass *x11_texture_class =
       CLUTTER_X11_TEXTURE_PIXMAP_CLASS (klass);
-  ClutterBackend               *default_backend;
 
   g_type_class_add_private (klass, sizeof (ClutterGLXTexturePixmapPrivate));
 
-  object_class->constructor = clutter_glx_texture_pixmap_constructor;
   object_class->dispose = clutter_glx_texture_pixmap_dispose;
   object_class->notify = clutter_glx_texture_pixmap_notify;
 
@@ -110,17 +125,28 @@ clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
 
   x11_texture_class->update_area = clutter_glx_texture_pixmap_update_area;
 
-  default_backend = clutter_get_default_backend ();
-  if (!CLUTTER_IS_BACKEND_GLX (default_backend))
+  if (_ext_check_done == FALSE)
     {
-      g_critical ("ClutterGLXTexturePixmap instanciated with a "
-                  "non-GLX backend");
-      return;
+      const gchar *glx_extensions = NULL;
+
+      glx_extensions = 
+        glXQueryExtensionsString (clutter_x11_get_default_display (),
+                                  clutter_x11_get_default_screen ());
+      
+      /* Check for the texture from pixmap extension */
+      if (cogl_check_extension ("GLX_EXT_texture_from_pixmap", glx_extensions))
+        {
+          _gl_bind_tex_image =
+            (BindTexImage)cogl_get_proc_address ("glXBindTexImageEXT");
+          _gl_release_tex_image =
+            (ReleaseTexImage)cogl_get_proc_address ("glXReleaseTexImageEXT");
+          
+          if (_gl_bind_tex_image && _gl_release_tex_image)
+            _have_tex_from_pixmap_ext = TRUE;
+        }
+      
+      _ext_check_done = TRUE;
     }
-
-  backend = (ClutterBackendGLX *)default_backend;
-/*  backend->t_f_p = FALSE;*/
-
 }
 
 static void
@@ -133,40 +159,29 @@ clutter_glx_texture_pixmap_init (ClutterGLXTexturePixmap *self)
                                    CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
                                    ClutterGLXTexturePixmapPrivate);
 
-
   if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE))
     priv->target_type = CGL_TEXTURE_RECTANGLE_ARB;
   else
     priv->target_type = CGL_TEXTURE_2D;
 }
 
-static GObject *
-clutter_glx_texture_pixmap_constructor (GType                  type,
-                                        guint                  n_construct_properties,
-                                        GObjectConstructParam *construct_properties)
-{
-  GObject *object = G_OBJECT_CLASS (clutter_glx_texture_pixmap_parent_class)->
-      constructor (type, n_construct_properties, construct_properties);
-
-  g_object_set (object,
-                "sync-size", FALSE,
-                NULL);
-
-  return object;
-}
-
 static void
 clutter_glx_texture_pixmap_dispose (GObject *object)
 {
-  ClutterGLXTexturePixmapPrivate *priv = CLUTTER_GLX_TEXTURE_PIXMAP (object)->priv;
+  ClutterGLXTexturePixmapPrivate *priv;
+
+  priv = CLUTTER_GLX_TEXTURE_PIXMAP (object)->priv;
 
   if (priv->glx_pixmap != None)
     {
       clutter_x11_trap_x_errors ();
-      glXDestroyGLXPixmap (((ClutterBackendX11 *)backend)->xdpy,
+
+      glXDestroyGLXPixmap (clutter_x11_get_default_display(),
                            priv->glx_pixmap);
-      XSync (((ClutterBackendX11 *)backend)->xdpy, FALSE);
+      XSync (clutter_x11_get_default_display(), FALSE);
+
       clutter_x11_untrap_x_errors ();
+
       priv->glx_pixmap = None;
     }
 
@@ -179,7 +194,6 @@ clutter_glx_texture_pixmap_notify (GObject *object, GParamSpec *pspec)
   if (g_str_equal (pspec->name, "pixmap"))
     {
       ClutterGLXTexturePixmap *texture = CLUTTER_GLX_TEXTURE_PIXMAP (object);
-
       clutter_glx_texture_pixmap_create_glx_pixmap (texture);
     }
 }
@@ -187,17 +201,17 @@ clutter_glx_texture_pixmap_notify (GObject *object, GParamSpec *pspec)
 static void
 clutter_glx_texture_pixmap_realize (ClutterActor *actor)
 {
-  ClutterGLXTexturePixmapPrivate *priv =
-      CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
-  COGLenum                      pixel_type, pixel_format,
-                                filter_quality;
-  gboolean                      repeat_x, repeat_y;
-  guint                         width, height;
-
-  if (!backend->t_f_p)
+  ClutterGLXTexturePixmapPrivate *priv;
+  COGLenum                        pixel_type, pixel_format,filter_quality;
+  gboolean                        repeat_x, repeat_y;
+  guint                           width, height;
+
+  priv = CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
+
+  if (!_have_tex_from_pixmap_ext) 
     {
       CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
-          realize (actor);
+        realize (actor);
       return;
     }
 
@@ -233,11 +247,13 @@ clutter_glx_texture_pixmap_realize (ClutterActor *actor)
 static void
 clutter_glx_texture_pixmap_unrealize (ClutterActor *actor)
 {
-  ClutterGLXTexturePixmapPrivate *priv =
-      CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
-  Display                        *dpy = ((ClutterBackendX11 *)backend)->xdpy;
+  ClutterGLXTexturePixmapPrivate *priv;
+  Display                        *dpy;
+
+  priv = CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
+  dpy = clutter_x11_get_default_display();
 
-  if (!backend->t_f_p)
+  if (!_have_tex_from_pixmap_ext)
     {
       CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
           unrealize (actor);
@@ -249,9 +265,14 @@ clutter_glx_texture_pixmap_unrealize (ClutterActor *actor)
 
   if (priv->bound && priv->glx_pixmap)
     {
-      (backend->release_tex_image) (dpy,
-                                    priv->glx_pixmap,
-                                    GLX_FRONT_LEFT_EXT);
+      clutter_x11_trap_x_errors ();
+
+      (_gl_release_tex_image) (dpy,
+                               priv->glx_pixmap,
+                               GLX_FRONT_LEFT_EXT);
+
+      XSync (clutter_x11_get_default_display(), FALSE);
+      clutter_x11_untrap_x_errors ();
     }
 
   cogl_textures_destroy (1, &priv->texture_id);
@@ -314,7 +335,7 @@ clutter_glx_texture_pixmap_paint (ClutterActor *actor)
   gint            x_1, y_1, x_2, y_2;
   ClutterColor    col = { 0xff, 0xff, 0xff, 0xff };
 
-  if (!backend->t_f_p)
+  if (!_have_tex_from_pixmap_ext)
     {
       CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
           paint (actor);
@@ -354,11 +375,13 @@ get_fbconfig_for_depth (guint depth)
 {
   GLXFBConfig *fbconfigs, *ret = NULL;
   int          n_elements, i, found;
-  Display     *dpy = ((ClutterBackendX11 *)backend)->xdpy;
+  Display     *dpy;
   int          db, stencil, alpha, mipmap, rgba, value;
 
+  dpy = clutter_x11_get_default_display ();
+
   fbconfigs = glXGetFBConfigs (dpy,
-                               ((ClutterBackendX11 *)backend)->xscreen_num,
+                               clutter_x11_get_default_screen (),
                                &n_elements);
 
   db      = G_MAXSHORT;
@@ -404,7 +427,6 @@ get_fbconfig_for_depth (guint depth)
                                 fbconfigs[i],
                                 GLX_BIND_TO_TEXTURE_RGBA_EXT,
                                 &value);
-
           if (value)
             rgba = 1;
         }
@@ -462,12 +484,17 @@ clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
   GLXPixmap                       glx_pixmap;
   int                             attribs[7], i = 0;
   GLXFBConfig                    *fbconfig;
-  Display                        *dpy = ((ClutterBackendX11 *)backend)->xdpy;
+  Display                        *dpy;
   guint                           depth;
   Pixmap                          pixmap;
+  ClutterBackendGLX             *backend_glx;
+
+  backend_glx = CLUTTER_BACKEND_GLX(clutter_get_default_backend ());
+
+  dpy = clutter_x11_get_default_display ();
 
   g_object_get (texture,
-                "depth",                &depth,
+                "pixmap-depth",                &depth,
                 "pixmap",               &pixmap,
                 NULL);
 
@@ -522,15 +549,23 @@ clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
     {
       if (priv->glx_pixmap)
         {
-          if (backend->t_f_p &&
+          if (_have_tex_from_pixmap_ext &&
               CLUTTER_ACTOR_IS_REALIZED (texture) &&
               priv->bound)
             {
               cogl_texture_bind (priv->target_type, priv->texture_id);
 
-              (backend->release_tex_image) (dpy,
-                                            priv->glx_pixmap,
-                                            GLX_FRONT_LEFT_EXT);
+              clutter_x11_trap_x_errors ();
+
+              (_gl_release_tex_image) (dpy,
+                                       priv->glx_pixmap,
+                                       GLX_FRONT_LEFT_EXT);
+
+              XSync (clutter_x11_get_default_display(), FALSE);
+              
+              if (clutter_x11_untrap_x_errors ())
+                g_warning ("Failed to bind texture pixmap");
+
             }
 
           clutter_x11_trap_x_errors ();
@@ -551,16 +586,17 @@ clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
                                         gint                     height)
 {
   ClutterGLXTexturePixmapPrivate       *priv;
-  Display                              *dpy =
-      ((ClutterBackendX11 *)backend)->xdpy;
+  Display                              *dpy;
 
   priv = CLUTTER_GLX_TEXTURE_PIXMAP (texture)->priv;
+  dpy = clutter_x11_get_default_display();
 
-  if (!backend->t_f_p)
+  if (!_have_tex_from_pixmap_ext)
     {
-      CLUTTER_X11_TEXTURE_PIXMAP_CLASS (texture)->update_area (texture,
-                                                               x, y,
-                                                               width, height);
+      CLUTTER_X11_TEXTURE_PIXMAP_CLASS 
+        (texture)->update_area (texture,
+                                x, y,
+                                width, height);
       return;
     }
 
@@ -569,12 +605,19 @@ clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
 
   cogl_texture_bind (priv->target_type, priv->texture_id);
 
-  if (backend->t_f_p)
+  if (_have_tex_from_pixmap_ext)
     {
-      (backend->bind_tex_image) (dpy,
-                                 priv->glx_pixmap,
-                                 GLX_FRONT_LEFT_EXT,
-                                 NULL);
+      clutter_x11_trap_x_errors ();
+
+      (_gl_bind_tex_image) (dpy,
+                            priv->glx_pixmap,
+                            GLX_FRONT_LEFT_EXT,
+                            NULL);
+
+      XSync (clutter_x11_get_default_display(), FALSE);
+
+      if (clutter_x11_untrap_x_errors ())
+        g_warning ("Failed to bind texture pixmap");
 
       priv->bound = TRUE;
     }
@@ -592,18 +635,12 @@ clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
  * Since: 0.8
  **/
 ClutterActor *
-clutter_glx_texture_pixmap_new_with_pixmap (Pixmap pixmap,
-                                           guint  width,
-                                           guint  height,
-                                           guint  depth)
+clutter_glx_texture_pixmap_new_with_pixmap (Pixmap pixmap)
 {
   ClutterActor *actor;
 
   actor = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
                         "pixmap", pixmap,
-                        "pixmap-width",  width,
-                        "pixmap-height", height,
-                        "depth",  depth,
                         NULL);
 
   return actor;
index a24ebe6..f77f17f 100644 (file)
@@ -60,10 +60,7 @@ GType clutter_glx_texture_pixmap_get_type (void);
 
 ClutterActor * clutter_glx_texture_pixmap_new (void);
 
-ClutterActor * clutter_glx_texture_pixmap_new_with_pixmap (Pixmap pixmap,
-                                                          guint width,
-                                                          guint height,
-                                                          guint depth);
+ClutterActor * clutter_glx_texture_pixmap_new_with_pixmap (Pixmap pixmap);
 
 G_END_DECLS
 
index 908574b..1fbf0e7 100644 (file)
@@ -507,7 +507,7 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func,
   GSList                *tmp_list, *this;
   ClutterX11EventFilter *filter;
 
-  g_return_if_fail (func == NULL);
+  g_return_if_fail (func != NULL);
 
   tmp_list = backend_singleton->event_filters;
 
index af17d50..3268540 100644 (file)
 
 #include "cogl.h"
 
+/* FIXME: Check exts exist in autogen */
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/Xcomposite.h>
+
 enum
 {
   PROP_PIXMAP = 1,
   PROP_PIXMAP_WIDTH,
   PROP_PIXMAP_HEIGHT,
-  PROP_DEPTH
+  PROP_DEPTH,
+  PROP_AUTO
 };
 
 enum
 {
   UPDATE_AREA,
-
+  /* FIXME: Pixmap lost signal? */
   LAST_SIGNAL
 };
 
+static ClutterX11FilterReturn 
+on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data);
+
+static void
+clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
+                                             gint                     x,
+                                             gint                     y,
+                                             gint                     width,
+                                             gint                     height);
+
 static guint signals[LAST_SIGNAL] = { 0, };
 
 struct _ClutterX11TexturePixmapPrivate
@@ -72,133 +87,128 @@ struct _ClutterX11TexturePixmapPrivate
 
   XImage       *image;
 
+  gboolean      automatic_updates;     
+  Damage        damage;
+
 };
 
-static ClutterBackendX11 *backend = NULL;
-
-static void clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass);
-static void clutter_x11_texture_pixmap_init       (ClutterX11TexturePixmap *self);
-static GObject *clutter_x11_texture_pixmap_constructor (GType                  type,
-                                                        guint                  n_construct_properties,
-                                                        GObjectConstructParam *construct_properties);
-static void clutter_x11_texture_pixmap_dispose    (GObject *object);
-static void clutter_x11_texture_pixmap_set_property (GObject      *object,
-                                                     guint         prop_id,
-                                                     const GValue *value,
-                                                     GParamSpec   *pspec);
-static void clutter_x11_texture_pixmap_get_property (GObject      *object,
-                                                     guint         prop_id,
-                                                     GValue       *value,
-                                                     GParamSpec   *pspec);
-
-static void clutter_x11_texture_pixmap_realize (ClutterActor *actor);
-static void clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
-                                                         gint x,
-                                                         gint y,
-                                                         gint width,
-                                                         gint height);
-
-G_DEFINE_TYPE (ClutterX11TexturePixmap, clutter_x11_texture_pixmap, CLUTTER_TYPE_TEXTURE);
+static int _damage_event_base = 0;
 
-static void
-clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
+/* FIXME: Ultimatly with current cogl we should subclass clutter actor */
+G_DEFINE_TYPE (ClutterX11TexturePixmap, \
+               clutter_x11_texture_pixmap, \
+               CLUTTER_TYPE_TEXTURE);
+
+static gboolean
+check_extensions (ClutterX11TexturePixmap *texture)
 {
-  GObjectClass      *object_class = G_OBJECT_CLASS (klass);
-  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
-  GParamSpec        *pspec;
-  ClutterBackend    *default_backend;
+  int                             event_base, error_base;
+  int                             damage_error;
+  ClutterX11TexturePixmapPrivate *priv;
+  Display                        *dpy;
 
-  g_type_class_add_private (klass, sizeof (ClutterX11TexturePixmapPrivate));
+  priv = texture->priv;
 
-  object_class->constructor = clutter_x11_texture_pixmap_constructor;
-  object_class->dispose = clutter_x11_texture_pixmap_dispose;
-  object_class->set_property = clutter_x11_texture_pixmap_set_property;
-  object_class->get_property = clutter_x11_texture_pixmap_get_property;
+  if (_damage_event_base)
+    return TRUE;
 
-  actor_class->realize   = clutter_x11_texture_pixmap_realize;
+  dpy = clutter_x11_get_default_display();
 
-  klass->update_area = clutter_x11_texture_pixmap_update_area_real;
+  if (!XCompositeQueryExtension (dpy, &event_base, &error_base))
+    {
+      g_warning ("No composite extension\n");
+      return FALSE;
+    }
 
-  pspec = g_param_spec_uint ("pixmap",
-                             "Pixmap",
-                             "The X Pixmap to which this texture will be bound",
-                             0, G_MAXINT,
-                             None,
-                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+  if (!XDamageQueryExtension (dpy,
+                              &_damage_event_base, &damage_error))
+    {
+      g_warning ("No Damage extension\n");
+      return FALSE;
+    }
 
-  g_object_class_install_property (object_class,
-                                   PROP_PIXMAP,
-                                   pspec);
+  return TRUE;
+}
 
-  pspec = g_param_spec_uint ("pixmap-width",
-                             "Pixmap width",
-                             "The width of the "
-                             "pixmap bound to this texture",
-                             0, G_MAXUINT,
-                             0,
-                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+static ClutterX11FilterReturn 
+on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data)
+{
+  ClutterX11TexturePixmap        *texture;
+  ClutterX11TexturePixmapPrivate *priv;
+  Display                        *dpy;
 
-  g_object_class_install_property (object_class,
-                                   PROP_PIXMAP_WIDTH,
-                                   pspec);
+  texture = CLUTTER_X11_TEXTURE_PIXMAP (data);
+  
+  g_return_val_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture), \
+                        CLUTTER_X11_FILTER_CONTINUE);
 
-  pspec = g_param_spec_uint ("pixmap-height",
-                             "Pixmap height",
-                             "The height of the "
-                             "pixmap bound to this texture",
-                             0, G_MAXUINT,
-                             0,
-                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+  dpy = clutter_x11_get_default_display();
+  priv = texture->priv;
+  
+  if (xev->type == _damage_event_base + XDamageNotify)
+    {
+      XserverRegion  parts;
+      gint           i, r_count;
+      XRectangle    *r_damage;
+      XRectangle     r_bounds;
+      XDamageNotifyEvent *dev = (XDamageNotifyEvent*)xev;
+      
+      if (dev->drawable != priv->pixmap)
+        return CLUTTER_X11_FILTER_CONTINUE;
+
+
+      clutter_x11_trap_x_errors ();
+      /*
+       * Retrieve the damaged region and break it down into individual
+       * rectangles so we do not have to update the whole shebang.
+       */
+      parts = XFixesCreateRegion (dpy, 0, 0);
+      XDamageSubtract (dpy, priv->damage, None, parts);
+
+      r_damage = XFixesFetchRegionAndBounds (dpy, 
+                                             parts,
+                                             &r_count,
+                                             &r_bounds);
+
+      clutter_x11_untrap_x_errors ();
+
+      if (r_damage)
+        {
+          for (i = 0; i < r_count; ++i)
+            clutter_x11_texture_pixmap_update_area (texture,
+                                                    r_damage[i].x,
+                                                    r_damage[i].y,
+                                                    r_damage[i].width,
+                                                    r_damage[i].height);
+          XFree (r_damage);
+        }
 
-  g_object_class_install_property (object_class,
-                                   PROP_PIXMAP_HEIGHT,
-                                   pspec);
+      XFixesDestroyRegion (dpy, parts);
+    }
 
-  pspec = g_param_spec_uint ("depth",
-                             "Depth",
-                             "The depth (in number of bits) of the "
-                             "pixmap bound to this texture",
-                             0, G_MAXUINT,
-                             0,
-                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+  return  CLUTTER_X11_FILTER_CONTINUE;
+}
 
-  g_object_class_install_property (object_class,
-                                   PROP_DEPTH,
-                                   pspec);
-  /**
-   * ClutterX11TexturePixmap::update-area:
-   * @texture: the object which received the signal
-   *
-   * The ::hide signal is emitted to ask the texture to update its
-   * content from its source pixmap.
-   *
-   * Since: 0.8
-   */
-  signals[UPDATE_AREA] =
-      g_signal_new ("update-area",
-                    G_TYPE_FROM_CLASS (object_class),
-                    G_SIGNAL_RUN_FIRST,
-                    G_STRUCT_OFFSET (ClutterX11TexturePixmapClass, update_area),
-                    NULL, NULL,
-                    clutter_marshal_VOID__INT_INT_INT_INT,
-                    G_TYPE_NONE, 4,
-                    G_TYPE_INT,
-                    G_TYPE_INT,
-                    G_TYPE_INT,
-                    G_TYPE_INT);
 
-  default_backend = clutter_get_default_backend ();
-  if (!CLUTTER_IS_BACKEND_X11 (default_backend))
+static void
+free_damage_resources (ClutterX11TexturePixmap *texture)
+{
+  ClutterX11TexturePixmapPrivate *priv;
+  Display                        *dpy;
+
+  priv = texture->priv;
+  dpy = clutter_x11_get_default_display();
+
+  if (priv->damage)
     {
-      g_critical ("ClutterX11TexturePixmap instanciated with a "
-                  "non-X11 backend");
-      return;
+      XDamageDestroy (dpy, priv->damage);
+      priv->damage = None;
     }
 
-  backend = (ClutterBackendX11 *)default_backend;
-
+  clutter_x11_remove_filter (on_x_event_filter, (gpointer)texture);
 }
 
+
 static void
 clutter_x11_texture_pixmap_init (ClutterX11TexturePixmap *self)
 {
@@ -207,15 +217,21 @@ clutter_x11_texture_pixmap_init (ClutterX11TexturePixmap *self)
                                    CLUTTER_X11_TYPE_TEXTURE_PIXMAP,
                                    ClutterX11TexturePixmapPrivate);
 
+  if (!check_extensions (self))
+    {
+      /* FIMXE: means display lacks needed extensions for at least auto. 
+       *        - a _can_autoupdate() method ?
+      */
+    }
 }
 
 static GObject *
 clutter_x11_texture_pixmap_constructor (GType                  type,
-                                        guint                  n_construct_properties,
-                                        GObjectConstructParam *construct_properties)
+                                        guint                  n_props,
+                                        GObjectConstructParam *props)
 {
   GObject *object = G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->
-      constructor (type, n_construct_properties, construct_properties);
+    constructor (type, n_props, props);
 
   g_object_set (object,
                 "sync-size", FALSE,
@@ -227,9 +243,11 @@ clutter_x11_texture_pixmap_constructor (GType                  type,
 static void
 clutter_x11_texture_pixmap_dispose (GObject *object)
 {
-  ClutterX11TexturePixmap        *texture = CLUTTER_X11_TEXTURE_PIXMAP (object);
+  ClutterX11TexturePixmap *texture = CLUTTER_X11_TEXTURE_PIXMAP (object);
   ClutterX11TexturePixmapPrivate *priv = texture->priv;
 
+  free_damage_resources (texture);
+
   if (priv->image)
     {
       XDestroyImage (priv->image);
@@ -237,7 +255,6 @@ clutter_x11_texture_pixmap_dispose (GObject *object)
     }
 
   G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->dispose (object);
-
 }
 
 static void
@@ -246,42 +263,21 @@ clutter_x11_texture_pixmap_set_property (GObject      *object,
                                          const GValue *value,
                                          GParamSpec   *pspec)
 {
-  ClutterX11TexturePixmap        *texture = CLUTTER_X11_TEXTURE_PIXMAP (object);
-  ClutterX11TexturePixmapPrivate *priv = texture->priv;
+  ClutterX11TexturePixmap  *texture = CLUTTER_X11_TEXTURE_PIXMAP (object);
 
   switch (prop_id)
     {
     case PROP_PIXMAP:
-        clutter_x11_texture_pixmap_set_pixmap (texture,
-                                               g_value_get_uint (value),
-                                               priv->pixmap_width,
-                                               priv->pixmap_height,
-                                               priv->depth);
-        break;
-    case PROP_PIXMAP_WIDTH:
-        clutter_x11_texture_pixmap_set_pixmap (texture,
-                                               priv->pixmap,
-                                               g_value_get_uint (value),
-                                               priv->pixmap_height,
-                                               priv->depth);
-        break;
-    case PROP_PIXMAP_HEIGHT:
-        clutter_x11_texture_pixmap_set_pixmap (texture,
-                                               priv->pixmap,
-                                               priv->pixmap_width,
-                                               g_value_get_uint (value),
-                                               priv->depth);
-        break;
-    case PROP_DEPTH:
-        clutter_x11_texture_pixmap_set_pixmap (texture,
-                                               priv->pixmap,
-                                               priv->pixmap_width,
-                                               priv->pixmap_height,
-                                               g_value_get_uint (value));
-        break;
+      clutter_x11_texture_pixmap_set_pixmap (texture,
+                                             g_value_get_uint (value));
+      break;
+    case PROP_AUTO:
+      clutter_x11_texture_pixmap_set_automatic (texture,
+                                                g_value_get_boolean (value));
+      break;
     default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        break;
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
     }
 }
 
@@ -291,26 +287,29 @@ clutter_x11_texture_pixmap_get_property (GObject      *object,
                                          GValue       *value,
                                          GParamSpec   *pspec)
 {
-  ClutterX11TexturePixmap        *texture = CLUTTER_X11_TEXTURE_PIXMAP (object);
+  ClutterX11TexturePixmap *texture = CLUTTER_X11_TEXTURE_PIXMAP (object);
   ClutterX11TexturePixmapPrivate *priv = texture->priv;
 
   switch (prop_id)
     {
     case PROP_PIXMAP:
-        g_value_set_uint (value, priv->pixmap);
-        break;
+      g_value_set_uint (value, priv->pixmap);
+      break;
     case PROP_PIXMAP_WIDTH:
-        g_value_set_uint (value, priv->pixmap_width);
-        break;
+      g_value_set_uint (value, priv->pixmap_width);
+      break;
     case PROP_PIXMAP_HEIGHT:
-        g_value_set_uint (value, priv->pixmap_height);
-        break;
+      g_value_set_uint (value, priv->pixmap_height);
+      break;
     case PROP_DEPTH:
-        g_value_set_uint (value, priv->depth);
-        break;
+      g_value_set_uint (value, priv->depth);
+      break;
+    case PROP_AUTO:
+      g_value_set_boolean (value, priv->automatic_updates);
+      break;
     default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        break;
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
     }
 }
 
@@ -332,6 +331,107 @@ clutter_x11_texture_pixmap_realize (ClutterActor *actor)
 }
 
 static void
+clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
+{
+  GObjectClass      *object_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  GParamSpec        *pspec;
+  ClutterBackend    *default_backend;
+
+  g_type_class_add_private (klass, sizeof (ClutterX11TexturePixmapPrivate));
+
+  object_class->constructor  = clutter_x11_texture_pixmap_constructor;
+  object_class->dispose      = clutter_x11_texture_pixmap_dispose;
+  object_class->set_property = clutter_x11_texture_pixmap_set_property;
+  object_class->get_property = clutter_x11_texture_pixmap_get_property;
+
+  actor_class->realize       = clutter_x11_texture_pixmap_realize;
+
+  klass->update_area         = clutter_x11_texture_pixmap_update_area_real;
+
+  pspec = g_param_spec_uint ("pixmap",
+                             "Pixmap",
+                             "The X11 Pixmap to be bound",
+                             0, G_MAXINT,
+                             None,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_property (object_class, PROP_PIXMAP, pspec);
+
+  pspec = g_param_spec_uint ("pixmap-width",
+                             "Pixmap width",
+                             "The width of the "
+                             "pixmap bound to this texture",
+                             0, G_MAXUINT,
+                             0,
+                             G_PARAM_READABLE);
+
+  g_object_class_install_property (object_class, PROP_PIXMAP_WIDTH, pspec);
+
+  pspec = g_param_spec_uint ("pixmap-height",
+                             "Pixmap height",
+                             "The height of the "
+                             "pixmap bound to this texture",
+                             0, G_MAXUINT,
+                             0,
+                             G_PARAM_READABLE);
+
+  g_object_class_install_property (object_class, PROP_PIXMAP_HEIGHT, pspec);
+
+  pspec = g_param_spec_uint ("pixmap-depth",
+                             "Pixmap Depth",
+                             "The depth (in number of bits) of the "
+                             "pixmap bound to this texture",
+                             0, G_MAXUINT,
+                             0,
+                             G_PARAM_READABLE);
+
+  g_object_class_install_property (object_class, PROP_DEPTH, pspec);
+
+  pspec = g_param_spec_boolean ("automatic-updates",
+                                "Automatic Updates",
+                                "If the texture should be kept in "
+                                "sync with any pixmap changes.",
+                                FALSE,
+                                G_PARAM_READWRITE);
+
+  g_object_class_install_property (object_class, PROP_AUTO, pspec);
+
+
+  /**
+   * ClutterX11TexturePixmap::update-area:
+   * @texture: the object which received the signal
+   *
+   * The ::hide signal is emitted to ask the texture to update its
+   * content from its source pixmap.
+   *
+   * Since: 0.8
+   */
+  signals[UPDATE_AREA] =
+      g_signal_new ("update-area",
+                    G_TYPE_FROM_CLASS (object_class),
+                    G_SIGNAL_RUN_FIRST,
+                    G_STRUCT_OFFSET (ClutterX11TexturePixmapClass, \
+                                     update_area),
+                    NULL, NULL,
+                    clutter_marshal_VOID__INT_INT_INT_INT,
+                    G_TYPE_NONE, 4,
+                    G_TYPE_INT,
+                    G_TYPE_INT,
+                    G_TYPE_INT,
+                    G_TYPE_INT);
+
+  default_backend = clutter_get_default_backend ();
+
+  if (!CLUTTER_IS_BACKEND_X11 (default_backend))
+    {
+      g_critical ("ClutterX11TexturePixmap instanciated with a "
+                  "non-X11 backend");
+      return;
+    }
+}
+
+static void
 clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
                                              gint                     x,
                                              gint                     y,
@@ -352,9 +452,11 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
     return;
 
   priv = texture->priv;
-  dpy  = ((ClutterBackendX11 *)backend)->xdpy;
+  dpy  = clutter_x11_get_default_display();
 
   clutter_x11_trap_x_errors ();
+
+  /* FIXME: Use XSHM here! */
   if (!priv->image)
     priv->image = XGetImage (dpy,
                              priv->pixmap,
@@ -373,8 +475,15 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
                   x, y);
 
   XSync (dpy, FALSE);
+
   if ((err_code = clutter_x11_untrap_x_errors ()))
-    return;
+    {
+      g_warning ("Failed to get XImage of pixmap: %lx, removing.",
+                 priv->pixmap);
+      /* safe to assume pixmap has gone away? - therefor reset */
+      clutter_x11_texture_pixmap_set_pixmap (texture, None);
+      return;
+    }
 
   image = priv->image;
 
@@ -490,18 +599,12 @@ clutter_x11_texture_pixmap_new (void)
  * Since 0.8
  **/
 ClutterActor *
-clutter_x11_texture_pixmap_new_with_pixmap (Pixmap     pixmap,
-                                           guint      width,
-                                           guint      height,
-                                           guint      depth)
+clutter_x11_texture_pixmap_new_with_pixmap (Pixmap pixmap)
 {
   ClutterActor *actor;
 
   actor = g_object_new (CLUTTER_X11_TYPE_TEXTURE_PIXMAP,
                        "pixmap", pixmap,
-                        "pixmap-width",  width,
-                        "pixmap-height", height,
-                        "depth",  depth,
                        NULL);
 
   return actor;
@@ -521,67 +624,87 @@ clutter_x11_texture_pixmap_new_with_pixmap (Pixmap     pixmap,
  **/
 void
 clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
-                                       Pixmap                   pixmap,
-                                       guint                    width,
-                                       guint                    height,
-                                       guint                    depth)
+                                       Pixmap                   pixmap)
 {
+  Window       root;
+  int          x, y; 
+  unsigned int width, height, border_width, depth;
+  Status       status = 0;
+
   ClutterX11TexturePixmapPrivate *priv;
 
   g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture));
 
   priv = texture->priv;
 
+  clutter_x11_trap_x_errors ();
+
+  status = XGetGeometry (clutter_x11_get_default_display(),
+                         (Drawable)pixmap, 
+                         &root,
+                         &x, 
+                         &y, 
+                         &width,
+                         &height, 
+                         &border_width,
+                         &depth);
+
+  if (clutter_x11_untrap_x_errors () || status == 0)
+    {
+      if (pixmap != None)
+        g_warning ("Unable to query pixmap: %lx\n", pixmap);
+      pixmap = None;
+      width = height = depth = 0; 
+    }
+
+  if (priv->image)
+    {
+      XDestroyImage (priv->image);
+      priv->image = NULL;
+    }
+  
+  g_object_ref (texture);
+
   if (priv->pixmap != pixmap)
     {
       priv->pixmap = pixmap;
-
       g_object_notify (G_OBJECT (texture), "pixmap");
-
     }
 
   if (priv->pixmap_width != width)
     {
       priv->pixmap_width = width;
-
       g_object_notify (G_OBJECT (texture), "pixmap-width");
-
     }
 
   if (priv->pixmap_height != height)
     {
       priv->pixmap_height = height;
-
       g_object_notify (G_OBJECT (texture), "pixmap-height");
-
     }
 
   if (priv->depth != depth)
     {
       priv->depth = depth;
-
-      g_object_notify (G_OBJECT (texture), "depth");
-
+      g_object_notify (G_OBJECT (texture), "pixmap-depth");
     }
 
+  g_object_unref (texture);
+
   if (priv->depth != 0 &&
       priv->pixmap != None &&
       priv->pixmap_width != 0 &&
       priv->pixmap_height != 0)
     {
-      if (priv->image)
-        {
-          XDestroyImage (priv->image);
-          priv->image = NULL;
-        }
-
       if (CLUTTER_ACTOR_IS_REALIZED (texture))
         clutter_x11_texture_pixmap_update_area (texture,
                                                 0, 0,
                                                 priv->pixmap_width,
                                                 priv->pixmap_height);
     }
-
+  
+  clutter_actor_set_size (CLUTTER_ACTOR(texture), 
+                          priv->pixmap_width, priv->pixmap_height);
 }
 
 /**
@@ -609,3 +732,71 @@ clutter_x11_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
 
   g_signal_emit (texture, signals[UPDATE_AREA], 0, x, y, width, height);
 }
+
+/* FIXME: to implement */
+void
+clutter_x11_texture_pixmap_set_from_window (ClutterX11TexturePixmap *texture,
+                                            Window                   win,
+                                            gboolean                 reflect)
+{
+  ClutterX11TexturePixmapPrivate *priv;
+
+  g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture));
+
+  /* This would mainly be used for compositing type situations 
+   * with named pixmap (cannot be regular pixmap) and setting up  
+   * actual window redirection.
+   *
+   * It also seems to can pass a window to texture_pixmap and it
+   * it works like redirectwindow automatic. 
+   *
+   * Note windows do however change size, whilst pixmaps do not. 
+  */
+
+  priv = texture->priv;
+
+  /*
+  priv->window_pixmap = XCompositeNameWindowPixmap (dpy, win);
+
+  XCompositeRedirectWindow(clutter_x11_get_default_display(),
+                           win_remote,
+                           CompositeRedirectAutomatic);
+  */
+}
+
+
+
+/* FIXME: Below will change, just proof of concept atm - it will not work
+ *        100% for named pixmaps. 
+*/
+void
+clutter_x11_texture_pixmap_set_automatic (ClutterX11TexturePixmap *texture,
+                                          gboolean                 setting)
+{
+  ClutterX11TexturePixmapPrivate *priv;
+  Display                        *dpy;
+
+  g_return_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture));
+
+  priv = texture->priv;
+
+  if (setting == priv->automatic_updates)
+    return;
+
+  dpy = clutter_x11_get_default_display();
+
+  if (setting == TRUE)
+    {
+      clutter_x11_add_filter (on_x_event_filter, (gpointer)texture);
+          
+      /* NOTE: Appears this will not work for a named pixmap  */
+      priv->damage = XDamageCreate (dpy,
+                                    priv->pixmap,
+                                    XDamageReportNonEmpty);
+    }
+  else
+    free_damage_resources (texture);
+
+  priv->automatic_updates = setting;
+
+}
index 77f8731..a46000b 100644 (file)
@@ -67,16 +67,10 @@ struct _ClutterX11TexturePixmap
 GType clutter_x11_texture_pixmap_get_type (void);
 ClutterActor * clutter_x11_texture_pixmap_new (void);
 
-ClutterActor * clutter_x11_texture_pixmap_new_with_pixmap (Pixmap     pixmap,
-                                                          guint      width,
-                                                          guint      height,
-                                                          guint      depth);
+ClutterActor * clutter_x11_texture_pixmap_new_with_pixmap (Pixmap     pixmap);
 
 void  clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
-                                             Pixmap                   pixmap,
-                                             guint                    width,
-                                             guint                    height,
-                                             guint                    depth);
+                                             Pixmap                   pixmap);
 
 void  clutter_x11_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
                                               gint                     x,
@@ -84,6 +78,9 @@ void  clutter_x11_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
                                               gint                     width,
                                               gint                     height);
 
+void
+clutter_x11_texture_pixmap_set_automatic (ClutterX11TexturePixmap *texture,
+                                          gboolean                 setting);
 
 G_END_DECLS
 
index 6b3b8eb..b41a661 100644 (file)
@@ -113,6 +113,29 @@ if test x$have_xfixes = xyes; then
       X11_LIBS="$X11_LIBS -lXfixes"
 fi
 
+PKG_CHECK_MODULES(XDAMAGE, xdamage, [have_xdamage=yes], [have_xdamage=no])
+if test x$have_xdamage = xyes; then
+      AC_DEFINE(HAVE_XDAMAGE, 1, Have the XDAMAGE X extension)
+      X11_LIBS="$X11_LIBS -lXdamage"
+fi
+
+# FIXME: Composite 0.3/0.4 likely needed when window redirection complete.
+#        though may not be needed at all
+PKG_CHECK_MODULES(XCOMPOSITE, xcomposite, [have_xcomposite=yes], [have_xcomposite=no])
+if test x$have_xcomposite = xyes; then
+      AC_DEFINE(HAVE_XCOMPOSITE, 1, Have the XCOMPOSITE X extension)
+      X11_LIBS="$X11_LIBS -lXcomposite"
+fi
+
+# Currently require all extentions, may not for actual release.
+if test "x$clutterbackend" = "xglx" || test "x$clutterbackend" = "xeglx" 
+then
+      if test "x$have_xdamage" = "xno" || test "x$have_xfixes" = "xno" || test "x$have_xcomposite" = "xno" 
+      then
+            AC_MSG_ERROR([[Required backend X11 Libraries not found.]])
+      fi
+fi 
+
 clutter_gl_header=""
 
 case $clutterbackend in
@@ -458,7 +481,6 @@ echo "                  Flavour:   ${clutterbackend}/${CLUTTER_COGL}"
 echo "               GL Headers:   ${CLUTTER_GL_HEADER}"
 echo "           Target library:   ${clutterbackendlib}"
 echo "              Debug level:   ${enable_debug}"
-echo "      Fast FP conversions:   ${enable_fast_fp_conversions}"
 echo "           Compiler flags:   ${CPPFLAGS}"
 echo "        API Documentation:   ${enable_gtk_doc}"
 echo "     Manual Documentation:   ${enable_manual}"
index a5186bf..a14a5b1 100644 (file)
@@ -7,7 +7,7 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
                  test-threads test-timeline test-score test-script \
                  test-model test-grab test-effects test-fullscreen \
                  test-shader test-unproject test-viewport test-fbo \
-                 test-opacity test-multistage
+                 test-opacity test-multistage test-pixmap
 
 INCLUDES = -I$(top_srcdir)/
 LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
@@ -44,5 +44,6 @@ test_viewport_SOURCES    = test-viewport.c
 test_fbo_SOURCES         = test-fbo.c
 test_opacity_SOURCES     = test-opacity.c
 test_multistage_SOURCES     = test-multistage.c
+test_pixmap_SOURCES      = test-pixmap.c
 
 EXTRA_DIST = redhand.png test-script.json
diff --git a/tests/test-pixmap.c b/tests/test-pixmap.c
new file mode 100644 (file)
index 0000000..1302a23
--- /dev/null
@@ -0,0 +1,199 @@
+#include <config.h>
+#include <clutter/clutter.h>
+#include <clutter/x11/clutter-x11.h>
+#include <clutter/x11/clutter-x11-texture-pixmap.h>
+
+#if HAVE_CLUTTER_GLX
+#include <clutter/glx/clutter-glx.h>
+#include <clutter/glx/clutter-glx-texture-pixmap.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xcomposite.h>
+#include <string.h>
+
+#define IMAGE "redhand.png"
+
+
+
+static gboolean
+stage_press_cb (ClutterActor    *actor,
+               ClutterEvent    *event,
+               gpointer         data)
+{
+  Pixmap        pxm = (Pixmap)data;
+  Display      *dpy = clutter_x11_get_default_display ();
+  GC            gc;
+  XGCValues     gc_values = {0};
+
+
+  gc = XCreateGC (dpy,
+                  pxm,
+                  0,
+                  &gc_values);
+
+  XDrawLine (dpy, pxm, gc, 0, 0, 100, 100); 
+}
+
+
+Pixmap
+create_pixmap (guint *width, guint *height, guint *depth)
+{
+  Display      *dpy = clutter_x11_get_default_display ();
+  Pixmap        pixmap;
+  GdkPixbuf    *pixbuf;
+  GError       *error = NULL;
+  XImage       *image;
+  char         *data, *d;
+  guchar       *p, *line, *endofline, *end;
+  guint         w, h, rowstride;
+  GC            gc;
+  XGCValues     gc_values = {0};
+
+  pixbuf = gdk_pixbuf_new_from_file (IMAGE, &error);
+  if (error)
+    g_error (error->message);
+
+  /* We assume that the image had an alpha channel */
+  g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
+
+  w = gdk_pixbuf_get_width  (pixbuf);
+  h = gdk_pixbuf_get_height (pixbuf);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+  data = malloc (w * h * 4);
+  image = XCreateImage (dpy,
+                        None,
+                        32,
+                        ZPixmap,
+                        0,
+                        data,
+                        w, h,
+                        8,
+                        w * 4);
+
+  p = gdk_pixbuf_get_pixels (pixbuf);
+  d  = data;
+  end = p + rowstride*h;
+
+  /* Convert from RGBA as contained in the pixmap to ARGB as used in X */
+  for (line = p; line < end ; line += rowstride)
+  {
+    p = line;
+    endofline = p + 4 * w;
+
+    for (p = line; p < endofline; p += 4, d+=4)
+      {
+
+#define r ((guint32)(*(p)))
+#define g ((guint32)(*(p+1)))
+#define b ((guint32)(*(p+2)))
+#define a ((guint32)(*(p+3)))
+        guint32 pixel =
+            ((a << 24) & 0xFF000000  ) |
+            ((r << 16) & 0x00FF0000  ) |
+            ((g <<  8) & 0x0000FF00) |
+            ((b)       & 0x000000FF );
+
+        *((guint32 *)d) = pixel;
+
+      }
+#undef r
+#undef g
+#undef b
+#undef a
+
+  }
+
+  g_object_unref (pixbuf);
+
+  pixmap = XCreatePixmap (dpy,
+                          DefaultRootWindow (dpy),
+                          w, h,
+                          32);
+
+  gc = XCreateGC (dpy,
+                  pixmap,
+                  0,
+                  &gc_values);
+
+  XPutImage (dpy,
+             pixmap,
+             gc,
+             image,
+             0, 0,
+             0, 0,
+             w, h);
+
+  XFreeGC (dpy, gc);
+  XDestroyImage (image);
+
+  if (width) *width = w;
+  if (height) *height = h;
+  if (depth) *depth = 32;
+
+  return pixmap;
+}
+
+int
+main (int argc, char **argv)
+{
+  ClutterActor         *stage, *tex;
+  Pixmap                pixmap;
+  guint                 w, h, d;
+  const ClutterColor    gry = { 0x99, 0x99, 0x99, 0xFF };
+  Window                win_remote;
+
+  clutter_init (&argc, &argv);
+
+  if (argc < 2)
+    g_error ("usage: %s <window id>", argv[0]);
+
+  win_remote = atol(argv[1]);
+
+  stage = clutter_stage_get_default ();
+  clutter_stage_set_color (CLUTTER_STAGE (stage), &gry);
+
+  pixmap = win_remote;
+
+  /*
+  XCompositeRedirectWindow(clutter_x11_get_default_display(),
+                           win_remote,
+                           CompositeRedirectAutomatic);
+
+  pixmap = XCompositeNameWindowPixmap (clutter_x11_get_default_display(), 
+                                       win_remote);
+  */
+
+  tex = clutter_x11_texture_pixmap_new_with_pixmap (pixmap);
+
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), tex);
+
+  clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex), 
+                                            TRUE);
+
+#ifdef HAVE_CLUTTER_GLX
+  pixmap = create_pixmap (&w, &h, &d);
+
+  tex = clutter_glx_texture_pixmap_new_with_pixmap (pixmap);
+
+  clutter_actor_set_position (tex,
+                              clutter_actor_get_width (stage) 
+                              - clutter_actor_get_width (tex),
+                              0);
+
+  clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex), 
+                                            FALSE);
+
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage),
+                               tex);
+#endif
+
+  g_signal_connect (stage, "button-press-event", 
+                    G_CALLBACK (stage_press_cb), (gpointer)pixmap);
+
+  clutter_actor_show (stage);
+
+  clutter_main ();
+
+}