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.
This commit is contained in:
Matthew Allum 2008-04-29 16:30:47 +00:00
parent 19058afe82
commit ca3074f772
8 changed files with 453 additions and 308 deletions

View File

@ -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

View 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) \

View 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
*
@ -70,28 +72,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,
@ -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);
GLuint handle = 0;
GLenum target = 0;
CoglHandle cogl_tex;
cogl_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE(tex));
g_type_class_add_private (klass, sizeof (ClutterGLXTexturePixmapPrivate));
if (!cogl_texture_get_gl_texture (cogl_tex, &handle, &target))
return FALSE;
object_class->dispose = clutter_glx_texture_pixmap_dispose;
object_class->notify = clutter_glx_texture_pixmap_notify;
glEnable(target);
actor_class->realize = clutter_glx_texture_pixmap_realize;
actor_class->unrealize = clutter_glx_texture_pixmap_unrealize;
actor_class->paint = clutter_glx_texture_pixmap_paint;
/* FIXME: fire off an error here? */
glBindTexture (target, handle);
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 ());
/* 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);
if (!pixmap)
return;
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);
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)
{
@ -482,6 +362,41 @@ get_fbconfig_for_depth (guint depth)
return ret;
}
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)
{
@ -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);
if (clutter_x11_untrap_x_errors ())
g_warning ("Failed to bind texture pixmap");
}
clutter_x11_trap_x_errors ();
glXDestroyGLXPixmap (dpy, priv->glx_pixmap);
XSync (dpy, FALSE);
clutter_x11_untrap_x_errors ();
}
clutter_glx_texture_pixmap_free_glx_pixmap (texture);
priv->glx_pixmap = glx_pixmap;
if (!clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture)))
{
create_cogl_texture (texture,
pixmap_width,
pixmap_height);
}
}
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 (!_have_tex_from_pixmap_ext)
{
CLUTTER_X11_TEXTURE_PIXMAP_CLASS
(texture)->update_area (texture,
x, y,
width, height);
return;
}
if (!CLUTTER_ACTOR_IS_REALIZED (texture))
return;
/* FIXME: Obsolete.
cogl_texture_bind (priv->target_type, priv->texture_id); */
if (!_have_tex_from_pixmap_ext)
{
parent_class->update_area (texture,
x, y,
width, height);
return;
}
}
static void
clutter_glx_texture_pixmap_paint (ClutterActor *self)
{
ClutterGLXTexturePixmapPrivate *priv;
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

View File

@ -28,6 +28,7 @@
#include <glib.h>
#include <glib-object.h>
#include <clutter/x11/clutter-x11-texture-pixmap.h>
#include <GL/glx.h>

View 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

View File

@ -51,6 +51,11 @@
#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,15 +560,38 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
clutter_x11_trap_x_errors ();
/* FIXME: Use XSHM here! */
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
{
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,
@ -476,6 +600,11 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
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 (ypos=0; ypos<height; ypos++)
for (xpos=0; xpos<width; xpos++)
{
for (pixel = l + x; pixel != l + x + width; pixel ++)
{
((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 (ypos=0; ypos<height; ypos++)
for (xpos=0; xpos<width; xpos++)
{
for (pixel = l, p = lp + x; pixel != l + width; pixel ++, p++)
{
*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 &&

View 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])

View 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);