diff options
Diffstat (limited to '0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch')
-rw-r--r-- | 0007-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch | 552 |
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, ¶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 + |