1From 16302ea084be281cbd71bb40ceda7d30b1c44eff 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 25/95] 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 | 427 ++++++++++++++++++++++++++++-------- 14 2 files changed, 338 insertions(+), 99 deletions(-) 15 16diff --git a/libweston/meson.build b/libweston/meson.build 17index 313a84f..6a845cc 100644 18--- a/libweston/meson.build 19+++ b/libweston/meson.build 20@@ -73,12 +73,10 @@ srcs_libweston = [ 21 22 subdir('desktop') 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 07b7888..7339541 100644 39--- a/libweston/pixman-renderer.c 40+++ b/libweston/pixman-renderer.c 41@@ -47,6 +47,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 pixman_image_t *shadow_image; 60 pixman_image_t *hw_buffer; 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@@ -669,6 +704,91 @@ pixman_renderer_surface_set_color(struct weston_surface *es, 98 ps->image = pixman_image_create_solid_fill(&color); 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+ attributes->modifier[i] != DRM_FORMAT_MOD_LINEAR) 133+ return false; 134+ } 135+ 136+ /* reject all flags we do not recognize or handle */ 137+ if (attributes->flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT) 138+ return false; 139+ 140+ if (attributes->n_planes < 0) 141+ return false; 142+ 143+ if (attributes->n_planes == 1) 144+ goto out; 145+ 146+ vstride0 = (attributes->offset[1] - attributes->offset[0]) / 147+ attributes->stride[0]; 148+ 149+ for (i = 1; i < attributes->n_planes; i++) { 150+ size_t size = attributes->offset[i] - attributes->offset[i - 1]; 151+ size_t vstride = size / attributes->stride[i - 1]; 152+ 153+ /* not contig */ 154+ if (size <= 0 || vstride <= 0 || 155+ attributes->offset[i - 1] + size > total_size) 156+ return false; 157+ 158+ /* stride unmatched */ 159+ if ((vstride != vstride0 && vstride != vstride0 / 2) || 160+ (attributes->stride[i] != attributes->stride[0] && 161+ attributes->stride[i] != attributes->stride[0] / 2)) 162+ return false; 163+ } 164+ 165+out: 166+ /* Handle contig dma buffer */ 167+ 168+ ptr = mmap(NULL, total_size, PROT_READ, 169+ MAP_SHARED, attributes->fd[0], 0); 170+ if (!ptr) 171+ return false; 172+ 173+ data = zalloc(sizeof *data); 174+ if (!data) { 175+ munmap(ptr, total_size); 176+ return false; 177+ } 178+ 179+ data->size = total_size; 180+ data->ptr = ptr; 181+ linux_dmabuf_buffer_set_user_data(dmabuf, data, 182+ pixman_renderer_destroy_dmabuf); 183+ return true; 184+} 185+ 186 static void 187 pixman_renderer_attach_dmabuf(struct weston_surface *es, 188 struct weston_buffer *buffer, 189@@ -680,14 +800,12 @@ pixman_renderer_attach_dmabuf(struct weston_surface *es, 190 pixman_format_code_t pixman_format; 191 size_t vstride; 192 193+ if (!pixman_renderer_prepare_dmabuf(dmabuf)) 194+ goto err; 195+ 196 data = linux_dmabuf_buffer_get_user_data(dmabuf); 197- if (!data || !data->ptr) { 198- weston_buffer_reference(&ps->buffer_ref, NULL, 199- BUFFER_WILL_NOT_BE_ACCESSED); 200- weston_buffer_release_reference(&ps->buffer_release_ref, 201- NULL); 202- return; 203- } 204+ if (!data || !data->ptr) 205+ goto err; 206 207 buffer->width = attributes->width; 208 buffer->height = attributes->height; 209@@ -752,11 +870,7 @@ pixman_renderer_attach_dmabuf(struct weston_surface *es, 210 #endif 211 default: 212 weston_log("Unsupported dmabuf format\n"); 213- weston_buffer_reference(&ps->buffer_ref, NULL, 214- BUFFER_WILL_NOT_BE_ACCESSED); 215- weston_buffer_release_reference(&ps->buffer_release_ref, 216- NULL); 217- return; 218+ goto err; 219 break; 220 } 221 222@@ -769,6 +883,11 @@ pixman_renderer_attach_dmabuf(struct weston_surface *es, 223 buffer_state_handle_buffer_destroy; 224 wl_signal_add(&buffer->destroy_signal, 225 &ps->buffer_destroy_listener); 226+ return; 227+err: 228+ weston_buffer_reference(&ps->buffer_ref, NULL, 229+ BUFFER_WILL_NOT_BE_ACCESSED); 230+ weston_buffer_release_reference(&ps->buffer_release_ref, NULL); 231 } 232 233 static void 234@@ -776,7 +895,6 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) 235 { 236 struct pixman_surface_state *ps = get_surface_state(es); 237 struct wl_shm_buffer *shm_buffer; 238- struct linux_dmabuf_buffer *dmabuf; 239 const struct pixel_format_info *pixel_info; 240 241 weston_buffer_reference(&ps->buffer_ref, buffer, 242@@ -810,17 +928,40 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) 243 return; 244 } 245 246- if (buffer->type != WESTON_BUFFER_SHM) { 247- if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) { 248- pixman_renderer_attach_dmabuf(es, buffer, dmabuf); 249- } else { 250- weston_log("unhandled buffer type!\n"); 251- weston_buffer_reference(&ps->buffer_ref, NULL, 252- BUFFER_WILL_NOT_BE_ACCESSED); 253- weston_buffer_release_reference(&ps->buffer_release_ref, 254- NULL); 255- } 256+ if (buffer->type == WESTON_BUFFER_DMABUF) { 257+ struct linux_dmabuf_buffer *dmabuf = 258+ linux_dmabuf_buffer_get(buffer->resource); 259+ pixman_renderer_attach_dmabuf(es, buffer, dmabuf); 260+ return; 261+ } 262+ 263+#ifdef ENABLE_EGL 264+ if (buffer->type == WESTON_BUFFER_RENDERER_OPAQUE) { 265+ struct egl_buffer_info *info; 266+ struct linux_dmabuf_buffer dmabuf = { 0 }; 267+ struct dmabuf_attributes *attributes = &dmabuf.attributes; 268+ 269+ info = wl_resource_get_user_data(buffer->resource); 270 271+ attributes->format = buffer->pixel_format->format; 272+ attributes->width = buffer->width; 273+ attributes->height = buffer->height; 274+ 275+ attributes->n_planes = 1; 276+ attributes->fd[0] = info->dma_fd; 277+ attributes->stride[0] = info->stride; 278+ 279+ pixman_renderer_attach_dmabuf(es, buffer, &dmabuf); 280+ return; 281+ } 282+#endif 283+ 284+ if (buffer->type != WESTON_BUFFER_SHM) { 285+ weston_log("unhandled buffer type!\n"); 286+ weston_buffer_reference(&ps->buffer_ref, NULL, 287+ BUFFER_WILL_NOT_BE_ACCESSED); 288+ weston_buffer_release_reference(&ps->buffer_release_ref, 289+ NULL); 290 return; 291 } 292 293@@ -849,6 +990,70 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) 294 &ps->buffer_destroy_listener); 295 } 296 297+#ifdef ENABLE_EGL 298+static bool 299+pixman_renderer_fill_buffer_info(struct weston_compositor *ec, 300+ struct weston_buffer *buffer) 301+{ 302+ struct pixman_renderer *pr = get_renderer(ec); 303+ struct egl_buffer_info *info; 304+ struct stat s; 305+ EGLint format; 306+ uint32_t fourcc; 307+ EGLint y_inverted; 308+ bool ret = true; 309+ 310+ if (!pr->egl_inited) 311+ return false; 312+ 313+ info = wl_resource_get_user_data(buffer->resource); 314+ if (!info) 315+ return false; 316+ 317+ buffer->legacy_buffer = (struct wl_buffer *)buffer->resource; 318+ ret &= pr->query_buffer(pr->egl_display, buffer->legacy_buffer, 319+ EGL_WIDTH, &buffer->width); 320+ ret &= pr->query_buffer(pr->egl_display, buffer->legacy_buffer, 321+ EGL_HEIGHT, &buffer->height); 322+ ret &= pr->query_buffer(pr->egl_display, buffer->legacy_buffer, 323+ EGL_TEXTURE_FORMAT, &format); 324+ if (!ret) { 325+ weston_log("eglQueryWaylandBufferWL failed\n"); 326+ return false; 327+ } 328+ 329+ if (fstat(info->dma_fd, &s) < 0 || 330+ info->width != buffer->width || info->height != buffer->height) 331+ return false; 332+ 333+ switch (format) { 334+ case EGL_TEXTURE_RGB: 335+ fourcc = DRM_FORMAT_XRGB8888; 336+ break; 337+ case EGL_TEXTURE_RGBA: 338+ fourcc = DRM_FORMAT_ARGB8888; 339+ break; 340+ default: 341+ return false; 342+ } 343+ 344+ buffer->pixel_format = pixel_format_get_info(fourcc); 345+ assert(buffer->pixel_format); 346+ buffer->format_modifier = DRM_FORMAT_MOD_INVALID; 347+ 348+ /* Assume scanout co-ordinate space i.e. (0,0) is top-left 349+ * if the query fails */ 350+ ret = pr->query_buffer(pr->egl_display, buffer->legacy_buffer, 351+ EGL_WAYLAND_Y_INVERTED_WL, &y_inverted); 352+ if (!ret || y_inverted) 353+ buffer->buffer_origin = ORIGIN_TOP_LEFT; 354+ else 355+ buffer->buffer_origin = ORIGIN_BOTTOM_LEFT; 356+ 357+ return true; 358+} 359+#endif 360+ 361 static void 362 pixman_renderer_surface_state_destroy(struct pixman_surface_state *ps) 363 { 364@@ -928,6 +1133,21 @@ pixman_renderer_destroy(struct weston_compositor *ec) 365 { 366 struct pixman_renderer *pr = get_renderer(ec); 367 368+#ifdef ENABLE_EGL 369+ if (pr->egl_inited) { 370+ if (pr->unbind_display) 371+ pr->unbind_display(pr->egl_display, ec->wl_display); 372+ 373+ eglTerminate(pr->egl_display); 374+ eglReleaseThread(); 375+ 376+ if (pr->gbm) 377+ gbm_device_destroy(pr->gbm); 378+ 379+ close(pr->drm_fd); 380+ } 381+#endif 382+ 383 wl_signal_emit(&pr->destroy_signal, pr); 384 weston_binding_destroy(pr->debug_binding); 385 386@@ -991,80 +1211,11 @@ debug_binding(struct weston_keyboard *keyboard, const struct timespec *time, 387 } 388 } 389 390-static void 391-pixman_renderer_destroy_dmabuf(struct linux_dmabuf_buffer *dmabuf) 392-{ 393- struct dmabuf_data *data = dmabuf->user_data; 394- linux_dmabuf_buffer_set_user_data(dmabuf, NULL, NULL); 395- 396- if (data) { 397- if (data->ptr) 398- munmap(data->ptr, data->size); 399- 400- free(data); 401- } 402-} 403- 404 static bool 405 pixman_renderer_import_dmabuf(struct weston_compositor *ec, 406 struct linux_dmabuf_buffer *dmabuf) 407 { 408- struct dmabuf_attributes *attributes = &dmabuf->attributes; 409- struct dmabuf_data *data; 410- size_t total_size, vstride0; 411- int i; 412- 413- for (i = 0; i < attributes->n_planes; i++) { 414- if (attributes->modifier[i] != DRM_FORMAT_MOD_INVALID && 415- attributes->modifier[i] != DRM_FORMAT_MOD_LINEAR) 416- return false; 417- } 418- 419- /* reject all flags we do not recognize or handle */ 420- if (attributes->flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT) 421- return false; 422- 423- if (attributes->n_planes < 0) 424- return false; 425- 426- if (attributes->n_planes == 1) 427- goto out; 428- 429- total_size = lseek(attributes->fd[0], 0, SEEK_END); 430- vstride0 = (attributes->offset[1] - attributes->offset[0]) / 431- attributes->stride[0]; 432- 433- for (i = 1; i < attributes->n_planes; i++) { 434- size_t size = attributes->offset[i] - attributes->offset[i - 1]; 435- size_t vstride = size / attributes->stride[i - 1]; 436- 437- /* not contig */ 438- if (size <= 0 || vstride <= 0 || 439- attributes->offset[i - 1] + size > total_size) 440- return false; 441- 442- /* stride unmatched */ 443- if ((vstride != vstride0 && vstride != vstride0 / 2) || 444- (attributes->stride[i] != attributes->stride[0] && 445- attributes->stride[i] != attributes->stride[0] / 2)) 446- return false; 447- } 448- 449-out: 450- /* Handle contig dma buffer */ 451- 452- data = zalloc(sizeof *data); 453- if (!data) 454- return false; 455- 456- linux_dmabuf_buffer_set_user_data(dmabuf, data, 457- pixman_renderer_destroy_dmabuf); 458- 459- data->size = lseek(attributes->fd[0], 0, SEEK_END); 460- 461- data->ptr = mmap(NULL, data->size, PROT_READ, 462- MAP_SHARED, attributes->fd[0], 0); 463- return data->ptr != MAP_FAILED; 464+ return pixman_renderer_prepare_dmabuf(dmabuf); 465 } 466 467 static const struct weston_drm_format_array * 468@@ -1120,6 +1271,89 @@ out: 469 return ret; 470 } 471 472+#ifdef ENABLE_EGL 473+static bool 474+pixman_renderer_init_egl(struct pixman_renderer *pr, 475+ struct weston_compositor *ec) 476+{ 477+ PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display; 478+ const char *extensions; 479+ 480+ get_platform_display = 481+ (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); 482+ pr->query_buffer = 483+ (void *) eglGetProcAddress("eglQueryWaylandBufferWL"); 484+ pr->bind_display = 485+ (void *) eglGetProcAddress("eglBindWaylandDisplayWL"); 486+ pr->unbind_display = 487+ (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL"); 488+ 489+ if (!get_platform_display || !pr->query_buffer || 490+ !pr->bind_display || !pr->unbind_display) { 491+ weston_log("Failed to get egl proc\n"); 492+ return false; 493+ } 494+ 495+ pr->drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); 496+ if (pr->drm_fd < 0) { 497+ weston_log("Failed to open drm dev\n"); 498+ return false; 499+ } 500+ 501+ pr->gbm = gbm_create_device(pr->drm_fd); 502+ if (!pr->gbm) { 503+ weston_log("Failed to create gbm device\n"); 504+ goto err_close_fd; 505+ } 506+ 507+ pr->egl_display = get_platform_display(EGL_PLATFORM_GBM_KHR, 508+ (void*) pr->gbm, NULL); 509+ if (pr->egl_display == EGL_NO_DISPLAY) { 510+ weston_log("Failed to create egl display\n"); 511+ goto err_destroy_gbm; 512+ } 513+ 514+ if (!eglInitialize(pr->egl_display, NULL, NULL)) { 515+ weston_log("Failed to initialize egl\n"); 516+ goto err_terminate_display; 517+ } 518+ 519+ extensions = 520+ (const char *) eglQueryString(pr->egl_display, EGL_EXTENSIONS); 521+ if (!extensions) { 522+ weston_log("Retrieving EGL extension string failed.\n"); 523+ goto err_terminate_display; 524+ } 525+ 526+ if (!weston_check_egl_extension(extensions, 527+ "EGL_WL_bind_wayland_display")) { 528+ weston_log("Wayland extension not supported.\n"); 529+ goto err_terminate_display; 530+ } 531+ 532+ if (!eglBindAPI(EGL_OPENGL_ES_API)) { 533+ weston_log("Failed to bind api\n"); 534+ goto err_terminate_display; 535+ } 536+ 537+ if (!pr->bind_display(pr->egl_display, ec->wl_display)) 538+ goto err_terminate_display; 539+ 540+ pr->egl_inited = true; 541+ return true; 542+ 543+err_terminate_display: 544+ eglTerminate(pr->egl_display); 545+err_destroy_gbm: 546+ gbm_device_destroy(pr->gbm); 547+ pr->gbm = NULL; 548+err_close_fd: 549+ close(pr->drm_fd); 550+ pr->drm_fd = -1; 551+ return false; 552+} 553+#endif 554+ 555 WL_EXPORT int 556 pixman_renderer_init(struct weston_compositor *ec) 557 { 558@@ -1141,6 +1375,9 @@ pixman_renderer_init(struct weston_compositor *ec) 559 renderer->base.destroy = pixman_renderer_destroy; 560 renderer->base.surface_copy_content = 561 pixman_renderer_surface_copy_content; 562+#ifdef ENABLE_EGL 563+ renderer->base.fill_buffer_info = pixman_renderer_fill_buffer_info; 564+#endif 565 ec->renderer = &renderer->base; 566 ec->capabilities |= WESTON_CAP_ROTATION_ANY; 567 ec->capabilities |= WESTON_CAP_VIEW_CLIP_MASK; 568@@ -1181,6 +1418,10 @@ pixman_renderer_init(struct weston_compositor *ec) 569 renderer->base.get_supported_formats = 570 pixman_renderer_get_supported_formats; 571 572+#ifdef ENABLE_EGL 573+ pixman_renderer_init_egl(renderer, ec); 574+#endif 575+ 576 return 0; 577 } 578 579-- 5802.20.1 581 582