mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-08 14:48:05 +02:00
compositor-drm: Use plane_state_coords_for_view for scanout
Now that we have a helper to fill the plane state co-ordinates from a view, use this for the scanout plane. We now explicitly check that the view fills exactly the fullscreen area and nothing else. We then use the new helper to fill out the plane state values, and do further checks against the filled-in co-ordinates, i.e. that we're not trying to show an offset into the buffer, or to scale the image. This now allows cases where the buffer -> surface -> view -> output transform chain cancels each other out for scaling: previously, we would never consider a buffer for scanout unless its scale matched the output's. We now only look at the final result of the buffer -> output transformation, to check that this does not result in translation or scaling. An audit of the error paths found some places where we would leave a plane state hanging; this makes them all consistent. Signed-off-by: Daniel Stone <daniels@collabora.com> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Tested-by: Emre Ucan <eucan@de.adit-jv.com>
This commit is contained in:
parent
ce137472fa
commit
7cdf231c76
1 changed files with 29 additions and 33 deletions
|
|
@ -1670,8 +1670,8 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
|
|||
struct drm_plane *scanout_plane = output->scanout_plane;
|
||||
struct drm_plane_state *state;
|
||||
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
|
||||
struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
|
||||
struct gbm_bo *bo;
|
||||
pixman_box32_t *extents;
|
||||
|
||||
/* Don't import buffers which span multiple outputs. */
|
||||
if (ev->output_mask != (1u << output->base.id))
|
||||
|
|
@ -1686,21 +1686,13 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
|
|||
if (wl_shm_buffer_get(buffer->resource))
|
||||
return NULL;
|
||||
|
||||
/* Make sure our view is exactly compatible with the output. */
|
||||
if (ev->geometry.x != output->base.x ||
|
||||
ev->geometry.y != output->base.y)
|
||||
return NULL;
|
||||
if (buffer->width != output->base.current_mode->width ||
|
||||
buffer->height != output->base.current_mode->height)
|
||||
return NULL;
|
||||
|
||||
if (ev->transform.enabled)
|
||||
return NULL;
|
||||
if (ev->geometry.scissor_enabled)
|
||||
return NULL;
|
||||
if (viewport->buffer.scale != output->base.current_scale)
|
||||
return NULL;
|
||||
if (!drm_view_transform_supported(ev, &output->base))
|
||||
/* Check the view spans exactly the output size, calculated in the
|
||||
* logical co-ordinate space. */
|
||||
extents = pixman_region32_extents(&ev->transform.boundingbox);
|
||||
if (extents->x1 != output->base.x ||
|
||||
extents->y1 != output->base.y ||
|
||||
extents->x2 != output->base.x + output->base.width ||
|
||||
extents->y2 != output->base.y + output->base.height)
|
||||
return NULL;
|
||||
|
||||
if (ev->alpha != 1.0f)
|
||||
|
|
@ -1715,44 +1707,48 @@ drm_output_prepare_scanout_view(struct drm_output_state *output_state,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
state->output = output;
|
||||
if (!drm_plane_state_coords_for_view(state, ev))
|
||||
goto err;
|
||||
|
||||
/* The legacy API does not let us perform cropping or scaling. */
|
||||
if (state->src_x != 0 || state->src_y != 0 ||
|
||||
state->src_w != state->dest_w << 16 ||
|
||||
state->src_h != state->dest_h << 16 ||
|
||||
state->dest_x != 0 || state->dest_y != 0 ||
|
||||
state->dest_w != (unsigned) output->base.current_mode->width ||
|
||||
state->dest_h != (unsigned) output->base.current_mode->height)
|
||||
goto err;
|
||||
|
||||
bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||
buffer->resource, GBM_BO_USE_SCANOUT);
|
||||
|
||||
/* Unable to use the buffer for scanout */
|
||||
if (!bo)
|
||||
return NULL;
|
||||
goto err;
|
||||
|
||||
state->fb = drm_fb_get_from_bo(bo, b, drm_view_is_opaque(ev),
|
||||
BUFFER_CLIENT);
|
||||
if (!state->fb) {
|
||||
drm_plane_state_put_back(state);
|
||||
/* We need to explicitly destroy the BO. */
|
||||
gbm_bo_destroy(bo);
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Can't change formats with just a pageflip */
|
||||
if (state->fb->format->format != output->gbm_format) {
|
||||
/* No need to destroy the GBM BO here, as it's now owned
|
||||
* by the FB. */
|
||||
drm_plane_state_put_back(state);
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
drm_fb_set_buffer(state->fb, buffer);
|
||||
|
||||
state->output = output;
|
||||
|
||||
state->src_x = 0;
|
||||
state->src_y = 0;
|
||||
state->src_w = state->fb->width << 16;
|
||||
state->src_h = state->fb->height << 16;
|
||||
|
||||
state->dest_x = 0;
|
||||
state->dest_y = 0;
|
||||
state->dest_w = output->base.current_mode->width;
|
||||
state->dest_h = output->base.current_mode->height;
|
||||
|
||||
return &scanout_plane->base;
|
||||
|
||||
err:
|
||||
drm_plane_state_put_back(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct drm_fb *
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue