Re: [PATCH weston v2 2/3] compositor-drm: Add scanout support for linux_dmabuf buffers
Hi, Fabien Thanks for your reviewing. On 2016/10/05 0:45, Fabien DESSENNE wrote: > On 09/30/2016 11:28 AM, Tomohito Esaki wrote: >> +width = dmabuf->attributes.width; >> +height = dmabuf->attributes.height; >> +if (backend->min_width > width || >> +width > backend->max_width || >> +backend->min_height > height || >> +height > backend->max_height) >> +return NULL; > Just like in drm_fb_get_from_bo(), add an error log "bo geometry out of > bounds" I removed this logging in v2 because of the possibility of flooding the compoitor log, as Pekka pointed out (see below). Pekka wrote below for v1: On 2016/06/15 17:20, Pekka Paalanen wrote: > > Is there a possibility that if this triggers, it will trigger every > frame and flood the compositor log? > > If yes, I'd just remove this logging. The rest below are fine by me, > since those should not be failing, right? (https://lists.freedesktop.org/archives/wayland-devel/2016-June/029466.html) Otherwise I will update patches as you suggested. Best regards. -- -- IGEL Co., Ltd. Tomohito Esaki e...@igel.co.jp ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston v2 2/3] compositor-drm: Add scanout support for linux_dmabuf buffers
Hi, Derek Thanks for your reviewing and testing. On 2016/10/04 3:20, Derek Foreman wrote: > If I mess up redraw() to call exit(1); after drawing 100 frames I get > the same weston crash with intel_do_flush_locked failed. > > I don't have a lot of time to dig into this right now - can you test an > exit() with a full screen dmabuf surface on scanout on your driver stack? I tried testing on my ARM based platform and also on Intel Graphics and AMD stacks. I modified simple-dmabuf-intel as follows: * Create dmabuf buffer by using drmIoctl(fd, DRM_IOCTL_MODE_DUMB, ) insted of the Intel specific API. * Add full screen mode based on simple-egl. I tried exit()ing with a full screen dmabuf surface on scanout and on the Intel and AMD platforms weston crashed, but there wasn't any problem on my ARM board. Our graphics drivers don't use mesa, which the Intel and AMD do, so that may be a factor, but I'm not sure. Best regards. -- -- IGEL Co., Ltd. Tomohito Esaki e...@igel.co.jp ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH weston v2 2/3] compositor-drm: Add scanout support for linux_dmabuf buffers
Hi Thank you for the patch. Please, find some minor comments below. On 09/30/2016 11:28 AM, Tomohito Esaki wrote: > This implementations bypasses gbm and passes the dmabuf handles directly > to libdrm for composition. Maybe you can split the patch in two parts: - one part dealing with drm_fb_create_dmabuf (since this part is used by both scanout and sprites) - a second part dealing with scanout > > Signed-off-by: Tomohito Esaki> --- > libweston/compositor-drm.c | 125 > ++--- > 1 file changed, 107 insertions(+), 18 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index a707fc4..b15fa01 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -151,6 +151,9 @@ struct drm_fb { > > /* Used by dumb fbs */ > void *map; > + > + /* Used by dmabuf */ > + bool is_dmabuf; > }; > > struct drm_edid { > @@ -389,6 +392,76 @@ drm_fb_destroy_dumb(struct drm_fb *fb) > drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, _arg); > } > > +static inline void > +close_drm_handle(int fd, uint32_t handle) > +{ > + struct drm_gem_close gem_close = { .handle = handle }; > + int ret; > + > + ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, _close); > + if (ret) > + weston_log("DRM_IOCTL_GEM_CLOSE failed.(%s)\n", > +strerror(errno)); > +} > + > +static struct drm_fb * > +drm_fb_create_dmabuf(struct linux_dmabuf_buffer *dmabuf, > + struct drm_backend *backend, uint32_t format) > +{ > + struct drm_fb *fb = NULL; > + uint32_t width, height, fb_id, handles[4] = {0}; > + int i, ret; > + > + if (!format) > + return NULL; I do not think that this check is needed (you already checked format in the caller function + you can delegate this error handling to drmModeAddFB2) > + > + width = dmabuf->attributes.width; > + height = dmabuf->attributes.height; > + if (backend->min_width > width || > + width > backend->max_width || > + backend->min_height > height || > + height > backend->max_height) > + return NULL; Just like in drm_fb_get_from_bo(), add an error log "bo geometry out of bounds" > + > + for (i = 0; i < dmabuf->attributes.n_planes; i++) { > + ret = drmPrimeFDToHandle(backend->drm.fd, > + dmabuf->attributes.fd[i], > + [i]); > + if (ret) Add an error log here too (ex "drmPrimeFDToHandle failed") > + goto done; > + } > + > + ret = drmModeAddFB2(backend->drm.fd, width, height, > + format, handles, dmabuf->attributes.stride, > + dmabuf->attributes.offset, _id, 0); Flags are ignore here (using "0"). Suggesting to use something like this: if (dmabuf->attributes.flags & ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED) flags |= DRM_MODE_FB_INTERLACED; > + if (ret) > + goto done; Just like in drm_fb_get_from_bo(), add an error log "addfb2 failed" > + > + fb = zalloc(sizeof *fb); > + if (!fb) > + goto done; > + > + fb->fb_id = fb_id; > + fb->stride = dmabuf->attributes.stride[0]; > + fb->fd = backend->drm.fd; > + fb->is_dmabuf = true; > + > +done: > + for (i = 0; i < dmabuf->attributes.n_planes; i++) { > + if (!handles[i]) > + continue; > + close_drm_handle(backend->drm.fd, handles[i]); > + } > + > + return fb; > +} > + > +static void > +drm_fb_destroy_dmabuf(struct drm_fb *fb) > +{ > + drm_fb_destroy(fb, fb->fd); > +} > + > static struct drm_fb * > drm_fb_get_from_bo(struct gbm_bo *bo, > struct drm_backend *backend, uint32_t format) > @@ -475,6 +548,8 @@ drm_output_release_fb(struct drm_output *output, struct > drm_fb *fb) > if (fb->map && > (fb != output->dumb[0] && fb != output->dumb[1])) { > drm_fb_destroy_dumb(fb); > + } else if (fb->is_dmabuf) { > + drm_fb_destroy_dmabuf(fb); > } else if (fb->bo) { > if (fb->is_client_buffer) > gbm_bo_destroy(fb->bo); > @@ -486,12 +561,12 @@ drm_output_release_fb(struct drm_output *output, struct > drm_fb *fb) > > static uint32_t > drm_output_check_scanout_format(struct drm_output *output, > - struct weston_surface *es, struct gbm_bo *bo) > + struct weston_surface *es, uint32_t format) > { > - uint32_t format; > pixman_region32_t r; > > - format = gbm_bo_get_format(bo); > + /* We relay on the GBM format enum and DRM format enum to be > +identical */ > > if (format == GBM_FORMAT_ARGB) { > /* We can scanout an ARGB buffer if the surface's > @@ -521,12 +596,13 @@
Re: [PATCH weston v2 2/3] compositor-drm: Add scanout support for linux_dmabuf buffers
On 30/09/16 04:28 AM, Tomohito Esaki wrote: This implementations bypasses gbm and passes the dmabuf handles directly to libdrm for composition. Signed-off-by: Tomohito EsakiVery cool work! Acked-by: Derek Foreman I don't see anything here that Eric hasn't already mentioned, but I'm having a problem testing it. Running terminology (an EFL terminal emulator) with: ELM_ACCEL=shm EVAS_WAYLAND_SHM_USE_DMABUF=1 terminology if I hit f11 to go fullscreen, then ctrl-d to exit while fullscreen, weston exit()s directly from eglSwapBuffers() which logs: intel_do_flush_locked failed: No such file or directory While it was fullscreen damage tracking was completely flaky as well. I'm not 100% confident in EFL's damage updates, but it works well fullscreen without this weston patch... I've also tested with the intel-simple-dmabuf.c included with weston - I just added a zxdg_toplevel_v6_set_fullscreen(window->xdg_toplevel, NULL); at the very end of create_window(), and changed the create_window() call to have the same resolution as my screen - it also hits the scanout path. If I mess up redraw() to call exit(1); after drawing 100 frames I get the same weston crash with intel_do_flush_locked failed. I don't have a lot of time to dig into this right now - can you test an exit() with a full screen dmabuf surface on scanout on your driver stack? Thanks, Derek --- libweston/compositor-drm.c | 125 ++--- 1 file changed, 107 insertions(+), 18 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a707fc4..b15fa01 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -151,6 +151,9 @@ struct drm_fb { /* Used by dumb fbs */ void *map; + + /* Used by dmabuf */ + bool is_dmabuf; }; struct drm_edid { @@ -389,6 +392,76 @@ drm_fb_destroy_dumb(struct drm_fb *fb) drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, _arg); } +static inline void +close_drm_handle(int fd, uint32_t handle) +{ + struct drm_gem_close gem_close = { .handle = handle }; + int ret; + + ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, _close); + if (ret) + weston_log("DRM_IOCTL_GEM_CLOSE failed.(%s)\n", + strerror(errno)); +} + +static struct drm_fb * +drm_fb_create_dmabuf(struct linux_dmabuf_buffer *dmabuf, +struct drm_backend *backend, uint32_t format) +{ + struct drm_fb *fb = NULL; + uint32_t width, height, fb_id, handles[4] = {0}; + int i, ret; + + if (!format) + return NULL; + + width = dmabuf->attributes.width; + height = dmabuf->attributes.height; + if (backend->min_width > width || + width > backend->max_width || + backend->min_height > height || + height > backend->max_height) + return NULL; + + for (i = 0; i < dmabuf->attributes.n_planes; i++) { + ret = drmPrimeFDToHandle(backend->drm.fd, +dmabuf->attributes.fd[i], +[i]); + if (ret) + goto done; + } + + ret = drmModeAddFB2(backend->drm.fd, width, height, + format, handles, dmabuf->attributes.stride, + dmabuf->attributes.offset, _id, 0); + if (ret) + goto done; + + fb = zalloc(sizeof *fb); + if (!fb) + goto done; + + fb->fb_id = fb_id; + fb->stride = dmabuf->attributes.stride[0]; + fb->fd = backend->drm.fd; + fb->is_dmabuf = true; + +done: + for (i = 0; i < dmabuf->attributes.n_planes; i++) { + if (!handles[i]) + continue; + close_drm_handle(backend->drm.fd, handles[i]); + } + + return fb; +} + +static void +drm_fb_destroy_dmabuf(struct drm_fb *fb) +{ + drm_fb_destroy(fb, fb->fd); +} + static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, uint32_t format) @@ -475,6 +548,8 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) if (fb->map && (fb != output->dumb[0] && fb != output->dumb[1])) { drm_fb_destroy_dumb(fb); + } else if (fb->is_dmabuf) { + drm_fb_destroy_dmabuf(fb); } else if (fb->bo) { if (fb->is_client_buffer) gbm_bo_destroy(fb->bo); @@ -486,12 +561,12 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) static uint32_t drm_output_check_scanout_format(struct drm_output *output, - struct weston_surface *es, struct gbm_bo *bo) + struct weston_surface *es, uint32_t format) { - uint32_t format; pixman_region32_t r; -
Re: [PATCH weston v2 2/3] compositor-drm: Add scanout support for linux_dmabuf buffers
On Fri, Sep 30, 2016 at 06:28:52PM +0900, Tomohito Esaki wrote: > This implementations bypasses gbm and passes the dmabuf handles directly > to libdrm for composition. > > Signed-off-by: Tomohito Esaki> --- > libweston/compositor-drm.c | 125 > ++--- > 1 file changed, 107 insertions(+), 18 deletions(-) > > diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c > index a707fc4..b15fa01 100644 > --- a/libweston/compositor-drm.c > +++ b/libweston/compositor-drm.c > @@ -151,6 +151,9 @@ struct drm_fb { > > /* Used by dumb fbs */ > void *map; > + > + /* Used by dmabuf */ > + bool is_dmabuf; > }; > > struct drm_edid { > @@ -389,6 +392,76 @@ drm_fb_destroy_dumb(struct drm_fb *fb) > drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, _arg); > } > > +static inline void > +close_drm_handle(int fd, uint32_t handle) > +{ > + struct drm_gem_close gem_close = { .handle = handle }; > + int ret; > + > + ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, _close); > + if (ret) > + weston_log("DRM_IOCTL_GEM_CLOSE failed.(%s)\n", > +strerror(errno)); > +} > + > +static struct drm_fb * > +drm_fb_create_dmabuf(struct linux_dmabuf_buffer *dmabuf, > + struct drm_backend *backend, uint32_t format) > +{ > + struct drm_fb *fb = NULL; > + uint32_t width, height, fb_id, handles[4] = {0}; > + int i, ret; > + > + if (!format) > + return NULL; > + > + width = dmabuf->attributes.width; > + height = dmabuf->attributes.height; > + if (backend->min_width > width || > + width > backend->max_width || > + backend->min_height > height || > + height > backend->max_height) > + return NULL; > + > + for (i = 0; i < dmabuf->attributes.n_planes; i++) { > + ret = drmPrimeFDToHandle(backend->drm.fd, > + dmabuf->attributes.fd[i], > + [i]); > + if (ret) > + goto done; > + } > + > + ret = drmModeAddFB2(backend->drm.fd, width, height, > + format, handles, dmabuf->attributes.stride, > + dmabuf->attributes.offset, _id, 0); > + if (ret) > + goto done; > + > + fb = zalloc(sizeof *fb); > + if (!fb) > + goto done; Nit: indentation > + > + fb->fb_id = fb_id; > + fb->stride = dmabuf->attributes.stride[0]; > + fb->fd = backend->drm.fd; > + fb->is_dmabuf = true; > + > +done: > + for (i = 0; i < dmabuf->attributes.n_planes; i++) { > + if (!handles[i]) > + continue; > + close_drm_handle(backend->drm.fd, handles[i]); No need for `continue`, you can remove it and invert the if. > + } > + > + return fb; > +} > + > +static void > +drm_fb_destroy_dmabuf(struct drm_fb *fb) > +{ > + drm_fb_destroy(fb, fb->fd); > +} Not sure this is really needed :) > + > static struct drm_fb * > drm_fb_get_from_bo(struct gbm_bo *bo, > struct drm_backend *backend, uint32_t format) > @@ -475,6 +548,8 @@ drm_output_release_fb(struct drm_output *output, struct > drm_fb *fb) > if (fb->map && > (fb != output->dumb[0] && fb != output->dumb[1])) { > drm_fb_destroy_dumb(fb); > + } else if (fb->is_dmabuf) { > + drm_fb_destroy_dmabuf(fb); > } else if (fb->bo) { > if (fb->is_client_buffer) > gbm_bo_destroy(fb->bo); > @@ -486,12 +561,12 @@ drm_output_release_fb(struct drm_output *output, struct > drm_fb *fb) > > static uint32_t > drm_output_check_scanout_format(struct drm_output *output, > - struct weston_surface *es, struct gbm_bo *bo) > + struct weston_surface *es, uint32_t format) > { > - uint32_t format; > pixman_region32_t r; > > - format = gbm_bo_get_format(bo); > + /* We relay on the GBM format enum and DRM format enum to be "rely" Otherwise it looks good :) Cheers, Eric > +identical */ > > if (format == GBM_FORMAT_ARGB) { > /* We can scanout an ARGB buffer if the surface's > @@ -521,12 +596,13 @@ drm_output_prepare_scanout_view(struct drm_output > *output, > struct drm_backend *b = to_drm_backend(output->base.compositor); > struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; > struct weston_buffer_viewport *viewport = >surface->buffer_viewport; > - struct gbm_bo *bo; > + struct linux_dmabuf_buffer *dmabuf; > + struct gbm_bo *bo = NULL; > uint32_t format; > > if (ev->geometry.x != output->base.x || > ev->geometry.y != output->base.y || > - buffer == NULL || b->gbm == NULL || > + buffer == NULL || > buffer->width != output->base.current_mode->width || >
[PATCH weston v2 2/3] compositor-drm: Add scanout support for linux_dmabuf buffers
This implementations bypasses gbm and passes the dmabuf handles directly to libdrm for composition. Signed-off-by: Tomohito Esaki--- libweston/compositor-drm.c | 125 ++--- 1 file changed, 107 insertions(+), 18 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index a707fc4..b15fa01 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -151,6 +151,9 @@ struct drm_fb { /* Used by dumb fbs */ void *map; + + /* Used by dmabuf */ + bool is_dmabuf; }; struct drm_edid { @@ -389,6 +392,76 @@ drm_fb_destroy_dumb(struct drm_fb *fb) drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, _arg); } +static inline void +close_drm_handle(int fd, uint32_t handle) +{ + struct drm_gem_close gem_close = { .handle = handle }; + int ret; + + ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, _close); + if (ret) + weston_log("DRM_IOCTL_GEM_CLOSE failed.(%s)\n", + strerror(errno)); +} + +static struct drm_fb * +drm_fb_create_dmabuf(struct linux_dmabuf_buffer *dmabuf, +struct drm_backend *backend, uint32_t format) +{ + struct drm_fb *fb = NULL; + uint32_t width, height, fb_id, handles[4] = {0}; + int i, ret; + + if (!format) + return NULL; + + width = dmabuf->attributes.width; + height = dmabuf->attributes.height; + if (backend->min_width > width || + width > backend->max_width || + backend->min_height > height || + height > backend->max_height) + return NULL; + + for (i = 0; i < dmabuf->attributes.n_planes; i++) { + ret = drmPrimeFDToHandle(backend->drm.fd, +dmabuf->attributes.fd[i], +[i]); + if (ret) + goto done; + } + + ret = drmModeAddFB2(backend->drm.fd, width, height, + format, handles, dmabuf->attributes.stride, + dmabuf->attributes.offset, _id, 0); + if (ret) + goto done; + + fb = zalloc(sizeof *fb); + if (!fb) + goto done; + + fb->fb_id = fb_id; + fb->stride = dmabuf->attributes.stride[0]; + fb->fd = backend->drm.fd; + fb->is_dmabuf = true; + +done: + for (i = 0; i < dmabuf->attributes.n_planes; i++) { + if (!handles[i]) + continue; + close_drm_handle(backend->drm.fd, handles[i]); + } + + return fb; +} + +static void +drm_fb_destroy_dmabuf(struct drm_fb *fb) +{ + drm_fb_destroy(fb, fb->fd); +} + static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, uint32_t format) @@ -475,6 +548,8 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) if (fb->map && (fb != output->dumb[0] && fb != output->dumb[1])) { drm_fb_destroy_dumb(fb); + } else if (fb->is_dmabuf) { + drm_fb_destroy_dmabuf(fb); } else if (fb->bo) { if (fb->is_client_buffer) gbm_bo_destroy(fb->bo); @@ -486,12 +561,12 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb) static uint32_t drm_output_check_scanout_format(struct drm_output *output, - struct weston_surface *es, struct gbm_bo *bo) + struct weston_surface *es, uint32_t format) { - uint32_t format; pixman_region32_t r; - format = gbm_bo_get_format(bo); + /* We relay on the GBM format enum and DRM format enum to be + identical */ if (format == GBM_FORMAT_ARGB) { /* We can scanout an ARGB buffer if the surface's @@ -521,12 +596,13 @@ drm_output_prepare_scanout_view(struct drm_output *output, struct drm_backend *b = to_drm_backend(output->base.compositor); struct weston_buffer *buffer = ev->surface->buffer_ref.buffer; struct weston_buffer_viewport *viewport = >surface->buffer_viewport; - struct gbm_bo *bo; + struct linux_dmabuf_buffer *dmabuf; + struct gbm_bo *bo = NULL; uint32_t format; if (ev->geometry.x != output->base.x || ev->geometry.y != output->base.y || - buffer == NULL || b->gbm == NULL || + buffer == NULL || buffer->width != output->base.current_mode->width || buffer->height != output->base.current_mode->height || output->base.transform != viewport->buffer.transform || @@ -536,22 +612,35 @@ drm_output_prepare_scanout_view(struct drm_output *output, if (ev->geometry.scissor_enabled) return NULL; - bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER, -