[PATCH v3 2/2] drm: rcar-du: Clip planes to screen boundaries
Kieran Bingham
kieran.bingham+renesas at ideasonboard.com
Mon Dec 4 14:12:00 UTC 2017
Hi Laurent,
Thankyou for the patch.
On 26/11/17 11:30, Laurent Pinchart wrote:
> Unlike the KMS API, the hardware doesn't support planes exceeding the
> screen boundaries or planes being located fully off-screen. We need to
> clip plane coordinates to support the use case.
>
> Fortunately the DRM core offers a drm_atomic_helper_check_plane_state()
> helper that valides the scaling factor and clips the plane coordinates.
s/valides/validates/
> Use it to implement the plane atomic check and use the clipped source
> and destination rectangles from the plane state instead of the unclipped
> source and CRTC coordinates to configure the device.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
Aside from the spelling error above - I can't find a fault here. Maybe next time :-)
Reviewed-by: Kieran Bingham <kieran.bingham+renesas at ideasonboard.com>
> ---
> Changes since v2:
>
> - Actually use the clipped source and destination rectangles
> - Use drm_crtc_state::mode instead of drm_crtc_state::adjusted_mode
> where applicable
> - Removed spurious semicolon
> - Rebased on top of latest drm+drm-misc
> ---
> drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 3 +-
> drivers/gpu/drm/rcar-du/rcar_du_plane.c | 50 ++++++++++++++++++++++++---------
> drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 42 ++++++++++++++-------------
> 3 files changed, 62 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index b492063a6e1f..5685d5af6998 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -319,7 +319,8 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
> struct rcar_du_plane *plane = &rcrtc->group->planes[i];
> unsigned int j;
>
> - if (plane->plane.state->crtc != &rcrtc->crtc)
> + if (plane->plane.state->crtc != &rcrtc->crtc ||
> + !plane->plane.state->visible)
> continue;
>
> /* Insert the plane in the sorted planes array. */
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> index 4f076c364f25..4a3d16cf3ed6 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> @@ -332,8 +332,8 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
> static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
> const struct rcar_du_plane_state *state)
> {
> - unsigned int src_x = state->state.src_x >> 16;
> - unsigned int src_y = state->state.src_y >> 16;
> + unsigned int src_x = state->state.src.x1 >> 16;
> + unsigned int src_y = state->state.src.y1 >> 16;
> unsigned int index = state->hwindex;
> unsigned int pitch;
> bool interlaced;
> @@ -357,7 +357,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
> dma[i] = gem->paddr + fb->offsets[i];
> }
> } else {
> - pitch = state->state.src_w >> 16;
> + pitch = drm_rect_width(&state->state.src) >> 16;
> dma[0] = 0;
> dma[1] = 0;
> }
> @@ -521,6 +521,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
> const struct rcar_du_plane_state *state)
> {
> struct rcar_du_device *rcdu = rgrp->dev;
> + const struct drm_rect *dst = &state->state.dst;
>
> if (rcdu->info->gen < 3)
> rcar_du_plane_setup_format_gen2(rgrp, index, state);
> @@ -528,10 +529,10 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
> rcar_du_plane_setup_format_gen3(rgrp, index, state);
>
> /* Destination position and size */
> - rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
> - rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
> - rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
> - rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
> + rcar_du_plane_write(rgrp, index, PnDSXR, drm_rect_width(dst));
> + rcar_du_plane_write(rgrp, index, PnDSYR, drm_rect_height(dst));
> + rcar_du_plane_write(rgrp, index, PnDPXR, dst->x1);
> + rcar_du_plane_write(rgrp, index, PnDPYR, dst->y1);
>
> if (rcdu->info->gen < 3) {
> /* Wrap-around and blinking, disabled */
> @@ -570,16 +571,39 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
> const struct rcar_du_format_info **format)
> {
> struct drm_device *dev = plane->dev;
> + struct drm_crtc_state *crtc_state;
> + struct drm_rect clip;
> + int ret;
>
> - if (!state->fb || !state->crtc) {
> + if (!state->crtc) {
> + /*
> + * The visible field is not reset by the DRM core but only
> + * updated by drm_plane_helper_check_state(), set it manually.
> + */
> + state->visible = false;
> *format = NULL;
> return 0;
> }
>
> - if (state->src_w >> 16 != state->crtc_w ||
> - state->src_h >> 16 != state->crtc_h) {
> - dev_dbg(dev->dev, "%s: scaling not supported\n", __func__);
> - return -EINVAL;
> + crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
> + if (IS_ERR(crtc_state))
> + return PTR_ERR(crtc_state);
> +
> + clip.x1 = 0;
> + clip.y1 = 0;
> + clip.x2 = crtc_state->mode.hdisplay;
> + clip.y2 = crtc_state->mode.vdisplay;
> +
> + ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
> + DRM_PLANE_HELPER_NO_SCALING,
> + DRM_PLANE_HELPER_NO_SCALING,
> + true, true);
> + if (ret < 0)
> + return ret;
> +
> + if (!state->visible) {
> + *format = NULL;
> + return 0;
> }
>
> *format = rcar_du_format_info(state->fb->format->format);
> @@ -607,7 +631,7 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
> struct rcar_du_plane_state *old_rstate;
> struct rcar_du_plane_state *new_rstate;
>
> - if (!plane->state->crtc)
> + if (!plane->state->visible)
> return;
>
> rcar_du_plane_setup(rplane);
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> index dd66dcb8da23..2c260c33840b 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
> @@ -55,14 +55,14 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
> struct rcar_du_plane_state state = {
> .state = {
> .crtc = &crtc->crtc,
> - .crtc_x = 0,
> - .crtc_y = 0,
> - .crtc_w = mode->hdisplay,
> - .crtc_h = mode->vdisplay,
> - .src_x = 0,
> - .src_y = 0,
> - .src_w = mode->hdisplay << 16,
> - .src_h = mode->vdisplay << 16,
> + .dst.x1 = 0,
> + .dst.y1 = 0,
> + .dst.x2 = mode->hdisplay,
> + .dst.y2 = mode->vdisplay,
> + .src.x1 = 0,
> + .src.y1 = 0,
> + .src.x2 = mode->hdisplay << 16,
> + .src.y2 = mode->vdisplay << 16,
> .zpos = 0,
> },
> .format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
> @@ -178,15 +178,15 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
> };
> unsigned int i;
>
> - cfg.src.left = state->state.src_x >> 16;
> - cfg.src.top = state->state.src_y >> 16;
> - cfg.src.width = state->state.src_w >> 16;
> - cfg.src.height = state->state.src_h >> 16;
> + cfg.src.left = state->state.src.x1 >> 16;
> + cfg.src.top = state->state.src.y1 >> 16;
> + cfg.src.width = drm_rect_width(&state->state.src) >> 16;
> + cfg.src.height = drm_rect_height(&state->state.src) >> 16;
>
> - cfg.dst.left = state->state.crtc_x;
> - cfg.dst.top = state->state.crtc_y;
> - cfg.dst.width = state->state.crtc_w;
> - cfg.dst.height = state->state.crtc_h;
> + cfg.dst.left = state->state.dst.x1;
> + cfg.dst.top = state->state.dst.y1;
> + cfg.dst.width = drm_rect_width(&state->state.dst);
> + cfg.dst.height = drm_rect_height(&state->state.dst);
>
> for (i = 0; i < state->format->planes; ++i)
> cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl)
> @@ -212,7 +212,11 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane,
> unsigned int i;
> int ret;
>
> - if (!state->fb)
> + /*
> + * There's no need to prepare (and unprepare) the framebuffer when the
> + * plane is not visible, as it will not be displayed.
> + */
> + if (!state->visible)
> return 0;
>
> for (i = 0; i < rstate->format->planes; ++i) {
> @@ -253,7 +257,7 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane,
> struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp;
> unsigned int i;
>
> - if (!state->fb)
> + if (!state->visible)
> return;
>
> for (i = 0; i < rstate->format->planes; ++i) {
> @@ -278,7 +282,7 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
> struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
> struct rcar_du_crtc *crtc = to_rcar_crtc(old_state->crtc);
>
> - if (plane->state->crtc)
> + if (plane->state->visible)
> rcar_du_vsp_plane_setup(rplane);
> else
> vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe,
>
More information about the dri-devel
mailing list