summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-08-12 15:56:22 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-08-12 17:08:27 +0100
commit391abd1a8edc6103ee2007d8eff510102ea932ca (patch)
tree403864b9f2f801283efedcc3d33d0694a1e58bfe
parent2e769723623ef1b7c5cd673ee1fb701d45505bab (diff)
Add a skia demo backend
Note that this then requires us to be C++ clean.
-rw-r--r--Makefile9
-rw-r--r--chart-demo.c2
-rw-r--r--demo.c8
-rw-r--r--demo.h12
-rw-r--r--fish-demo.c14
-rw-r--r--maze-demo.c2
-rw-r--r--skia.c201
-rw-r--r--spinner-demo.c6
-rw-r--r--ximage.c4
9 files changed, 241 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index 64fdabe..bf8711f 100644
--- a/Makefile
+++ b/Makefile
@@ -46,6 +46,15 @@ else
DEFINES+=-DHAVE_COGL=0
endif
+SKIA:=$(shell pkg-config --exists cairo-skia && echo 1 || echo 0)
+ifneq ($(SKIA),0)
+DEFINES+=-DHAVE_SKIA=1
+SOURCES+=skia.c
+REQUIRES+=cairo-skia
+else
+DEFINES+=-DHAVE_SKIA=0
+endif
+
all: spiral-demo tiger-demo fish-demo flowers-demo gears-demo gradient-demo chart-demo waterfall-demo dragon-demo pythagoras-demo wave-demo sierpinski-demo maze-demo
ifeq ($(shell pkg-config --exists poppler-glib && echo 1), 1)
diff --git a/chart-demo.c b/chart-demo.c
index a7c7b36..cad22f4 100644
--- a/chart-demo.c
+++ b/chart-demo.c
@@ -40,7 +40,7 @@ static void chart_init(struct chart *c,
{
int n;
- c->array = malloc(size);
+ c->array = (int8_t *)malloc(size);
c->y = y;
c->scale = scale;
c->size = size;
diff --git a/demo.c b/demo.c
index ed7cb5f..c50bf1e 100644
--- a/demo.c
+++ b/demo.c
@@ -145,6 +145,7 @@ struct device *device_open(int argc, char **argv)
AUTO,
XLIB,
XIMAGE,
+ SKIA,
XCB,
GLX,
COGL,
@@ -165,6 +166,8 @@ struct device *device_open(int argc, char **argv)
backend = GLX;
} else if (strcmp (argv[n], "--cogl") == 0) {
backend = COGL;
+ } else if (strcmp (argv[n], "--skia") == 0) {
+ backend = SKIA;
}
}
@@ -181,6 +184,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_SKIA)
+ device = skia_open (argc, argv);
} else switch (backend) {
case AUTO:
case XLIB:
@@ -192,6 +197,9 @@ struct device *device_open(int argc, char **argv)
case XIMAGE:
device = ximage_open (argc, argv);
break;
+ case SKIA:
+ device = skia_open (argc, argv);
+ break;
case GLX:
device = glx_open (argc, argv);
break;
diff --git a/demo.h b/demo.h
index ff32058..17a2109 100644
--- a/demo.h
+++ b/demo.h
@@ -40,7 +40,8 @@ enum split {
SPLIT_TOP_RIGHT,
SPLIT_BOTTOM_LEFT,
SPLIT_BOTTOM_RIGHT,
-} device_get_split(int argc, char **argv);
+};
+enum split device_get_split(int argc, char **argv);
cairo_antialias_t device_get_antialias(int argc, char **argv);
const char *device_antialias_to_string(cairo_antialias_t antialias);
@@ -54,7 +55,8 @@ enum clip {
CLIP_BOX2,
CLIP_DIAMOND,
CLIP_CIRCLE,
-} device_get_clip(int argc, char **argv);
+};
+enum clip device_get_clip(int argc, char **argv);
void device_apply_clip(struct device *device, cairo_t *cr, enum clip c);
#if HAVE_COGL
@@ -93,6 +95,12 @@ struct device *drm_open (int argc, char **argv);
static inline struct device *drm_open (int argc, char **argv) { return 0; }
#endif
+#if HAVE_SKIA
+struct device *skia_open (int argc, char **argv);
+#else
+static inline struct device *skia_open (int argc, char **argv) { return 0; }
+#endif
+
#if HAVE_GDK_PIXBUF
#include <gdk-pixbuf/gdk-pixbuf.h>
diff --git a/fish-demo.c b/fish-demo.c
index 6082d47..8555166 100644
--- a/fish-demo.c
+++ b/fish-demo.c
@@ -84,7 +84,7 @@ static cairo_surface_t **create_strip(struct device *device)
fish_width = width;
fish_height = height;
- strip = malloc(sizeof(cairo_surface_t*)*48);
+ strip = (cairo_surface_t **)malloc(sizeof(cairo_surface_t*)*48);
for (y = 0; y < 3; y++) {
for (x = 0; x < 16; x++) {
strip[y*16+x] =
@@ -205,11 +205,12 @@ int main (int argc, char **argv)
if (strncmp(argv[n], "--num-fish=", 11) == 0)
num_fish = atoi(argv[n]+11);
else if (strcmp(argv[n], "--reflection") == 0)
- reflection = (void *)1;
+ reflection = (cairo_pattern_t *)1;
else if (strcmp(argv[n], "--solid-background") == 0)
solid_bg = 1;
}
+ x1 = -1;
if (solid_bg)
bg = solid_background();
else
@@ -217,9 +218,7 @@ int main (int argc, char **argv)
if (cairo_pattern_status(bg))
return 1;
- if (reflection == NULL || x1 < 0) {
- x1 = 0, x2 = device->width;
- } else {
+ if (reflection != NULL && x1 >= 0) {
reflection = cairo_pattern_create_linear(0,0, device->width, 0);
cairo_pattern_add_color_stop_rgba(reflection, 0, 0, 0, 0, 0);
cairo_pattern_add_color_stop_rgba(reflection, x1/(double)device->width, 0, 0, 0, .75);
@@ -227,11 +226,12 @@ int main (int argc, char **argv)
cairo_pattern_add_color_stop_rgba(reflection, x2/(double)device->width, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba(reflection, x2/(double)device->width, 0, 0, 0, .75);
cairo_pattern_add_color_stop_rgba(reflection, 1, 0, 0, 0, 0);
- }
+ } else
+ x1 = 0, x2 = device->width;
strip = create_strip(device);
- fish = malloc(sizeof(*fish)*num_fish);
+ fish = (struct fish *)malloc(sizeof(*fish)*num_fish);
for (n = 0; n < num_fish; n++)
fish_init(device, &fish[n], x1, x2);
diff --git a/maze-demo.c b/maze-demo.c
index e6b51b7..c6e7286 100644
--- a/maze-demo.c
+++ b/maze-demo.c
@@ -216,7 +216,7 @@ static void maze_create(void)
int i, h2 = 2 * h + 2, w2 = 2 * w + 2;
uint8_t **p;
- p = calloc(sizeof(uint8_t*) * (h2 + 2) + w2 * h2 + 1, 1);
+ p = (uint8_t **)calloc(sizeof(uint8_t*) * (h2 + 2) + w2 * h2 + 1, 1);
p[1] = (uint8_t*)(p + h2 + 2) + 1;
each(i, 2, h2) p[i] = p[i-1] + w2;
diff --git a/skia.c b/skia.c
new file mode 100644
index 0000000..6efa0d8
--- /dev/null
+++ b/skia.c
@@ -0,0 +1,201 @@
+#include <cairo-xlib.h>
+#include <cairo-skia.h>
+
+#include "demo.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <X11/extensions/XShm.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+struct skia_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 skia_device *device = (struct skia_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);
+}
+
+static struct framebuffer *
+get_fb (struct device *abstract_device)
+{
+ struct skia_device *device = (struct skia_device *) abstract_device;
+ return &device->fb;
+}
+
+struct device *
+skia_open (int argc, char **argv)
+{
+ struct skia_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 skia_device *) malloc (sizeof (struct skia_device));
+ device->base.name = "skia";
+ 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_skia_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;
+}
diff --git a/spinner-demo.c b/spinner-demo.c
index f737fe1..ea2921e 100644
--- a/spinner-demo.c
+++ b/spinner-demo.c
@@ -41,8 +41,7 @@ static int load_source(const char *filename, struct device *device)
if (!preload && !prescale) {
struct source *s;
- s = realloc(sources,
- (num_sources+1)*sizeof(struct source));
+ s = (struct source *)realloc(sources, (num_sources+1)*sizeof(struct source));
if (s == NULL) {
cairo_surface_destroy(image);
return 0;
@@ -89,8 +88,7 @@ static int load_source(const char *filename, struct device *device)
if (status == CAIRO_STATUS_SUCCESS) {
struct source *s;
- s = realloc(sources,
- (num_sources+1)*sizeof(struct source));
+ s = (struct source *)realloc(sources, (num_sources+1)*sizeof(struct source));
if (s) {
s[num_sources].surface =
cairo_surface_reference(surface);
diff --git a/ximage.c b/ximage.c
index 77456ee..9ff23ff 100644
--- a/ximage.c
+++ b/ximage.c
@@ -102,7 +102,7 @@ ximage_open (int argc, char **argv)
return NULL;
}
- device = malloc (sizeof (struct ximage_device));
+ device = (struct ximage_device *) malloc (sizeof (struct ximage_device));
device->base.name = "ximage";
device->base.get_framebuffer = get_fb;
device->display = dpy;
@@ -161,7 +161,7 @@ ximage_open (int argc, char **argv)
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 = shmat (device->shm.shmid, NULL, 0);
+ device->shm.shmaddr = (char *) shmat (device->shm.shmid, NULL, 0);
device->shm.readOnly = False;
if (!XShmAttach (dpy, &device->shm))