mutter/tests/test-pixmap.c
Matthew Allum 34f6defca9 2008-07-08 Matthew Allum <mallum@openedhand.com>
Bug 1011 - Fix TFP fallback mechanism (take 2)

        * clutter/glx/clutter-glx-texture-pixmap.c:
        * tests/test-pixmap.c:
        Slightly modified patch from Gwenole Beauchesne applied
       to better handle both falling back to non accelerated tfp
       and improvements to the test case.
2008-07-08 11:58:08 +00:00

262 lines
6.1 KiB
C

#include <config.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_CLUTTER_GLX
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#include <clutter/x11/clutter-x11-texture-pixmap.h>
#include <clutter/glx/clutter-glx.h>
#include <clutter/glx/clutter-glx-texture-pixmap.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>
#define IMAGE "redhand.png"
# ifdef USE_GDKPIXBUF
static gboolean disable_x11 = FALSE;
static gboolean disable_glx = FALSE;
static GOptionEntry g_options[] =
{
{ "disable-x11",
0, 0,
G_OPTION_ARG_NONE,
&disable_x11,
"Disable redirection through X11 pixmap",
NULL },
{ "disable-glx",
0, 0,
G_OPTION_ARG_NONE,
&disable_glx,
"Disable redirection through GLX pixmap",
NULL },
{ NULL }
};
static gboolean
stage_key_release_cb (ClutterActor *actor,
ClutterEvent *event,
gpointer data)
{
switch (clutter_key_event_symbol (&event->key))
{
case CLUTTER_q:
case CLUTTER_Q:
clutter_main_quit ();
break;
}
return FALSE;
}
static gboolean
stage_button_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);
return FALSE;
}
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 = g_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;
}
# endif /* USE_GDKPIXBUF */
int
main (int argc, char **argv)
{
#ifdef USE_GDKPIXBUF
GOptionContext *context;
ClutterActor *stage, *tex;
Pixmap pixmap;
const ClutterColor gry = { 0x99, 0x99, 0x99, 0xFF };
Window win_remote;
gboolean glx_only = FALSE;
guint w, h, d;
clutter_init (&argc, &argv);
context = g_option_context_new (" - text-pixmap options");
g_option_context_add_main_entries (context, g_options, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
if (argc < 2)
g_error ("usage: %s <window id>", argv[0]);
win_remote = strtol (argv[1], NULL, 0);
stage = clutter_stage_get_default ();
clutter_stage_set_color (CLUTTER_STAGE (stage), &gry);
/* a pixmap */
pixmap = create_pixmap (&w, &h, &d);
tex = clutter_x11_texture_pixmap_new_with_pixmap (pixmap);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), tex);
/* oddly, the actor's size is 0 until it is realized, even though
pixmap-height is set */
clutter_actor_set_position (tex, 0,
clutter_actor_get_height (stage)
- clutter_actor_get_height (tex));
/* a window */
if (!disable_x11)
{
tex = clutter_x11_texture_pixmap_new_with_window (win_remote);
clutter_actor_set_position (tex, 0, 0);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), tex);
clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex),
TRUE);
}
# ifdef HAVE_CLUTTER_GLX
/* a window with glx */
if (!disable_glx)
{
tex = clutter_glx_texture_pixmap_new_with_window (win_remote);
clutter_actor_set_position (tex,
clutter_actor_get_width (stage)
- clutter_actor_get_width (tex),
0);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), tex);
clutter_x11_texture_pixmap_set_automatic (CLUTTER_X11_TEXTURE_PIXMAP (tex),
TRUE);
}
#endif /* HAVE_CLUTTER_GLX */
g_signal_connect (stage, "key-release-event",
G_CALLBACK (stage_key_release_cb), (gpointer)pixmap);
g_signal_connect (stage, "button-press-event",
G_CALLBACK (stage_button_press_cb), (gpointer)pixmap);
clutter_actor_show_all (stage);
clutter_main ();
# endif /* USE_GDKPIXBUF */
return EXIT_SUCCESS;
}
#else /* HAVE_CLUTTER_GLX */
int main (int argc, char **argv) { return EXIT_SUCCESS; };
#endif /* HAVE_CLUTTER_GLX */