... in order to be able to use it from scanout as well.

Signed-off-by: Daniel Stone <dani...@collabora.com>
---
 libweston/compositor-drm.c | 221 ++++++++++++++++++++++++---------------------
 1 file changed, 119 insertions(+), 102 deletions(-)

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index dbe53513b..195eef725 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -1234,6 +1234,109 @@ drm_plane_state_coords_for_view(struct drm_plane_state 
*state,
        state->src_h = wl_fixed_from_double(syf2 - syf1) << 8;
 }
 
+static bool
+drm_view_is_opaque(struct weston_view *ev)
+{
+       pixman_region32_t r;
+       bool ret = false;
+
+       /* We can scanout an ARGB buffer if the surface's
+        * opaque region covers the whole output, but we have
+        * to use XRGB as the KMS format code. */
+       pixman_region32_init_rect(&r, 0, 0,
+                                 ev->surface->width,
+                                 ev->surface->height);
+       pixman_region32_subtract(&r, &r, &ev->surface->opaque);
+
+       if (!pixman_region32_not_empty(&r))
+               ret = true;
+
+       pixman_region32_fini(&r);
+
+       return ret;
+}
+
+static struct drm_fb *
+drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev)
+{
+       struct drm_output *output = state->output;
+       struct drm_backend *b = to_drm_backend(output->base.compositor);
+       struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
+       struct linux_dmabuf_buffer *dmabuf;
+       struct drm_fb *fb;
+       struct gbm_bo *bo;
+
+       /* Don't import buffers which span multiple outputs. */
+       if (ev->output_mask != (1u << output->base.id))
+               return NULL;
+
+       if (ev->alpha != 1.0f)
+               return NULL;
+
+       if (!buffer)
+               return NULL;
+
+       if (wl_shm_buffer_get(buffer->resource))
+               return NULL;
+
+       if (!b->gbm)
+               return NULL;
+
+       dmabuf = linux_dmabuf_buffer_get(buffer->resource);
+       if (dmabuf) {
+#ifdef HAVE_GBM_FD_IMPORT
+               /* XXX: TODO:
+                *
+                * Use AddFB2 directly, do not go via GBM.
+                * Add support for multiplanar formats.
+                * Both require refactoring in the DRM-backend to
+                * support a mix of gbm_bos and drmfbs.
+                */
+                struct gbm_import_fd_data gbm_dmabuf = {
+                        .fd = dmabuf->attributes.fd[0],
+                        .width = dmabuf->attributes.width,
+                        .height = dmabuf->attributes.height,
+                        .stride = dmabuf->attributes.stride[0],
+                        .format = dmabuf->attributes.format
+                };
+
+                /* XXX: TODO:
+                 *
+                 * Currently the buffer is rejected if any dmabuf attribute
+                 * flag is set.  This keeps us from passing an inverted /
+                 * interlaced / bottom-first buffer (or any other type that may
+                 * be added in the future) through to an overlay.  Ultimately,
+                 * these types of buffers should be handled through buffer
+                 * transforms and not as spot-checks requiring specific
+                 * knowledge. */
+               if (dmabuf->attributes.n_planes != 1 ||
+                    dmabuf->attributes.offset[0] != 0 ||
+                   dmabuf->attributes.flags)
+                       return NULL;
+
+               bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_FD, &gbm_dmabuf,
+                                  GBM_BO_USE_SCANOUT);
+#else
+               return NULL;
+#endif
+       } else {
+               bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
+                                  buffer->resource, GBM_BO_USE_SCANOUT);
+       }
+
+       if (!bo)
+               return NULL;
+
+       fb = drm_fb_get_from_bo(bo, b, drm_view_is_opaque(ev), BUFFER_CLIENT);
+       if (!fb) {
+               gbm_bo_destroy(bo);
+               return NULL;
+       }
+
+       drm_fb_set_buffer(fb, buffer);
+       return fb;
+}
+
 /**
  * Return a plane state from a drm_output_state.
  */
@@ -1575,28 +1678,6 @@ drm_output_assign_state(struct drm_output_state *state,
        }
 }
 
-static bool
-drm_view_is_opaque(struct weston_view *ev)
-{
-       pixman_region32_t r;
-       bool ret = false;
-
-       /* We can scanout an ARGB buffer if the surface's
-        * opaque region covers the whole output, but we have
-        * to use XRGB as the KMS format code. */
-       pixman_region32_init_rect(&r, 0, 0,
-                                 ev->surface->width,
-                                 ev->surface->height);
-       pixman_region32_subtract(&r, &r, &ev->surface->opaque);
-
-       if (!pixman_region32_not_empty(&r))
-               ret = true;
-
-       pixman_region32_fini(&r);
-
-       return ret;
-}
-
 static struct weston_plane *
 drm_output_prepare_scanout_view(struct drm_output_state *output_state,
                                struct weston_view *ev)
