2008-04-29 Matthew Allum <mallum@openedhand.com>
authorMatthew Allum <mallum@openedhand.com>
Tue, 29 Apr 2008 16:30:47 +0000 (16:30 +0000)
committerMatthew Allum <mallum@openedhand.com>
Tue, 29 Apr 2008 16:30:47 +0000 (16:30 +0000)
        * clutter/glx/Makefile.am:
        * clutter/glx/clutter-glx-texture-pixmap.c:
        * clutter/glx/clutter-glx-texture-pixmap.h:
        * clutter/x11/Makefile.am:
        * clutter/x11/clutter-x11-texture-pixmap.c:
        * tests/test-pixmap.c:
        Commit newer x11 texture pixmap stuff (optionally using SHM).
        Also seemingly still broken overhauled glx-texture-pixmap
        (code by Robert and myself)

* configure.ac:
        Minor formatting change.

ChangeLog
clutter/glx/Makefile.am
clutter/glx/clutter-glx-texture-pixmap.c
clutter/glx/clutter-glx-texture-pixmap.h
clutter/x11/Makefile.am
clutter/x11/clutter-x11-texture-pixmap.c
configure.ac
tests/test-pixmap.c

index 925a961..0563db9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2008-04-29  Matthew Allum  <mallum@openedhand.com>
+
+       * clutter/glx/Makefile.am:
+       * clutter/glx/clutter-glx-texture-pixmap.c:
+       * clutter/glx/clutter-glx-texture-pixmap.h:
+       * clutter/x11/Makefile.am:
+       * clutter/x11/clutter-x11-texture-pixmap.c:
+       * tests/test-pixmap.c:
+        Commit newer x11 texture pixmap stuff (optionally using SHM).
+        Also seemingly still broken overhauled glx-texture-pixmap
+        (code by Robert and myself) 
+
+       * configure.ac:
+        Minor formatting change.
+
 2008-04-29  Neil Roberts  <neil@o-hand.com>
 
        Removed COGLhandle and changed shader and program functions to be
index 182825a..7bdefd0 100644 (file)
@@ -1,10 +1,11 @@
-libclutterincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter
-libclutterinclude_HEADERS = clutter-glx.h clutter-glx-texture-pixmap.h
+libclutter_glx_includedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter/glx
+libclutter_glx_include_HEADERS = clutter-glx.h clutter-glx-texture-pixmap.h
 
 INCLUDES = \
        -DG_LOG_DOMAIN=\"ClutterGLX\" \
        -I$(top_srcdir) \
        -I$(top_srcdir)/clutter \
+       -I$(top_srcdir)/clutter/x11 \
        -I$(top_builddir)/clutter \
        $(CLUTTER_CFLAGS) \
        $(CLUTTER_DEBUG_CFLAGS) \
index a5c3b43..f2420f1 100644 (file)
@@ -4,6 +4,8 @@
  * An OpenGL based 'interactive canvas' library.
  *
  * Authored By Johan Bilien  <johan.bilien@nokia.com>
+ *             Matthew Allum <mallum@o-hand.com>
+ *             Robert Bragg  <bob@o-hand.com>
  *
  * Copyright (C) 2007 OpenedHand
  *
@@ -71,28 +73,6 @@ struct _ClutterGLXTexturePixmapPrivate
 };
 
 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_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_update_area (ClutterX11TexturePixmap *texture,
                                         gint x,
                                         gint y,
@@ -102,51 +82,29 @@ clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
 static void 
 clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *tex);
 
+static ClutterX11TexturePixmapClass *parent_class = NULL;
+
 G_DEFINE_TYPE (ClutterGLXTexturePixmap,    \
                clutter_glx_texture_pixmap, \
                CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
 
-static void
-clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
+static gboolean
+texture_bind (ClutterGLXTexturePixmap *tex)
 {
-  GObjectClass                 *object_class = G_OBJECT_CLASS (klass);
-  ClutterActorClass            *actor_class = CLUTTER_ACTOR_CLASS (klass);
-  ClutterX11TexturePixmapClass *x11_texture_class =
-      CLUTTER_X11_TEXTURE_PIXMAP_CLASS (klass);
-
-  g_type_class_add_private (klass, sizeof (ClutterGLXTexturePixmapPrivate));
+  GLuint     handle = 0;
+  GLenum     target = 0;
+  CoglHandle cogl_tex;
+  cogl_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE(tex));
 
-  object_class->dispose = clutter_glx_texture_pixmap_dispose;
-  object_class->notify = clutter_glx_texture_pixmap_notify;
-
-  actor_class->realize   = clutter_glx_texture_pixmap_realize;
-  actor_class->unrealize = clutter_glx_texture_pixmap_unrealize;
-  actor_class->paint     = clutter_glx_texture_pixmap_paint;
+  if (!cogl_texture_get_gl_texture (cogl_tex, &handle, &target))
+      return FALSE;
 
-  x11_texture_class->update_area = clutter_glx_texture_pixmap_update_area;
+  glEnable(target);
 
-  if (_ext_check_done == FALSE)
-    {
-      const gchar *glx_extensions = NULL;
+  /* FIXME: fire off an error here? */
+  glBindTexture (target, handle);
 
-      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;
-    }
+  return TRUE;
 }
 
 static void
