summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniels@collabora.com>2016-11-17 17:32:42 +0000
committerDaniel Stone <daniels@collabora.com>2017-02-07 19:16:33 +0000
commitee0837ee8007bc333b60d98b9b0b4d9e92b28f79 (patch)
tree84c4579453b46d4601cf344675c0cf8e02a5db1d
parent6d6085497bdb755947f12d88143bd10b524357c5 (diff)
compositor-drm: Extract overlay FB import to helper
... in order to be able to use it from scanout as well. Signed-off-by: Daniel Stone <daniels@collabora.com> Differential Revision: https://phabricator.freedesktop.org/D1520
-rw-r--r--libweston/compositor-drm.c221
1 files changed, 119 insertions, 102 deletions
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 7b6b1b44..3f431f82 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -1276,6 +1276,109 @@ drm_plane_state_coords_for_view(struct drm_plane_state *state,
state->src_h = (sy2 - sy1) << 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)
+ goto err;
+
+ 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.
*/
@@ -1488,28 +1591,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)
@@ -2258,31 +2339,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) {
@@ -2297,6 +2363,14 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state,
if (p->state_cur->output && p->state_cur->output != 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;
@@ -2307,76 +2381,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: