diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-08-12 15:56:22 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-08-12 17:08:27 +0100 |
commit | 391abd1a8edc6103ee2007d8eff510102ea932ca (patch) | |
tree | 403864b9f2f801283efedcc3d33d0694a1e58bfe | |
parent | 2e769723623ef1b7c5cd673ee1fb701d45505bab (diff) |
Add a skia demo backend
Note that this then requires us to be C++ clean.
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | chart-demo.c | 2 | ||||
-rw-r--r-- | demo.c | 8 | ||||
-rw-r--r-- | demo.h | 12 | ||||
-rw-r--r-- | fish-demo.c | 14 | ||||
-rw-r--r-- | maze-demo.c | 2 | ||||
-rw-r--r-- | skia.c | 201 | ||||
-rw-r--r-- | spinner-demo.c | 6 | ||||
-rw-r--r-- | ximage.c | 4 |
9 files changed, 241 insertions, 17 deletions
@@ -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; @@ -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; @@ -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; @@ -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); @@ -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)) |