mirror of
https://github.com/brl/mutter.git
synced 2024-11-10 07:56:14 -05:00
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.
This commit is contained in:
parent
3d1f2a0859
commit
c2cb5bf64a
29
ChangeLog
29
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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -48,13 +48,18 @@
|
||||
|
||||
#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_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,
|
||||
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_realize (ClutterActor *actor);
|
||||
|
||||
static void clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
|
||||
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,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
static void clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture);
|
||||
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;
|
||||
}
|
||||
|
||||
backend = (ClutterBackendGLX *)default_backend;
|
||||
/* backend->t_f_p = FALSE;*/
|
||||
|
||||
_ext_check_done = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
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,14 +201,14 @@ 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;
|
||||
ClutterGLXTexturePixmapPrivate *priv;
|
||||
COGLenum pixel_type, pixel_format,filter_quality;
|
||||
gboolean repeat_x, repeat_y;
|
||||
guint width, height;
|
||||
|
||||
if (!backend->t_f_p)
|
||||
priv = CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
|
||||
|
||||
if (!_have_tex_from_pixmap_ext)
|
||||
{
|
||||
CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
|
||||
realize (actor);
|
||||
@ -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;
|
||||
|
||||
if (!backend->t_f_p)
|
||||
priv = CLUTTER_GLX_TEXTURE_PIXMAP (actor)->priv;
|
||||
dpy = clutter_x11_get_default_display();
|
||||
|
||||
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,
|
||||
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,
|
||||
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,14 +586,15 @@ 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,
|
||||
CLUTTER_X11_TEXTURE_PIXMAP_CLASS
|
||||
(texture)->update_area (texture,
|
||||
x, y,
|
||||
width, height);
|
||||
return;
|
||||
@ -569,13 +605,20 @@ 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,
|
||||
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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -47,21 +47,36 @@
|
||||
|
||||
#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 int _damage_event_base = 0;
|
||||
|
||||
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);
|
||||
/* FIXME: Ultimatly with current cogl we should subclass clutter actor */
|
||||
G_DEFINE_TYPE (ClutterX11TexturePixmap, \
|
||||
clutter_x11_texture_pixmap, \
|
||||
CLUTTER_TYPE_TEXTURE);
|
||||
|
||||
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);
|
||||
static gboolean
|
||||
check_extensions (ClutterX11TexturePixmap *texture)
|
||||
{
|
||||
int event_base, error_base;
|
||||
int damage_error;
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
Display *dpy;
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
if (_damage_event_base)
|
||||
return TRUE;
|
||||
|
||||
dpy = clutter_x11_get_default_display();
|
||||
|
||||
if (!XCompositeQueryExtension (dpy, &event_base, &error_base))
|
||||
{
|
||||
g_warning ("No composite extension\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!XDamageQueryExtension (dpy,
|
||||
&_damage_event_base, &damage_error))
|
||||
{
|
||||
g_warning ("No Damage extension\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ClutterX11FilterReturn
|
||||
on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data)
|
||||
{
|
||||
ClutterX11TexturePixmap *texture;
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
Display *dpy;
|
||||
|
||||
texture = CLUTTER_X11_TEXTURE_PIXMAP (data);
|
||||
|
||||
g_return_val_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture), \
|
||||
CLUTTER_X11_FILTER_CONTINUE);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
XFixesDestroyRegion (dpy, parts);
|
||||
}
|
||||
|
||||
return CLUTTER_X11_FILTER_CONTINUE;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (ClutterX11TexturePixmap, clutter_x11_texture_pixmap, CLUTTER_TYPE_TEXTURE);
|
||||
|
||||
static void
|
||||
clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
|
||||
free_damage_resources (ClutterX11TexturePixmap *texture)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
ClutterBackend *default_backend;
|
||||
ClutterX11TexturePixmapPrivate *priv;
|
||||
Display *dpy;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (ClutterX11TexturePixmapPrivate));
|
||||
priv = texture->priv;
|
||||
dpy = clutter_x11_get_default_display();
|
||||
|
||||
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 X Pixmap to which this texture will 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_READWRITE | G_PARAM_CONSTRUCT);
|
||||
|
||||
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_READWRITE | G_PARAM_CONSTRUCT);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_PIXMAP_HEIGHT,
|
||||
pspec);
|
||||
|
||||
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);
|
||||
|
||||
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))
|
||||
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,
|
||||
@ -230,6 +246,8 @@ clutter_x11_texture_pixmap_dispose (GObject *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
|
||||
@ -247,38 +264,17 @@ clutter_x11_texture_pixmap_set_property (GObject *object,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterX11TexturePixmap *texture = CLUTTER_X11_TEXTURE_PIXMAP (object);
|
||||
ClutterX11TexturePixmapPrivate *priv = texture->priv;
|
||||
|
||||
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;
|
||||
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;
|
||||
@ -308,6 +304,9 @@ clutter_x11_texture_pixmap_get_property (GObject *object,
|
||||
case PROP_DEPTH:
|
||||
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;
|
||||
@ -331,6 +330,107 @@ clutter_x11_texture_pixmap_realize (ClutterActor *actor)
|
||||
priv->pixmap_height);
|
||||
}
|
||||
|
||||
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,
|
||||
@ -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 ()))
|
||||
{
|
||||
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,60 +624,78 @@ 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;
|
||||
|
||||
if (priv->pixmap != pixmap)
|
||||
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)
|
||||
{
|
||||
priv->pixmap = pixmap;
|
||||
|
||||
g_object_notify (G_OBJECT (texture), "pixmap");
|
||||
|
||||
if (pixmap != None)
|
||||
g_warning ("Unable to query pixmap: %lx\n", pixmap);
|
||||
pixmap = None;
|
||||
width = height = depth = 0;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
}
|
||||
|
||||
if (priv->depth != 0 &&
|
||||
priv->pixmap != None &&
|
||||
priv->pixmap_width != 0 &&
|
||||
priv->pixmap_height != 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), "pixmap-depth");
|
||||
}
|
||||
|
||||
g_object_unref (texture);
|
||||
|
||||
if (priv->depth != 0 &&
|
||||
priv->pixmap != None &&
|
||||
priv->pixmap_width != 0 &&
|
||||
priv->pixmap_height != 0)
|
||||
{
|
||||
if (CLUTTER_ACTOR_IS_REALIZED (texture))
|
||||
clutter_x11_texture_pixmap_update_area (texture,
|
||||
0, 0,
|
||||
@ -582,6 +703,8 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
||||
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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
24
configure.ac
24
configure.ac
@ -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}"
|
||||
|
@ -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
|
||||
|
199
tests/test-pixmap.c
Normal file
199
tests/test-pixmap.c
Normal file
@ -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 ();
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user