diff options
Diffstat (limited to 'src/pixmap.c')
-rw-r--r-- | src/pixmap.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/pixmap.c b/src/pixmap.c new file mode 100644 index 0000000..820c023 --- /dev/null +++ b/src/pixmap.c @@ -0,0 +1,147 @@ +#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 "Xlib-wayland.h" + +#include "private.h" + +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct csx_pixmap *pixmap = data; +} + +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; + void *data; + const char *path; + char name[PATH_MAX]; + + 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 (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); + + memset(pixmap->data, 55, size); + + 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) + /* BadAlloc */; + + memset(pixmap, 0, sizeof pixmap); + pixmap->width = width; + pixmap->height = height; + pixmap->depth = depth; + pixmap->refcount = 1; + + 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 = xdisplay->csx_display; + struct csx_pixmap *pixmap; + void *resource; + Pixmap id; + + resource = csx_display_lookup_resource(display, drawable); + /* FIXME: Need to check resource type too */ + if (resource == NULL) { + /* Raise error */; + return 0; /* need to return valid id */ + } + + id = csx_display_add_resource(display, pixmap); + + return id; +} + +WL_EXPORT int +XFreePixmap(Display *xdisplay, Pixmap xpixmap) +{ + struct csx_display *display = xdisplay->csx_display; + 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? */; +} |