@@ -159,11 +117,6 @@ clutter_glx_texture_pixmap_init (ClutterGLXTexturePixmap *self)
                                    CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
                                    ClutterGLXTexturePixmapPrivate);
 
-  /* FIXME: Obsolete. Move to new cogl api.
-  if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE))
-    priv->target_type = CGL_TEXTURE_RECTANGLE_ARB;
-  else
-    priv->target_type = CGL_TEXTURE_2D; */
 }
 
 static void
@@ -195,55 +148,75 @@ clutter_glx_texture_pixmap_notify (GObject *object, GParamSpec *pspec)
   if (g_str_equal (pspec->name, "pixmap"))
     {
       ClutterGLXTexturePixmap *texture = CLUTTER_GLX_TEXTURE_PIXMAP (object);
+      printf("notify\n");
+
       clutter_glx_texture_pixmap_create_glx_pixmap (texture);
     }
 }
 
 static void
+create_cogl_texture (ClutterTexture *texture,
+                    guint width,
+                    guint height)
+{
+  CoglHandle  handle;
+
+  handle = cogl_texture_new_with_size (width, height,
+                                       64,
+                                       COGL_PIXEL_FORMAT_RGBA_8888|COGL_BGR_BIT);
+
+  printf("handle: %i, width: %i, height: %i\n",
+         (int)handle, width, height);
+
+  if (handle)
+    {
+      clutter_texture_set_cogl_texture (texture, handle);
+
+      CLUTTER_ACTOR_SET_FLAGS (texture, CLUTTER_ACTOR_REALIZED);
+
+      printf("realised, updating\n");
+
+      clutter_glx_texture_pixmap_update_area
+                                  (CLUTTER_X11_TEXTURE_PIXMAP (texture),
+                                   0, 0,
+                                   width, height);
+    }
+  else
+    g_warning ("unable to realize");
+}
+
+static void
 clutter_glx_texture_pixmap_realize (ClutterActor *actor)
 {
   ClutterGLXTexturePixmapPrivate *priv;
-  COGLenum                        pixel_type, pixel_format,filter_quality;
-  gboolean                        repeat_x, repeat_y;
-  guint                           width, height;
+  Pixmap                          pixmap;
+  guint                           pixmap_width, pixmap_height;
+  printf("realise\n");
 
   priv = CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
 
-  if (!_have_tex_from_pixmap_ext) 
+  if (!_have_tex_from_pixmap_ext
+      || !clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE))
     {
+      /* Fall back */
+      /* FIXME: Also check for sliced npots ? */
+
+      g_warning("Falling back....");
       CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
         realize (actor);
       return;
     }
 
   g_object_get (actor,
-                "pixel-type",     &pixel_type,
-                "pixel-format",   &pixel_format,
-                "repeat-x",       &repeat_x,
-                "repeat-y",       &repeat_y,
-                "filter-quality", &filter_quality,
-                "pixmap-width",   &width,
-                "pixmap-height",  &height,
+                "pixmap", &pixmap,
+                "pixmap-width",   &pixmap_width,
+                "pixmap-height",  &pixmap_height,
                 NULL);
   
-  /* FIXME: Obsolete. Move to new cogl api
-  cogl_textures_create (1, &priv->texture_id);
-  */
-  clutter_glx_texture_pixmap_update_area (CLUTTER_X11_TEXTURE_PIXMAP (actor),
-                                          0, 0,
-                                          width, height);
-  /*
-  cogl_texture_set_alignment (priv->target_type, 4, width);
-  
-  cogl_texture_set_filters (priv->target_type,
-                            filter_quality ? CGL_LINEAR : CGL_NEAREST,
-                            filter_quality ? CGL_LINEAR : CGL_NEAREST);
-
-  cogl_texture_set_wrap (priv->target_type,
-                         repeat_x ? CGL_REPEAT : CGL_CLAMP_TO_EDGE,
-                         repeat_y ? CGL_REPEAT : CGL_CLAMP_TO_EDGE);
-  */
-  CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
+  if (!pixmap)
+    return;
+
+  create_cogl_texture (CLUTTER_TEXTURE (actor), pixmap_width, pixmap_height);
 }
 
 static void
