diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-28 12:21:50 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-03-28 14:43:23 -0400 |
commit | d39bda76c4007c42452a81883fefc671b816a74b (patch) | |
tree | 509a9c669bf2679085e27a1ff1b0c95526abf14c /client/pool-buffer.c | |
parent | Refactor configure/ack configure/commit flow (diff) | |
download | sway-d39bda76c4007c42452a81883fefc671b816a74b.tar.gz sway-d39bda76c4007c42452a81883fefc671b816a74b.tar.zst sway-d39bda76c4007c42452a81883fefc671b816a74b.zip |
Address review comments
Diffstat (limited to 'client/pool-buffer.c')
-rw-r--r-- | client/pool-buffer.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/client/pool-buffer.c b/client/pool-buffer.c new file mode 100644 index 00000000..93cfcfc5 --- /dev/null +++ b/client/pool-buffer.c | |||
@@ -0,0 +1,124 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <assert.h> | ||
3 | #include <cairo/cairo.h> | ||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <string.h> | ||
7 | #include <sys/mman.h> | ||
8 | #include <pango/pangocairo.h> | ||
9 | #include <unistd.h> | ||
10 | #include <wayland-client.h> | ||
11 | #include "config.h" | ||
12 | #include "pool-buffer.h" | ||
13 | |||
14 | static int create_pool_file(size_t size, char **name) { | ||
15 | static const char template[] = "sway-client-XXXXXX"; | ||
16 | const char *path = getenv("XDG_RUNTIME_DIR"); | ||
17 | if (!path) { | ||
18 | return -1; | ||
19 | } | ||
20 | |||
21 | int ts = (path[strlen(path) - 1] == '/'); | ||
22 | |||
23 | *name = malloc( | ||
24 | strlen(template) + | ||
25 | strlen(path) + | ||
26 | (ts ? 0 : 1) + 1); | ||
27 | sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); | ||
28 | |||
29 | int fd = mkstemp(*name); | ||
30 | |||
31 | if (fd < 0) { | ||
32 | return -1; | ||
33 | } | ||
34 | |||
35 | if (ftruncate(fd, size) < 0) { | ||
36 | close(fd); | ||
37 | return -1; | ||
38 | } | ||
39 | |||
40 | return fd; | ||
41 | } | ||
42 | |||
43 | static void buffer_release(void *data, struct wl_buffer *wl_buffer) { | ||
44 | struct pool_buffer *buffer = data; | ||
45 | buffer->busy = false; | ||
46 | } | ||
47 | |||
48 | static const struct wl_buffer_listener buffer_listener = { | ||
49 | .release = buffer_release | ||
50 | }; | ||
51 | |||
52 | static struct pool_buffer *create_buffer(struct wl_shm *shm, | ||
53 | struct pool_buffer *buf, int32_t width, int32_t height, | ||
54 | uint32_t format) { | ||
55 | uint32_t stride = width * 4; | ||
56 | uint32_t size = stride * height; | ||
57 | |||
58 | char *name; | ||
59 | int fd = create_pool_file(size, &name); | ||
60 | assert(fd); | ||
61 | void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | ||
62 | struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); | ||
63 | buf->buffer = wl_shm_pool_create_buffer(pool, 0, | ||
64 | width, height, stride, format); | ||
65 | wl_shm_pool_destroy(pool); | ||
66 | close(fd); | ||
67 | unlink(name); | ||
68 | free(name); | ||
69 | fd = -1; | ||
70 | |||
71 | buf->width = width; | ||
72 | buf->height = height; | ||
73 | buf->surface = cairo_image_surface_create_for_data(data, | ||
74 | CAIRO_FORMAT_ARGB32, width, height, stride); | ||
75 | buf->cairo = cairo_create(buf->surface); | ||
76 | buf->pango = pango_cairo_create_context(buf->cairo); | ||
77 | |||
78 | wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); | ||
79 | return buf; | ||
80 | } | ||
81 | |||
82 | static void destroy_buffer(struct pool_buffer *buffer) { | ||
83 | if (buffer->buffer) { | ||
84 | wl_buffer_destroy(buffer->buffer); | ||
85 | } | ||
86 | if (buffer->cairo) { | ||
87 | cairo_destroy(buffer->cairo); | ||
88 | } | ||
89 | if (buffer->surface) { | ||
90 | cairo_surface_destroy(buffer->surface); | ||
91 | } | ||
92 | if (buffer->pango) { | ||
93 | g_object_unref(buffer->pango); | ||
94 | } | ||
95 | memset(buffer, 0, sizeof(struct pool_buffer)); | ||
96 | } | ||
97 | |||
98 | struct pool_buffer *get_next_buffer(struct wl_shm *shm, | ||
99 | struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { | ||
100 | struct pool_buffer *buffer = NULL; | ||
101 | |||
102 | for (size_t i = 0; i < 2; ++i) { | ||
103 | if (pool[i].busy) { | ||
104 | continue; | ||
105 | } | ||
106 | buffer = &pool[i]; | ||
107 | } | ||
108 | |||
109 | if (!buffer) { | ||
110 | return NULL; | ||
111 | } | ||
112 | |||
113 | if (buffer->width != width || buffer->height != height) { | ||
114 | destroy_buffer(buffer); | ||
115 | } | ||
116 | |||
117 | if (!buffer->buffer) { | ||
118 | if (!create_buffer(shm, buffer, width, height, | ||
119 | WL_SHM_FORMAT_ARGB8888)) { | ||
120 | return NULL; | ||
121 | } | ||
122 | } | ||
123 | return buffer; | ||
124 | } | ||