summaryrefslogtreecommitdiff
path: root/pixmap.c
diff options
context:
space:
mode:
authorKristian H. Kristensen <hoegsberg@chromium.org>2016-12-07 15:37:15 -0800
committerKristian H. Kristensen <hoegsberg@chromium.org>2016-12-07 15:37:29 -0800
commita0ae742ad343de399df4e4a9200b588a096c3b5b (patch)
tree7b7777f6b5f446b672ed8a017e8b2a084dd26fe4 /pixmap.c
parentd911f1d5ee8be18c7b37816084be81e0d9c7ae41 (diff)
Switch to meson build systemHEADmaster
Diffstat (limited to 'pixmap.c')
-rw-r--r--pixmap.c166
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? */;
+}