@@ -252,6 +225,8 @@ clutter_glx_texture_pixmap_unrealize (ClutterActor *actor)
   ClutterGLXTexturePixmapPrivate *priv;
   Display                        *dpy;
 
+  printf("unrealise\n");
+
   priv = CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
   dpy = clutter_x11_get_default_display();
 
@@ -277,104 +252,9 @@ clutter_glx_texture_pixmap_unrealize (ClutterActor *actor)
       clutter_x11_untrap_x_errors ();
     }
   
-  /* FIXME: Obsolete. Move to new cogl api.
-  cogl_textures_destroy (1, &priv->texture_id);
-  */
   CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
 }
 
-static void
-texture_render_to_gl_quad (ClutterGLXTexturePixmap *texture,
-                           int                      x_1,
-                           int                      y_1,
-                           int                      x_2,
-                           int                      y_2)
-{
-  /* FIXME: Obsolete. Move to new cogl api
-  ClutterGLXTexturePixmapPrivate *priv = texture->priv;
-
-  int   qx1 = 0, qx2 = 0, qy1 = 0, qy2 = 0;
-  int   qwidth = 0, qheight = 0;
-  float tx, ty;
-  guint width, height;
-
-  g_object_get (texture,
-                "pixmap-width",         &width,
-                "pixmap-height",        &height,
-                NULL);
-
-  qwidth  = x_2 - x_1;
-  qheight = y_2 - y_1;
-
-  cogl_texture_bind (priv->target_type, priv->texture_id);
-
-  if (priv->target_type == CGL_TEXTURE_2D)
-    {
-      tx = (float) width  / clutter_util_next_p2 (width);
-      ty = (float) height / clutter_util_next_p2 (height);
-    }
-  else
-    {
-      tx = (float) width;
-      ty = (float) height;
-
-    }
-
-  qx1 = x_1; qx2 = x_2;
-  qy1 = y_1; qy2 = y_2;
-
-  cogl_texture_quad (x_1, x_2, y_1, y_2,
-                     0,
-                     0,
-                     CLUTTER_FLOAT_TO_FIXED (tx),
-                     CLUTTER_FLOAT_TO_FIXED (ty)); */
-}
-
-static void
-clutter_glx_texture_pixmap_paint (ClutterActor *actor)
-{
-  ClutterGLXTexturePixmap        *texture = CLUTTER_GLX_TEXTURE_PIXMAP (actor);
-  ClutterGLXTexturePixmapPrivate *priv = texture->priv;
-
-  gint            x_1, y_1, x_2, y_2;
-  ClutterColor    col = { 0xff, 0xff, 0xff, 0xff };
-
-  if (!_have_tex_from_pixmap_ext)
-    {
-      CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
-          paint (actor);
-      return;
-    }
-
-  if (!CLUTTER_ACTOR_IS_REALIZED (actor))
-    clutter_actor_realize (actor);
-
-  cogl_push_matrix ();
-
-  /* FIXME: Obsolete. Move to new cogl api.
-  switch (priv->target_type)
-    {
-      case CGL_TEXTURE_2D:
-          cogl_enable (CGL_ENABLE_TEXTURE_2D|CGL_ENABLE_BLEND);
-          break;
-      case CGL_TEXTURE_RECTANGLE_ARB:
-          cogl_enable (CGL_ENABLE_TEXTURE_RECT|CGL_ENABLE_BLEND);
-          break;
-      default:
-          break;
-    } */
-
-  col.alpha = clutter_actor_get_opacity (actor);
-
-  cogl_color (&col);
-
-  clutter_actor_get_coords (actor, &x_1, &y_1, &x_2, &y_2);
-
-  texture_render_to_gl_quad (texture, 0, 0, x_2 - x_1, y_2 - y_1);
-
-  cogl_pop_matrix ();
-}
-
 static GLXFBConfig *
 get_fbconfig_for_depth (guint depth)
 {
@@ -483,6 +363,41 @@ get_fbconfig_for_depth (guint depth)
 }
 
 static void
