On Mon, Mar 21, 2016 at 05:41:32PM +0100, Miguel A. Vico wrote: > 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 <mvicom...@nvidia.com> > Reviewed-by: Andy Ritger <arit...@nvidia.com> > Reviewed-by: Adam Cheney <ache...@nvidia.com>
Andy did a presentation about these extensions at xdc 2014, and consensus reply from folks (not just me) was "no way". I've seen a few other discussions fly by meanwhile, with exactly the same opinions. If you really can't have a display driver in the kernel, why not fake proper drm with something like CUSE (or well similar, probably need to interface with at least dma-bufs from the kernel blob somwehere)? Or just like use the existing kernel driver and improve that to suit your needs, like everyone else at least plans to. I don't expect you'll ever be able to sell this to the community and get it merged. -Daniel > --- > 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 ecb340d..82097ff 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 1850fa6..2494414 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.1 > > _______________________________________________ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/wayland-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel