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, &params_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