+clutter_glx_texture_pixmap_free_glx_pixmap (ClutterGLXTexturePixmap *texture)
+{
+  ClutterGLXTexturePixmapPrivate *priv = texture->priv;
+  Display                        *dpy;
+
+  dpy = clutter_x11_get_default_display ();
+
+  if (_have_tex_from_pixmap_ext &&
+      CLUTTER_ACTOR_IS_REALIZED (texture) &&
+      priv->bound)
+    {
+      texture_bind (texture);
+
+      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 unbind texture pixmap");
+
+
+      printf("Destroyed pxm: %li\n", priv->glx_pixmap);
+    }
+
+  clutter_x11_trap_x_errors ();
+  glXDestroyGLXPixmap (dpy, priv->glx_pixmap);
+  XSync (dpy, FALSE);
+  clutter_x11_untrap_x_errors ();
+}
+
+static void
 clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
 {
   ClutterGLXTexturePixmapPrivate *priv = texture->priv;
@@ -492,16 +407,23 @@ clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
   Display                        *dpy;
   guint                           depth;
   Pixmap                          pixmap;
+  guint                                  pixmap_width, pixmap_height;
   ClutterBackendGLX             *backend_glx;
 
+  printf("create\n");
+
   backend_glx = CLUTTER_BACKEND_GLX(clutter_get_default_backend ());
 
   dpy = clutter_x11_get_default_display ();
 
   g_object_get (texture,
+                "pixmap-width", &pixmap_width,
+                "pixmap-height", &pixmap_height,
                 "pixmap-depth",                &depth,
                 "pixmap",               &pixmap,
                 NULL);
+  if (!pixmap)
+    return;
 
   fbconfig = get_fbconfig_for_depth (depth);
 
@@ -516,10 +438,12 @@ clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
   if (depth == 24)
     {
       attribs[i++] = GLX_TEXTURE_FORMAT_RGB_EXT;
+      printf("depth: %i\n", 24);
     }
   else if (depth == 32)
     {
       attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT;
+      printf("depth: %i\n", 32);
     }
   else
     {
@@ -531,58 +455,38 @@ clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
   attribs[i++] = 0;
 
   attribs[i++] = GLX_TEXTURE_TARGET_EXT;
-
-  /* FIXME: Obsolete. Move to new cogl api
-  if (priv->target_type == CGL_TEXTURE_RECTANGLE_ARB)
     attribs[i++] = GLX_TEXTURE_RECTANGLE_EXT;
-  else
-    attribs[i++] = GLX_TEXTURE_2D_EXT; */
   
   attribs[i++] = None;
 
-
   clutter_x11_trap_x_errors ();
   glx_pixmap = glXCreatePixmap (dpy,
                                 *fbconfig,
                                 pixmap,
                                 attribs);
   XSync (dpy, FALSE);
-  clutter_x11_untrap_x_errors ();
+  if (clutter_x11_untrap_x_errors ())
+    g_warning ("glx pixmap creation failed");
 
   g_free (fbconfig);
 
   if (glx_pixmap != None)
     {
       if (priv->glx_pixmap)
-        {
-          if (_have_tex_from_pixmap_ext &&
-              CLUTTER_ACTOR_IS_REALIZED (texture) &&
-              priv->bound)
-            {
-             /*
-              cogl_texture_bind (priv->target_type, priv->texture_id); */
-             
-              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_glx_texture_pixmap_free_glx_pixmap (texture);
+
+      priv->glx_pixmap = glx_pixmap;
               
-              if (clutter_x11_untrap_x_errors ())
-                g_warning ("Failed to bind texture pixmap");
 
+      if (!clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture)))
+       {
+         create_cogl_texture (texture,
+                              pixmap_width,
+                              pixmap_height);
             }
-
-          clutter_x11_trap_x_errors ();
-          glXDestroyGLXPixmap (dpy, priv->glx_pixmap);
-          XSync (dpy, FALSE);
-          clutter_x11_untrap_x_errors ();
         }
 
-      priv->glx_pixmap = glx_pixmap;
-    }
+  printf("Created pxm: %li\n", priv->glx_pixmap);
 }
 
 static void
@@ -595,26 +499,41 @@ clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
   ClutterGLXTexturePixmapPrivate       *priv;
   Display                              *dpy;
 
+  printf("update area\n");
+
   priv = CLUTTER_GLX_TEXTURE_PIXMAP (texture)->priv;
   dpy = clutter_x11_get_default_display();
 
+
+  if (!CLUTTER_ACTOR_IS_REALIZED (texture))
+    return;
+
   if (!_have_tex_from_pixmap_ext)
     {
-      CLUTTER_X11_TEXTURE_PIXMAP_CLASS 
-        (texture)->update_area (texture,
+      parent_class->update_area (texture,
                                 x, y,
                                 width, height);
       return;
     }
+}
 
