commit 3333dfd
Michael Forney
·
2014-02-07 12:07:06 +0000 UTC
parent cae8594
shm: Use our own wl_shm implementation
2 files changed,
+213,
-77
+213,
-3
1@@ -1,6 +1,10 @@
2 /* swc: libswc/shm.c
3 *
4- * Copyright (c) 2013 Michael Forney
5+ * Copyright (c) 2013, 2014 Michael Forney
6+ *
7+ * Based in part upon wayland-shm.c from wayland, which is:
8+ *
9+ * Copyright © 2008 Kristian Høgsberg
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13@@ -23,13 +27,210 @@
14
15 #include "shm.h"
16 #include "internal.h"
17+#include "util.h"
18+#include "wayland_buffer.h"
19
20-#include <stddef.h>
21-#include <wld/wld.h>
22+#include <errno.h>
23+#include <stdlib.h>
24+#include <sys/mman.h>
25+#include <wayland-server.h>
26 #include <wld/pixman.h>
27+#include <wld/wld.h>
28
29 struct swc_shm swc_shm;
30
31+static struct
32+{
33+ struct wl_global * global;
34+} shm;
35+
36+struct pool
37+{
38+ struct wl_resource * resource;
39+ void * data;
40+ uint32_t size;
41+ unsigned references;
42+};
43+
44+struct pool_reference
45+{
46+ struct wld_destructor destructor;
47+ struct pool * pool;
48+};
49+
50+static void unref_pool(struct wl_resource * resource)
51+{
52+ struct pool * pool = wl_resource_get_user_data(resource);
53+
54+ if (--pool->references > 0)
55+ return;
56+
57+ munmap(pool->data, pool->size);
58+ free(pool);
59+}
60+
61+static void handle_buffer_destroy(struct wld_destructor * destructor)
62+{
63+ struct pool_reference * reference
64+ = CONTAINER_OF(destructor, typeof(*reference), destructor);
65+
66+ unref_pool(reference->pool->resource);
67+}
68+
69+static inline uint32_t format_shm_to_wld(uint32_t format)
70+{
71+ switch (format)
72+ {
73+ case WL_SHM_FORMAT_ARGB8888:
74+ return WLD_FORMAT_ARGB8888;
75+ case WL_SHM_FORMAT_XRGB8888:
76+ return WLD_FORMAT_XRGB8888;
77+ default:
78+ return format;
79+ }
80+}
81+
82+static void create_buffer(struct wl_client * client,
83+ struct wl_resource * resource, uint32_t id,
84+ int32_t offset, int32_t width, int32_t height,
85+ int32_t stride, uint32_t format)
86+{
87+ struct pool * pool = wl_resource_get_user_data(resource);
88+ struct pool_reference * reference;
89+ struct wld_buffer * buffer;
90+ struct wl_resource * buffer_resource;
91+ union wld_object object;
92+
93+ if (offset > pool->size || offset < 0)
94+ {
95+ wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_STRIDE,
96+ "offset is too big or negative");
97+ return;
98+ }
99+
100+ object.ptr = (void *)((uintptr_t) pool->data + offset);
101+ buffer = wld_import_buffer(swc.shm->context, WLD_OBJECT_DATA, object,
102+ width, height, format_shm_to_wld(format),
103+ stride);
104+
105+ if (!buffer)
106+ goto error0;
107+
108+ buffer_resource = swc_wayland_buffer_create_resource(client, id, buffer);
109+
110+ if (!buffer_resource)
111+ goto error1;
112+
113+ if (!(reference = malloc(sizeof *reference)))
114+ goto error2;
115+
116+ reference->pool = pool;
117+ reference->destructor.destroy = &handle_buffer_destroy;
118+ wld_buffer_add_destructor(buffer, &reference->destructor);
119+ ++pool->references;
120+
121+ return;
122+
123+ error2:
124+ wl_resource_destroy(buffer_resource);
125+ error1:
126+ wld_buffer_unreference(buffer);
127+ error0:
128+ wl_resource_post_no_memory(resource);
129+}
130+
131+static void destroy(struct wl_client * client, struct wl_resource * resource)
132+{
133+ wl_resource_destroy(resource);
134+}
135+
136+static void resize(struct wl_client * client, struct wl_resource * resource,
137+ int32_t size)
138+{
139+ struct pool * pool = wl_resource_get_user_data(resource);
140+ void * data;
141+
142+ data = mremap(pool->data, pool->size, size, MREMAP_MAYMOVE);
143+
144+ if (data == MAP_FAILED)
145+ {
146+ wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD,
147+ "mremap failed: %s", strerror(errno));
148+ return;
149+ }
150+
151+ pool->data = data;
152+ pool->size = size;
153+}
154+
155+static struct wl_shm_pool_interface shm_pool_implementation = {
156+ .create_buffer = &create_buffer,
157+ .destroy = &destroy,
158+ .resize = &resize
159+};
160+
161+static void create_pool(struct wl_client * client,
162+ struct wl_resource * resource, uint32_t id,
163+ int32_t fd, int32_t size)
164+{
165+ struct pool * pool;
166+
167+ if (!(pool = malloc(sizeof *pool)))
168+ {
169+ wl_resource_post_no_memory(resource);
170+ return;
171+ }
172+
173+ pool->resource = wl_resource_create(client, &wl_shm_pool_interface,
174+ wl_resource_get_version(resource), id);
175+
176+ if (!pool->resource)
177+ {
178+ wl_resource_post_no_memory(resource);
179+ goto error0;
180+ }
181+
182+ wl_resource_set_implementation(pool->resource, &shm_pool_implementation,
183+ pool, &unref_pool);
184+ pool->data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
185+
186+ if (pool->data == MAP_FAILED)
187+ {
188+ wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD,
189+ "mmap failed: %s", strerror(errno));
190+ goto error1;
191+ }
192+
193+ pool->size = size;
194+ pool->references = 1;
195+
196+ return;
197+
198+ error1:
199+ wl_resource_destroy(pool->resource);
200+ error0:
201+ free(pool);
202+}
203+
204+static struct wl_shm_interface shm_implementation = {
205+ .create_pool = &create_pool
206+};
207+
208+static void bind_shm(struct wl_client * client, void * data, uint32_t version,
209+ uint32_t id)
210+{
211+ struct wl_resource * resource;
212+
213+ if (version >= 1)
214+ version = 1;
215+
216+ resource = wl_resource_create(client, &wl_shm_interface, version, id);
217+ wl_resource_set_implementation(resource, &shm_implementation, NULL, NULL);
218+
219+ wl_shm_send_format(resource, WL_SHM_FORMAT_XRGB8888);
220+ wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888);
221+}
222+
223 bool swc_shm_initialize()
224 {
225 if (!(swc.shm->context = wld_pixman_create_context()))
226@@ -38,8 +239,16 @@ bool swc_shm_initialize()
227 if (!(swc.shm->renderer = wld_create_renderer(swc.shm->context)))
228 goto error1;
229
230+ shm.global = wl_global_create(swc.display, &wl_shm_interface, 1,
231+ NULL, &bind_shm);
232+
233+ if (!shm.global)
234+ goto error2;
235+
236 return true;
237
238+ error2:
239+ wld_destroy_renderer(swc.shm->renderer);
240 error1:
241 wld_destroy_context(swc.shm->context);
242 error0:
243@@ -48,6 +257,7 @@ bool swc_shm_initialize()
244
245 void swc_shm_finalize()
246 {
247+ wl_global_destroy(shm.global);
248 wld_destroy_renderer(swc.shm->renderer);
249 wld_destroy_context(swc.shm->context);
250 }
+0,
-74
1@@ -29,12 +29,6 @@
2 #include <wld/wld.h>
3 #include <wld/pixman.h>
4
5-struct wayland_buffer
6-{
7- struct wld_buffer * wld;
8- struct wl_listener destroy_listener;
9-};
10-
11 static void destroy(struct wl_client * client, struct wl_resource * resource)
12 {
13 wl_resource_destroy(resource);
14@@ -44,30 +38,6 @@ static const struct wl_buffer_interface buffer_implementation = {
15 .destroy = &destroy
16 };
17
18-/* NOTE: Needed because the implementation for SHM buffers comes from
19- * libwayland-server. */
20-static void handle_buffer_destroy(struct wl_listener * listener, void * data)
21-{
22- struct wayland_buffer * buffer
23- = CONTAINER_OF(listener, typeof(*buffer), destroy_listener);
24-
25- wld_buffer_unreference(buffer->wld);
26- free(buffer);
27-}
28-
29-static inline uint32_t format_shm_to_wld(uint32_t format)
30-{
31- switch (format)
32- {
33- case WL_SHM_FORMAT_ARGB8888:
34- return WLD_FORMAT_ARGB8888;
35- case WL_SHM_FORMAT_XRGB8888:
36- return WLD_FORMAT_XRGB8888;
37- default:
38- return format;
39- }
40-}
41-
42 struct wld_buffer * swc_wayland_buffer_get(struct wl_resource * resource)
43 {
44 if (wl_resource_instance_of(resource, &wl_buffer_interface,
45@@ -76,50 +46,6 @@ struct wld_buffer * swc_wayland_buffer_get(struct wl_resource * resource)
46 return wl_resource_get_user_data(resource);
47 }
48
49- struct wl_listener * listener;
50- struct wayland_buffer * buffer;
51-
52- listener = wl_resource_get_destroy_listener(resource,
53- &handle_buffer_destroy);
54-
55- if (listener)
56- {
57- buffer = CONTAINER_OF(listener, typeof(*buffer), destroy_listener);
58-
59- return buffer->wld;
60- }
61-
62- if (!(buffer = malloc(sizeof *buffer)))
63- goto error0;
64-
65- struct wl_shm_buffer * shm_buffer;
66-
67- if ((shm_buffer = wl_shm_buffer_get(resource)))
68- {
69- union wld_object object = {
70- .ptr = wl_shm_buffer_get_data(shm_buffer)
71- };
72-
73- buffer->wld = wld_import_buffer
74- (swc.shm->context, WLD_OBJECT_DATA, object,
75- wl_shm_buffer_get_width(shm_buffer),
76- wl_shm_buffer_get_height(shm_buffer),
77- format_shm_to_wld(wl_shm_buffer_get_format(shm_buffer)),
78- wl_shm_buffer_get_stride(shm_buffer));
79- }
80-
81- if (!buffer->wld)
82- goto error1;
83-
84- buffer->destroy_listener.notify = &handle_buffer_destroy;
85- wl_resource_add_destroy_listener(resource,
86- &buffer->destroy_listener);
87-
88- return buffer->wld;
89-
90- error1:
91- free(buffer);
92- error0:
93 return NULL;
94 }
95