commit 029cdb9
Michael Forney
·
2019-08-28 22:00:04 +0000 UTC
parent f0e0669
Implement linux-dmabuf protocol
6 files changed,
+259,
-3
+1,
-0
1@@ -8,6 +8,7 @@ protocol/wayland-drm-protocol.c
2 protocol/wayland-drm-server-protocol.h
3 protocol/xdg-shell-protocol.c
4 protocol/xdg-shell-server-protocol.h
5+protocol/linux-dmabuf-unstable-v1-server-protocol.h
6
7 /.deps/
8 /swc.pc
+214,
-0
1@@ -0,0 +1,214 @@
2+/* swc: dmabuf.c
3+ *
4+ * Copyright (c) 2019 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#include "dmabuf.h"
26+#include "drm.h"
27+#include "internal.h"
28+#include "util.h"
29+#include "wayland_buffer.h"
30+
31+#include <stdint.h>
32+#include <stdlib.h>
33+#include <drm_fourcc.h>
34+#include <unistd.h>
35+#include <wld/wld.h>
36+#include <wld/drm.h>
37+#include "linux-dmabuf-unstable-v1-server-protocol.h"
38+
39+struct params {
40+ struct wl_resource *resource;
41+ int fd[4];
42+ uint32_t offset[4];
43+ uint32_t stride[4];
44+ uint64_t modifier[4];
45+ bool created;
46+};
47+
48+static void
49+destroy(struct wl_client *client, struct wl_resource *resource)
50+{
51+ wl_resource_destroy(resource);
52+}
53+
54+static void
55+add(struct wl_client *client, struct wl_resource *resource, int32_t fd, uint32_t i, uint32_t offset, uint32_t stride, uint32_t modifier_hi, uint32_t modifier_lo)
56+{
57+ struct params *params = wl_resource_get_user_data(resource);
58+
59+ if (params->created) {
60+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "buffer already created");
61+ return;
62+ }
63+ if (i > ARRAY_LENGTH(params->fd)) {
64+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, "plane index too large");
65+ return;
66+ }
67+ if (params->fd[i] != -1) {
68+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET, "buffer plane already set");
69+ return;
70+ }
71+ params->fd[i] = fd;
72+ params->offset[i] = offset;
73+ params->stride[i] = stride;
74+ params->modifier[i] = (uint64_t)modifier_hi << 32 | modifier_lo;
75+}
76+
77+static void
78+create_immed(struct wl_client *client, struct wl_resource *resource, uint32_t id,
79+ int32_t width, int32_t height, uint32_t format, uint32_t flags)
80+{
81+ struct params *params = wl_resource_get_user_data(resource);
82+ struct wld_buffer *buffer;
83+ struct wl_resource *buffer_resource;
84+ union wld_object object;
85+ int num_planes, i;
86+
87+ if (params->created) {
88+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "buffer already created");
89+ return;
90+ }
91+ params->created = true;
92+ switch (format) {
93+ case DRM_FORMAT_XRGB8888:
94+ case DRM_FORMAT_ARGB8888:
95+ num_planes = 1;
96+ break;
97+ default:
98+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "unsupported format %#" PRIx32, format);
99+ return;
100+ }
101+ for (i = 0; i < num_planes; ++i) {
102+ if (params->fd[i] == -1)
103+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "missing plane %d", i);
104+ }
105+ for (; i < ARRAY_LENGTH(params->fd); ++i) {
106+ if (params->fd[i] != -1)
107+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "too many planes");
108+ }
109+ object.i = params->fd[0];
110+ buffer = wld_import_buffer(swc.drm->context, WLD_DRM_OBJECT_PRIME_FD, object, width, height, format, params->stride[0]);
111+ for (i = 0; i < num_planes; ++i) {
112+ close(params->fd[i]);
113+ params->fd[i] = -1;
114+ }
115+ if (!buffer)
116+ zwp_linux_buffer_params_v1_send_failed(resource);
117+
118+ buffer_resource = wayland_buffer_create_resource(client, 1, id, buffer);
119+ if (!buffer_resource) {
120+ if (buffer)
121+ wld_buffer_unreference(buffer);
122+ wl_resource_post_no_memory(resource);
123+ return;
124+ }
125+ if (id == 0 && buffer)
126+ zwp_linux_buffer_params_v1_send_created(resource, buffer_resource);
127+}
128+
129+static void
130+create(struct wl_client *client, struct wl_resource *resource,
131+ int32_t width, int32_t height, uint32_t format, uint32_t flags)
132+{
133+ create_immed(client, resource, 0, width, height, format, flags);
134+}
135+
136+static const struct zwp_linux_buffer_params_v1_interface params_impl = {
137+ .destroy = destroy,
138+ .add = add,
139+ .create = create,
140+ .create_immed = create_immed,
141+};
142+
143+static void
144+params_destroy(struct wl_resource *resource)
145+{
146+ struct params *params = wl_resource_get_user_data(resource);
147+ int i;
148+
149+ for (i = 0; i < ARRAY_LENGTH(params->fd); ++i)
150+ close(params->fd[i]);
151+}
152+
153+static void
154+create_params(struct wl_client *client, struct wl_resource *resource, uint32_t id)
155+{
156+ struct params *params;
157+ int i;
158+
159+ params = malloc(sizeof(*params));
160+ if (!params)
161+ goto error0;
162+ params->created = false;
163+ params->resource = wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, wl_resource_get_version(resource), id);
164+ if (!params->resource)
165+ goto error1;
166+ for (i = 0; i < ARRAY_LENGTH(params->fd); ++i)
167+ params->fd[i] = -1;
168+ wl_resource_set_implementation(params->resource, ¶ms_impl, params, params_destroy);
169+ return;
170+
171+error1:
172+ free(params);
173+error0:
174+ wl_resource_post_no_memory(resource);
175+}
176+
177+static const struct zwp_linux_dmabuf_v1_interface dmabuf_impl = {
178+ .destroy = destroy,
179+ .create_params = create_params,
180+};
181+
182+static void
183+bind_dmabuf(struct wl_client *client, void *data, uint32_t version, uint32_t id)
184+{
185+ static const uint32_t formats[] = {
186+ DRM_FORMAT_XRGB8888,
187+ DRM_FORMAT_ARGB8888,
188+ };
189+ uint64_t modifier = DRM_FORMAT_MOD_INVALID;
190+ struct wl_resource *resource;
191+ size_t i;
192+
193+ if (version > 3)
194+ version = 3;
195+ resource = wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, version, id);
196+ if (!resource) {
197+ wl_client_post_no_memory(client);
198+ return;
199+ }
200+ wl_resource_set_implementation(resource, &dmabuf_impl, NULL, NULL);
201+ for (i = 0; i < ARRAY_LENGTH(formats); ++i) {
202+ if (version >= 3) {
203+ /* TODO: need a way to query DRM modifiers of wld */
204+ zwp_linux_dmabuf_v1_send_modifier(resource, formats[i], modifier >> 32, modifier & 0xffffffff);
205+ } else {
206+ zwp_linux_dmabuf_v1_send_format(resource, formats[i]);
207+ }
208+ }
209+}
210+
211+struct wl_global *
212+swc_dmabuf_create(struct wl_display *display)
213+{
214+ return wl_global_create(display, &zwp_linux_dmabuf_v1_interface, 3, NULL, &bind_dmabuf);
215+}
+31,
-0
1@@ -0,0 +1,31 @@
2+/* swc: libswc/dmabuf.h
3+ *
4+ * Copyright (c) 2019 Michael Forney
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef SWC_DMABUF_H
26+#define SWC_DMABUF_H
27+
28+struct wl_display;
29+
30+struct wl_global *swc_dmabuf_create(struct wl_display *display);
31+
32+#endif
+7,
-1
1@@ -22,6 +22,7 @@
2 */
3
4 #include "drm.h"
5+#include "dmabuf.h"
6 #include "event.h"
7 #include "internal.h"
8 #include "launch.h"
9@@ -53,6 +54,7 @@ static struct {
10 uint32_t taken_ids;
11
12 struct wl_global *global;
13+ struct wl_global *dmabuf;
14 struct wl_event_source *event_source;
15 } drm;
16
17@@ -299,11 +301,15 @@ drm_initialize(void)
18
19 if (!wld_drm_is_dumb(swc.drm->context)) {
20 drm.global = wl_global_create(swc.display, &wl_drm_interface, 2, NULL, &bind_drm);
21-
22 if (!drm.global) {
23 ERROR("Could not create wl_drm global\n");
24 goto error4;
25 }
26+
27+ drm.dmabuf = swc_dmabuf_create(swc.display);
28+ if (!drm.dmabuf) {
29+ WARNING("Could not create wp_linux_dmabuf global\n");
30+ }
31 }
32
33 return true;
+4,
-1
1@@ -28,6 +28,7 @@ SWC_SOURCES = \
2 libswc/data.c \
3 libswc/data_device.c \
4 libswc/data_device_manager.c \
5+ libswc/dmabuf.c \
6 libswc/drm.c \
7 libswc/input.c \
8 libswc/keyboard.c \
9@@ -55,7 +56,8 @@ SWC_SOURCES = \
10 libswc/xdg_shell.c \
11 protocol/swc-protocol.c \
12 protocol/wayland-drm-protocol.c \
13- protocol/xdg-shell-protocol.c
14+ protocol/xdg-shell-protocol.c \
15+ protocol/linux-dmabuf-unstable-v1-protocol.c
16
17 ifeq ($(ENABLE_LIBUDEV),1)
18 $(dir)_CFLAGS += -DENABLE_LIBUDEV
19@@ -68,6 +70,7 @@ SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo)
20 # Explicitly state dependencies on generated files
21 objects = $(foreach obj,$(1),$(dir)/$(obj).o $(dir)/$(obj).lo)
22 $(call objects,compositor panel_manager panel screen): protocol/swc-server-protocol.h
23+$(call objects,dmabuf): protocol/linux-dmabuf-unstable-v1-server-protocol.h
24 $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h
25 $(call objects,xdg_shell): protocol/xdg-shell-server-protocol.h
26 $(call objects,pointer): cursor/cursor_data.h
+2,
-1
1@@ -6,7 +6,8 @@ wayland_protocols := $(call pkgconfig,wayland-protocols,variable=pkgdatadir,DATA
2 PROTOCOL_EXTENSIONS = \
3 $(dir)/swc.xml \
4 $(dir)/wayland-drm.xml \
5- $(wayland_protocols)/stable/xdg-shell/xdg-shell.xml
6+ $(wayland_protocols)/stable/xdg-shell/xdg-shell.xml \
7+ $(wayland_protocols)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
8
9 $(dir)_PACKAGES := wayland-server
10