From ff59b4dda8fcfc7c21f7c8dac00e81d077b5186f Mon Sep 17 00:00:00 2001 From: Jeffy Chen 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 --- 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 +#include + +#include +#include +#include +#include +#include +#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