1From 0f3dea67852b76216bfe1f8ea59274513000a1a9 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Fri, 3 Jul 2020 14:53:52 +0800
4Subject: [PATCH 22/79] HACK: pixman-renderer: Support mali egl client and egl
5 buffer attaching
6
7The mali clients requires mali_buffer_sharing extension, and it needs
8lots of hacks to attach a wl_buffer created in that way.
9
10Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
11---
12 libweston/meson.build       |  10 +-
13 libweston/pixman-renderer.c | 365 ++++++++++++++++++++++++++++--------
14 2 files changed, 290 insertions(+), 85 deletions(-)
15
16diff --git a/libweston/meson.build b/libweston/meson.build
17index 257d695..a73e932 100644
18--- a/libweston/meson.build
19+++ b/libweston/meson.build
20@@ -70,12 +70,10 @@ srcs_libweston = [
21 	weston_direct_display_server_protocol_h,
22 ]
23
24-if get_option('renderer-gl')
25-	dep_egl = dependency('egl', required: false)
26-	if not dep_egl.found()
27-		error('libweston + gl-renderer requires egl which was not found. Or, you can use \'-Drenderer-gl=false\'.')
28-	endif
29-	deps_libweston += dep_egl
30+dep_egl = dependency('egl', required: false)
31+dep_gbm = dependency('gbm', required: false)
32+if dep_egl.found() and dep_gbm.found()
33+	deps_libweston += [ dep_egl, dep_gbm ]
34 endif
35
36 lib_weston = shared_library(
37diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c
38index d5c5422..ece4d91 100644
39--- a/libweston/pixman-renderer.c
40+++ b/libweston/pixman-renderer.c
41@@ -46,6 +46,19 @@
42 #include "linux-dmabuf.h"
43 #include "linux-dmabuf-unstable-v1-server-protocol.h"
44
45+#ifdef ENABLE_EGL
46+#include <fcntl.h>
47+#include <sys/stat.h>
48+
49+#include <gbm.h>
50+#include <EGL/egl.h>
51+#include <EGL/eglext.h>
52+#include <GLES2/gl2.h>
53+#include <GLES2/gl2ext.h>
54+#include "shared/platform.h"
55+#include "shared/weston-egl-ext.h"  /* for PFN* stuff */
56+#endif
57+
58 struct pixman_output_state {
59 	void *shadow_buffer;
60 	pixman_image_t *shadow_image;
61@@ -75,6 +88,18 @@ struct pixman_renderer {
62 	struct wl_signal destroy_signal;
63
64 	struct weston_drm_format_array supported_formats;
65+
66+#ifdef ENABLE_EGL
67+	PFNEGLBINDWAYLANDDISPLAYWL bind_display;
68+	PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
69+	PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
70+	EGLDisplay egl_display;
71+
72+	int drm_fd;
73+	struct gbm_device *gbm;
74+
75+	bool egl_inited;
76+#endif
77 };
78
79 struct dmabuf_data {
80@@ -82,6 +107,16 @@ struct dmabuf_data {
81 	size_t size;
82 };
83
84+#ifdef ENABLE_EGL
85+/* HACK: For mali_buffer_sharing */
86+struct egl_buffer_info {
87+	int dma_fd;
88+	int width;
89+	int height;
90+	unsigned int stride;
91+};
92+#endif
93+
94 static inline struct pixman_output_state *
95 get_output_state(struct weston_output *output)
96 {
97@@ -636,6 +671,90 @@ buffer_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
98 	ps->buffer_destroy_listener.notify = NULL;
99 }
100
101+static void
102+pixman_renderer_destroy_dmabuf(struct linux_dmabuf_buffer *dmabuf)
103+{
104+	struct dmabuf_data *data = dmabuf->user_data;
105+	linux_dmabuf_buffer_set_user_data(dmabuf, NULL, NULL);
106+
107+	if (data) {
108+		if (data->ptr)
109+			munmap(data->ptr, data->size);
110+
111+		free(data);
112+	}
113+}
114+
115+static bool
116+pixman_renderer_prepare_dmabuf(struct linux_dmabuf_buffer *dmabuf)
117+{
118+	struct dmabuf_attributes *attributes = &dmabuf->attributes;
119+	struct dmabuf_data *data;
120+	size_t total_size, vstride0;
121+	void *ptr;
122+	int i;
123+
124+	data = linux_dmabuf_buffer_get_user_data(dmabuf);
125+	if (data)
126+		return true;
127+
128+	total_size = lseek(attributes->fd[0], 0, SEEK_END);
129+
130+	for (i = 0; i < attributes->n_planes; i++) {
131+		if (attributes->modifier[i] != DRM_FORMAT_MOD_INVALID)
132+			return false;
133+	}
134+
135+	/* reject all flags we do not recognize or handle */
136+	if (attributes->flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT)
137+		return false;
138+
139+	if (attributes->n_planes < 0)
140+		return false;
141+
142+	if (attributes->n_planes == 1)
143+		goto out;
144+
145+	vstride0 = (attributes->offset[1] - attributes->offset[0]) /
146+		attributes->stride[0];
147+
148+	for (i = 1; i < attributes->n_planes; i++) {
149+		size_t size = attributes->offset[i] - attributes->offset[i - 1];
150+		size_t vstride = size / attributes->stride[i - 1];
151+
152+		/* not contig */
153+		if (size <= 0 || vstride <= 0 ||
154+		    attributes->offset[i - 1] + size > total_size)
155+			return false;
156+
157+		/* stride unmatched */
158+		if ((vstride != vstride0 && vstride != vstride0 / 2) ||
159+		    (attributes->stride[i] != attributes->stride[0] &&
160+		     attributes->stride[i] != attributes->stride[0] / 2))
161+			return false;
162+	}
163+
164+out:
165+	/* Handle contig dma buffer */
166+
167+	ptr = mmap(NULL, total_size, PROT_READ,
168+		   MAP_SHARED, attributes->fd[0], 0);
169+	if (!ptr)
170+		return false;
171+
172+	data = zalloc(sizeof *data);
173+	if (!data) {
174+		munmap(ptr, total_size);
175+		return false;
176+	}
177+
178+	data->size = total_size;
179+	data->ptr = ptr;
180+	linux_dmabuf_buffer_set_user_data(dmabuf, data,
181+					  pixman_renderer_destroy_dmabuf);
182+	return true;
183+}
184+
185 static void
186 pixman_renderer_attach_dmabuf(struct weston_surface *es,
187 			      struct weston_buffer *buffer,
188@@ -647,13 +766,12 @@ pixman_renderer_attach_dmabuf(struct weston_surface *es,
189 	pixman_format_code_t pixman_format;
190 	size_t vstride;
191
192+	if (!pixman_renderer_prepare_dmabuf(dmabuf))
193+		goto err;
194+
195 	data = linux_dmabuf_buffer_get_user_data(dmabuf);
196-	if (!data || !data->ptr) {
197-		weston_buffer_reference(&ps->buffer_ref, NULL);
198-		weston_buffer_release_reference(&ps->buffer_release_ref,
199-						NULL);
200-		return;
201-	}
202+	if (!data || !data->ptr)
203+		goto err;
204
205 	buffer->width = attributes->width;
206 	buffer->height = attributes->height;
207@@ -694,10 +812,7 @@ pixman_renderer_attach_dmabuf(struct weston_surface *es,
208 #endif
209 	default:
210 		weston_log("Unsupported dmabuf format\n");
211-		weston_buffer_reference(&ps->buffer_ref, NULL);
212-		weston_buffer_release_reference(&ps->buffer_release_ref,
213-						NULL);
214-		return;
215+		goto err;
216 	break;
217 	}
218
219@@ -710,16 +825,25 @@ pixman_renderer_attach_dmabuf(struct weston_surface *es,
220 		buffer_state_handle_buffer_destroy;
221 	wl_signal_add(&buffer->destroy_signal,
222 		      &ps->buffer_destroy_listener);
223+	return;
224+err:
225+	weston_buffer_reference(&ps->buffer_ref, NULL);
226+	weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
227 }
228
229 static void
230 pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
231 {
232+	struct pixman_renderer *pr = get_renderer(es->compositor);
233 	struct pixman_surface_state *ps = get_surface_state(es);
234 	struct wl_shm_buffer *shm_buffer;
235 	struct linux_dmabuf_buffer *dmabuf;
236 	const struct pixel_format_info *pixel_info;
237
238+#ifdef ENABLE_EGL
239+	EGLint format;
240+#endif
241+
242 	weston_buffer_reference(&ps->buffer_ref, buffer);
243 	weston_buffer_release_reference(&ps->buffer_release_ref,
244 					es->buffer_release_ref.buffer_release);
245@@ -742,7 +866,56 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
246 	if (! shm_buffer) {
247 		if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) {
248 			pixman_renderer_attach_dmabuf(es, buffer, dmabuf);
249+#ifdef ENABLE_EGL
250+		} else if (pr->egl_inited &&
251+			   pr->query_buffer(pr->egl_display,
252+					    (void *)buffer->resource,
253+					    EGL_TEXTURE_FORMAT, &format)){
254+			struct egl_buffer_info *info;
255+			struct linux_dmabuf_buffer dmabuf = { 0 };
256+			struct dmabuf_attributes *attributes =
257+				&dmabuf.attributes;
258+			struct stat s;
259+			int width, height;
260+
261+			pr->query_buffer(pr->egl_display,
262+					 (void *)buffer->resource,
263+					 EGL_WIDTH, &width);
264+			pr->query_buffer(pr->egl_display,
265+					 (void *)buffer->resource,
266+					 EGL_HEIGHT, &height);
267+
268+			info = wl_resource_get_user_data(buffer->resource);
269+			if (!info)
270+				goto err;
271+
272+			if (fstat(info->dma_fd, &s) < 0 ||
273+			    info->width != width || info->height != height)
274+				goto err;
275+
276+			switch (format) {
277+			case EGL_TEXTURE_RGB:
278+				attributes->format = DRM_FORMAT_RGB888;
279+				break;
280+			case EGL_TEXTURE_RGBA:
281+				attributes->format = DRM_FORMAT_ARGB8888;
282+				break;
283+			default:
284+				goto err;
285+			}
286+
287+			attributes->n_planes = 1;
288+			attributes->fd[0] = info->dma_fd;
289+			attributes->width = info->width;
290+			attributes->height = info->height;
291+			attributes->stride[0] = info->stride;
292+
293+			pixman_renderer_attach_dmabuf(es, buffer, &dmabuf);
294+		} else {
295+err:
296+#else
297 		} else {
298+#endif
299 			weston_log("unhandled buffer type!\n");
300 			weston_buffer_reference(&ps->buffer_ref, NULL);
301 			weston_buffer_release_reference(&ps->buffer_release_ref,
302@@ -880,6 +1053,21 @@ pixman_renderer_destroy(struct weston_compositor *ec)
303 {
304 	struct pixman_renderer *pr = get_renderer(ec);
305
306+#ifdef ENABLE_EGL
307+	if (pr->egl_inited) {
308+		if (pr->unbind_display)
309+			pr->unbind_display(pr->egl_display, ec->wl_display);
310+
311+		eglTerminate(pr->egl_display);
312+		eglReleaseThread();
313+
314+		if (pr->gbm)
315+			gbm_device_destroy(pr->gbm);
316+
317+		close(pr->drm_fd);
318+	}
319+#endif
320+
321 	wl_signal_emit(&pr->destroy_signal, pr);
322 	weston_binding_destroy(pr->debug_binding);
323
324@@ -958,79 +1146,11 @@ debug_binding(struct weston_keyboard *keyboard, const struct timespec *time,
325 	}
326 }
327
328-static void
329-pixman_renderer_destroy_dmabuf(struct linux_dmabuf_buffer *dmabuf)
330-{
331-	struct dmabuf_data *data = dmabuf->user_data;
332-	linux_dmabuf_buffer_set_user_data(dmabuf, NULL, NULL);
333-
334-	if (data) {
335-		if (data->ptr)
336-			munmap(data->ptr, data->size);
337-
338-		free(data);
339-	}
340-}
341-
342 static bool
343 pixman_renderer_import_dmabuf(struct weston_compositor *ec,
344 			      struct linux_dmabuf_buffer *dmabuf)
345 {
346-	struct dmabuf_attributes *attributes = &dmabuf->attributes;
347-	struct dmabuf_data *data;
348-	size_t total_size, vstride0;
349-	int i;
350-
351-	for (i = 0; i < attributes->n_planes; i++) {
352-		if (attributes->modifier[i] != DRM_FORMAT_MOD_INVALID)
353-			return false;
354-	}
355-
356-	/* reject all flags we do not recognize or handle */
357-	if (attributes->flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT)
358-		return false;
359-
360-	if (attributes->n_planes < 0)
361-		return false;
362-
363-	if (attributes->n_planes == 1)
364-		goto out;
365-
366-	total_size = lseek(attributes->fd[0], 0, SEEK_END);
367-	vstride0 = (attributes->offset[1] - attributes->offset[0]) /
368-		attributes->stride[0];
369-
370-	for (i = 1; i < attributes->n_planes; i++) {
371-		size_t size = attributes->offset[i] - attributes->offset[i - 1];
372-		size_t vstride = size / attributes->stride[i - 1];
373-
374-		/* not contig */
375-		if (size <= 0 || vstride <= 0 ||
376-		    attributes->offset[i - 1] + size > total_size)
377-			return false;
378-
379-		/* stride unmatched */
380-		if ((vstride != vstride0 && vstride != vstride0 / 2) ||
381-		    (attributes->stride[i] != attributes->stride[0] &&
382-		     attributes->stride[i] != attributes->stride[0] / 2))
383-			return false;
384-	}
385-
386-out:
387-	/* Handle contig dma buffer */
388-
389-	data = zalloc(sizeof *data);
390-	if (!data)
391-		return false;
392-
393-	linux_dmabuf_buffer_set_user_data(dmabuf, data,
394-					  pixman_renderer_destroy_dmabuf);
395-
396-	data->size = lseek(attributes->fd[0], 0, SEEK_END);
397-
398-	data->ptr = mmap(NULL, data->size, PROT_READ,
399-			 MAP_SHARED, attributes->fd[0], 0);
400-	return data->ptr != MAP_FAILED;
401+	return pixman_renderer_prepare_dmabuf(dmabuf);
402 }
403
404 static const struct weston_drm_format_array *
405@@ -1086,6 +1206,89 @@ out:
406 	return ret;
407 }
408
409+#ifdef ENABLE_EGL
410+static bool
411+pixman_renderer_init_egl(struct pixman_renderer *pr,
412+			 struct weston_compositor *ec)
413+{
414+	PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display;
415+	const char *extensions;
416+
417+	get_platform_display =
418+		(void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
419+	pr->query_buffer =
420+		(void *) eglGetProcAddress("eglQueryWaylandBufferWL");
421+	pr->bind_display =
422+		(void *) eglGetProcAddress("eglBindWaylandDisplayWL");
423+	pr->unbind_display =
424+		(void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
425+
426+	if (!get_platform_display || !pr->query_buffer ||
427+	    !pr->bind_display || !pr->unbind_display) {
428+		weston_log("Failed to get egl proc\n");
429+		return false;
430+	}
431+
432+	pr->drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
433+	if (pr->drm_fd < 0) {
434+		weston_log("Failed to open drm dev\n");
435+		return false;
436+	}
437+
438+	pr->gbm = gbm_create_device(pr->drm_fd);
439+	if (!pr->gbm) {
440+		weston_log("Failed to create gbm device\n");
441+		goto err_close_fd;
442+	}
443+
444+	pr->egl_display = get_platform_display(EGL_PLATFORM_GBM_KHR,
445+					       (void*) pr->gbm, NULL);
446+	if (pr->egl_display == EGL_NO_DISPLAY) {
447+		weston_log("Failed to create egl display\n");
448+		goto err_destroy_gbm;
449+	}
450+
451+	if (!eglInitialize(pr->egl_display, NULL, NULL)) {
452+		weston_log("Failed to initialize egl\n");
453+		goto err_terminate_display;
454+	}
455+
456+	extensions =
457+		(const char *) eglQueryString(pr->egl_display, EGL_EXTENSIONS);
458+	if (!extensions) {
459+		weston_log("Retrieving EGL extension string failed.\n");
460+		goto err_terminate_display;
461+	}
462+
463+	if (!weston_check_egl_extension(extensions,
464+					"EGL_WL_bind_wayland_display")) {
465+		weston_log("Wayland extension not supported.\n");
466+		goto err_terminate_display;
467+	}
468+
469+	if (!eglBindAPI(EGL_OPENGL_ES_API)) {
470+		weston_log("Failed to bind api\n");
471+		goto err_terminate_display;
472+	}
473+
474+	if (!pr->bind_display(pr->egl_display, ec->wl_display))
475+		goto err_terminate_display;
476+
477+	pr->egl_inited = true;
478+	return true;
479+
480+err_terminate_display:
481+	eglTerminate(pr->egl_display);
482+err_destroy_gbm:
483+	gbm_device_destroy(pr->gbm);
484+	pr->gbm = NULL;
485+err_close_fd:
486+	close(pr->drm_fd);
487+	pr->drm_fd = -1;
488+	return false;
489+}
490+#endif
491+
492 WL_EXPORT int
493 pixman_renderer_init(struct weston_compositor *ec)
494 {
495@@ -1150,6 +1353,10 @@ pixman_renderer_init(struct weston_compositor *ec)
496 	renderer->base.get_supported_formats =
497 		pixman_renderer_get_supported_formats;
498
499+#ifdef ENABLE_EGL
500+	pixman_renderer_init_egl(renderer, ec);
501+#endif
502+
503 	return 0;
504 }
505
506--
5072.20.1
508
509