-  if (!CLUTTER_ACTOR_IS_REALIZED (texture))
-    return;
+static void
+clutter_glx_texture_pixmap_paint (ClutterActor *self)
+{
+  ClutterGLXTexturePixmapPrivate *priv;
 
-  /* FIXME: Obsolete.
-  cogl_texture_bind (priv->target_type, priv->texture_id); */
+  priv = CLUTTER_GLX_TEXTURE_PIXMAP (self)->priv;
 
   if (_have_tex_from_pixmap_ext)
     {
+      Display                        *dpy;
+
+      dpy = clutter_x11_get_default_display();
+
+      if (texture_bind (CLUTTER_GLX_TEXTURE_PIXMAP(self)))
+        {
+          printf("no fallback pxm: %li\n", priv->glx_pixmap);
+
       clutter_x11_trap_x_errors ();
 
       (_gl_bind_tex_image) (dpy,
@@ -629,8 +548,61 @@ clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
 
       priv->bound = TRUE;
     }
+        else
+          g_warning ("Failed to bind initial tex");
+    }
+
+
+ CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->paint(self);
 }
 
+static void
+clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
+{
+  GObjectClass                 *object_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass            *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  ClutterX11TexturePixmapClass *x11_texture_class =
+      CLUTTER_X11_TEXTURE_PIXMAP_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (ClutterGLXTexturePixmapPrivate));
+
+  parent_class = g_type_class_peek_parent(klass);
+
+  object_class->dispose = clutter_glx_texture_pixmap_dispose;
+  object_class->notify  = clutter_glx_texture_pixmap_notify;
+
+  actor_class->realize   = clutter_glx_texture_pixmap_realize;
+  actor_class->unrealize = clutter_glx_texture_pixmap_unrealize;
+  actor_class->paint     = clutter_glx_texture_pixmap_paint;
+
+  x11_texture_class->update_area = clutter_glx_texture_pixmap_update_area;
+
+  if (_ext_check_done == FALSE)
+    {
+      const gchar *glx_extensions = NULL;
+
+      glx_extensions =
+        glXQueryExtensionsString (clutter_x11_get_default_display (),
+                                  clutter_x11_get_default_screen ());
+      printf("GLX extension string:%s\n", glx_extensions);
+
+      /* 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;
+    }
+}
+
+
 /**
  * clutter_glx_texture_pixmap_new_with_pixmap:
  * @pixmap: the X Pixmap to which this texture should be bound
index f77f17f..963820d 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
+#include <clutter/x11/clutter-x11-texture-pixmap.h>
 
 #include <GL/glx.h>
 
index d3632d7..193971a 100644 (file)
@@ -1,5 +1,5 @@
-libclutterincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter
-libclutterinclude_HEADERS = clutter-x11.h \
+libclutter_x11_includedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter/x11
+libclutter_x11_include_HEADERS = clutter-x11.h \
                             clutter-x11-texture-pixmap.h
 
 clutter-x11-$(CLUTTER_API_VERSION).pc: clutter-x11.pc
index 55ebbc8..a0d58a5 100644 (file)
 #include <X11/extensions/Xdamage.h>
 #include <X11/extensions/Xcomposite.h>
 
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+#include <X11/extensions/XShm.h>
+
 enum
 {
   PROP_PIXMAP = 1,
@@ -86,10 +91,12 @@ struct _ClutterX11TexturePixmapPrivate
   guint         depth;
 
   XImage       *image;
+  XShmSegmentInfo shminfo;
 
   gboolean      automatic_updates;     
   Damage        damage;
 
+  gboolean     have_shm;
 };
 
 static int _damage_event_base = 0;
@@ -130,6 +137,108 @@ check_extensions (ClutterX11TexturePixmap *texture)
   return TRUE;
 }
 
+static void
+free_shm_resources (ClutterX11TexturePixmap *texture)
+{
+  ClutterX11TexturePixmapPrivate *priv;
+
+  priv = texture->priv;
+
+  if (priv->shminfo.shmid != -1)
+    {
+      XShmDetach(clutter_x11_get_default_display(),
+                &priv->shminfo);
+      shmdt(priv->shminfo.shmaddr);
+      shmctl(priv->shminfo.shmid, IPC_RMID, 0);
+      priv->shminfo.shmid = -1;
+    }
+}
+
+/* Tries to allocate enough shared mem to handle a full size
+ * update size of the X Pixmap. */
+static gboolean
+try_alloc_shm (ClutterX11TexturePixmap *texture)
+{
+  ClutterX11TexturePixmapPrivate  *priv;
+  XImage                         *dummy_image;
+  Display                        *dpy;
+
+  priv = texture->priv;
+  dpy  = clutter_x11_get_default_display();
+
+  g_return_val_if_fail (priv->pixmap, FALSE);
+
+  if (!XShmQueryExtension(dpy) || g_getenv("CLUTTER_X11_NO_SHM"))
+    {
+      priv->have_shm = FALSE;
+      return FALSE;
+    }
+
+  clutter_x11_trap_x_errors ();
+
+  /* We are creating a dummy_image so we can have Xlib calculate
+   * image->bytes_per_line - including any magic padding it may
+   * want - for the largest possible ximage we might need to use
+   * when handling updates to the texture.
+   *
+   * Note: we pass a NULL shminfo here, but that has no bearing
+   * on the setup of the XImage, except that ximage->obdata will
+   * == NULL.
+   */
+  dummy_image =
+    XShmCreateImage(dpy,
+                   DefaultVisual(dpy,
+                                 clutter_x11_get_default_screen()),
+                   priv->depth,
+                   ZPixmap,
+                   NULL,
+                   NULL, /* shminfo, */
+                   priv->pixmap_width,
+                   priv->pixmap_height);
+  if (!dummy_image)
+    goto failed_image_create;
+
+  priv->shminfo.shmid = shmget (IPC_PRIVATE,
+                               dummy_image->bytes_per_line
+                               * dummy_image->height,
+                               IPC_CREAT|0777);
+  if (priv->shminfo.shmid == -1)
+    goto failed_shmget;
+
+  priv->shminfo.shmaddr =
+    shmat (priv->shminfo.shmid, 0, 0);
+  if (priv->shminfo.shmaddr == (void *)-1)
+    goto failed_shmat;
+
+  priv->shminfo.readOnly = False;
+
+  if (XShmAttach(dpy, &priv->shminfo) == 0)
+    goto failed_xshmattach;
+
+  if (clutter_x11_untrap_x_errors ())
+    g_warning ("X Error: Failed to setup XShm.");
+
+  priv->have_shm = TRUE;
+  return TRUE;
+
+failed_xshmattach:
+  g_warning ("XShmAttach failed");
+  shmdt(priv->shminfo.shmaddr);
+failed_shmat:
+  g_warning ("shmat failed");
+  shmctl(priv->shminfo.shmid, IPC_RMID, 0);
+failed_shmget:
+  g_warning ("shmget failed");
+  XDestroyImage(dummy_image);
+failed_image_create:
+
+  if (clutter_x11_untrap_x_errors ())
+    g_warning ("X Error: Failed to setup XShm.");
+
+  priv->have_shm = FALSE;
+  return FALSE;
+}
+
 static ClutterX11FilterReturn 
 on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data)
 {
@@ -223,21 +332,12 @@ clutter_x11_texture_pixmap_init (ClutterX11TexturePixmap *self)
        *        - a _can_autoupdate() method ?
       */
     }
-}
-
-static GObject *
-clutter_x11_texture_pixmap_constructor (GType                  type,
-                                        guint                  n_props,
-                                        GObjectConstructParam *props)
-{
-  GObject *object = G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->
-    constructor (type, n_props, props);
 
-  g_object_set (object,
-                "sync-size", FALSE,
-                NULL);
-
-  return object;
+  self->priv->image = NULL;
+  self->priv->automatic_updates = FALSE;
+  self->priv->damage = None;
+  self->priv->pixmap = None;
+  self->priv->shminfo.shmid = -1;
 }
 
 static void
