summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-08-17 22:20:18 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-08-17 22:20:18 +0100
commit6f000c3538e7fe1faf669104d120f76d8cc6f154 (patch)
tree7b2f70419d1a7fc54f0e937127b637e120e7d52f
parente5bac9de50fe2f6bd241e78b2838c4893abecbff (diff)
Rename ximage to xshm and create a new demo based on similar-image
-rw-r--r--Makefile7
-rw-r--r--demo.c8
-rw-r--r--demo.h6
-rw-r--r--ximage.c122
-rw-r--r--xlib.c2
-rw-r--r--xshm.c200
6 files changed, 243 insertions, 102 deletions
diff --git a/Makefile b/Makefile
index 7090311..dc1467f 100644
--- a/Makefile
+++ b/Makefile
@@ -12,11 +12,11 @@ endif
XLIB:=$(shell pkg-config --exists cairo-xlib && echo 1 || echo 0)
ifneq ($(XLIB),0)
-DEFINES+=-DHAVE_XLIB=1 -DHAVE_XIMAGE=1
-SOURCES+=xlib.c ximage.c
+DEFINES+=-DHAVE_XLIB=1 -DHAVE_XIMAGE=1 -DHAVE_XSHM=1
+SOURCES+=xlib.c ximage.c xshm.c
REQUIRES+=cairo-xlib xext
else
-DEFINES+=-DHAVE_XLIB=0
+DEFINES+=-DHAVE_XLIB=0 -DHAVE_XIMAGE=0 -DHAVE_XSHM=0
endif
XCB:=$(shell pkg-config --exists cairo-xcb && echo 1 || echo 0)
@@ -29,6 +29,7 @@ DEFINES+=-DHAVE_XCB=0
endif
GLX:=$(shell pkg-config --exists cairo-gl && echo 1 || echo 0)
+GLX:=0
ifneq ($(GLX),0)
DEFINES+=-DHAVE_GLX=1
SOURCES+=glx.c
diff --git a/demo.c b/demo.c
index d2f65f7..797fa38 100644
--- a/demo.c
+++ b/demo.c
@@ -145,6 +145,7 @@ struct device *device_open(int argc, char **argv)
AUTO,
XLIB,
XIMAGE,
+ XSHM,
SKIA,
XCB,
GLX,
@@ -160,6 +161,8 @@ struct device *device_open(int argc, char **argv)
backend = XCB;
} else if (strcmp (argv[n], "--ximage") == 0) {
backend = XIMAGE;
+ } else if (strcmp (argv[n], "--xshm") == 0) {
+ backend = XSHM;
} else if (strcmp (argv[n], "--drm") == 0) {
backend = DRM;
} else if (strcmp (argv[n], "--glx") == 0) {
@@ -184,6 +187,8 @@ struct device *device_open(int argc, char **argv)
device = cogl_open (argc, argv);
if (device == 0 && HAVE_XIMAGE)
device = ximage_open (argc, argv);
+ if (device == 0 && HAVE_XSHM)
+ device = xshm_open (argc, argv);
if (device == 0 && HAVE_SKIA)
device = skia_open (argc, argv);
} else switch (backend) {
@@ -197,6 +202,9 @@ struct device *device_open(int argc, char **argv)
case XIMAGE:
device = ximage_open (argc, argv);
break;
+ case XSHM:
+ device = xshm_open (argc, argv);
+ break;
case SKIA:
device = skia_open (argc, argv);
break;
diff --git a/demo.h b/demo.h
index c3d3c17..829586e 100644
--- a/demo.h
+++ b/demo.h
@@ -89,6 +89,12 @@ struct device *ximage_open (int argc, char **argv);
static inline struct device *ximage_open (int argc, char **argv) { return 0; }
#endif
+#if HAVE_XSHM
+struct device *xshm_open (int argc, char **argv);
+#else
+static inline struct device *xshm_open (int argc, char **argv) { return 0; }
+#endif
+
#if HAVE_DRM
struct device *drm_open (int argc, char **argv);
#else
diff --git a/ximage.c b/ximage.c
index 9ff23ff..1fb7f9b 100644
--- a/ximage.c
+++ b/ximage.c
@@ -12,14 +12,6 @@
struct ximage_device {
struct device base;
struct framebuffer fb;
-
- Display *display;
- Window drawable;
-
- int stride;
- Pixmap pixmap;
- GC gc;
- XShmSegmentInfo shm;
};
static void
@@ -27,51 +19,15 @@ destroy (struct framebuffer *abstract_framebuffer)
{
}
-static cairo_bool_t
-_native_byte_order_lsb (void)
-{
- int x = 1;
-
- return *((char *) &x) == 1;
-}
-
static void
show (struct framebuffer *fb)
{
struct ximage_device *device = (struct ximage_device *) fb->device;
-
- if (device->pixmap) {
- XCopyArea (device->display, device->pixmap, device->drawable, device->gc,
- 0, 0,
- device->base.width, device->base.height,
- 0, 0);
- } else {
- XImage ximage;
- int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
-
- ximage.width = device->base.width;
- ximage.height = device->base.height;
- ximage.format = ZPixmap;
- ximage.byte_order = native_byte_order;
- ximage.bitmap_unit = 32; /* always for libpixman */
- ximage.bitmap_bit_order = native_byte_order;
- ximage.bitmap_pad = 32; /* always for libpixman */
- ximage.depth = 24;
- ximage.red_mask = 0xff;
- ximage.green_mask = 0xff00;
- ximage.blue_mask = 0xff000;
- ximage.xoffset = 0;
- ximage.bits_per_pixel = 32;
- ximage.data = device->shm.shmaddr;
- ximage.obdata = (char *) &device->shm;
- ximage.bytes_per_line = device->stride;
-
- XShmPutImage (device->display, device->drawable, device->gc, &ximage,
- 0, 0, 0, 0, device->base.width, device->base.height,
- False);
- }
-
- XSync (device->display, True);
+ cairo_t *cr = cairo_create (device->base.scanout);
+ cairo_set_source_surface (cr, fb->surface, 0, 0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ cairo_destroy (cr);
}
static struct framebuffer *
@@ -87,25 +43,18 @@ ximage_open (int argc, char **argv)
struct ximage_device *device;
Display *dpy;
Screen *scr;
+ Window win;
int screen;
XSetWindowAttributes attr;
- int major, minor, has_pixmap;
int x, y;
- XGCValues gcv;
dpy = XOpenDisplay (NULL);
if (dpy == NULL)
return NULL;
- if (! XShmQueryExtension (dpy)) {
- XCloseDisplay (dpy);
- return NULL;
- }
-
device = (struct ximage_device *) malloc (sizeof (struct ximage_device));
device->base.name = "ximage";
device->base.get_framebuffer = get_fb;
- device->display = dpy;
screen = DefaultScreen (dpy);
scr = XScreenOfDisplay (dpy, screen);
@@ -149,52 +98,27 @@ ximage_open (int argc, char **argv)
}
attr.override_redirect = True;
- device->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
- x, y,
- device->base.width, device->base.height, 0,
- DefaultDepth (dpy, screen),
- InputOutput,
- DefaultVisual (dpy, screen),
- CWOverrideRedirect, &attr);
- XMapWindow (dpy, device->drawable);
-
- device->stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, device->base.width);
-
- device->shm.shmid = shmget(IPC_PRIVATE, device->stride * device->base.height, IPC_CREAT | 0777);
- device->shm.shmaddr = (char *) shmat (device->shm.shmid, NULL, 0);
- device->shm.readOnly = False;
-
- if (!XShmAttach (dpy, &device->shm))
- abort ();
-
- device->base.scanout = cairo_image_surface_create_for_data ((uint8_t *) device->shm.shmaddr,
- CAIRO_FORMAT_RGB24,
- device->base.width,
- device->base.height,
- device->stride);
- XShmQueryVersion (dpy, &major, &minor, &has_pixmap);
-
- if (has_pixmap) {
- printf ("Using SHM Pixmap\n");
- device->pixmap = XShmCreatePixmap (dpy,
- device->drawable,
- device->shm.shmaddr,
- &device->shm,
- device->base.width,
- device->base.height,
- 24);
- } else {
- printf ("Using SHM PutImage\n");
- device->pixmap = 0;
- }
-
- gcv.graphics_exposures = False;
- device->gc = XCreateGC (dpy, device->drawable, GCGraphicsExposures, &gcv);
+ win = XCreateWindow (dpy, DefaultRootWindow (dpy),
+ x, y,
+ device->base.width, device->base.height, 0,
+ DefaultDepth (dpy, screen),
+ InputOutput,
+ DefaultVisual (dpy, screen),
+ CWOverrideRedirect, &attr);
+ XMapWindow (dpy, win);
+
+ device->base.scanout = cairo_xlib_surface_create (dpy, win,
+ DefaultVisual (dpy, screen),
+ device->base.width, device->base.height);
+
+ device->fb.surface =
+ cairo_surface_create_similar_image (device->base.scanout,
+ CAIRO_FORMAT_RGB24,
+ device->base.width, device->base.height);
device->fb.device = &device->base;
device->fb.show = show;
device->fb.destroy = destroy;
- device->fb.surface = device->base.scanout;
return &device->base;
}
diff --git a/xlib.c b/xlib.c
index 9003384..6ca665d 100644
--- a/xlib.c
+++ b/xlib.c
@@ -28,6 +28,8 @@ show (struct framebuffer *fb)
{
struct xlib_device *device = (struct xlib_device *) fb->device;
+ cairo_surface_flush (fb->surface);
+
XCopyArea(device->display,
device->pixmap[device->q&1],
device->drawable,
diff --git a/xshm.c b/xshm.c
new file mode 100644
index 0000000..27adbff
--- /dev/null
+++ b/xshm.c
@@ -0,0 +1,200 @@
+#include <cairo-xlib.h>
+
+#include "demo.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <X11/extensions/XShm.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+struct xshm_device {
+ struct device base;
+ struct framebuffer fb;
+
+ Display *display;
+ Window drawable;
+
+ int stride;
+ Pixmap pixmap;
+ GC gc;
+ XShmSegmentInfo shm;
+};
+
+static void
+destroy (struct framebuffer *abstract_framebuffer)
+{
+}
+
+static cairo_bool_t
+_native_byte_order_lsb (void)
+{
+ int x = 1;
+
+ return *((char *) &x) == 1;
+}
+
+static void
+show (struct framebuffer *fb)
+{
+ struct xshm_device *device = (struct xshm_device *) fb->device;
+
+ if (device->pixmap) {
+ XCopyArea (device->display, device->pixmap, device->drawable, device->gc,
+ 0, 0,
+ device->base.width, device->base.height,
+ 0, 0);
+ } else {
+ XImage xshm;
+ int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
+
+ xshm.width = device->base.width;
+ xshm.height = device->base.height;
+ xshm.format = ZPixmap;
+ xshm.byte_order = native_byte_order;
+ xshm.bitmap_unit = 32; /* always for libpixman */
+ xshm.bitmap_bit_order = native_byte_order;
+ xshm.bitmap_pad = 32; /* always for libpixman */
+ xshm.depth = 24;
+ xshm.red_mask = 0xff;
+ xshm.green_mask = 0xff00;
+ xshm.blue_mask = 0xff000;
+ xshm.xoffset = 0;
+ xshm.bits_per_pixel = 32;
+ xshm.data = device->shm.shmaddr;
+ xshm.obdata = (char *) &device->shm;
+ xshm.bytes_per_line = device->stride;
+
+ XShmPutImage (device->display, device->drawable, device->gc, &xshm,
+ 0, 0, 0, 0, device->base.width, device->base.height,
+ False);
+ }
+
+ XSync (device->display, True);
+}
+
+static struct framebuffer *
+get_fb (struct device *abstract_device)
+{
+ struct xshm_device *device = (struct xshm_device *) abstract_device;
+ return &device->fb;
+}
+
+struct device *
+xshm_open (int argc, char **argv)
+{
+ struct xshm_device *device;
+ Display *dpy;
+ Screen *scr;
+ int screen;
+ XSetWindowAttributes attr;
+ int major, minor, has_pixmap;
+ int x, y;
+ XGCValues gcv;
+
+ dpy = XOpenDisplay (NULL);
+ if (dpy == NULL)
+ return NULL;
+
+ if (! XShmQueryExtension (dpy)) {
+ XCloseDisplay (dpy);
+ return NULL;
+ }
+
+ device = (struct xshm_device *) malloc (sizeof (struct xshm_device));
+ device->base.name = "xshm";
+ device->base.get_framebuffer = get_fb;
+ device->display = dpy;
+
+ screen = DefaultScreen (dpy);
+ scr = XScreenOfDisplay (dpy, screen);
+ device->base.width = WidthOfScreen (scr);
+ device->base.height = HeightOfScreen (scr);
+ device_get_size (argc, argv, &device->base.width, &device->base.height);
+ x = y = 0;
+ switch (device_get_split(argc, argv)) {
+ case SPLIT_NONE:
+ break;
+ case SPLIT_LEFT:
+ device->base.width /= 2;
+ break;
+ case SPLIT_RIGHT:
+ x = device->base.width /= 2;
+ break;
+ case SPLIT_TOP:
+ device->base.height /= 2;
+ break;
+ case SPLIT_BOTTOM:
+ y = device->base.height /= 2;
+ break;
+
+ case SPLIT_BOTTOM_LEFT:
+ device->base.width /= 2;
+ y = device->base.height /= 2;
+ break;
+ case SPLIT_BOTTOM_RIGHT:
+ x = device->base.width /= 2;
+ y = device->base.height /= 2;
+ break;
+
+ case SPLIT_TOP_LEFT:
+ device->base.width /= 2;
+ device->base.height /= 2;
+ break;
+ case SPLIT_TOP_RIGHT:
+ x = device->base.width /= 2;
+ device->base.height /= 2;
+ break;
+ }
+
+ attr.override_redirect = True;
+ device->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy),
+ x, y,
+ device->base.width, device->base.height, 0,
+ DefaultDepth (dpy, screen),
+ InputOutput,
+ DefaultVisual (dpy, screen),
+ CWOverrideRedirect, &attr);
+ XMapWindow (dpy, device->drawable);
+
+ device->stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, device->base.width);
+
+ device->shm.shmid = shmget(IPC_PRIVATE, device->stride * device->base.height, IPC_CREAT | 0777);
+ device->shm.shmaddr = (char *) shmat (device->shm.shmid, NULL, 0);
+ device->shm.readOnly = False;
+
+ if (!XShmAttach (dpy, &device->shm))
+ abort ();
+
+ device->base.scanout = cairo_image_surface_create_for_data ((uint8_t *) device->shm.shmaddr,
+ CAIRO_FORMAT_RGB24,
+ device->base.width,
+ device->base.height,
+ device->stride);
+ XShmQueryVersion (dpy, &major, &minor, &has_pixmap);
+
+ if (has_pixmap) {
+ printf ("Using SHM Pixmap\n");
+ device->pixmap = XShmCreatePixmap (dpy,
+ device->drawable,
+ device->shm.shmaddr,
+ &device->shm,
+ device->base.width,
+ device->base.height,
+ 24);
+ } else {
+ printf ("Using SHM PutImage\n");
+ device->pixmap = 0;
+ }
+
+ gcv.graphics_exposures = False;
+ device->gc = XCreateGC (dpy, device->drawable, GCGraphicsExposures, &gcv);
+
+ device->fb.device = &device->base;
+ device->fb.show = show;
+ device->fb.destroy = destroy;
+ device->fb.surface = device->base.scanout;
+
+ return &device->base;
+}