diff options
Diffstat (limited to '0011-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch')
-rw-r--r-- | 0011-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch | 559 |
1 files changed, 559 insertions, 0 deletions
diff --git a/0011-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch b/0011-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch new file mode 100644 index 000000000000..8fb95c0c0f71 --- /dev/null +++ b/0011-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch @@ -0,0 +1,559 @@ +From cb241882dc1903c2330dc68f08c21c76c9a14e91 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Thu, 28 Jan 2016 19:37:10 +0100 +Subject: [PATCH 11/11] 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> +Reviewed-by: James Jones <jajones@nvidia.com> + +[aplattner@nvidia.com: rebased on top of Weston 1.11.0] +--- + src/compositor-drm.c | 328 +++++++++++++++++++++++++++++++++++---------------- + src/compositor-drm.h | 3 + + src/main.c | 2 + + 3 files changed, 233 insertions(+), 100 deletions(-) + +diff --git a/src/compositor-drm.c b/src/compositor-drm.c +index 51d90e1d6437..0844cec9f570 100644 +--- a/src/compositor-drm.c ++++ b/src/compositor-drm.c +@@ -76,6 +76,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 ++ + struct drm_backend { + struct weston_backend base; + struct weston_compositor *compositor; +@@ -91,7 +95,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; +@@ -114,6 +121,7 @@ struct drm_backend { + int cursors_are_broken; + + int use_pixman; ++ int use_egldevice; + + uint32_t prev_state; + +@@ -523,17 +531,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; ++ } + } + } + +@@ -658,9 +670,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; + } +@@ -731,7 +748,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; +@@ -787,10 +803,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; + } +@@ -1322,6 +1342,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; +@@ -1352,12 +1375,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); +@@ -1456,9 +1477,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"); +@@ -1545,11 +1564,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 +@@ -1562,6 +1576,39 @@ create_gbm_device(int fd) + return gbm; + } + ++static EGLDeviceEXT ++find_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 substitute an ARGB format for an XRGB one. + * +@@ -1588,38 +1635,61 @@ fallback_format_for(uint32_t format) + static int + drm_backend_create_gl_renderer(struct drm_backend *b) + { +- EGLint format[3] = { +- b->gbm_format, +- fallback_format_for(b->gbm_format), +- 0, +- }; +- int n_formats = 2; +- +- if (format[1]) +- n_formats = 3; +- if (gl_renderer->display_create(b->compositor, +- EGL_PLATFORM_GBM_KHR, +- (void *)b->gbm, +- NULL, +- gl_renderer->opaque_attribs, +- format, +- n_formats) < 0) { +- return -1; +- } ++ if (b->use_egldevice) { ++ EGLint device_platform_attribs[] = { ++ EGL_DRM_MASTER_FD_EXT, b->drm.fd, ++ EGL_NONE ++ }; + +- return 0; ++ return gl_renderer->display_create(b->compositor, ++ EGL_PLATFORM_DEVICE_EXT, ++ (void *)b->egldevice, ++ device_platform_attribs, ++ gl_renderer->opaque_stream_attribs, ++ NULL, ++ 0); ++ } else { ++ EGLint format[] = { ++ b->gbm_format, ++ fallback_format_for(b->gbm_format), ++ 0 ++ }; ++ int n_formats = 2; ++ ++ if (format[1]) ++ n_formats = 3; ++ ++ return gl_renderer->display_create(b->compositor, ++ EGL_PLATFORM_GBM_KHR, ++ (void *)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 = find_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; + } + +@@ -1846,55 +1916,95 @@ 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 black 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; ++ } ++ memset(output->dumb[0]->map, 0, output->dumb[0]->size); + +- 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) + { +@@ -2344,8 +2454,10 @@ create_output_for_connector(struct drm_backend *b, + + mode = b->configure_output(b->compositor, b->use_current_mode, + output->base.name, &config); +- if (parse_gbm_format(config.gbm_format, b->gbm_format, &output->gbm_format) == -1) +- output->gbm_format = b->gbm_format; ++ if (!b->use_egldevice && parse_gbm_format(config.gbm_format, ++ b->gbm_format, ++ &output->gbm_format) == -1) ++ output->gbm_format = b->gbm_format; + + setup_output_seat_constraint(b, &output->base, + config.seat ? config.seat : ""); +@@ -2955,6 +3067,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); + +@@ -3010,11 +3127,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 = find_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) +@@ -3023,7 +3149,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); +@@ -3080,6 +3207,7 @@ drm_backend_create(struct weston_compositor *compositor, + b->sprites_are_broken = 1; + b->compositor = compositor; + b->use_pixman = config->use_pixman; ++ b->use_egldevice = config->use_egldevice; + b->configure_output = config->configure_output; + b->use_current_mode = config->use_current_mode; + +diff --git a/src/compositor-drm.h b/src/compositor-drm.h +index 3f150dba28b3..816830434aeb 100644 +--- a/src/compositor-drm.h ++++ b/src/compositor-drm.h +@@ -87,6 +87,9 @@ struct weston_drm_backend_config { + /** Whether to use the pixman renderer instead of the OpenGL ES renderer. */ + bool use_pixman; + ++ /** Whether to use EGLDevice rather than GBM. */ ++ bool use_egldevice; ++ + /** The seat to be used for input and output. + * + * If NULL the default "seat0" will be used. The backend will +diff --git a/src/main.c b/src/main.c +index 3279ac6a8b02..ad1a1fc98344 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -277,6 +277,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 + +@@ -750,6 +751,7 @@ load_drm_backend(struct weston_compositor *c, const char *backend, + { WESTON_OPTION_INTEGER, "tty", 0, &config.tty }, + { WESTON_OPTION_BOOLEAN, "current-mode", 0, &config.use_current_mode }, + { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman }, ++ { WESTON_OPTION_BOOLEAN, "use-egldevice", 0, &config.use_egldevice }, + }; + + parse_options(options, ARRAY_LENGTH(options), argc, argv); +-- +2.8.3 + |