@@ -254,6 +354,8 @@ clutter_x11_texture_pixmap_dispose (GObject *object)
       priv->image = NULL;
     }
 
+  free_shm_resources (texture);
+
   G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->dispose (object);
 }
 
@@ -340,7 +442,6 @@ clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
 
   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;
@@ -441,10 +542,10 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
   ClutterX11TexturePixmapPrivate       *priv;
   Display                              *dpy;
   XImage                               *image;
-  guint                                *pixel, *l;
+  char                                *first_pixel;
   GError                               *error = NULL;
   guint                                 bytes_per_line;
-  guint8                               *data;
+  char                                *data;
   gboolean                              data_allocated = FALSE;
   int                                   err_code;
 
@@ -459,23 +560,51 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
 
   clutter_x11_trap_x_errors ();
 
-  /* FIXME: Use XSHM here! */
-  if (!priv->image)
-    priv->image = XGetImage (dpy,
-                             priv->pixmap,
-                             0, 0,
-                             priv->pixmap_width, priv->pixmap_height,
-                             AllPlanes,
-                             ZPixmap);
+  if (priv->have_shm)
+    {
+      image =
+       XShmCreateImage(dpy,
+                       DefaultVisual(dpy,
+                                     clutter_x11_get_default_screen()),
+                       priv->depth,
+                       ZPixmap,
+                       NULL,
+                       &priv->shminfo,
+                       width,
+                       height);
+      image->data = priv->shminfo.shmaddr;
+
+      XShmGetImage (dpy, priv->pixmap, image, x, y, AllPlanes);
+      first_pixel = image->data;
+    }
   else
