drm/amd/display: fix 270 degree rotation for mixed-SLS mode

[Why]
When we rotate 270 in mixed SLS mode, the recouts occupy the
right side of the display.  So all the recout_skip_v values
are relative to the left side of the display.  This causes
adjust_vp_and_init_for_seamless_clip() to incorrectly increase
the data->viewport.height for that recout.  The rotation looks
like the bottom half is duplicated twice.

[How]
recout.x values are being adjusted based on
stream->timing.h_border_left.  Instead of using h_border_left,
use dst.x to represent the border.  Shift dst.x by the amount of
stream->timing.h_border_left and set
stream->timing.h_border_left to 0.  Do all the calculations
and then revert stream->timing.h_border_left and
stream->dst.x back to their original values.
When calculating pipe_ctx->plane_res.scl_data.h_active,
make sure to use the original stream->timing.h_border_left
value.

Signed-off-by: Samson Tam <Samson.Tam@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Samson Tam 2019-11-28 15:55:01 -05:00 committed by Alex Deucher
parent 1f0674fd5c
commit 89d07b662f

View file

@ -940,11 +940,51 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
}
/*
* When handling 270 rotation in mixed SLS mode, we have
* stream->timing.h_border_left that is non zero. If we are doing
* pipe-splitting, this h_border_left value gets added to recout.x and when it
* calls calculate_inits_and_adj_vp() and
* adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a
* pipe to be incorrect.
*
* To fix this, instead of using stream->timing.h_border_left, we can use
* stream->dst.x to represent the border instead. So we will set h_border_left
* to 0 and shift the appropriate amount in stream->dst.x. We will then
* perform all calculations in resource_build_scaling_params() based on this
* and then restore the h_border_left and stream->dst.x to their original
* values.
*
* shift_border_left_to_dst() will shift the amount of h_border_left to
* stream->dst.x and set h_border_left to 0. restore_border_left_from_dst()
* will restore h_border_left and stream->dst.x back to their original values
* We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the
* original h_border_left value in its calculation.
*/
int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
{
int store_h_border_left = pipe_ctx->stream->timing.h_border_left;
if (store_h_border_left) {
pipe_ctx->stream->timing.h_border_left = 0;
pipe_ctx->stream->dst.x += store_h_border_left;
}
return store_h_border_left;
}
void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
int store_h_border_left)
{
pipe_ctx->stream->dst.x -= store_h_border_left;
pipe_ctx->stream->timing.h_border_left = store_h_border_left;
}
bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
{
const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
bool res = false;
int store_h_border_left = shift_border_left_to_dst(pipe_ctx);
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
/* Important: scaling ratio calculation requires pixel format,
* lb depth calculation requires recout and taps require scaling ratios.
@ -957,8 +997,14 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
calculate_viewport(pipe_ctx);
if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16)
if (pipe_ctx->plane_res.scl_data.viewport.height < 16 ||
pipe_ctx->plane_res.scl_data.viewport.width < 16) {
if (store_h_border_left) {
restore_border_left_from_dst(pipe_ctx,
store_h_border_left);
}
return false;
}
calculate_recout(pipe_ctx);
@ -971,8 +1017,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
store_h_border_left + timing->h_border_right;
pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable +
timing->v_border_top + timing->v_border_bottom;
/* Taps calculations */
if (pipe_ctx->plane_res.xfm != NULL)
@ -1019,6 +1067,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
plane_state->dst_rect.x,
plane_state->dst_rect.y);
if (store_h_border_left)
restore_border_left_from_dst(pipe_ctx, store_h_border_left);
return res;
}