xref: /OK3568_Linux_fs/buildroot/package/weston/0021-pixman-renderer-Support-linux-dmabuf.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From a2b9d85182c9089e27ecf02c4f3fecd7a8006bce Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Fri, 3 Jul 2020 14:43:49 +0800
4Subject: [PATCH 21/95] pixman-renderer: Support linux dmabuf
5
6NOTE: Only support contig dmabuf.
7
8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
9---
10 libweston/pixman-renderer.c | 287 +++++++++++++++++++++++++++++++++++-
11 1 file changed, 281 insertions(+), 6 deletions(-)
12
13diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c
14index 62c2cb1..07b7888 100644
15--- a/libweston/pixman-renderer.c
16+++ b/libweston/pixman-renderer.c
17@@ -37,9 +37,16 @@
18 #include "pixel-formats.h"
19 #include "shared/helpers.h"
20 #include "shared/signal.h"
21+#include "shared/weston-drm-fourcc.h"
22
23+#include <string.h>
24+#include <unistd.h>
25+#include <sys/mman.h>
26 #include <linux/input.h>
27
28+#include "linux-dmabuf.h"
29+#include "linux-dmabuf-unstable-v1-server-protocol.h"
30+
31 struct pixman_output_state {
32 	pixman_image_t *shadow_image;
33 	pixman_image_t *hw_buffer;
34@@ -66,6 +73,13 @@ struct pixman_renderer {
35 	struct weston_binding *debug_binding;
36
37 	struct wl_signal destroy_signal;
38+
39+	struct weston_drm_format_array supported_formats;
40+};
41+
42+struct dmabuf_data {
43+	void *ptr;
44+	size_t size;
45 };
46
47 static inline struct pixman_output_state *
48@@ -350,7 +364,8 @@ repaint_region(struct weston_view *ev, struct weston_output *output,
49 	else
50 		filter = PIXMAN_FILTER_NEAREST;
51
52-	if (ps->buffer_ref.buffer)
53+	if (ps->buffer_ref.buffer &&
54+	    ps->buffer_ref.buffer->type == WESTON_BUFFER_SHM)
55 		wl_shm_buffer_begin_access(ps->buffer_ref.buffer->shm_buffer);
56
57 	if (ev->alpha < 1.0) {
58@@ -370,7 +385,8 @@ repaint_region(struct weston_view *ev, struct weston_output *output,
59 	if (mask_image)
60 		pixman_image_unref(mask_image);
61
62-	if (ps->buffer_ref.buffer)
63+	if (ps->buffer_ref.buffer &&
64+	    ps->buffer_ref.buffer->type == WESTON_BUFFER_SHM)
65 		wl_shm_buffer_end_access(ps->buffer_ref.buffer->shm_buffer);
66
67 	if (pr->repaint_debug)
68@@ -653,11 +669,114 @@ pixman_renderer_surface_set_color(struct weston_surface *es,
69 	ps->image = pixman_image_create_solid_fill(&color);
70 }
71
72+static void
73+pixman_renderer_attach_dmabuf(struct weston_surface *es,
74+			      struct weston_buffer *buffer,
75+			      struct linux_dmabuf_buffer *dmabuf)
76+{
77+	struct pixman_surface_state *ps = get_surface_state(es);
78+	struct dmabuf_attributes *attributes = &dmabuf->attributes;
79+	struct dmabuf_data *data;
80+	pixman_format_code_t pixman_format;
81+	size_t vstride;
82+
83+	data = linux_dmabuf_buffer_get_user_data(dmabuf);
84+	if (!data || !data->ptr) {
85+		weston_buffer_reference(&ps->buffer_ref, NULL,
86+					BUFFER_WILL_NOT_BE_ACCESSED);
87+		weston_buffer_release_reference(&ps->buffer_release_ref,
88+						NULL);
89+		return;
90+	}
91+
92+	buffer->width = attributes->width;
93+	buffer->height = attributes->height;
94+
95+	if (attributes->n_planes == 1)
96+		vstride = attributes->height;
97+	else
98+		vstride = (attributes->offset[1] - attributes->offset[0]) /
99+			attributes->stride[0];
100+
101+	switch (attributes->format) {
102+	case DRM_FORMAT_RGBA8888:
103+		pixman_format = PIXMAN_r8g8b8a8;
104+		break;
105+	case DRM_FORMAT_RGBX8888:
106+		pixman_format = PIXMAN_r8g8b8x8;
107+		break;
108+	case DRM_FORMAT_BGRA8888:
109+		pixman_format = PIXMAN_b8g8r8a8;
110+		break;
111+	case DRM_FORMAT_BGRX8888:
112+		pixman_format = PIXMAN_b8g8r8x8;
113+		break;
114+	case DRM_FORMAT_ABGR8888:
115+		pixman_format = PIXMAN_a8b8g8r8;
116+		break;
117+	case DRM_FORMAT_XBGR8888:
118+		pixman_format = PIXMAN_x8b8g8r8;
119+		break;
120+	case DRM_FORMAT_BGR888:
121+		pixman_format = PIXMAN_b8g8r8;
122+		break;
123+	case DRM_FORMAT_ARGB8888:
124+		pixman_format = PIXMAN_a8r8g8b8;
125+		break;
126+	case DRM_FORMAT_XRGB8888:
127+		pixman_format = PIXMAN_x8r8g8b8;
128+		break;
129+	case DRM_FORMAT_RGB888:
130+		pixman_format = PIXMAN_r8g8b8;
131+		break;
132+	case DRM_FORMAT_YUYV:
133+		pixman_format = PIXMAN_yuy2;
134+		break;
135+	case DRM_FORMAT_YVU420:
136+		pixman_format = PIXMAN_yv12;
137+		break;
138+#ifdef HAVE_PIXMAN_I420
139+	case DRM_FORMAT_YUV420:
140+		pixman_format = PIXMAN_i420;
141+		break;
142+#endif
143+#ifdef HAVE_PIXMAN_NV12
144+	case DRM_FORMAT_NV12:
145+		pixman_format = PIXMAN_nv12;
146+		break;
147+#endif
148+#ifdef HAVE_PIXMAN_NV16
149+	case DRM_FORMAT_NV16:
150+		pixman_format = PIXMAN_nv16;
151+		break;
152+#endif
153+	default:
154+		weston_log("Unsupported dmabuf format\n");
155+		weston_buffer_reference(&ps->buffer_ref, NULL,
156+					BUFFER_WILL_NOT_BE_ACCESSED);
157+		weston_buffer_release_reference(&ps->buffer_release_ref,
158+						NULL);
159+		return;
160+	break;
161+	}
162+
163+	ps->image = pixman_image_create_bits(pixman_format,
164+					     buffer->width, vstride,
165+					     data->ptr + attributes->offset[0],
166+					     attributes->stride[0]);
167+
168+	ps->buffer_destroy_listener.notify =
169+		buffer_state_handle_buffer_destroy;
170+	wl_signal_add(&buffer->destroy_signal,
171+		      &ps->buffer_destroy_listener);
172+}
173+
174 static void
175 pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
176 {
177 	struct pixman_surface_state *ps = get_surface_state(es);
178 	struct wl_shm_buffer *shm_buffer;
179+	struct linux_dmabuf_buffer *dmabuf;
180 	const struct pixel_format_info *pixel_info;
181
182 	weston_buffer_reference(&ps->buffer_ref, buffer,
183@@ -692,10 +811,16 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
184 	}
185
186 	if (buffer->type != WESTON_BUFFER_SHM) {
187-		weston_log("Pixman renderer supports only SHM buffers\n");
188-		weston_buffer_reference(&ps->buffer_ref, NULL,
189-					BUFFER_WILL_NOT_BE_ACCESSED);
190-		weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
191+		if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) {
192+			pixman_renderer_attach_dmabuf(es, buffer, dmabuf);
193+		} else {
194+			weston_log("unhandled buffer type!\n");
195+			weston_buffer_reference(&ps->buffer_ref, NULL,
196+						BUFFER_WILL_NOT_BE_ACCESSED);
197+			weston_buffer_release_reference(&ps->buffer_release_ref,
198+							NULL);
199+		}
200+
201 		return;
202 	}
203
204@@ -792,6 +917,9 @@ pixman_renderer_create_surface(struct weston_surface *surface)
205 	wl_signal_add(&pr->destroy_signal,
206 		      &ps->renderer_destroy_listener);
207
208+	if (surface->buffer_ref.buffer)
209+		pixman_renderer_attach(surface, surface->buffer_ref.buffer);
210+
211 	return 0;
212 }
213
214@@ -802,6 +930,9 @@ pixman_renderer_destroy(struct weston_compositor *ec)
215
216 	wl_signal_emit(&pr->destroy_signal, pr);
217 	weston_binding_destroy(pr->debug_binding);
218+
219+	weston_drm_format_array_fini(&pr->supported_formats);
220+
221 	free(pr);
222
223 	ec->renderer = NULL;
224@@ -860,12 +991,142 @@ debug_binding(struct weston_keyboard *keyboard, const struct timespec *time,
225 	}
226 }
227
228+static void
229+pixman_renderer_destroy_dmabuf(struct linux_dmabuf_buffer *dmabuf)
230+{
231+	struct dmabuf_data *data = dmabuf->user_data;
232+	linux_dmabuf_buffer_set_user_data(dmabuf, NULL, NULL);
233+
234+	if (data) {
235+		if (data->ptr)
236+			munmap(data->ptr, data->size);
237+
238+		free(data);
239+	}
240+}
241+
242+static bool
243+pixman_renderer_import_dmabuf(struct weston_compositor *ec,
244+			      struct linux_dmabuf_buffer *dmabuf)
245+{
246+	struct dmabuf_attributes *attributes = &dmabuf->attributes;
247+	struct dmabuf_data *data;
248+	size_t total_size, vstride0;
249+	int i;
250+
251+	for (i = 0; i < attributes->n_planes; i++) {
252+		if (attributes->modifier[i] != DRM_FORMAT_MOD_INVALID &&
253+		    attributes->modifier[i] != DRM_FORMAT_MOD_LINEAR)
254+			return false;
255+	}
256+
257+	/* reject all flags we do not recognize or handle */
258+	if (attributes->flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT)
259+		return false;
260+
261+	if (attributes->n_planes < 0)
262+		return false;
263+
264+	if (attributes->n_planes == 1)
265+		goto out;
266+
267+	total_size = lseek(attributes->fd[0], 0, SEEK_END);
268+	vstride0 = (attributes->offset[1] - attributes->offset[0]) /
269+		attributes->stride[0];
270+
271+	for (i = 1; i < attributes->n_planes; i++) {
272+		size_t size = attributes->offset[i] - attributes->offset[i - 1];
273+		size_t vstride = size / attributes->stride[i - 1];
274+
275+		/* not contig */
276+		if (size <= 0 || vstride <= 0 ||
277+		    attributes->offset[i - 1] + size > total_size)
278+			return false;
279+
280+		/* stride unmatched */
281+		if ((vstride != vstride0 && vstride != vstride0 / 2) ||
282+		    (attributes->stride[i] != attributes->stride[0] &&
283+		     attributes->stride[i] != attributes->stride[0] / 2))
284+			return false;
285+	}
286+
287+out:
288+	/* Handle contig dma buffer */
289+
290+	data = zalloc(sizeof *data);
291+	if (!data)
292+		return false;
293+
294+	linux_dmabuf_buffer_set_user_data(dmabuf, data,
295+					  pixman_renderer_destroy_dmabuf);
296+
297+	data->size = lseek(attributes->fd[0], 0, SEEK_END);
298+
299+	data->ptr = mmap(NULL, data->size, PROT_READ,
300+			 MAP_SHARED, attributes->fd[0], 0);
301+	return data->ptr != MAP_FAILED;
302+}
303+
304+static const struct weston_drm_format_array *
305+pixman_renderer_get_supported_formats(struct weston_compositor *ec)
306+{
307+	struct pixman_renderer *pr = get_renderer(ec);
308+
309+	return &pr->supported_formats;
310+}
311+
312+static int
313+populate_supported_formats(struct weston_compositor *ec,
314+			   struct weston_drm_format_array *supported_formats)
315+{
316+	struct weston_drm_format *fmt;
317+	int i, ret = 0;
318+
319+	/* TODO: support more formats */
320+	static const int formats[] = {
321+		DRM_FORMAT_ARGB8888,
322+		DRM_FORMAT_XRGB8888,
323+		DRM_FORMAT_RGBA8888,
324+		DRM_FORMAT_RGBX8888,
325+		DRM_FORMAT_ABGR8888,
326+		DRM_FORMAT_XBGR8888,
327+		DRM_FORMAT_BGRA8888,
328+		DRM_FORMAT_BGRX8888,
329+		DRM_FORMAT_YUYV,
330+		DRM_FORMAT_YVU420,
331+		DRM_FORMAT_YUV420,
332+		DRM_FORMAT_NV12,
333+		DRM_FORMAT_NV16,
334+	};
335+
336+	int num_formats = ARRAY_LENGTH(formats);
337+
338+	for (i = 0; i < num_formats; i++) {
339+		fmt = weston_drm_format_array_add_format(supported_formats,
340+							 formats[i]);
341+		if (!fmt) {
342+			ret = -1;
343+			goto out;
344+		}
345+
346+		/* Always add DRM_FORMAT_MOD_INVALID, as EGL implementations
347+		 * support implicit modifiers. */
348+		ret = weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_INVALID);
349+		if (ret < 0)
350+			goto out;
351+	}
352+
353+out:
354+	return ret;
355+}
356+
357 WL_EXPORT int
358 pixman_renderer_init(struct weston_compositor *ec)
359 {
360 	struct pixman_renderer *renderer;
361 	const struct pixel_format_info *pixel_info, *info_argb8888, *info_xrgb8888;
362 	unsigned int i, num_formats;
363+	int ret;
364
365 	renderer = zalloc(sizeof *renderer);
366 	if (renderer == NULL)
367@@ -884,6 +1145,15 @@ pixman_renderer_init(struct weston_compositor *ec)
368 	ec->capabilities |= WESTON_CAP_ROTATION_ANY;
369 	ec->capabilities |= WESTON_CAP_VIEW_CLIP_MASK;
370
371+	weston_drm_format_array_init(&renderer->supported_formats);
372+
373+	ret = populate_supported_formats(ec, &renderer->supported_formats);
374+	if (ret < 0) {
375+		weston_drm_format_array_fini(&renderer->supported_formats);
376+		free(renderer);
377+		return -1;
378+	}
379+
380 	renderer->debug_binding =
381 		weston_compositor_add_debug_binding(ec, KEY_R,
382 						    debug_binding, ec);
383@@ -906,6 +1176,11 @@ pixman_renderer_init(struct weston_compositor *ec)
384
385 	wl_signal_init(&renderer->destroy_signal);
386
387+	renderer->base.import_dmabuf = pixman_renderer_import_dmabuf;
388+
389+	renderer->base.get_supported_formats =
390+		pixman_renderer_get_supported_formats;
391+
392 	return 0;
393 }
394
395--
3962.20.1
397
398