* 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
*
};
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,
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
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
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
ClutterGLXTexturePixmapPrivate *priv;
Display *dpy;
+ printf("unrealise\n");
+
priv = CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
dpy = clutter_x11_get_default_display();
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)
{
}
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;
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);
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
{
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
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,
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
#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,
guint depth;
XImage *image;
+ XShmSegmentInfo shminfo;
gboolean automatic_updates;
Damage damage;
+ gboolean have_shm;
};
static int _damage_event_base = 0;
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)
{
* - 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
priv->image = NULL;
}
+ free_shm_resources (texture);
+
G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->dispose (object);
}
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;
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;
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);
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;
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,
&error);
else
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (texture),
- data,
+ (guint8 *)data,
TRUE,
width, height,
bytes_per_line,
if (data_allocated)
g_free (data);
+
+ if (priv->have_shm)
+ XFree (image);
}
/**
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;
clutter_x11_trap_x_errors ();
+ if (pixmap != None)
status = XGetGeometry (clutter_x11_get_default_display(),
(Drawable)pixmap,
&root,
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 &&