diff options
-rw-r--r-- | .SRCINFO | 22 | ||||
-rw-r--r-- | 0001-gl-renderer-Renaming-of-things-and-minor-improvement.patch | 212 | ||||
-rw-r--r-- | 0002-gl-renderer-Refactor-gl_renderer_output_window_creat.patch | 169 | ||||
-rw-r--r-- | 0003-gl-renderer-Implement-use-check_extension.patch | 167 | ||||
-rw-r--r-- | 0004-gl-renderer-Add-support-for-EGLDevice-EGLOutput.patch | 820 | ||||
-rw-r--r-- | 0005-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch | 82 | ||||
-rw-r--r-- | 0006-compositor-drm-Renaming-of-gbm-fields.patch | 228 | ||||
-rw-r--r-- | 0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch | 552 | ||||
-rw-r--r-- | PKGBUILD | 44 |
9 files changed, 2285 insertions, 11 deletions
@@ -1,5 +1,5 @@ -pkgbase = weston - pkgdesc = Reference implementation of a Wayland compositor +pkgbase = weston-eglstream + pkgdesc = Reference implementation of a Wayland compositor with EGLStream support pkgver = 1.10.0 pkgrel = 1 url = http://wayland.freedesktop.org @@ -17,8 +17,24 @@ pkgbase = weston depends = glu depends = pango depends = colord + provides = weston + conflicts = weston source = http://wayland.freedesktop.org/releases/weston-1.10.0.tar.xz + source = 0001-gl-renderer-Renaming-of-things-and-minor-improvement.patch + source = 0002-gl-renderer-Refactor-gl_renderer_output_window_creat.patch + source = 0003-gl-renderer-Implement-use-check_extension.patch + source = 0004-gl-renderer-Add-support-for-EGLDevice-EGLOutput.patch + source = 0005-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch + source = 0006-compositor-drm-Renaming-of-gbm-fields.patch + source = 0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch sha1sums = c9c2c8e2e798b25e7bf6b31bf0c4ef08724a7ebb + sha1sums = c623cdf628a20a4bde5a98cc40867c32a8300e79 + sha1sums = 3441d0a7da0ae64835a5b29545caab4bc7977417 + sha1sums = f6742fadb973ec6c2b55e5500127309e70579312 + sha1sums = 31e3a447a1209712d604d739d0ac7e5b1925e940 + sha1sums = b483f21b3f880d3978cc678bf5f97802f7ddddaf + sha1sums = 13d217d76a0811f5eb8d7180d31ec7a69fbbaabd + sha1sums = 6bab10ac02a7e69b1bb1bf1982b5804e87870e0e -pkgname = weston +pkgname = weston-eglstream diff --git a/0001-gl-renderer-Renaming-of-things-and-minor-improvement.patch b/0001-gl-renderer-Renaming-of-things-and-minor-improvement.patch new file mode 100644 index 000000000000..ae7acd6ca073 --- /dev/null +++ b/0001-gl-renderer-Renaming-of-things-and-minor-improvement.patch @@ -0,0 +1,212 @@ +From 50b2478345ae978143364abde179080a36479e94 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Mon, 21 Mar 2016 17:37:31 +0100 +Subject: [PATCH 1/7] gl-renderer: Renaming of things and minor improvements +X-NVConfidentiality: public + +In preparation for follow-on changes to support frame presentation +through EGLDevice+EGLOutput, this change includes the following: + -Rename gl_renderer_output_create to gl_renderer_output_window_create + -Add <platform_attribs> argument to gl_renderer_create + -Rename <attribs> argument for gl_renderer_create() and + gl_renderer_output_window_create() to <config_attribs> + -Accept non-NULL empty <visual_id> arrays (n_ids == 0) both in + gl_renderer_create() and gl_renderer_output_window_create() + +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +Reviewed-by: Andy Ritger <aritger@nvidia.com> +--- + src/compositor-drm.c | 3 ++- + src/compositor-fbdev.c | 3 ++- + src/compositor-wayland.c | 3 ++- + src/compositor-x11.c | 4 ++-- + src/gl-renderer.c | 18 +++++++++--------- + src/gl-renderer.h | 7 ++++--- + 6 files changed, 21 insertions(+), 17 deletions(-) + +diff --git a/src/compositor-drm.c b/src/compositor-drm.c +index 538e56eb58ba..ded15f83c3e6 100644 +--- a/src/compositor-drm.c ++++ b/src/compositor-drm.c +@@ -1588,6 +1588,7 @@ drm_backend_create_gl_renderer(struct drm_backend *b) + if (gl_renderer->create(b->compositor, + EGL_PLATFORM_GBM_KHR, + (void *)b->gbm, ++ NULL, + gl_renderer->opaque_attribs, + format, + n_formats) < 0) { +@@ -1852,7 +1853,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b) + + if (format[1]) + n_formats = 2; +- if (gl_renderer->output_create(&output->base, ++ if (gl_renderer->output_window_create(&output->base, + (EGLNativeWindowType)output->surface, + output->surface, + gl_renderer->opaque_attribs, +diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c +index 36d7ae0ae500..84435b7f2fbd 100644 +--- a/src/compositor-fbdev.c ++++ b/src/compositor-fbdev.c +@@ -526,7 +526,7 @@ fbdev_output_create(struct fbdev_backend *backend, + goto out_hw_surface; + } else { + setenv("HYBRIS_EGLPLATFORM", "wayland", 1); +- if (gl_renderer->output_create(&output->base, ++ if (gl_renderer->output_window_create(&output->base, + (EGLNativeWindowType)NULL, NULL, + gl_renderer->opaque_attribs, + NULL, 0) < 0) { +@@ -799,6 +799,7 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv + + if (gl_renderer->create(compositor, NO_EGL_PLATFORM, + EGL_DEFAULT_DISPLAY, ++ NULL, + gl_renderer->opaque_attribs, + NULL, 0) < 0) { + weston_log("gl_renderer_create failed.\n"); +diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c +index d1c020d886a1..d38376a9ee38 100644 +--- a/src/compositor-wayland.c ++++ b/src/compositor-wayland.c +@@ -657,7 +657,7 @@ wayland_output_init_gl_renderer(struct wayland_output *output) + return -1; + } + +- if (gl_renderer->output_create(&output->base, ++ if (gl_renderer->output_window_create(&output->base, + output->gl.egl_window, + output->gl.egl_window, + gl_renderer->alpha_attribs, +@@ -2250,6 +2250,7 @@ wayland_backend_create(struct weston_compositor *compositor, int use_pixman, + if (gl_renderer->create(compositor, + EGL_PLATFORM_WAYLAND_KHR, + b->parent.wl_display, ++ NULL, + gl_renderer->alpha_attribs, + NULL, + 0) < 0) { +diff --git a/src/compositor-x11.c b/src/compositor-x11.c +index 13a5d7304568..bc35db66f6fc 100644 +--- a/src/compositor-x11.c ++++ b/src/compositor-x11.c +@@ -932,7 +932,7 @@ x11_backend_create_output(struct x11_backend *b, int x, int y, + * but eglCreateWindowSurface takes a Window. */ + Window xid = (Window) output->window; + +- ret = gl_renderer->output_create(&output->base, ++ ret = gl_renderer->output_window_create(&output->base, + (EGLNativeWindowType) output->window, + &xid, + gl_renderer->opaque_attribs, +@@ -1562,7 +1562,7 @@ init_gl_renderer(struct x11_backend *b) + return -1; + + ret = gl_renderer->create(b->compositor, EGL_PLATFORM_X11_KHR, (void *) b->dpy, +- gl_renderer->opaque_attribs, NULL, 0); ++ NULL, gl_renderer->opaque_attribs, NULL, 0); + + return ret; + } +diff --git a/src/gl-renderer.c b/src/gl-renderer.c +index cb083448bfdb..0c55e0b9ebd2 100644 +--- a/src/gl-renderer.c ++++ b/src/gl-renderer.c +@@ -2493,7 +2493,7 @@ egl_choose_config(struct gl_renderer *gr, const EGLint *attribs, + goto out; + } + +- if (!visual_id) ++ if (!visual_id || n_ids == 0) + config_index = 0; + + for (i = 0; config_index == -1 && i < n_ids; i++) +@@ -2547,10 +2547,10 @@ static int + gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface); + + static int +-gl_renderer_output_create(struct weston_output *output, ++gl_renderer_output_window_create(struct weston_output *output, + EGLNativeWindowType window_for_legacy, + void *window_for_platform, +- const EGLint *attribs, ++ const EGLint *config_attribs, + const EGLint *visual_id, + int n_ids) + { +@@ -2560,7 +2560,7 @@ gl_renderer_output_create(struct weston_output *output, + EGLConfig egl_config; + int i; + +- if (egl_choose_config(gr, attribs, visual_id, ++ if (egl_choose_config(gr, config_attribs, visual_id, + n_ids, &egl_config) == -1) { + weston_log("failed to choose EGL config for output\n"); + return -1; +@@ -2846,8 +2846,8 @@ platform_to_extension(EGLenum platform) + + static int + gl_renderer_create(struct weston_compositor *ec, EGLenum platform, +- void *native_window, const EGLint *attribs, +- const EGLint *visual_id, int n_ids) ++ void *native_window, const EGLint* platform_attribs, ++ const EGLint *config_attribs, const EGLint *visual_id, int n_ids) + { + struct gl_renderer *gr; + EGLint major, minor; +@@ -2889,7 +2889,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLenum platform, + if (get_platform_display && platform) { + gr->egl_display = get_platform_display(platform, + native_window, +- NULL); ++ platform_attribs); + } + } + +@@ -2910,7 +2910,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLenum platform, + goto fail_with_error; + } + +- if (egl_choose_config(gr, attribs, visual_id, ++ if (egl_choose_config(gr, config_attribs, visual_id, + n_ids, &gr->egl_config) < 0) { + weston_log("failed to choose EGL config\n"); + goto fail_terminate; +@@ -3121,7 +3121,7 @@ WL_EXPORT struct gl_renderer_interface gl_renderer_interface = { + + .create = gl_renderer_create, + .display = gl_renderer_display, +- .output_create = gl_renderer_output_create, ++ .output_window_create = gl_renderer_output_window_create, + .output_destroy = gl_renderer_output_destroy, + .output_surface = gl_renderer_output_surface, + .output_set_border = gl_renderer_output_set_border, +diff --git a/src/gl-renderer.h b/src/gl-renderer.h +index 71f6b46e49e1..af8dd267e700 100644 +--- a/src/gl-renderer.h ++++ b/src/gl-renderer.h +@@ -78,16 +78,17 @@ struct gl_renderer_interface { + int (*create)(struct weston_compositor *ec, + EGLenum platform, + void *native_window, +- const EGLint *attribs, ++ const EGLint *platform_attribs, ++ const EGLint *config_attribs, + const EGLint *visual_id, + const int n_ids); + + EGLDisplay (*display)(struct weston_compositor *ec); + +- int (*output_create)(struct weston_output *output, ++ int (*output_window_create)(struct weston_output *output, + EGLNativeWindowType window_for_legacy, + void *window_for_platform, +- const EGLint *attribs, ++ const EGLint *config_attribs, + const EGLint *visual_id, + const int n_ids); + +-- +2.7.4 + diff --git a/0002-gl-renderer-Refactor-gl_renderer_output_window_creat.patch b/0002-gl-renderer-Refactor-gl_renderer_output_window_creat.patch new file mode 100644 index 000000000000..2c4528b94998 --- /dev/null +++ b/0002-gl-renderer-Refactor-gl_renderer_output_window_creat.patch @@ -0,0 +1,169 @@ +From 1a6f5e3586cf62029a8bed8072bd41e845746bad Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Mon, 21 Mar 2016 17:37:32 +0100 +Subject: [PATCH 2/7] gl-renderer: Refactor gl_renderer_output_window_create() +X-NVConfidentiality: public + +In preparation for follow-on changes to support frame presentation +through EGLDevice+EGLOutput, this change refactors +gl_renderer_output_window_create() to separate out window surface +creation code from output common creation code. + +Bonus: Fix EGLSurface leakage upon gl_renderer_setup() failure. + +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +Reviewed-by: Andy Ritger <aritger@nvidia.com> +--- + src/gl-renderer.c | 91 +++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 62 insertions(+), 29 deletions(-) + +diff --git a/src/gl-renderer.c b/src/gl-renderer.c +index 0c55e0b9ebd2..1d6d98c9b86b 100644 +--- a/src/gl-renderer.c ++++ b/src/gl-renderer.c +@@ -1,6 +1,7 @@ + /* + * Copyright © 2012 Intel Corporation + * Copyright © 2015 Collabora, Ltd. ++ * Copyright © 2016 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the +@@ -2546,24 +2547,21 @@ gl_renderer_output_set_border(struct weston_output *output, + static int + gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface); + +-static int +-gl_renderer_output_window_create(struct weston_output *output, ++static EGLSurface ++gl_renderer_create_window_surface(struct gl_renderer *gr, + EGLNativeWindowType window_for_legacy, + void *window_for_platform, + const EGLint *config_attribs, + const EGLint *visual_id, + int n_ids) + { +- struct weston_compositor *ec = output->compositor; +- struct gl_renderer *gr = get_renderer(ec); +- struct gl_output_state *go; ++ EGLSurface egl_surface = EGL_NO_SURFACE; + EGLConfig egl_config; +- int i; + + if (egl_choose_config(gr, config_attribs, visual_id, + n_ids, &egl_config) == -1) { + weston_log("failed to choose EGL config for output\n"); +- return -1; ++ return EGL_NO_SURFACE; + } + + if (egl_config != gr->egl_config && +@@ -2571,48 +2569,83 @@ gl_renderer_output_window_create(struct weston_output *output, + weston_log("attempted to use a different EGL config for an " + "output but EGL_MESA_configless_context is not " + "supported\n"); +- return -1; ++ return EGL_NO_SURFACE; + } + +- go = zalloc(sizeof *go); +- if (go == NULL) +- return -1; ++ log_egl_config_info(gr->egl_display, egl_config); + +- if (gr->create_platform_window) { +- go->egl_surface = +- gr->create_platform_window(gr->egl_display, +- egl_config, +- window_for_platform, +- NULL); +- } else { +- go->egl_surface = +- eglCreateWindowSurface(gr->egl_display, +- egl_config, +- window_for_legacy, NULL); +- } ++ if (gr->create_platform_window) ++ egl_surface = gr->create_platform_window(gr->egl_display, ++ egl_config, ++ window_for_platform, ++ NULL); ++ else ++ egl_surface = eglCreateWindowSurface(gr->egl_display, ++ egl_config, ++ window_for_legacy, NULL); ++ ++ return egl_surface; ++} ++ ++static int ++gl_renderer_output_create(struct weston_output *output, ++ EGLSurface surface) ++{ ++ struct weston_compositor *ec = output->compositor; ++ struct gl_renderer *gr = get_renderer(ec); ++ struct gl_output_state *go; ++ int i; + +- if (go->egl_surface == EGL_NO_SURFACE) { ++ if (surface == EGL_NO_SURFACE) { + weston_log("failed to create egl surface\n"); +- free(go); + return -1; + } + + if (gr->egl_context == NULL) +- if (gl_renderer_setup(ec, go->egl_surface) < 0) { +- free(go); ++ if (gl_renderer_setup(ec, surface) < 0) { + return -1; + } + ++ go = zalloc(sizeof *go); ++ if (go == NULL) ++ return -1; ++ ++ go->egl_surface = surface; ++ + for (i = 0; i < BUFFER_DAMAGE_COUNT; i++) + pixman_region32_init(&go->buffer_damage[i]); + + output->renderer_state = go; + +- log_egl_config_info(gr->egl_display, egl_config); +- + return 0; + } + ++static int ++gl_renderer_output_window_create(struct weston_output *output, ++ EGLNativeWindowType window_for_legacy, ++ void *window_for_platform, ++ const EGLint *config_attribs, ++ const EGLint *visual_id, ++ int n_ids) ++{ ++ struct weston_compositor *ec = output->compositor; ++ struct gl_renderer *gr = get_renderer(ec); ++ EGLSurface egl_surface = EGL_NO_SURFACE; ++ int ret = 0; ++ ++ egl_surface = gl_renderer_create_window_surface(gr, ++ window_for_legacy, ++ window_for_platform, ++ config_attribs, ++ visual_id, n_ids); ++ ++ ret = gl_renderer_output_create(output, egl_surface); ++ if (ret < 0 && egl_surface != EGL_NO_SURFACE) ++ eglDestroySurface(gr->egl_display, egl_surface); ++ ++ return ret; ++} ++ + static void + gl_renderer_output_destroy(struct weston_output *output) + { +-- +2.7.4 + diff --git a/0003-gl-renderer-Implement-use-check_extension.patch b/0003-gl-renderer-Implement-use-check_extension.patch new file mode 100644 index 000000000000..deed6e719faa --- /dev/null +++ b/0003-gl-renderer-Implement-use-check_extension.patch @@ -0,0 +1,167 @@ +From c513bd330d06c7e57ca294f5e3cf7f0824afefc4 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Mon, 21 Mar 2016 17:37:33 +0100 +Subject: [PATCH 3/7] gl-renderer: Implement & use check_extension +X-NVConfidentiality: public + +Using strstr(3) for checking for extensions is an error-prone mechanism +as extension names can be prefixes of other extension names (see +https://www.opengl.org/registry/doc/rules.html#using). + +This change implements the check_extension() function to properly check +for an extension and replaces all usages of strstr(3). + +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +Reviewed-by: Andy Ritger <aritger@nvidia.com> +Reviewed-by: Daniel Stone <daniels@collabora.com> +[Pekka: move 'bool' to the same line with 'static'] +Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> + +(cherry picked from commit cc3a192b448153a7911d44aa0fa549099607911d) +--- + src/gl-renderer.c | 56 +++++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 42 insertions(+), 14 deletions(-) + +diff --git a/src/gl-renderer.c b/src/gl-renderer.c +index 1d6d98c9b86b..887d131674f5 100644 +--- a/src/gl-renderer.c ++++ b/src/gl-renderer.c +@@ -2701,6 +2701,34 @@ gl_renderer_destroy(struct weston_compositor *ec) + free(gr); + } + ++static bool ++check_extension(const char *extensions, const char *extension) ++{ ++ size_t extlen = strlen(extension); ++ const char *end = extensions + strlen(extensions); ++ ++ while (extensions < end) { ++ size_t n = 0; ++ ++ /* Skip whitespaces, if any */ ++ if (*extensions == ' ') { ++ extensions++; ++ continue; ++ } ++ ++ n = strcspn(extensions, " "); ++ ++ /* Compare strings */ ++ if (n == extlen && strncmp(extension, extensions, n) == 0) ++ return true; /* Found */ ++ ++ extensions += n; ++ } ++ ++ /* Not found */ ++ return false; ++} ++ + static void + renderer_setup_egl_client_extensions(struct gl_renderer *gr) + { +@@ -2712,7 +2740,7 @@ renderer_setup_egl_client_extensions(struct gl_renderer *gr) + return; + } + +- if (strstr(extensions, "EGL_EXT_platform_base")) ++ if (check_extension(extensions, "EGL_EXT_platform_base")) + gr->create_platform_window = + (void *) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); + else +@@ -2742,7 +2770,7 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec) + return -1; + } + +- if (strstr(extensions, "EGL_WL_bind_wayland_display")) ++ if (check_extension(extensions, "EGL_WL_bind_wayland_display")) + gr->has_bind_display = 1; + if (gr->has_bind_display) { + ret = gr->bind_display(gr->egl_display, ec->wl_display); +@@ -2750,14 +2778,14 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec) + gr->has_bind_display = 0; + } + +- if (strstr(extensions, "EGL_EXT_buffer_age")) ++ if (check_extension(extensions, "EGL_EXT_buffer_age")) + gr->has_egl_buffer_age = 1; + else + weston_log("warning: EGL_EXT_buffer_age not supported. " + "Performance could be affected.\n"); + + #ifdef EGL_EXT_swap_buffers_with_damage +- if (strstr(extensions, "EGL_EXT_swap_buffers_with_damage")) ++ if (check_extension(extensions, "EGL_EXT_swap_buffers_with_damage")) + gr->swap_buffers_with_damage = + (void *) eglGetProcAddress("eglSwapBuffersWithDamageEXT"); + else +@@ -2766,12 +2794,12 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec) + #endif + + #ifdef EGL_MESA_configless_context +- if (strstr(extensions, "EGL_MESA_configless_context")) ++ if (check_extension(extensions, "EGL_MESA_configless_context")) + gr->has_configless_context = 1; + #endif + + #ifdef EGL_EXT_image_dma_buf_import +- if (strstr(extensions, "EGL_EXT_image_dma_buf_import")) ++ if (check_extension(extensions, "EGL_EXT_image_dma_buf_import")) + gr->has_dmabuf_import = 1; + #endif + +@@ -2840,19 +2868,19 @@ gl_renderer_supports(struct weston_compositor *ec, + extensions); + } + +- if (!strstr(extensions, "EGL_EXT_platform_base")) ++ if (!check_extension(extensions, "EGL_EXT_platform_base")) + return 0; + + snprintf(s, sizeof s, "EGL_KHR_platform_%s", extension_suffix); +- if (strstr(extensions, s)) ++ if (check_extension(extensions, s)) + return 1; + + snprintf(s, sizeof s, "EGL_EXT_platform_%s", extension_suffix); +- if (strstr(extensions, s)) ++ if (check_extension(extensions, s)) + return 1; + + snprintf(s, sizeof s, "EGL_MESA_platform_%s", extension_suffix); +- if (strstr(extensions, s)) ++ if (check_extension(extensions, s)) + return 1; + + /* at this point we definitely have some platform extensions but +@@ -3104,22 +3132,22 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) + return -1; + } + +- if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) { ++ if (!check_extension(extensions, "GL_EXT_texture_format_BGRA8888")) { + weston_log("GL_EXT_texture_format_BGRA8888 not available\n"); + return -1; + } + +- if (strstr(extensions, "GL_EXT_read_format_bgra")) ++ if (check_extension(extensions, "GL_EXT_read_format_bgra")) + ec->read_format = PIXMAN_a8r8g8b8; + else + ec->read_format = PIXMAN_a8b8g8r8; + + #ifdef GL_EXT_unpack_subimage +- if (strstr(extensions, "GL_EXT_unpack_subimage")) ++ if (check_extension(extensions, "GL_EXT_unpack_subimage")) + gr->has_unpack_subimage = 1; + #endif + +- if (strstr(extensions, "GL_OES_EGL_image_external")) ++ if (check_extension(extensions, "GL_OES_EGL_image_external")) + gr->has_egl_image_external = 1; + + glActiveTexture(GL_TEXTURE0); +-- +2.7.4 + diff --git a/0004-gl-renderer-Add-support-for-EGLDevice-EGLOutput.patch b/0004-gl-renderer-Add-support-for-EGLDevice-EGLOutput.patch new file mode 100644 index 000000000000..f720cef9b67c --- /dev/null +++ b/0004-gl-renderer-Add-support-for-EGLDevice-EGLOutput.patch @@ -0,0 +1,820 @@ +From 89af96dc92477e94383ea02712b46fa2da03a438 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Mon, 21 Mar 2016 17:37:34 +0100 +Subject: [PATCH 4/7] gl-renderer: Add support for EGLDevice+EGLOutput +X-NVConfidentiality: public + +EGLDevice provides means to enumerate native devices, and then create +an EGL display connection from them. + +Similarly, EGLOutput will provide means to access different +portions of display control hardware associated with an EGLDevice. + +For instance, EGLOutputLayer represents a portion of display +control hardware that accepts an image as input and processes it +for presentation on a display device. + +EGLStream implements a mechanism to communicate frame producers and +frame consumers. By attaching an EGLOutputLayer consumer to a stream, +a producer will be able to present frames on a display device. + +Thus, a compositor could produce frames and feed them to an +EGLOutputLayer through an EGLStream for presentation on a display +device. + +In a similar way, by attaching a GLTexture consumer to a stream, a +producer (wayland client) could feed frames to a texture, which in +turn can be used by a compositor to prepare the final frame to be +presented. + +This change adds required logic to support presentation approach +described above. + +Note that some unpublished EGL extensions were needed: + + - EGL_NV_stream_attrib: + https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_NV_stream_attrib.txt + + - EGL_EXT_stream_acquire_mode: + https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_EXT_stream_acquire_mode.txt + + - EGL_NV_output_drm_flip_event: + https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_NV_output_drm_flip_event.txt + +Also, in order to allow wl_buffers to be bound to EGLStreams, we +kludged eglQueryWaylandBufferWL(EGL_WAYLAND_BUFFER_WL) to return +the stream file descriptor. + +We think the proper way to handle this should be: + + - Update WL_bind_wayland_display such that eglQueryWaylandBufferWL() accepts + a new attribute EGL_WAYLAND_BUFFER_TYPE_WL, returning + EGL_WAYLAND_BUFFER_EGLIMAGE_WL for the non-stream case. + + - Add a new WL_wayland_buffer_eglstream extension, which would define + EGL_WAYLAND_BUFFER_EGLSTREAM_WL as a return value for + EGL_WAYLAND_BUFFER_TYPE_WL, and yet another attribute + EGL_WAYLAND_BUFFER_EGLSTREAM_FD_WL to query the stream file descriptor. + +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +Reviewed-by: Andy Ritger <aritger@nvidia.com> +Reviewed-by: Adam Cheney <acheney@nvidia.com> +--- + src/gl-renderer.c | 476 ++++++++++++++++++++++++++++++++++++++++++++++++++- + src/gl-renderer.h | 26 +++ + src/weston-egl-ext.h | 19 ++ + 3 files changed, 517 insertions(+), 4 deletions(-) + +diff --git a/src/gl-renderer.c b/src/gl-renderer.c +index 887d131674f5..07879cb83b60 100644 +--- a/src/gl-renderer.c ++++ b/src/gl-renderer.c +@@ -30,6 +30,7 @@ + #include <GLES2/gl2.h> + #include <GLES2/gl2ext.h> + ++#include <unistd.h> + #include <stdbool.h> + #include <stdlib.h> + #include <string.h> +@@ -84,6 +85,8 @@ struct gl_output_state { + struct gl_border_image borders[4]; + enum gl_border_status border_status; + ++ EGLStreamKHR egl_stream; ++ + struct weston_matrix output_matrix; + }; + +@@ -159,6 +162,9 @@ struct gl_surface_state { + int height; /* in pixels */ + int y_inverted; + ++ EGLStreamKHR egl_stream; ++ bool stream_frame_acquired; ++ + struct weston_surface *surface; + + struct wl_listener surface_destroy_listener; +@@ -202,6 +208,36 @@ struct gl_renderer { + + int has_configless_context; + ++ PFNEGLCREATESTREAMKHRPROC create_stream; ++ PFNEGLDESTROYSTREAMKHRPROC destroy_stream; ++ PFNEGLQUERYSTREAMKHRPROC query_stream; ++ int has_egl_stream; ++ ++ PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC create_stream_producer_surface; ++ int has_egl_stream_producer_eglsurface; ++ ++ PFNEGLSTREAMCONSUMEROUTPUTEXTPROC stream_consumer_output; ++ int has_egl_stream_consumer_egloutput; ++ ++ PFNEGLSTREAMCONSUMERACQUIREKHRPROC stream_consumer_acquire; ++#ifdef EGL_EXT_stream_acquire_mode ++ PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC stream_consumer_acquire_attrib; ++#endif ++ int has_egl_stream_acquire_mode; ++ ++ int has_egl_output_drm; ++ int has_egl_output_drm_flip_event; ++ ++ PFNEGLGETOUTPUTLAYERSEXTPROC get_output_layers; ++ PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC query_output_layer_attrib; ++ int has_egl_output_base; ++ ++ PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC create_stream_from_file_descriptor; ++ int has_egl_stream_cross_process_fd; ++ ++ PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC stream_consumer_gltexture; ++ int has_egl_stream_consumer_gltexture; ++ + int has_dmabuf_import; + struct wl_list dmabuf_images; + +@@ -735,6 +771,7 @@ draw_view(struct weston_view *ev, struct weston_output *output, + /* non-opaque region in surface coordinates: */ + pixman_region32_t surface_blend; + GLint filter; ++ EGLint stream_state = EGL_STREAM_STATE_EMPTY_KHR; + int i; + + /* In case of a runtime switch of renderers, we may not have received +@@ -743,6 +780,21 @@ draw_view(struct weston_view *ev, struct weston_output *output, + if (!gs->shader) + return; + ++ /* If using EGLStreams, only continue if we are certain we have something to ++ * render, i.e. a new frame is available or an old one was previously ++ * acquired and is ready to be re-used */ ++ if (gs->egl_stream != EGL_NO_STREAM_KHR) { ++ if (gr->query_stream(gr->egl_display, ++ gs->egl_stream, ++ EGL_STREAM_STATE_KHR, ++ &stream_state) != EGL_TRUE) ++ return; ++ ++ if (stream_state != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR && ++ !gs->stream_frame_acquired) ++ return; ++ } ++ + pixman_region32_init(&repaint); + pixman_region32_intersect(&repaint, + &ev->transform.boundingbox, damage); +@@ -774,6 +826,16 @@ draw_view(struct weston_view *ev, struct weston_output *output, + glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter); + } + ++ /* If using EGLStreams, we need to acquire the new frame, if any */ ++ if (gs->egl_stream != EGL_NO_STREAM_KHR && ++ stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) { ++ if (gr->stream_consumer_acquire(gr->egl_display, ++ gs->egl_stream) != EGL_TRUE) ++ goto out; ++ ++ gs->stream_frame_acquired = true; ++ } ++ + /* blended region is whole surface minus opaque region: */ + pixman_region32_init_rect(&surface_blend, 0, 0, + ev->surface->width, ev->surface->height); +@@ -1193,6 +1255,37 @@ gl_renderer_repaint_output(struct weston_output *output, + } + + static int ++gl_renderer_output_stream_flip(struct weston_output *output, ++ void *flip_data) ++{ ++#ifdef EGL_EXT_stream_acquire_mode ++ struct gl_output_state *go = get_output_state(output); ++ struct weston_compositor *compositor = output->compositor; ++ struct gl_renderer *gr = get_renderer(compositor); ++ ++ EGLAttrib acquire_attribs[3] = { EGL_NONE }; ++ ++#ifdef EGL_NV_output_drm_flip_event ++ if (gr->has_egl_output_drm_flip_event) { ++ acquire_attribs[0] = EGL_DRM_FLIP_EVENT_DATA_NV; ++ acquire_attribs[1] = (EGLAttrib)flip_data; ++ acquire_attribs[2] = EGL_NONE; ++ } ++#endif ++ ++ if (go->egl_stream != EGL_NO_STREAM_KHR) ++ if (EGL_TRUE != gr->stream_consumer_acquire_attrib(gr->egl_display, ++ go->egl_stream, ++ acquire_attribs)) ++ return -1; ++ ++ return 0; ++#else ++ return -1; ++#endif ++} ++ ++static int + gl_renderer_read_pixels(struct weston_output *output, + pixman_format_code_t format, void *pixels, + uint32_t x, uint32_t y, +@@ -1884,6 +1977,72 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface, + } + + static void ++gl_renderer_attach_egl_fd_texture(struct weston_surface *es, ++ struct weston_buffer *buffer, ++ EGLNativeFileDescriptorKHR streamFd) ++{ ++ struct weston_compositor *ec = es->compositor; ++ struct gl_renderer *gr = get_renderer(ec); ++ struct gl_surface_state *gs = get_surface_state(es); ++ ++ /* If an invalid streamFd is provided, either there was an error creating ++ * the buffer or this buffer is already attached. Either case, there's ++ * nothing to be done */ ++ if (streamFd < 0) ++ return; ++ ++ /* Clean up current stream resources, if needed */ ++ if (gs->egl_stream != EGL_NO_STREAM_KHR) { ++ gr->destroy_stream(gr->egl_display, gs->egl_stream); ++ gs->egl_stream = EGL_NO_STREAM_KHR; ++ gs->stream_frame_acquired = false; ++ } ++ ++ gs->egl_stream = ++ gr->create_stream_from_file_descriptor(gr->egl_display, streamFd); ++ close(streamFd); ++ ++ if (gs->egl_stream == EGL_NO_STREAM_KHR) { ++ weston_log("failed to create egl stream\n"); ++ goto err_attach_egl_fd_base; ++ } ++ ++ gs->shader = &gr->texture_shader_egl_external; ++ gs->target = GL_TEXTURE_EXTERNAL_OES; ++ ++ glActiveTexture(GL_TEXTURE0); ++ ensure_textures(gs, 1); ++ glBindTexture(gs->target, gs->textures[0]); ++ ++ if (gr->stream_consumer_gltexture(gr->egl_display, gs->egl_stream) != EGL_TRUE) { ++ weston_log("failed to set stream consumer\n"); ++ goto err_attach_egl_fd_stream; ++ } ++ ++ buffer->legacy_buffer = (void *)buffer->resource; ++ gr->query_buffer(gr->egl_display, buffer->legacy_buffer, ++ EGL_WIDTH, &buffer->width); ++ gr->query_buffer(gr->egl_display, buffer->legacy_buffer, ++ EGL_HEIGHT, &buffer->height); ++ buffer->y_inverted = 0; ++ ++ gs->pitch = buffer->width; ++ gs->height = buffer->height; ++ gs->buffer_type = BUFFER_TYPE_EGL; ++ gs->y_inverted = buffer->y_inverted; ++ ++ return; ++ ++err_attach_egl_fd_stream: ++ gr->destroy_stream(gr->egl_display, gs->egl_stream); ++ gs->egl_stream = EGL_NO_STREAM_KHR; ++ ++err_attach_egl_fd_base: ++ gl_renderer_print_egl_error_state(); ++ return; ++} ++ ++static void + gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) + { + struct weston_compositor *ec = es->compositor; +@@ -1891,6 +2050,7 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) + struct gl_surface_state *gs = get_surface_state(es); + struct wl_shm_buffer *shm_buffer; + struct linux_dmabuf_buffer *dmabuf; ++ EGLNativeFileDescriptorKHR streamFd; + EGLint format; + int i; + +@@ -1906,6 +2066,13 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) + gs->num_textures = 0; + gs->buffer_type = BUFFER_TYPE_NULL; + gs->y_inverted = 1; ++ ++ if (gs->egl_stream != EGL_NO_STREAM_KHR) { ++ gr->destroy_stream(gr->egl_display, gs->egl_stream); ++ gs->egl_stream = EGL_NO_STREAM_KHR; ++ gs->stream_frame_acquired = false; ++ } ++ + return; + } + +@@ -1918,7 +2085,11 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) + gl_renderer_attach_egl(es, buffer, format); + else if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) + gl_renderer_attach_dmabuf(es, buffer, dmabuf); +- else { ++ else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource, ++ EGL_WAYLAND_BUFFER_WL, &streamFd)) { ++ /* FIXME: WL_bind_wayland_display violation */ ++ gl_renderer_attach_egl_fd_texture(es, buffer, streamFd); ++ } else { + weston_log("unhandled buffer type!\n"); + weston_buffer_reference(&gs->buffer_ref, NULL); + gs->buffer_type = BUFFER_TYPE_NULL; +@@ -2106,6 +2277,10 @@ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr) + + weston_buffer_reference(&gs->buffer_ref, NULL); + pixman_region32_fini(&gs->texture_damage); ++ ++ if (gs->egl_stream != EGL_NO_STREAM_KHR) ++ gr->destroy_stream(gr->egl_display, gs->egl_stream); ++ + free(gs); + } + +@@ -2156,6 +2331,8 @@ gl_renderer_create_surface(struct weston_surface *surface) + + gs->surface = surface; + ++ gs->egl_stream = EGL_NO_STREAM_KHR; ++ + pixman_region32_init(&gs->texture_damage); + surface->renderer_state = gs; + +@@ -2587,9 +2764,92 @@ gl_renderer_create_window_surface(struct gl_renderer *gr, + return egl_surface; + } + ++static EGLSurface ++gl_renderer_create_stream_surface(struct gl_renderer *gr, ++ uint32_t plane_id, ++ uint32_t crtc_id, ++ EGLint width, EGLint height, ++ EGLStreamKHR *egl_stream) ++{ ++ EGLint stream_attribs[] = { ++ EGL_STREAM_FIFO_LENGTH_KHR, 1, ++#ifdef EGL_EXT_stream_acquire_mode ++ EGL_CONSUMER_AUTO_ACQUIRE_EXT, EGL_FALSE, ++#endif ++ EGL_NONE ++ }; ++ EGLAttrib output_attribs[3]; ++ EGLint stream_producer_attribs[] = { ++ EGL_WIDTH, width, ++ EGL_HEIGHT, height, ++ EGL_NONE ++ }; ++ ++ EGLint num_layers; ++ EGLOutputLayerEXT output_layer; ++ EGLSurface egl_surface = EGL_NO_SURFACE; ++ ++ *egl_stream = gr->create_stream(gr->egl_display, stream_attribs); ++ ++ if (*egl_stream == EGL_NO_STREAM_KHR) { ++ weston_log("Failed to create EGL stream.\n"); ++ goto err_egl_create_surf_base; ++ } ++ ++ if (plane_id != ~0u) { ++ output_attribs[0] = EGL_DRM_PLANE_EXT; ++ output_attribs[1] = plane_id; ++ } else { ++ assert(crtc_id != ~0u); ++ output_attribs[0] = EGL_DRM_CRTC_EXT; ++ output_attribs[1] = crtc_id; ++ } ++ output_attribs[2] = EGL_NONE; ++ ++ if (gr->get_output_layers(gr->egl_display, ++ output_attribs, ++ &output_layer, ++ 1, &num_layers) != EGL_TRUE) { ++ weston_log("Failed to get output layer.\n"); ++ goto err_egl_create_surf_stream; ++ } ++ ++ if (num_layers < 1) { ++ weston_log("Unable to find output layers.\n"); ++ goto err_egl_create_surf_stream; ++ } ++ ++ if (gr->stream_consumer_output(gr->egl_display, *egl_stream, ++ output_layer) != EGL_TRUE) { ++ weston_log("Failed to set EGL stream consumer.\n"); ++ goto err_egl_create_surf_stream; ++ } ++ ++ egl_surface = gr->create_stream_producer_surface(gr->egl_display, ++ gr->egl_config, ++ *egl_stream, ++ stream_producer_attribs); ++ ++ if (egl_surface == EGL_NO_SURFACE) { ++ weston_log("Failed to create EGL producer surface.\n"); ++ goto err_egl_create_surf_stream; ++ } ++ ++ return egl_surface; ++ ++err_egl_create_surf_stream: ++ gr->destroy_stream(gr->egl_display, *egl_stream); ++ *egl_stream = EGL_NO_STREAM_KHR; ++ ++err_egl_create_surf_base: ++ gl_renderer_print_egl_error_state(); ++ return EGL_NO_SURFACE; ++} ++ + static int + gl_renderer_output_create(struct weston_output *output, +- EGLSurface surface) ++ EGLSurface surface, ++ EGLStreamKHR stream) + { + struct weston_compositor *ec = output->compositor; + struct gl_renderer *gr = get_renderer(ec); +@@ -2611,6 +2871,7 @@ gl_renderer_output_create(struct weston_output *output, + return -1; + + go->egl_surface = surface; ++ go->egl_stream = stream; + + for (i = 0; i < BUFFER_DAMAGE_COUNT; i++) + pixman_region32_init(&go->buffer_damage[i]); +@@ -2639,13 +2900,41 @@ gl_renderer_output_window_create(struct weston_output *output, + config_attribs, + visual_id, n_ids); + +- ret = gl_renderer_output_create(output, egl_surface); ++ ret = gl_renderer_output_create(output, egl_surface, EGL_NO_STREAM_KHR); + if (ret < 0 && egl_surface != EGL_NO_SURFACE) + eglDestroySurface(gr->egl_display, egl_surface); + + return ret; + } + ++static int ++gl_renderer_output_stream_create(struct weston_output *output, ++ uint32_t plane_id, uint32_t crtc_id) ++{ ++ struct weston_compositor *ec = output->compositor; ++ struct gl_renderer *gr = get_renderer(ec); ++ EGLSurface egl_surface = EGL_NO_SURFACE; ++ EGLStreamKHR egl_stream = EGL_NO_STREAM_KHR; ++ int ret; ++ ++ egl_surface = ++ gl_renderer_create_stream_surface(gr, ++ plane_id, crtc_id, ++ output->current_mode->width, ++ output->current_mode->height, ++ &egl_stream); ++ ++ ret = gl_renderer_output_create(output, egl_surface, egl_stream); ++ if (ret < 0) { ++ if (egl_surface != EGL_NO_SURFACE) ++ eglDestroySurface(gr->egl_display, egl_surface); ++ if (egl_stream != EGL_NO_STREAM_KHR) ++ gr->destroy_stream(gr->egl_display, egl_stream); ++ } ++ ++ return ret; ++} ++ + static void + gl_renderer_output_destroy(struct weston_output *output) + { +@@ -2658,6 +2947,9 @@ gl_renderer_output_destroy(struct weston_output *output) + + eglDestroySurface(gr->egl_display, go->egl_surface); + ++ if (go->egl_stream != EGL_NO_STREAM_KHR) ++ gr->destroy_stream(gr->egl_display, go->egl_stream); ++ + free(go); + } + +@@ -2762,6 +3054,26 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec) + (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL"); + gr->query_buffer = + (void *) eglGetProcAddress("eglQueryWaylandBufferWL"); ++ gr->create_stream = (void *) eglGetProcAddress("eglCreateStreamKHR"); ++ gr->destroy_stream = (void *) eglGetProcAddress("eglDestroyStreamKHR"); ++ gr->query_stream = (void *) eglGetProcAddress("eglQueryStreamKHR"); ++ gr->create_stream_producer_surface = ++ (void *) eglGetProcAddress("eglCreateStreamProducerSurfaceKHR"); ++ gr->stream_consumer_output = ++ (void *) eglGetProcAddress("eglStreamConsumerOutputEXT"); ++ gr->get_output_layers = (void *) eglGetProcAddress("eglGetOutputLayersEXT"); ++ gr->query_output_layer_attrib = ++ (void *) eglGetProcAddress("eglQueryOutputLayerAttribEXT"); ++ gr->create_stream_from_file_descriptor = ++ (void *) eglGetProcAddress("eglCreateStreamFromFileDescriptorKHR"); ++ gr->stream_consumer_gltexture = ++ (void *) eglGetProcAddress("eglStreamConsumerGLTextureExternalKHR"); ++ gr->stream_consumer_acquire = ++ (void *) eglGetProcAddress("eglStreamConsumerAcquireKHR"); ++#ifdef EGL_EXT_stream_acquire_mode ++ gr->stream_consumer_acquire_attrib = ++ (void *) eglGetProcAddress("eglStreamConsumerAcquireAttribEXT"); ++#endif + + extensions = + (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS); +@@ -2803,6 +3115,33 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec) + gr->has_dmabuf_import = 1; + #endif + ++ if (check_extension(extensions, "EGL_KHR_stream")) ++ gr->has_egl_stream = 1; ++ ++ if (check_extension(extensions, "EGL_KHR_stream_producer_eglsurface")) ++ gr->has_egl_stream_producer_eglsurface = 1; ++ ++ if (check_extension(extensions, "EGL_EXT_stream_consumer_egloutput")) ++ gr->has_egl_stream_consumer_egloutput = 1; ++ ++ if (check_extension(extensions, "EGL_KHR_stream_consumer_gltexture")) ++ gr->has_egl_stream_consumer_gltexture = 1; ++ ++ if (check_extension(extensions, "EGL_EXT_stream_acquire_mode")) ++ gr->has_egl_stream_acquire_mode = 1; ++ ++ if (check_extension(extensions, "EGL_EXT_output_base")) ++ gr->has_egl_output_base = 1; ++ ++ if (check_extension(extensions, "EGL_EXT_output_drm")) ++ gr->has_egl_output_drm = 1; ++ ++ if (check_extension(extensions, "EGL_NV_output_drm_flip_event")) ++ gr->has_egl_output_drm_flip_event = 1; ++ ++ if (check_extension(extensions, "EGL_KHR_stream_cross_process_fd")) ++ gr->has_egl_stream_cross_process_fd = 1; ++ + renderer_setup_egl_client_extensions(gr); + + return 0; +@@ -2828,6 +3167,16 @@ static const EGLint gl_renderer_alpha_attribs[] = { + EGL_NONE + }; + ++static const EGLint gl_renderer_opaque_stream_attribs[] = { ++ EGL_SURFACE_TYPE, EGL_STREAM_BIT_KHR, ++ EGL_RED_SIZE, 1, ++ EGL_GREEN_SIZE, 1, ++ EGL_BLUE_SIZE, 1, ++ EGL_ALPHA_SIZE, 0, ++ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, ++ EGL_NONE ++}; ++ + /** Checks whether a platform EGL client extension is supported + * + * \param ec The weston compositor +@@ -2900,6 +3249,8 @@ platform_to_extension(EGLenum platform) + return "wayland"; + case EGL_PLATFORM_X11_KHR: + return "x11"; ++ case EGL_PLATFORM_DEVICE_EXT: ++ return "device"; + default: + assert(0 && "bad EGL platform enum"); + } +@@ -2985,6 +3336,38 @@ gl_renderer_create(struct weston_compositor *ec, EGLenum platform, + if (gl_renderer_setup_egl_extensions(ec) < 0) + goto fail_with_error; + ++ if (platform == EGL_PLATFORM_DEVICE_EXT) { ++ if (!gr->has_egl_output_base || ++ !gr->has_egl_output_drm || ++ !gr->has_egl_stream || ++ !gr->has_egl_stream_producer_eglsurface || ++ !gr->has_egl_stream_consumer_egloutput || ++ !gr->has_egl_stream_consumer_gltexture || ++ !gr->has_egl_stream_acquire_mode || ++ !gr->has_egl_stream_cross_process_fd) { ++ weston_log("following required extensions not supported:\n" ++ "%s%s%s%s%s%s%s%s", ++ (gr->has_egl_output_base ? " EGL_EXT_output_base\n" : ""), ++ (gr->has_egl_output_drm ? " EGL_EXT_output_drm\n" : ""), ++ (gr->has_egl_stream ? " EGL_KHR_stream\n" : ""), ++ (gr->has_egl_stream_producer_eglsurface ? ++ " EGL_KHR_stream_producer_eglsurface\n" : ""), ++ (gr->has_egl_stream_consumer_egloutput ? ++ " EGL_EXT_stream_consumer_egloutput\n" : ""), ++ (gr->has_egl_stream_consumer_gltexture ? ++ " EGL_KHR_stream_consumer_gltexture\n" : ""), ++ (gr->has_egl_stream_acquire_mode ? ++ " EGL_EXT_stream_acquire_mode\n" : ""), ++ (gr->has_egl_stream_cross_process_fd ? ++ " EGL_KHR_stream_cross_process_fd\n" : "")); ++ goto fail_terminate; ++ } ++ ++ if (!gr->has_egl_output_drm_flip_event) ++ weston_log("warning: EGL page flip event notification not" ++ " supported\n"); ++ } ++ + wl_list_init(&gr->dmabuf_images); + if (gr->has_dmabuf_import) + gr->base.import_dmabuf = gl_renderer_import_dmabuf; +@@ -3176,15 +3559,100 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface) + return 0; + } + ++static int ++gl_renderer_get_devices(EGLint max_devices, EGLDeviceEXT *devices, ++ EGLint *num_devices) ++{ ++ const char *extensions; ++ PFNEGLQUERYDEVICESEXTPROC query_devices; ++ ++ extensions = (const char *)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); ++ if (!extensions) { ++ weston_log("Retrieving EGL extension string failed.\n"); ++ return -1; ++ } ++ ++ if (!check_extension(extensions, "EGL_EXT_device_base")) { ++ weston_log("EGL_EXT_device_base not supported\n"); ++ return -1; ++ } ++ ++ query_devices = (void *) eglGetProcAddress("eglQueryDevicesEXT"); ++ if (!query_devices) { ++ weston_log("Failed to get eglQueryDevicesEXT function\n"); ++ return -1; ++ } ++ ++ if (query_devices(max_devices, devices, num_devices) != EGL_TRUE) { ++ weston_log("Failed to query EGL Devices\n"); ++ gl_renderer_print_egl_error_state(); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++gl_renderer_get_drm_device_file(EGLDeviceEXT device, ++ const char **drm_device_file) ++{ ++ const char *extensions; ++ PFNEGLQUERYDEVICESTRINGEXTPROC query_device_string; ++ ++ extensions = (const char *)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); ++ if (!extensions) { ++ weston_log("Retrieving EGL extension string failed.\n"); ++ return -1; ++ } ++ ++ if (!check_extension(extensions, "EGL_EXT_device_base")) { ++ weston_log("EGL_EXT_device_base not supported.\n"); ++ return -1; ++ } ++ ++ query_device_string = (void *) eglGetProcAddress("eglQueryDeviceStringEXT"); ++ if (!query_device_string) { ++ weston_log("Failed to get eglQueryDeviceStringEXT function\n"); ++ return -1; ++ } ++ ++ extensions = query_device_string(device, EGL_EXTENSIONS); ++ if (!extensions) { ++ weston_log("Retrieving EGL extension string failed.\n"); ++ return -1; ++ } ++ ++ if (!check_extension(extensions, "EGL_EXT_device_drm")) { ++ weston_log("EGL_EXT_device_drm not supported.\n"); ++ return -1; ++ } ++ ++ (*drm_device_file) = query_device_string(device, EGL_DRM_DEVICE_FILE_EXT); ++ if (*drm_device_file == NULL) { ++ weston_log("Failed to query DRM device name.\n"); ++ gl_renderer_print_egl_error_state(); ++ return -1; ++ } ++ ++ return 0; ++} ++ + WL_EXPORT struct gl_renderer_interface gl_renderer_interface = { + .opaque_attribs = gl_renderer_opaque_attribs, + .alpha_attribs = gl_renderer_alpha_attribs, ++ .opaque_stream_attribs = gl_renderer_opaque_stream_attribs, + + .create = gl_renderer_create, + .display = gl_renderer_display, + .output_window_create = gl_renderer_output_window_create, ++ .output_stream_create = gl_renderer_output_stream_create, + .output_destroy = gl_renderer_output_destroy, + .output_surface = gl_renderer_output_surface, + .output_set_border = gl_renderer_output_set_border, +- .print_egl_error_state = gl_renderer_print_egl_error_state ++ .print_egl_error_state = gl_renderer_print_egl_error_state, ++ ++ .get_devices = gl_renderer_get_devices, ++ .get_drm_device_file = gl_renderer_get_drm_device_file, ++ ++ .output_stream_flip = gl_renderer_output_stream_flip + }; +diff --git a/src/gl-renderer.h b/src/gl-renderer.h +index af8dd267e700..d1dc009b2f5e 100644 +--- a/src/gl-renderer.h ++++ b/src/gl-renderer.h +@@ -62,6 +62,10 @@ typedef EGLSurface (*PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, + #define EGL_PLATFORM_X11_KHR 0x31D5 + #endif + ++#ifndef EGL_PLATFORM_DEVICE_EXT ++#define EGL_PLATFORM_DEVICE_EXT 0x313F ++#endif ++ + #define NO_EGL_PLATFORM 0 + + enum gl_renderer_border_side { +@@ -74,6 +78,7 @@ enum gl_renderer_border_side { + struct gl_renderer_interface { + const EGLint *opaque_attribs; + const EGLint *alpha_attribs; ++ const EGLint *opaque_stream_attribs; + + int (*create)(struct weston_compositor *ec, + EGLenum platform, +@@ -92,6 +97,9 @@ struct gl_renderer_interface { + const EGLint *visual_id, + const int n_ids); + ++ int (*output_stream_create)(struct weston_output *output, ++ uint32_t plane_id, uint32_t crtc_id); ++ + void (*output_destroy)(struct weston_output *output); + + EGLSurface (*output_surface)(struct weston_output *output); +@@ -129,5 +137,23 @@ struct gl_renderer_interface { + int32_t tex_width, unsigned char *data); + + void (*print_egl_error_state)(void); ++ ++ int (*get_devices)(EGLint max_devices, ++ EGLDeviceEXT *devices, ++ EGLint *num_devices); ++ ++ int (*get_drm_device_file)(EGLDeviceEXT device, ++ const char **drm_device_file); ++ ++ /* ++ * output_stream_flip() makes the EGLOutput consumer attached to the ++ * corresponding <output> stream acquire the new available frame ++ * (repaint_output() has been called previously) and queue a page flip. ++ * Whenever DRM is the underlying API and EGL_NV_output_drm_flip_event is ++ * supported, page flip notification can be requested by passing a non-NULL ++ * <flip_data> pointer. Otherwise, compositors should rely on a different ++ * mechanism in order to re-schedule output repaints. ++ */ ++ int (*output_stream_flip)(struct weston_output *output, void *flip_data); + }; + +diff --git a/src/weston-egl-ext.h b/src/weston-egl-ext.h +index 32f6108fbb83..2faab1567c77 100644 +--- a/src/weston-egl-ext.h ++++ b/src/weston-egl-ext.h +@@ -116,5 +116,24 @@ typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) ( + #define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A + #endif + ++/* ++ * FIXME: Remove both EGL_EXT_stream_acquire_mode and ++ * EGL_NV_output_drm_flip_event definitions below once both extensions ++ * get published by Khronos and incorportated into Khronos' header files ++ */ ++#ifndef EGL_EXT_stream_acquire_mode ++#define EGL_EXT_stream_acquire_mode 1 ++#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B ++typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); ++#ifdef EGL_EGLEXT_PROTOTYPES ++EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribEXT (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); ++#endif ++#endif /* EGL_EXT_stream_acquire_mode */ ++ ++#ifndef EGL_NV_output_drm_flip_event ++#define EGL_NV_output_drm_flip_event 1 ++#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E ++#endif /* EGL_NV_output_drm_flip_event */ ++ + + #endif +-- +2.7.4 + diff --git a/0005-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch b/0005-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch new file mode 100644 index 000000000000..3c98a74abc15 --- /dev/null +++ b/0005-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch @@ -0,0 +1,82 @@ +From 851f5b55210835e6e7c5699d87e18e09cbbe69e3 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Mon, 21 Mar 2016 17:37:35 +0100 +Subject: [PATCH 5/7] compositor-drm: Gracefully handle vblank and flip invalid + timestamps +X-NVConfidentiality: public + +Instant query for vblank timestamp may always fail, resulting in +never scheduling a full repaint in drm_output_start_repaint_loop(). + +Additionally, timestamp provided in page_flip_handler() may also be +invalid. + +This change makes both drm_output_start_repaint_loop() and +page_flip_handler() to schedule a full repaint in any of the +situations above. + +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +Reviewed-by: Andy Ritger <aritger@nvidia.com> +--- + src/compositor-drm.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/src/compositor-drm.c b/src/compositor-drm.c +index ded15f83c3e6..a6d4573a922f 100644 +--- a/src/compositor-drm.c ++++ b/src/compositor-drm.c +@@ -1,6 +1,7 @@ + /* + * Copyright © 2008-2011 Kristian Høgsberg + * Copyright © 2011 Intel Corporation ++ * Copyright © 2016 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the +@@ -761,8 +762,16 @@ drm_output_start_repaint_loop(struct weston_output *output_base) + vbl.request.type |= drm_waitvblank_pipe(output); + ret = drmWaitVBlank(backend->drm.fd, &vbl); + +- /* Error ret or zero timestamp means failure to get valid timestamp */ +- if ((ret == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) { ++ if (ret) { ++ /* Immediate query failed. It may always fail so we'll never get a valid ++ * timestamp to update msc and call into finish frame. Hence, jump to ++ * finish frame here. ++ */ ++ goto finish_frame; ++ } ++ ++ /* Zero timestamp means failure to get valid timestamp */ ++ if (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0) { + ts.tv_sec = vbl.reply.tval_sec; + ts.tv_nsec = vbl.reply.tval_usec * 1000; + +@@ -783,7 +792,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base) + } + } + +- /* Immediate query didn't provide valid timestamp. ++ /* Immediate query succeeded, but didn't provide valid timestamp. + * Use pageflip fallback. + */ + fb_id = output->current->fb_id; +@@ -869,6 +878,15 @@ page_flip_handler(int fd, unsigned int frame, + else if (!output->vblank_pending) { + ts.tv_sec = sec; + ts.tv_nsec = usec * 1000; ++ ++ /* Zero timestamp means failure to get valid timestamp, so immediately ++ * finish frame */ ++ if (ts.tv_sec == 0 && ts.tv_nsec == 0) { ++ weston_compositor_read_presentation_clock(output->base.compositor, ++ &ts); ++ flags = PRESENTATION_FEEDBACK_INVALID; ++ } ++ + weston_output_finish_frame(&output->base, &ts, flags); + + /* We can't call this from frame_notify, because the output's +-- +2.7.4 + diff --git a/0006-compositor-drm-Renaming-of-gbm-fields.patch b/0006-compositor-drm-Renaming-of-gbm-fields.patch new file mode 100644 index 000000000000..7048d84cad69 --- /dev/null +++ b/0006-compositor-drm-Renaming-of-gbm-fields.patch @@ -0,0 +1,228 @@ +From b50d1674382c982747b9091215bb02c860380fd9 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Mon, 21 Mar 2016 17:41:03 +0100 +Subject: [PATCH 6/7] compositor-drm: Renaming of gbm fields +X-NVConfidentiality: public + +In preparation for follow-on changes to support frame presentation +through EGLDevice+EGLOutput, this change includes the following: + - Rename drm_backend::format to gbm_format + - Rename drm_output::format to gbm_format + - Rename drm_output::surface to gbm_surface + - Rename drm_output::cursor_bo to gbm_cursor_bo + +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +Reviewed-by: Andy Ritger <aritger@nvidia.com> +Reviewed-by: Daniel Stone <daniels@collabora.com> +[Pekka: trivial rebase out of the series] +Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> + +(cherry picked from commit fcf4b6c0aef3d2e3afda5fa8a4d4127585f7231b) + +Conflicts: + src/compositor-drm.c +--- + src/compositor-drm.c | 58 ++++++++++++++++++++++++++-------------------------- + 1 file changed, 29 insertions(+), 29 deletions(-) + +diff --git a/src/compositor-drm.c b/src/compositor-drm.c +index a6d4573a922f..6c2816152307 100644 +--- a/src/compositor-drm.c ++++ b/src/compositor-drm.c +@@ -107,7 +107,7 @@ struct drm_backend { + uint32_t crtc_allocator; + uint32_t connector_allocator; + struct wl_listener session_listener; +- uint32_t format; ++ uint32_t gbm_format; + + /* we need these parameters in order to not fail drmModeAddFB2() + * due to out of bounds dimensions, and then mistakenly set +@@ -170,7 +170,7 @@ struct drm_output { + drmModeCrtcPtr original_crtc; + struct drm_edid edid; + drmModePropertyPtr dpms_prop; +- uint32_t format; ++ uint32_t gbm_format; + + enum dpms_enum dpms; + +@@ -178,8 +178,8 @@ struct drm_output { + int page_flip_pending; + int destroy_pending; + +- struct gbm_surface *surface; +- struct gbm_bo *cursor_bo[2]; ++ struct gbm_surface *gbm_surface; ++ struct gbm_bo *gbm_cursor_bo[2]; + struct weston_plane cursor_plane; + struct weston_plane fb_plane; + struct weston_view *cursor_view; +@@ -439,7 +439,7 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) + if (fb->is_client_buffer) + gbm_bo_destroy(fb->bo); + else +- gbm_surface_release_buffer(output->surface, ++ gbm_surface_release_buffer(output->gbm_surface, + fb->bo); + } + } +@@ -468,7 +468,7 @@ drm_output_check_scanout_format(struct drm_output *output, + pixman_region32_fini(&r); + } + +- if (output->format == format) ++ if (output->gbm_format == format) + return format; + + return 0; +@@ -531,16 +531,16 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) + output->base.compositor->renderer->repaint_output(&output->base, + damage); + +- bo = gbm_surface_lock_front_buffer(output->surface); ++ bo = gbm_surface_lock_front_buffer(output->gbm_surface); + if (!bo) { + weston_log("failed to lock front buffer: %m\n"); + return; + } + +- output->next = drm_fb_get_from_bo(bo, b, output->format); ++ output->next = drm_fb_get_from_bo(bo, b, output->gbm_format); + if (!output->next) { + weston_log("failed to get drm_fb for bo\n"); +- gbm_surface_release_buffer(output->surface, bo); ++ gbm_surface_release_buffer(output->gbm_surface, bo); + return; + } + } +@@ -1210,7 +1210,7 @@ drm_output_set_cursor(struct drm_output *output) + pixman_region32_fini(&output->cursor_plane.damage); + pixman_region32_init(&output->cursor_plane.damage); + output->current_cursor ^= 1; +- bo = output->cursor_bo[output->current_cursor]; ++ bo = output->gbm_cursor_bo[output->current_cursor]; + + cursor_bo_update(b, bo, ev); + handle = gbm_bo_get_handle(bo).s32; +@@ -1362,7 +1362,7 @@ drm_output_destroy(struct weston_output *output_base) + drm_output_fini_pixman(output); + } else { + gl_renderer->output_destroy(output_base); +- gbm_surface_destroy(output->surface); ++ gbm_surface_destroy(output->gbm_surface); + } + + weston_plane_release(&output->fb_plane); +@@ -1463,7 +1463,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo + } + } else { + gl_renderer->output_destroy(&output->base); +- gbm_surface_destroy(output->surface); ++ gbm_surface_destroy(output->gbm_surface); + + if (drm_output_init_egl(output, b) < 0) { + weston_log("failed to init output egl state with " +@@ -1595,8 +1595,8 @@ static int + drm_backend_create_gl_renderer(struct drm_backend *b) + { + EGLint format[3] = { +- b->format, +- fallback_format_for(b->format), ++ b->gbm_format, ++ fallback_format_for(b->gbm_format), + 0, + }; + int n_formats = 2; +@@ -1853,18 +1853,18 @@ static int + drm_output_init_egl(struct drm_output *output, struct drm_backend *b) + { + EGLint format[2] = { +- output->format, +- fallback_format_for(output->format), ++ output->gbm_format, ++ fallback_format_for(output->gbm_format), + }; + int i, flags, n_formats = 1; + +- output->surface = gbm_surface_create(b->gbm, ++ output->gbm_surface = gbm_surface_create(b->gbm, + output->base.current_mode->width, + output->base.current_mode->height, + format[0], + GBM_BO_USE_SCANOUT | + GBM_BO_USE_RENDERING); +- if (!output->surface) { ++ if (!output->gbm_surface) { + weston_log("failed to create gbm surface\n"); + return -1; + } +@@ -1872,28 +1872,28 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b) + if (format[1]) + n_formats = 2; + if (gl_renderer->output_window_create(&output->base, +- (EGLNativeWindowType)output->surface, +- output->surface, ++ (EGLNativeWindowType)output->gbm_surface, ++ output->gbm_surface, + gl_renderer->opaque_attribs, + format, + n_formats) < 0) { + weston_log("failed to create gl renderer output state\n"); +- gbm_surface_destroy(output->surface); ++ gbm_surface_destroy(output->gbm_surface); + return -1; + } + + flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE; + + for (i = 0; i < 2; i++) { +- if (output->cursor_bo[i]) ++ if (output->gbm_cursor_bo[i]) + continue; + +- output->cursor_bo[i] = ++ output->gbm_cursor_bo[i] = + gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height, + GBM_FORMAT_ARGB8888, flags); + } + +- if (output->cursor_bo[0] == NULL || output->cursor_bo[1] == NULL) { ++ if (output->gbm_cursor_bo[0] == NULL || output->gbm_cursor_bo[1] == NULL) { + weston_log("cursor buffers unavailable, using gl cursors\n"); + b->cursors_are_broken = 1; + } +@@ -2375,9 +2375,9 @@ create_output_for_connector(struct drm_backend *b, + free(s); + + if (get_gbm_format_from_section(section, +- b->format, +- &output->format) == -1) +- output->format = b->format; ++ b->gbm_format, ++ &output->gbm_format) == -1) ++ output->gbm_format = b->gbm_format; + + weston_config_section_get_string(section, "seat", &s, ""); + setup_output_seat_constraint(b, &output->base, s); +@@ -2992,7 +2992,7 @@ recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key, + struct drm_output, base.link); + + if (!output->recorder) { +- if (output->format != GBM_FORMAT_XRGB8888) { ++ if (output->gbm_format != GBM_FORMAT_XRGB8888) { + weston_log("failed to start vaapi recorder: " + "output format not supported\n"); + return; +@@ -3118,7 +3118,7 @@ drm_backend_create(struct weston_compositor *compositor, + section = weston_config_get_section(config, "core", NULL, NULL); + if (get_gbm_format_from_section(section, + GBM_FORMAT_XRGB8888, +- &b->format) == -1) ++ &b->gbm_format) == -1) + goto err_base; + + b->use_pixman = param->use_pixman; +-- +2.7.4 + diff --git a/0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch b/0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch new file mode 100644 index 000000000000..dc1cf8129649 --- /dev/null +++ b/0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch @@ -0,0 +1,552 @@ +From c285314728543280bf9ebd4e2776fe5cf4d096b1 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Mon, 21 Mar 2016 17:41:32 +0100 +Subject: [PATCH 7/7] compositor-drm: Add support for EGLDevice+EGLOutput +X-NVConfidentiality: public + +As previously stated, EGLDevice and EGLOutput will provide means +to access native device objects and different portions of display +control hardware respectively. + +Whenever EGL_EXT_device_drm extension is present, EGLDevice can +be used to enumerate and access DRM KMS devices, and EGLOutputLayer +to enumerate and access DRM KMS crtcs and planes. + +By using EGLStreams and attaching an EGLOutputLayer consumer +(representing a DRM KMS crtc or plane) to it, compositor-drm can +produce final composition frames and present them on a DRM device. + +This change adds required logic to support presentation through +EGLDevice+EGLOutput+EGLStream. Whether GBM or EGLDevice should be +used can be controlled by --use-egldevice backend argument. + +Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com> +Reviewed-by: Andy Ritger <aritger@nvidia.com> +Reviewed-by: Adam Cheney <acheney@nvidia.com> +--- + src/compositor-drm.c | 319 +++++++++++++++++++++++++++++++++++---------------- + src/main.c | 1 + + 2 files changed, 224 insertions(+), 96 deletions(-) + +diff --git a/src/compositor-drm.c b/src/compositor-drm.c +index 6c2816152307..58f916a27fc8 100644 +--- a/src/compositor-drm.c ++++ b/src/compositor-drm.c +@@ -75,6 +75,10 @@ + #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64 + #endif + ++#ifndef EGL_DRM_MASTER_FD_EXT ++#define EGL_DRM_MASTER_FD_EXT 0x333C ++#endif ++ + static int option_current_mode = 0; + + enum output_config { +@@ -101,7 +105,10 @@ struct drm_backend { + int fd; + char *filename; + } drm; ++ ++ EGLDeviceEXT egldevice; + struct gbm_device *gbm; ++ + uint32_t *crtcs; + int num_crtcs; + uint32_t crtc_allocator; +@@ -124,6 +131,7 @@ struct drm_backend { + int cursors_are_broken; + + int use_pixman; ++ int use_egldevice; + + uint32_t prev_state; + +@@ -225,6 +233,7 @@ struct drm_parameters { + int connector; + int tty; + int use_pixman; ++ int use_egldevice; + const char *seat_id; + }; + +@@ -531,17 +540,21 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage) + output->base.compositor->renderer->repaint_output(&output->base, + damage); + +- bo = gbm_surface_lock_front_buffer(output->gbm_surface); +- if (!bo) { +- weston_log("failed to lock front buffer: %m\n"); +- return; +- } ++ if (b->use_egldevice) ++ output->next = output->dumb[0]; ++ else { ++ bo = gbm_surface_lock_front_buffer(output->gbm_surface); ++ if (!bo) { ++ weston_log("failed to lock front buffer: %m\n"); ++ return; ++ } + +- output->next = drm_fb_get_from_bo(bo, b, output->gbm_format); +- if (!output->next) { +- weston_log("failed to get drm_fb for bo\n"); +- gbm_surface_release_buffer(output->gbm_surface, bo); +- return; ++ output->next = drm_fb_get_from_bo(bo, b, output->gbm_format); ++ if (!output->next) { ++ weston_log("failed to get drm_fb for bo\n"); ++ gbm_surface_release_buffer(output->gbm_surface, bo); ++ return; ++ } + } + } + +@@ -666,9 +679,14 @@ drm_output_repaint(struct weston_output *output_base, + output_base->set_dpms(output_base, WESTON_DPMS_ON); + } + +- if (drmModePageFlip(backend->drm.fd, output->crtc_id, +- output->next->fb_id, +- DRM_MODE_PAGE_FLIP_EVENT, output) < 0) { ++ if (backend->use_egldevice) ++ ret = gl_renderer->output_stream_flip(&output->base, output); ++ else ++ ret = drmModePageFlip(backend->drm.fd, output->crtc_id, ++ output->next->fb_id, ++ DRM_MODE_PAGE_FLIP_EVENT, output); ++ ++ if (ret < 0) { + weston_log("queueing pageflip failed: %m\n"); + goto err_pageflip; + } +@@ -739,7 +757,6 @@ drm_output_start_repaint_loop(struct weston_output *output_base) + struct drm_output *output = (struct drm_output *) output_base; + struct drm_backend *backend = (struct drm_backend *) + output_base->compositor->backend; +- uint32_t fb_id; + struct timespec ts, tnow; + struct timespec vbl2now; + int64_t refresh_nsec; +@@ -795,10 +812,14 @@ drm_output_start_repaint_loop(struct weston_output *output_base) + /* Immediate query succeeded, but didn't provide valid timestamp. + * Use pageflip fallback. + */ +- fb_id = output->current->fb_id; ++ if (backend->use_egldevice) ++ ret = gl_renderer->output_stream_flip(&output->base, output); ++ else ++ ret = drmModePageFlip(backend->drm.fd, output->crtc_id, ++ output->current->fb_id, ++ DRM_MODE_PAGE_FLIP_EVENT, output); + +- if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id, +- DRM_MODE_PAGE_FLIP_EVENT, output) < 0) { ++ if (ret < 0) { + weston_log("queueing pageflip failed: %m\n"); + goto finish_frame; + } +@@ -1328,6 +1349,9 @@ static void + drm_output_fini_pixman(struct drm_output *output); + + static void ++drm_output_fini_egl(struct drm_output *output); ++ ++static void + drm_output_destroy(struct weston_output *output_base) + { + struct drm_output *output = (struct drm_output *) output_base; +@@ -1358,12 +1382,10 @@ drm_output_destroy(struct weston_output *output_base) + b->crtc_allocator &= ~(1 << output->crtc_id); + b->connector_allocator &= ~(1 << output->connector_id); + +- if (b->use_pixman) { ++ if (b->use_pixman) + drm_output_fini_pixman(output); +- } else { +- gl_renderer->output_destroy(output_base); +- gbm_surface_destroy(output->gbm_surface); +- } ++ else ++ drm_output_fini_egl(output); + + weston_plane_release(&output->fb_plane); + weston_plane_release(&output->cursor_plane); +@@ -1462,9 +1484,7 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo + return -1; + } + } else { +- gl_renderer->output_destroy(&output->base); +- gbm_surface_destroy(output->gbm_surface); +- ++ drm_output_fini_egl(output); + if (drm_output_init_egl(output, b) < 0) { + weston_log("failed to init output egl state with " + "new mode"); +@@ -1551,11 +1571,6 @@ create_gbm_device(int fd) + { + struct gbm_device *gbm; + +- gl_renderer = weston_load_module("gl-renderer.so", +- "gl_renderer_interface"); +- if (!gl_renderer) +- return NULL; +- + /* GBM will load a dri driver, but even though they need symbols from + * libglapi, in some version of Mesa they are not linked to it. Since + * only the gl-renderer module links to it, the call above won't make +@@ -1568,6 +1583,39 @@ create_gbm_device(int fd) + return gbm; + } + ++static EGLDeviceEXT ++create_egldevice(const char *filename) ++{ ++ EGLDeviceEXT egldevice = EGL_NO_DEVICE_EXT; ++ EGLDeviceEXT *devices; ++ EGLint num_devices; ++ const char *drm_path; ++ int i; ++ ++ if (gl_renderer->get_devices(0, NULL, &num_devices) < 0 || ++ num_devices < 1) ++ return EGL_NO_DEVICE_EXT; ++ ++ devices = zalloc(num_devices * sizeof *devices); ++ if (!devices) ++ return EGL_NO_DEVICE_EXT; ++ ++ if (gl_renderer->get_devices(num_devices, devices, &num_devices) < 0) { ++ free(devices); ++ return EGL_NO_DEVICE_EXT; ++ } ++ ++ for (i = 0; i < num_devices; i++) ++ if (gl_renderer->get_drm_device_file(devices[i], &drm_path) == 0 && ++ strcmp(filename, drm_path) == 0) { ++ egldevice = devices[i]; ++ break; ++ } ++ ++ free(devices); ++ return egldevice; ++} ++ + /* When initializing EGL, if the preferred buffer format isn't available + * we may be able to susbstitute an ARGB format for an XRGB one. + * +@@ -1594,38 +1642,59 @@ fallback_format_for(uint32_t format) + static int + drm_backend_create_gl_renderer(struct drm_backend *b) + { +- EGLint format[3] = { ++ EGLint platform_attribs[] = { ++ EGL_DRM_MASTER_FD_EXT, b->drm.fd, ++ EGL_NONE ++ }; ++ EGLint format[] = { + b->gbm_format, + fallback_format_for(b->gbm_format), +- 0, ++ 0 + }; + int n_formats = 2; + + if (format[1]) + n_formats = 3; +- if (gl_renderer->create(b->compositor, +- EGL_PLATFORM_GBM_KHR, +- (void *)b->gbm, +- NULL, +- gl_renderer->opaque_attribs, +- format, +- n_formats) < 0) { +- return -1; +- } + +- return 0; ++ if (b->use_egldevice) ++ return gl_renderer->create(b->compositor, ++ EGL_PLATFORM_DEVICE_EXT, ++ (void *)b->egldevice, ++ platform_attribs, ++ gl_renderer->opaque_stream_attribs, ++ NULL, ++ 0); ++ else ++ return gl_renderer->create(b->compositor, ++ EGL_PLATFORM_GBM_KHR, ++ b->gbm, ++ NULL, ++ gl_renderer->opaque_attribs, ++ format, ++ n_formats); + } + + static int + init_egl(struct drm_backend *b) + { +- b->gbm = create_gbm_device(b->drm.fd); +- +- if (!b->gbm) ++ gl_renderer = weston_load_module("gl-renderer.so", ++ "gl_renderer_interface"); ++ if (!gl_renderer) + return -1; + ++ if (b->use_egldevice) { ++ b->egldevice = create_egldevice(b->drm.filename); ++ if (b->egldevice == EGL_NO_DEVICE_EXT) ++ return -1; ++ } else { ++ b->gbm = create_gbm_device(b->drm.fd); ++ if (!b->gbm) ++ return -1; ++ } ++ + if (drm_backend_create_gl_renderer(b) < 0) { +- gbm_device_destroy(b->gbm); ++ if (b->gbm) ++ gbm_device_destroy(b->gbm); + return -1; + } + +@@ -1852,55 +1921,94 @@ find_crtc_for_connector(struct drm_backend *b, + static int + drm_output_init_egl(struct drm_output *output, struct drm_backend *b) + { +- EGLint format[2] = { +- output->gbm_format, +- fallback_format_for(output->gbm_format), +- }; +- int i, flags, n_formats = 1; +- +- output->gbm_surface = gbm_surface_create(b->gbm, +- output->base.current_mode->width, +- output->base.current_mode->height, +- format[0], +- GBM_BO_USE_SCANOUT | +- GBM_BO_USE_RENDERING); +- if (!output->gbm_surface) { +- weston_log("failed to create gbm surface\n"); +- return -1; +- } ++ if (b->use_egldevice) { ++ int w = output->base.current_mode->width; ++ int h = output->base.current_mode->height; + +- if (format[1]) +- n_formats = 2; +- if (gl_renderer->output_window_create(&output->base, +- (EGLNativeWindowType)output->gbm_surface, +- output->gbm_surface, +- gl_renderer->opaque_attribs, +- format, +- n_formats) < 0) { +- weston_log("failed to create gl renderer output state\n"); +- gbm_surface_destroy(output->gbm_surface); +- return -1; +- } ++ /* Create a dumb fb for modesetting */ ++ output->dumb[0] = drm_fb_create_dumb(b, w, h); ++ if (!output->dumb[0]) { ++ weston_log("failed to create dumb framebuffer\n"); ++ return -1; ++ } + +- flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE; ++ if (gl_renderer->output_stream_create(&output->base, ~0u, ++ output->crtc_id) < 0) { ++ weston_log("failed to create gl renderer output stream state\n"); ++ drm_fb_destroy_dumb(output->dumb[0]); ++ output->dumb[0] = NULL; ++ return -1; ++ } + +- for (i = 0; i < 2; i++) { +- if (output->gbm_cursor_bo[i]) +- continue; ++ /* FIXME: Add hw planes and cursors for EGL device when supported */ ++ b->sprites_are_broken = 1; ++ b->cursors_are_broken = 1; ++ } else { ++ EGLint format[2] = { ++ output->gbm_format, ++ fallback_format_for(output->gbm_format), ++ }; ++ int i, flags, n_formats = 1; ++ ++ output->gbm_surface = gbm_surface_create(b->gbm, ++ output->base.current_mode->width, ++ output->base.current_mode->height, ++ format[0], ++ GBM_BO_USE_SCANOUT | ++ GBM_BO_USE_RENDERING); ++ if (!output->gbm_surface) { ++ weston_log("failed to create gbm surface\n"); ++ return -1; ++ } + +- output->gbm_cursor_bo[i] = +- gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height, +- GBM_FORMAT_ARGB8888, flags); +- } ++ if (format[1]) ++ n_formats = 2; ++ if (gl_renderer->output_window_create( ++ &output->base, ++ (EGLNativeWindowType)output->gbm_surface, ++ output->gbm_surface, ++ gl_renderer->opaque_attribs, ++ format, ++ n_formats) < 0) { ++ weston_log("failed to create gl renderer output state\n"); ++ gbm_surface_destroy(output->gbm_surface); ++ return -1; ++ } + +- if (output->gbm_cursor_bo[0] == NULL || output->gbm_cursor_bo[1] == NULL) { +- weston_log("cursor buffers unavailable, using gl cursors\n"); +- b->cursors_are_broken = 1; ++ flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE; ++ ++ for (i = 0; i < 2; i++) { ++ if (output->gbm_cursor_bo[i]) ++ continue; ++ ++ output->gbm_cursor_bo[i] = ++ gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height, ++ GBM_FORMAT_ARGB8888, flags); ++ } ++ ++ if (output->gbm_cursor_bo[0] == NULL || output->gbm_cursor_bo[1] == NULL) { ++ weston_log("cursor buffers unavailable, using gl cursors\n"); ++ b->cursors_are_broken = 1; ++ } + } + + return 0; + } + ++static void ++drm_output_fini_egl(struct drm_output *output) ++{ ++ gl_renderer->output_destroy(&output->base); ++ ++ if (output->dumb[0]) { ++ drm_fb_destroy_dumb(output->dumb[0]); ++ output->dumb[0] = NULL; ++ } ++ ++ if (output->gbm_surface) ++ gbm_surface_destroy(output->gbm_surface); ++} ++ + static int + drm_output_init_pixman(struct drm_output *output, struct drm_backend *b) + { +@@ -2374,10 +2482,11 @@ create_output_for_connector(struct drm_backend *b, + + free(s); + +- if (get_gbm_format_from_section(section, +- b->gbm_format, +- &output->gbm_format) == -1) +- output->gbm_format = b->gbm_format; ++ if (!b->use_egldevice) ++ if (get_gbm_format_from_section(section, ++ b->gbm_format, ++ &output->gbm_format) == -1) ++ output->gbm_format = b->gbm_format; + + weston_config_section_get_string(section, "seat", &s, ""); + setup_output_seat_constraint(b, &output->base, s); +@@ -2988,6 +3097,11 @@ recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key, + struct drm_output *output; + int width, height; + ++ if (b->use_egldevice) { ++ weston_log("recorder not supported with EGL device\n"); ++ return; ++ } ++ + output = container_of(b->compositor->output_list.next, + struct drm_output, base.link); + +@@ -3043,11 +3157,20 @@ switch_to_gl_renderer(struct drm_backend *b) + + weston_log("Switching to GL renderer\n"); + +- b->gbm = create_gbm_device(b->drm.fd); +- if (!b->gbm) { +- weston_log("Failed to create gbm device. " +- "Aborting renderer switch\n"); +- return; ++ if (b->use_egldevice) { ++ b->egldevice = create_egldevice(b->drm.filename); ++ if (b->egldevice == EGL_NO_DEVICE_EXT) { ++ weston_log("Failed to create EGL device. " ++ "Aborting renderer switch\n"); ++ return; ++ } ++ } else { ++ b->gbm = create_gbm_device(b->drm.fd); ++ if (!b->gbm) { ++ weston_log("Failed to create gbm device. " ++ "Aborting renderer switch\n"); ++ return; ++ } + } + + wl_list_for_each(output, &b->compositor->output_list, base.link) +@@ -3056,7 +3179,8 @@ switch_to_gl_renderer(struct drm_backend *b) + b->compositor->renderer->destroy(b->compositor); + + if (drm_backend_create_gl_renderer(b) < 0) { +- gbm_device_destroy(b->gbm); ++ if (b->gbm) ++ gbm_device_destroy(b->gbm); + weston_log("Failed to create GL renderer. Quitting.\n"); + /* FIXME: we need a function to shutdown cleanly */ + assert(0); +@@ -3122,6 +3246,7 @@ drm_backend_create(struct weston_compositor *compositor, + goto err_base; + + b->use_pixman = param->use_pixman; ++ b->use_egldevice = param->use_egldevice; + + /* Check if we run drm-backend using weston-launch */ + compositor->launcher = weston_launcher_connect(compositor, param->tty, +@@ -3246,7 +3371,8 @@ err_drm_source: + err_udev_input: + udev_input_destroy(&b->input); + err_sprite: +- gbm_device_destroy(b->gbm); ++ if (b->gbm) ++ gbm_device_destroy(b->gbm); + destroy_sprites(b); + err_udev_dev: + udev_device_unref(drm_device); +@@ -3275,6 +3401,7 @@ backend_init(struct weston_compositor *compositor, int *argc, char *argv[], + { WESTON_OPTION_INTEGER, "tty", 0, ¶m.tty }, + { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode }, + { WESTON_OPTION_BOOLEAN, "use-pixman", 0, ¶m.use_pixman }, ++ { WESTON_OPTION_BOOLEAN, "use-egldevice", 0, ¶m.use_egldevice }, + }; + + param.seat_id = default_seat; +diff --git a/src/main.c b/src/main.c +index 1850fa633554..2494414138a8 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -266,6 +266,7 @@ usage(int error_code) + " --seat=SEAT\t\tThe seat that weston should run on\n" + " --tty=TTY\t\tThe tty to use\n" + " --use-pixman\t\tUse the pixman (CPU) renderer\n" ++ " --use-egldevice\tUse EGLDevice and EGLOutput with the GL renderer\n" + " --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n"); + #endif + +-- +2.7.4 + @@ -1,21 +1,49 @@ -# $Id: PKGBUILD 162349 2016-02-18 12:04:33Z seblu $ -# Maintainer: Sébastien Luttringer +# Maintainer: Aaron Plattner <aplattner@nvidia.com> +# Contributor: Sébastien Luttringer # Contributor: Joel Teichroeb <joel@teichroeb.net> -pkgname=weston +pkgname=weston-eglstream pkgver=1.10.0 pkgrel=1 -pkgdesc='Reference implementation of a Wayland compositor' +pkgdesc='Reference implementation of a Wayland compositor with EGLStream support' arch=('i686' 'x86_64') url='http://wayland.freedesktop.org' license=('MIT') depends=('wayland' 'libxkbcommon' 'libinput' 'libunwind' 'poppler-glib' 'mtdev' 'libxcursor' 'glu' 'pango' 'colord') makedepends=('wayland-protocols') -source=("http://wayland.freedesktop.org/releases/$pkgname-$pkgver.tar.xz") -sha1sums=('c9c2c8e2e798b25e7bf6b31bf0c4ef08724a7ebb') +provides=('weston') +conflicts=('weston') +source=("http://wayland.freedesktop.org/releases/weston-$pkgver.tar.xz" + '0001-gl-renderer-Renaming-of-things-and-minor-improvement.patch' + '0002-gl-renderer-Refactor-gl_renderer_output_window_creat.patch' + '0003-gl-renderer-Implement-use-check_extension.patch' + '0004-gl-renderer-Add-support-for-EGLDevice-EGLOutput.patch' + '0005-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch' + '0006-compositor-drm-Renaming-of-gbm-fields.patch' + '0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch') +sha1sums=('c9c2c8e2e798b25e7bf6b31bf0c4ef08724a7ebb' + 'c623cdf628a20a4bde5a98cc40867c32a8300e79' + '3441d0a7da0ae64835a5b29545caab4bc7977417' + 'f6742fadb973ec6c2b55e5500127309e70579312' + '31e3a447a1209712d604d739d0ac7e5b1925e940' + 'b483f21b3f880d3978cc678bf5f97802f7ddddaf' + '13d217d76a0811f5eb8d7180d31ec7a69fbbaabd' + '6bab10ac02a7e69b1bb1bf1982b5804e87870e0e') + +prepare() { + cd weston-$pkgver + + patch -Np1 -i "${srcdir}/0001-gl-renderer-Renaming-of-things-and-minor-improvement.patch" + patch -Np1 -i "${srcdir}/0002-gl-renderer-Refactor-gl_renderer_output_window_creat.patch" + patch -Np1 -i "${srcdir}/0003-gl-renderer-Implement-use-check_extension.patch" + patch -Np1 -i "${srcdir}/0004-gl-renderer-Add-support-for-EGLDevice-EGLOutput.patch" + patch -Np1 -i "${srcdir}/0005-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch" + patch -Np1 -i "${srcdir}/0006-compositor-drm-Renaming-of-gbm-fields.patch" + patch -Np1 -i "${srcdir}/0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch" +} build() { - cd $pkgname-$pkgver + cd weston-$pkgver ./configure \ --prefix=/usr \ --libexecdir=/usr/lib/weston \ @@ -25,7 +53,7 @@ build() { } package() { - cd $pkgname-$pkgver + cd weston-$pkgver make DESTDIR="$pkgdir" install # license install -Dm644 COPYING "$pkgdir/usr/share/licenses/$pkgname/COPYING" |