-    XGetSubImage (dpy,
-                  priv->pixmap,
-                  x, y,
-                  width, height,
-                  AllPlanes,
-                  ZPixmap,
-                  priv->image,
-                  x, y);
+    {
+      if (!priv->image)
+       {
+          priv->image = XGetImage (dpy,
+                                   priv->pixmap,
+                                   0, 0,
+                                   priv->pixmap_width, priv->pixmap_height,
+                                   AllPlanes,
+                                   ZPixmap);
+         first_pixel  = priv->image->data + priv->image->bytes_per_line * y
+                         + x * priv->image->bits_per_pixel/8;
+       }
+      else
+       {
+          XGetSubImage (dpy,
+                        priv->pixmap,
+                        x, y,
+                        width, height,
+                        AllPlanes,
+                        ZPixmap,
+                        priv->image,
+                        x, y);
+         first_pixel  = priv->image->data + priv->image->bytes_per_line * y
+            + x * priv->image->bits_per_pixel/8;
+       }
+      image = priv->image;
+    }
 
   XSync (dpy, FALSE);
 
@@ -488,53 +617,47 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
       return;
     }
 
-  image = priv->image;
-
   if (priv->depth == 24)
     {
-      guint *first_line = (guint *)image->data + y * image->bytes_per_line / 4;
+      guint xpos, ypos;
 
-      for (l =   first_line;
-           l != (first_line + height * image->bytes_per_line / 4);
-           l = l + image->bytes_per_line / 4)
-        {
-          for (pixel = l + x; pixel != l + x + width; pixel ++)
+      for (ypos=0; ypos<height; ypos++)
+       for (xpos=0; xpos<width; xpos++)
             {
-              ((guint8 *)pixel)[3] = 0xFF;
-            }
+           char *p = first_pixel + image->bytes_per_line*ypos
+                         + xpos * 4;
+           p[3] = 0xFF;
         }
 
-      data = (guint8 *)first_line + x * 4;
+      data = first_pixel;
       bytes_per_line = image->bytes_per_line;
     }
-
   else if (priv->depth == 16)
     {
-      guint16 *p, *lp;
-
+      guint xpos, ypos;
       data = g_malloc (height * width * 4);
       data_allocated = TRUE;
-      bytes_per_line = priv->pixmap_width * 4;
+      bytes_per_line = width * 4;
 
-      for (l =   (guint *)data,
-           lp = (guint16 *)image->data + y * image->bytes_per_line / 2;
-           l != ((guint *)data + height * width);
-           l = l + width, lp = lp + image->bytes_per_line / 2)
-        {
-          for (pixel = l, p = lp + x; pixel != l + width; pixel ++, p++)
+      for (ypos=0; ypos<height; ypos++)
+       for (xpos=0; xpos<width; xpos++)
             {
-              *pixel = 0xFF000000 |
-                      (guint)((*p) & 0xf800) << 8 |
-                      (guint)((*p) & 0x07e0) << 5 |
-                      (guint)((*p) & 0x001f) << 3;
-            }
-        }
-
+           char *src_p = first_pixel + image->bytes_per_line * ypos
+                           + xpos * 2;
+           guint16 *src_pixel = (guint16 *)src_p;
+           char *dst_p = data + bytes_per_line * ypos + xpos * 4;
+           guint32 *dst_pixel = (guint32 *)dst_p;
+
+           *dst_pixel =
+             ((((*src_pixel << 3) & 0xf8) | ((*src_pixel >> 2) & 0x7)) | \
+             (((*src_pixel << 5) & 0xfc00) | ((*src_pixel >> 1) & 0x300)) | \
+             (((*src_pixel << 8) & 0xf80000) | ((*src_pixel << 3) & 0x70000)));
+         }
     }
   else if (priv->depth == 32)
     {
       bytes_per_line = image->bytes_per_line;
-      data = (guint8 *)image->data + y * bytes_per_line + x * 4;
+      data = first_pixel;
     }
   else
     return;
