On Mon, Dec 03, 2018 at 02:34:12PM +0100, Boris Brezillon wrote:
> Add support for X/Y reflection when the plane is using linear or T-tiled
> formats. X/Y reflection hasn't been tested on SAND formats, so we reject
> them until proper testing/debugging has been done.

BTW you could also expose 180 degress easily. See
drm_rotation_simplify().

> 
> Signed-off-by: Boris Brezillon <boris.brezil...@bootlin.com>
> ---
>  drivers/gpu/drm/vc4/vc4_plane.c | 55 ++++++++++++++++++++++++++-------
>  1 file changed, 44 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index 75db62cbe468..bdcccf65cde0 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -492,7 +492,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
>       bool mix_plane_alpha;
>       bool covers_screen;
>       u32 scl0, scl1, pitch0;
> -     u32 tiling;
> +     u32 tiling, src_y;
>       u32 hvs_format = format->hvs;
>       int ret, i;
>  
> @@ -520,6 +520,11 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
>       h_subsample = drm_format_horz_chroma_subsampling(format->drm);
>       v_subsample = drm_format_vert_chroma_subsampling(format->drm);
>  
> +     /* We must point to the last line when Y reflection is enabled. */
> +     src_y = vc4_state->src_y;
> +     if (state->rotation & DRM_MODE_REFLECT_Y)
> +             src_y += vc4_state->src_h[0] - 1;
> +
>       switch (base_format_mod) {
>       case DRM_FORMAT_MOD_LINEAR:
>               tiling = SCALER_CTL0_TILING_LINEAR;
> @@ -529,9 +534,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
>                * out.
>                */
>               for (i = 0; i < num_planes; i++) {
> -                     vc4_state->offsets[i] += vc4_state->src_y /
> +                     vc4_state->offsets[i] += src_y /
>                                                (i ? v_subsample : 1) *
>                                                fb->pitches[i];
> +
>                       vc4_state->offsets[i] += vc4_state->src_x /
>                                                (i ? h_subsample : 1) *
>                                                fb->format->cpp[i];
> @@ -557,22 +563,38 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
>               u32 tiles_w = fb->pitches[0] >> (tile_size_shift - 
> tile_h_shift);
>               u32 tiles_l = vc4_state->src_x >> tile_w_shift;
>               u32 tiles_r = tiles_w - tiles_l;
> -             u32 tiles_t = vc4_state->src_y >> tile_h_shift;
> +             u32 tiles_t = src_y >> tile_h_shift;
>               /* Intra-tile offsets, which modify the base address (the
>                * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
>                * base address).
>                */
> -             u32 tile_y = (vc4_state->src_y >> 4) & 1;
> -             u32 subtile_y = (vc4_state->src_y >> 2) & 3;
> -             u32 utile_y = vc4_state->src_y & 3;
> +             u32 tile_y = (src_y >> 4) & 1;
> +             u32 subtile_y = (src_y >> 2) & 3;
> +             u32 utile_y = src_y & 3;
>               u32 x_off = vc4_state->src_x & tile_w_mask;
> -             u32 y_off = vc4_state->src_y & tile_h_mask;
> +             u32 y_off = src_y & tile_h_mask;
> +
> +             /* When Y reflection is requested we must set the
> +              * SCALER_PITCH0_TILE_LINE_DIR flag to tell HVS that all lines
> +              * after the initial one should be fetched in descending order,
> +              * which makes sense since we start from the last line and go
> +              * backward.
> +              * Don't know why we need y_off = max_y_off - y_off, but it's
> +              * definitely required (I guess it's also related to the "going
> +              * backward" situation).
> +              */
> +             if (state->rotation & DRM_MODE_REFLECT_Y) {
> +                     y_off = tile_h_mask - y_off;
> +                     pitch0 = SCALER_PITCH0_TILE_LINE_DIR;
> +             } else {
> +                     pitch0 = 0;
> +             }
>  
>               tiling = SCALER_CTL0_TILING_256B_OR_T;
> -             pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
> -                       VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
> -                       VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
> -                       VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
> +             pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
> +                        VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
> +                        VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
> +                        VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
>               vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift);
>               vc4_state->offsets[0] += subtile_y << 8;
>               vc4_state->offsets[0] += utile_y << 4;
> @@ -611,6 +633,11 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
>                       }
>               }
>  
> +             if (state->rotation & DRM_MODE_REFLECT_MASK) {
> +                     DRM_DEBUG_KMS("X/Y reflection not supported on SAND 
> formats\n");
> +                     return -ENOTSUPP;
> +             }
> +
>               switch (base_format_mod) {
>               case DRM_FORMAT_MOD_BROADCOM_SAND64:
>                       tiling = SCALER_CTL0_TILING_64B;
> @@ -643,6 +670,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
>       /* Control word */
>       vc4_dlist_write(vc4_state,
>                       SCALER_CTL0_VALID |
> +                     (state->rotation & DRM_MODE_REFLECT_X ? 
> SCALER_CTL0_HFLIP : 0) |
> +                     (state->rotation & DRM_MODE_REFLECT_Y ? 
> SCALER_CTL0_VFLIP : 0) |
>                       VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, 
> SCALER_CTL0_RGBA_EXPAND) |
>                       (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
>                       (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
> @@ -1123,6 +1152,10 @@ struct drm_plane *vc4_plane_init(struct drm_device 
> *dev,
>       drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
>  
>       drm_plane_create_alpha_property(plane);
> +     drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
> +                                        DRM_MODE_ROTATE_0 |
> +                                        DRM_MODE_REFLECT_X |
> +                                        DRM_MODE_REFLECT_Y);
>  
>       return plane;
>  }
> -- 
> 2.17.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Ville Syrjälä
Intel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to