#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #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? */; }