@@ -542,7 +665,7 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
   if (x != 0 || y != 0 ||
       width != priv->pixmap_width || height != priv->pixmap_height)
     clutter_texture_set_area_from_rgb_data  (CLUTTER_TEXTURE (texture),
-                                            data,
+                                            (guint8 *)data,
                                             TRUE,
                                             x, y,
                                             width, height,
@@ -552,7 +675,7 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
                                             &error);
   else
     clutter_texture_set_from_rgb_data  (CLUTTER_TEXTURE (texture),
-                                       data,
+                                       (guint8 *)data,
                                        TRUE,
                                        width, height,
                                        bytes_per_line,
@@ -571,6 +694,9 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
 
   if (data_allocated)
     g_free (data);
+
+  if (priv->have_shm)
+    XFree (image);
 }
 
 /**
@@ -633,6 +759,8 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
   int          x, y; 
   unsigned int width, height, border_width, depth;
   Status       status = 0;
+  gboolean     new_pixmap = FALSE, new_pixmap_width = FALSE;
+  gboolean     new_pixmap_height = FALSE, new_pixmap_depth = FALSE;
 
   ClutterX11TexturePixmapPrivate *priv;
 
@@ -642,6 +770,7 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
 
   clutter_x11_trap_x_errors ();
 
+  if (pixmap != None)
   status = XGetGeometry (clutter_x11_get_default_display(),
                          (Drawable)pixmap, 
                          &root,
@@ -666,34 +795,48 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
       priv->image = NULL;
     }
   
-  g_object_ref (texture);
-
   if (priv->pixmap != pixmap)
     {
       priv->pixmap = pixmap;
-      g_object_notify (G_OBJECT (texture), "pixmap");
+      new_pixmap = TRUE;
     }
 
   if (priv->pixmap_width != width)
     {
       priv->pixmap_width = width;
-      g_object_notify (G_OBJECT (texture), "pixmap-width");
+      new_pixmap_width = TRUE;
     }
 
   if (priv->pixmap_height != height)
     {
       priv->pixmap_height = height;
-      g_object_notify (G_OBJECT (texture), "pixmap-height");
+      new_pixmap_height = TRUE;
     }
 
   if (priv->depth != depth)
     {
       priv->depth = depth;
-      g_object_notify (G_OBJECT (texture), "pixmap-depth");
+      new_pixmap_depth = TRUE;
     }
 
+  /* NB: We defer sending the signals until updating all the
+   * above members so the values are all available to the
+   * signal handlers. */
+  g_object_ref (texture);
+  if (new_pixmap)
+    g_object_notify (G_OBJECT (texture), "pixmap");
+  if (new_pixmap_width)
+    g_object_notify (G_OBJECT (texture), "pixmap-width");
+  if (new_pixmap_height)
+    g_object_notify (G_OBJECT (texture), "pixmap-height");
+  if (new_pixmap_depth)
+    g_object_notify (G_OBJECT (texture), "pixmap-depth");
   g_object_unref (texture);
 
+  free_shm_resources (texture);
+  if (pixmap != None)
+    try_alloc_shm (texture);
+
   if (priv->depth != 0 &&
       priv->pixmap != None &&
       priv->pixmap_width != 0 &&
index 2e5ed4b..73e5614 100644 (file)
@@ -333,6 +333,7 @@ case $clutterbackend in
     ;;
 
   fruity)
+
     CLUTTER_FLAVOUR="fruity"
     CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_FRUITY"
     AC_DEFINE([HAVE_CLUTTER_FRUITY], 1, [We're building a fruity version of the eglnative backend])
index a3f789e..894ec10 100644 (file)
@@ -1,7 +1,8 @@
 
+#include <config.h>
 
 #if HAVE_CLUTTER_GLX
-#include <config.h>
+
 #include <clutter/clutter.h>
 #include <clutter/x11/clutter-x11.h>
 #include <clutter/x11/clutter-x11-texture-pixmap.h>
@@ -159,13 +160,11 @@ main (int argc, char **argv)
 
   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);
@@ -176,8 +175,21 @@ main (int argc, char **argv)
                                             TRUE);
 
 #ifdef HAVE_CLUTTER_GLX
+
   pixmap = create_pixmap (&w, &h, &d);
 
+#if 0
+  // pixmap = win_remote;
+
+
+  XCompositeRedirectWindow(clutter_x11_get_default_display(),
+                           win_remote,
+                           CompositeRedirectAutomatic);
+
+  pixmap = XCompositeNameWindowPixmap (clutter_x11_get_default_display(), 
+                                       win_remote);
+#endif
+
   tex = clutter_glx_texture_pixmap_new_with_pixmap (pixmap);
 
   clutter_actor_set_position (tex,
@@ -186,7 +198,7 @@ main (int argc, char **argv)
                               0);
 
   clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex), 
-                                            FALSE);
+                                            TRUE);
 
   clutter_container_add_actor (CLUTTER_CONTAINER (stage),
                                tex);