diff options
author | Kristian H. Kristensen <hoegsberg@chromium.org> | 2016-12-07 15:37:15 -0800 |
---|---|---|
committer | Kristian H. Kristensen <hoegsberg@chromium.org> | 2016-12-07 15:37:29 -0800 |
commit | a0ae742ad343de399df4e4a9200b588a096c3b5b (patch) | |
tree | 7b7777f6b5f446b672ed8a017e8b2a084dd26fe4 /pixmap.c | |
parent | d911f1d5ee8be18c7b37816084be81e0d9c7ae41 (diff) |
Diffstat (limited to 'pixmap.c')
-rw-r--r-- | pixmap.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/pixmap.c b/pixmap.c new file mode 100644 index 0000000..8c35dff --- /dev/null +++ b/pixmap.c @@ -0,0 +1,166 @@ +#define _GNU_SOURCE + +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <limits.h> +#include <sys/mman.h> + +#include <X11/Xproto.h> +#include <X11/Xlib.h> + +#include "private.h" + +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static int +create_shm_buffer(struct csx_display *display, struct csx_pixmap *pixmap) +{ + struct wl_shm_pool *pool; + int fd, size, stride, i; + const char *path; + char name[PATH_MAX]; + uint32_t *p; + + stride = pixmap->width * 4; + size = stride * pixmap->height; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + snprintf(name, sizeof name, "%s/csx-pixmap-XXXXXX", path); + fd = mkostemp(name, O_CLOEXEC); + if (fd < 0) + return -1; + + unlink(name); + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + pixmap->data = + mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (pixmap->data == MAP_FAILED) { + fprintf(stderr, "mmap failed: %m\n"); + close(fd); + return -1; + } + + pool = wl_shm_create_pool(display->shm, fd, size); + pixmap->buffer = wl_shm_pool_create_buffer(pool, 0, + pixmap->width, + pixmap->height, + stride, + WL_SHM_FORMAT_ARGB8888); + wl_buffer_add_listener(pixmap->buffer, &buffer_listener, pixmap); + wl_shm_pool_destroy(pool); + close(fd); + + p = pixmap->data; + for (i = 0; i < size / 4; i++) + p[i] = 0xff000000 | (0x00010004 * i); + + return 0; +} + +struct csx_pixmap * +csx_pixmap_create(struct csx_display *display, + unsigned int width, unsigned int height, unsigned int depth) +{ + struct csx_pixmap *pixmap; + + pixmap = malloc(sizeof *pixmap); + if (pixmap == NULL) + return NULL; + + memset(pixmap, 0, sizeof *pixmap); + pixmap->width = width; + pixmap->height = height; + pixmap->depth = depth; + pixmap->refcount = 1; + + /* Only create this for window backing pixmaps, just use + * malloc for "normal" pixmaps. */ + create_shm_buffer(display, pixmap); + + return pixmap; +} + +void +csx_pixmap_unref(struct csx_pixmap *pixmap) +{ + int size; + + pixmap->refcount--; + if (pixmap->refcount == 0) { + if (pixmap->buffer) { + size = pixmap->width * 4 * pixmap->height; + wl_buffer_destroy(pixmap->buffer); + munmap(pixmap->data, size); + } else { + free(pixmap->data); + } + free(pixmap); + } +} + +WL_EXPORT Pixmap +XCreatePixmap(Display *xdisplay, Drawable drawable, + unsigned int width, unsigned int height, unsigned int depth) +{ + struct csx_display *display = csx_display(xdisplay); + struct csx_pixmap *pixmap; + void *resource; + Pixmap id; + + csx_display_enter(display, X_CreatePixmap, 0); + + resource = csx_display_lookup_resource(display, drawable); + /* FIXME: Need to check resource type too */ + if (resource == NULL) { + csx_display_error(display, drawable, BadDrawable); + return None; + } + + pixmap = csx_pixmap_create(display, width, height, depth); + if (pixmap == NULL) { + csx_display_error(display, drawable, BadAlloc); + return None; + } + + id = csx_display_add_resource(display, pixmap); + if (id == None) { + csx_pixmap_unref(pixmap); + csx_display_error(display, drawable, BadAlloc); + return None; + } + + return id; +} + +WL_EXPORT int +XFreePixmap(Display *xdisplay, Pixmap xpixmap) +{ + struct csx_display *display = csx_display(xdisplay); + struct csx_pixmap *pixmap; + + pixmap = csx_display_lookup_resource(display, xpixmap); + csx_display_remove_resource(display, xpixmap); + csx_pixmap_unref(pixmap); + + return 0 /* return what? */; +} |