summarylogtreecommitdiffstats
path: root/0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch
diff options
context:
space:
mode:
Diffstat (limited to '0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch')
-rw-r--r--0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch552
1 files changed, 552 insertions, 0 deletions
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, &param.tty },
+ { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
+ { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &param.use_pixman },
++ { WESTON_OPTION_BOOLEAN, "use-egldevice", 0, &param.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
+