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