hc
2024-07-02 39af2116d7581c9a12be9e73bb6bdc31496495ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
From ff59b4dda8fcfc7c21f7c8dac00e81d077b5186f Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Fri, 3 Jul 2020 14:53:52 +0800
Subject: [PATCH 22/69] HACK: pixman-renderer: Support mali egl client and egl
 buffer attaching
 
The mali clients requires mali_buffer_sharing extension, and it needs
lots of hacks to attach a wl_buffer created in that way.
 
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 libweston/meson.build       |  10 +-
 libweston/pixman-renderer.c | 191 ++++++++++++++++++++++++++++++++++++
 2 files changed, 195 insertions(+), 6 deletions(-)
 
diff --git a/libweston/meson.build b/libweston/meson.build
index 257d69501..a73e9324b 100644
--- a/libweston/meson.build
+++ b/libweston/meson.build
@@ -70,12 +70,10 @@ srcs_libweston = [
     weston_direct_display_server_protocol_h,
 ]
 
-if get_option('renderer-gl')
-    dep_egl = dependency('egl', required: false)
-    if not dep_egl.found()
-        error('libweston + gl-renderer requires egl which was not found. Or, you can use \'-Drenderer-gl=false\'.')
-    endif
-    deps_libweston += dep_egl
+dep_egl = dependency('egl', required: false)
+dep_gbm = dependency('gbm', required: false)
+if dep_egl.found() and dep_gbm.found()
+    deps_libweston += [ dep_egl, dep_gbm ]
 endif
 
 lib_weston = shared_library(
diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c
index d5c5422f0..593d7c8c3 100644
--- a/libweston/pixman-renderer.c
+++ b/libweston/pixman-renderer.c
@@ -46,6 +46,19 @@
 #include "linux-dmabuf.h"
 #include "linux-dmabuf-unstable-v1-server-protocol.h"
 
+#ifdef ENABLE_EGL
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <gbm.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include "shared/platform.h"
+#include "shared/weston-egl-ext.h"  /* for PFN* stuff */
+#endif
+
 struct pixman_output_state {
     void *shadow_buffer;
     pixman_image_t *shadow_image;
@@ -75,6 +88,18 @@ struct pixman_renderer {
     struct wl_signal destroy_signal;
 
     struct weston_drm_format_array supported_formats;
+
+#ifdef ENABLE_EGL
+    PFNEGLBINDWAYLANDDISPLAYWL bind_display;
+    PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
+    PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
+    EGLDisplay egl_display;
+
+    int drm_fd;
+    struct gbm_device *gbm;
+
+    bool egl_inited;
+#endif
 };
 
 struct dmabuf_data {
@@ -82,6 +107,16 @@ struct dmabuf_data {
     size_t size;
 };
 
+#ifdef ENABLE_EGL
+/* HACK: For mali_buffer_sharing */
+struct egl_buffer_info {
+    int dma_fd;
+    int width;
+    int height;
+    unsigned int stride;
+};
+#endif
+
 static inline struct pixman_output_state *
 get_output_state(struct weston_output *output)
 {
@@ -715,11 +750,16 @@ pixman_renderer_attach_dmabuf(struct weston_surface *es,
 static void
 pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 {
+    struct pixman_renderer *pr = get_renderer(es->compositor);
     struct pixman_surface_state *ps = get_surface_state(es);
     struct wl_shm_buffer *shm_buffer;
     struct linux_dmabuf_buffer *dmabuf;
     const struct pixel_format_info *pixel_info;
 
+#ifdef ENABLE_EGL
+    EGLint format;
+#endif
+
     weston_buffer_reference(&ps->buffer_ref, buffer);
     weston_buffer_release_reference(&ps->buffer_release_ref,
                     es->buffer_release_ref.buffer_release);
@@ -742,7 +782,56 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
     if (! shm_buffer) {
         if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) {
             pixman_renderer_attach_dmabuf(es, buffer, dmabuf);
+#ifdef ENABLE_EGL
+        } else if (pr->egl_inited &&
+               pr->query_buffer(pr->egl_display,
+                        (void *)buffer->resource,
+                        EGL_TEXTURE_FORMAT, &format)){
+            struct egl_buffer_info *info;
+            struct linux_dmabuf_buffer dmabuf = { 0 };
+            struct dmabuf_attributes *attributes =
+                &dmabuf.attributes;
+            struct stat s;
+            int width, height;
+
+            pr->query_buffer(pr->egl_display,
+                     (void *)buffer->resource,
+                     EGL_WIDTH, &width);
+            pr->query_buffer(pr->egl_display,
+                     (void *)buffer->resource,
+                     EGL_HEIGHT, &height);
+
+            info = wl_resource_get_user_data(buffer->resource);
+            if (!info)
+                goto err;
+
+            if (fstat(info->dma_fd, &s) < 0 ||
+                info->width != width || info->height != height)
+                goto err;
+
+            switch (format) {
+            case EGL_TEXTURE_RGB:
+                attributes->format = DRM_FORMAT_RGB888;
+                break;
+            case EGL_TEXTURE_RGBA:
+                attributes->format = DRM_FORMAT_ARGB8888;
+                break;
+            default:
+                goto err;
+            }
+
+            attributes->n_planes = 1;
+            attributes->fd[0] = info->dma_fd;
+            attributes->width = info->width;
+            attributes->height = info->height;
+            attributes->stride[0] = info->stride;
+
+            pixman_renderer_attach_dmabuf(es, buffer, &dmabuf);
+        } else {
+err:
+#else
         } else {
+#endif
             weston_log("unhandled buffer type!\n");
             weston_buffer_reference(&ps->buffer_ref, NULL);
             weston_buffer_release_reference(&ps->buffer_release_ref,
@@ -880,6 +969,21 @@ pixman_renderer_destroy(struct weston_compositor *ec)
 {
     struct pixman_renderer *pr = get_renderer(ec);
 
+#ifdef ENABLE_EGL
+    if (pr->egl_inited) {
+        if (pr->unbind_display)
+            pr->unbind_display(pr->egl_display, ec->wl_display);
+
+        eglTerminate(pr->egl_display);
+        eglReleaseThread();
+
+        if (pr->gbm)
+            gbm_device_destroy(pr->gbm);
+
+        close(pr->drm_fd);
+    }
+#endif
+
     wl_signal_emit(&pr->destroy_signal, pr);
     weston_binding_destroy(pr->debug_binding);
 
@@ -1086,6 +1190,89 @@ out:
     return ret;
 }
 
+#ifdef ENABLE_EGL
+static bool
+pixman_renderer_init_egl(struct pixman_renderer *pr,
+             struct weston_compositor *ec)
+{
+    PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display;
+    const char *extensions;
+
+    get_platform_display =
+        (void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
+    pr->query_buffer =
+        (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
+    pr->bind_display =
+        (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
+    pr->unbind_display =
+        (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
+
+    if (!get_platform_display || !pr->query_buffer ||
+        !pr->bind_display || !pr->unbind_display) {
+        weston_log("Failed to get egl proc\n");
+        return false;
+    }
+
+    pr->drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
+    if (pr->drm_fd < 0) {
+        weston_log("Failed to open drm dev\n");
+        return false;
+    }
+
+    pr->gbm = gbm_create_device(pr->drm_fd);
+    if (!pr->gbm) {
+        weston_log("Failed to create gbm device\n");
+        goto err_close_fd;
+    }
+
+    pr->egl_display = get_platform_display(EGL_PLATFORM_GBM_KHR,
+                           (void*) pr->gbm, NULL);
+    if (pr->egl_display == EGL_NO_DISPLAY) {
+        weston_log("Failed to create egl display\n");
+        goto err_destroy_gbm;
+    }
+
+    if (!eglInitialize(pr->egl_display, NULL, NULL)) {
+        weston_log("Failed to initialize egl\n");
+        goto err_terminate_display;
+    }
+
+    extensions =
+        (const char *) eglQueryString(pr->egl_display, EGL_EXTENSIONS);
+    if (!extensions) {
+        weston_log("Retrieving EGL extension string failed.\n");
+        goto err_terminate_display;
+    }
+
+    if (!weston_check_egl_extension(extensions,
+                    "EGL_WL_bind_wayland_display")) {
+        weston_log("Wayland extension not supported.\n");
+        goto err_terminate_display;
+    }
+
+    if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+        weston_log("Failed to bind api\n");
+        goto err_terminate_display;
+    }
+
+    if (!pr->bind_display(pr->egl_display, ec->wl_display))
+        goto err_terminate_display;
+
+    pr->egl_inited = true;
+    return true;
+
+err_terminate_display:
+    eglTerminate(pr->egl_display);
+err_destroy_gbm:
+    gbm_device_destroy(pr->gbm);
+    pr->gbm = NULL;
+err_close_fd:
+    close(pr->drm_fd);
+    pr->drm_fd = -1;
+    return false;
+}
+#endif
+
 WL_EXPORT int
 pixman_renderer_init(struct weston_compositor *ec)
 {
@@ -1150,6 +1337,10 @@ pixman_renderer_init(struct weston_compositor *ec)
     renderer->base.get_supported_formats =
         pixman_renderer_get_supported_formats;
 
+#ifdef ENABLE_EGL
+    pixman_renderer_init_egl(renderer, ec);
+#endif
+
     return 0;
 }
 
-- 
2.20.1