@@ -2661,31 +2742,16 @@ drm_output_prepare_overlay_view(struct drm_output_state 
*output_state,
        struct drm_output *output = output_state->output;
        struct weston_compositor *ec = output->base.compositor;
        struct drm_backend *b = to_drm_backend(ec);
-       struct wl_resource *buffer_resource;
        struct drm_plane *p;
        struct drm_plane_state *state = NULL;
-       struct linux_dmabuf_buffer *dmabuf;
-       struct gbm_bo *bo;
+       struct drm_fb *fb;
        unsigned int i;
 
        if (b->sprites_are_broken)
                return NULL;
 
-       /* Don't import buffers which span multiple outputs. */
-       if (ev->output_mask != (1u << output->base.id))
-               return NULL;
-
-       /* We can only import GBM buffers. */
-       if (b->gbm == NULL)
-               return NULL;
-
-       if (ev->surface->buffer_ref.buffer == NULL)
-               return NULL;
-       buffer_resource = ev->surface->buffer_ref.buffer->resource;
-       if (wl_shm_buffer_get(buffer_resource))
-               return NULL;
-
-       if (ev->alpha != 1.0f)
+       fb = drm_fb_get_from_view(output_state, ev);
+       if (!fb)
                return NULL;
 
        wl_list_for_each(p, &b->plane_list, link) {
@@ -2695,6 +2761,14 @@ drm_output_prepare_overlay_view(struct drm_output_state 
*output_state,
                if (!drm_plane_is_available(p, output))
                        continue;
 
+               /* Check whether the format is supported */
+               for (i = 0; i < p->count_formats; i++) {
+                       if (p->formats[i] == fb->format->format)
+                               break;
+               }
+               if (i == p->count_formats)
+                       continue;
+
                state = drm_output_state_get_plane(output_state, p);
                if (state->fb) {
                        state = NULL;
@@ -2705,76 +2779,19 @@ drm_output_prepare_overlay_view(struct drm_output_state 
*output_state,
        }
 
        /* No sprites available */
-       if (!state)
+       if (!state) {
+               drm_fb_unref(fb);
                return NULL;
+       }
 
+       state->fb = fb;
        state->output = output;
+
        drm_plane_state_coords_for_view(state, ev);
        if (state->src_w != state->dest_w << 16 ||
            state->src_h != state->dest_h << 16)
                goto err;
 
-       if ((dmabuf = linux_dmabuf_buffer_get(buffer_resource))) {
-#ifdef HAVE_GBM_FD_IMPORT
-               /* XXX: TODO:
-                *
-                * Use AddFB2 directly, do not go via GBM.
-                * Add support for multiplanar formats.
-                * Both require refactoring in the DRM-backend to
-                * support a mix of gbm_bos and drmfbs.
-                */
-               struct gbm_import_fd_data gbm_dmabuf = {
-                       .fd     = dmabuf->attributes.fd[0],
-                       .width  = dmabuf->attributes.width,
-                       .height = dmabuf->attributes.height,
-                       .stride = dmabuf->attributes.stride[0],
-                       .format = dmabuf->attributes.format
-               };
-
-                /* XXX: TODO:
-                 *
-                 * Currently the buffer is rejected if any dmabuf attribute
-                 * flag is set.  This keeps us from passing an inverted /
-                 * interlaced / bottom-first buffer (or any other type that may
-                 * be added in the future) through to an overlay.  Ultimately,
-                 * these types of buffers should be handled through buffer
-                 * transforms and not as spot-checks requiring specific
-                 * knowledge. */
-               if (dmabuf->attributes.n_planes != 1 ||
-                    dmabuf->attributes.offset[0] != 0 ||
-                   dmabuf->attributes.flags)
-                       goto err;
-
-               bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_FD, &gbm_dmabuf,
-                                  GBM_BO_USE_SCANOUT);
-#else
-               goto err;
-#endif
-       } else {
-               bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
-                                  buffer_resource, GBM_BO_USE_SCANOUT);
-       }
-       if (!bo)
-               goto err;
-
-       state->fb = drm_fb_get_from_bo(bo, b, drm_view_is_opaque(ev),
-                                      BUFFER_CLIENT);
-       if (!state->fb) {
-               /* Destroy the BO as we've allocated it, but it won't yet
-                * be deallocated by the state. */
-               gbm_bo_destroy(bo);
-               goto err;
-       }
-
-       /* Check whether the format is supported */
-       for (i = 0; i < p->count_formats; i++)
-               if (p->formats[i] == state->fb->format->format)
-                       break;
-       if (i == p->count_formats)
-               goto err;
-
-       drm_fb_set_buffer(state->fb, ev->surface->buffer_ref.buffer);
-
        return &p->base;
 
 err:
-- 
2.14.3

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to