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