Commit a26a54fb authored by David Galiffi's avatar David Galiffi Committed by Alex Deucher

drm/amd/display: Fix rotated cursor offset calculation

[Why]
Underflow is observed when cursor is still enabled when the cursor
rectangle is outside the bounds of it's surface viewport.

[How]
Update parameters used to determine when cursor should be disabled.
Reviewed-by: default avatarMartin Leung <Martin.Leung@amd.com>
Acked-by: default avatarBrian Chang <Brian.Chang@amd.com>
Signed-off-by: default avatarDavid Galiffi <David.Galiffi@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e667ee3b
...@@ -436,34 +436,48 @@ void dpp1_set_cursor_position( ...@@ -436,34 +436,48 @@ void dpp1_set_cursor_position(
uint32_t height) uint32_t height)
{ {
struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
int src_x_offset = pos->x - pos->x_hotspot - param->viewport.x; int x_pos = pos->x - param->viewport.x;
int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y; int y_pos = pos->y - param->viewport.y;
int x_hotspot = pos->x_hotspot;
int y_hotspot = pos->y_hotspot;
int src_x_offset = x_pos - pos->x_hotspot;
int src_y_offset = y_pos - pos->y_hotspot;
int cursor_height = (int)height;
int cursor_width = (int)width;
uint32_t cur_en = pos->enable ? 1 : 0; uint32_t cur_en = pos->enable ? 1 : 0;
// Cursor width/height and hotspots need to be rotated for offset calculation // Transform cursor width / height and hotspots for offset calculations
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) { if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
swap(width, height); swap(cursor_height, cursor_width);
swap(x_hotspot, y_hotspot);
if (param->rotation == ROTATION_ANGLE_90) { if (param->rotation == ROTATION_ANGLE_90) {
src_x_offset = pos->x - pos->y_hotspot - param->viewport.x; // hotspot = (-y, x)
src_y_offset = pos->y - pos->x_hotspot - param->viewport.y; src_x_offset = x_pos - (cursor_width - x_hotspot);
src_y_offset = y_pos - y_hotspot;
} else if (param->rotation == ROTATION_ANGLE_270) {
// hotspot = (y, -x)
src_x_offset = x_pos - x_hotspot;
src_y_offset = y_pos - (cursor_height - y_hotspot);
} }
} else if (param->rotation == ROTATION_ANGLE_180) { } else if (param->rotation == ROTATION_ANGLE_180) {
// hotspot = (-x, -y)
if (!param->mirror) if (!param->mirror)
src_x_offset = pos->x - param->viewport.x; src_x_offset = x_pos - (cursor_width - x_hotspot);
src_y_offset = pos->y - param->viewport.y; src_y_offset = y_pos - (cursor_height - y_hotspot);
} }
if (src_x_offset >= (int)param->viewport.width) if (src_x_offset >= (int)param->viewport.width)
cur_en = 0; /* not visible beyond right edge*/ cur_en = 0; /* not visible beyond right edge*/
if (src_x_offset + (int)width <= 0) if (src_x_offset + cursor_width <= 0)
cur_en = 0; /* not visible beyond left edge*/ cur_en = 0; /* not visible beyond left edge*/
if (src_y_offset >= (int)param->viewport.height) if (src_y_offset >= (int)param->viewport.height)
cur_en = 0; /* not visible beyond bottom edge*/ cur_en = 0; /* not visible beyond bottom edge*/
if (src_y_offset + (int)height <= 0) if (src_y_offset + cursor_height <= 0)
cur_en = 0; /* not visible beyond top edge*/ cur_en = 0; /* not visible beyond top edge*/
REG_UPDATE(CURSOR0_CONTROL, REG_UPDATE(CURSOR0_CONTROL,
......
...@@ -1179,10 +1179,12 @@ void hubp1_cursor_set_position( ...@@ -1179,10 +1179,12 @@ void hubp1_cursor_set_position(
const struct dc_cursor_mi_param *param) const struct dc_cursor_mi_param *param)
{ {
struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
int src_x_offset = pos->x - pos->x_hotspot - param->viewport.x; int x_pos = pos->x - param->viewport.x;
int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y; int y_pos = pos->y - param->viewport.y;
int x_hotspot = pos->x_hotspot; int x_hotspot = pos->x_hotspot;
int y_hotspot = pos->y_hotspot; int y_hotspot = pos->y_hotspot;
int src_x_offset = x_pos - pos->x_hotspot;
int src_y_offset = y_pos - pos->y_hotspot;
int cursor_height = (int)hubp->curs_attr.height; int cursor_height = (int)hubp->curs_attr.height;
int cursor_width = (int)hubp->curs_attr.width; int cursor_width = (int)hubp->curs_attr.width;
uint32_t dst_x_offset; uint32_t dst_x_offset;
...@@ -1200,18 +1202,26 @@ void hubp1_cursor_set_position( ...@@ -1200,18 +1202,26 @@ void hubp1_cursor_set_position(
if (hubp->curs_attr.address.quad_part == 0) if (hubp->curs_attr.address.quad_part == 0)
return; return;
// Rotated cursor width/height and hotspots tweaks for offset calculation // Transform cursor width / height and hotspots for offset calculations
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) { if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
swap(cursor_height, cursor_width); swap(cursor_height, cursor_width);
swap(x_hotspot, y_hotspot);
if (param->rotation == ROTATION_ANGLE_90) { if (param->rotation == ROTATION_ANGLE_90) {
src_x_offset = pos->x - pos->y_hotspot - param->viewport.x; // hotspot = (-y, x)
src_y_offset = pos->y - pos->x_hotspot - param->viewport.y; src_x_offset = x_pos - (cursor_width - x_hotspot);
src_y_offset = y_pos - y_hotspot;
} else if (param->rotation == ROTATION_ANGLE_270) {
// hotspot = (y, -x)
src_x_offset = x_pos - x_hotspot;
src_y_offset = y_pos - (cursor_height - y_hotspot);
} }
} else if (param->rotation == ROTATION_ANGLE_180) { } else if (param->rotation == ROTATION_ANGLE_180) {
// hotspot = (-x, -y)
if (!param->mirror) if (!param->mirror)
src_x_offset = pos->x - param->viewport.x; src_x_offset = x_pos - (cursor_width - x_hotspot);
src_y_offset = pos->y - param->viewport.y; src_y_offset = y_pos - (cursor_height - y_hotspot);
} }
dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
...@@ -1248,8 +1258,8 @@ void hubp1_cursor_set_position( ...@@ -1248,8 +1258,8 @@ void hubp1_cursor_set_position(
CURSOR_Y_POSITION, pos->y); CURSOR_Y_POSITION, pos->y);
REG_SET_2(CURSOR_HOT_SPOT, 0, REG_SET_2(CURSOR_HOT_SPOT, 0,
CURSOR_HOT_SPOT_X, x_hotspot, CURSOR_HOT_SPOT_X, pos->x_hotspot,
CURSOR_HOT_SPOT_Y, y_hotspot); CURSOR_HOT_SPOT_Y, pos->y_hotspot);
REG_SET(CURSOR_DST_OFFSET, 0, REG_SET(CURSOR_DST_OFFSET, 0,
CURSOR_DST_X_OFFSET, dst_x_offset); CURSOR_DST_X_OFFSET, dst_x_offset);
......
...@@ -973,10 +973,12 @@ void hubp2_cursor_set_position( ...@@ -973,10 +973,12 @@ void hubp2_cursor_set_position(
const struct dc_cursor_mi_param *param) const struct dc_cursor_mi_param *param)
{ {
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
int src_x_offset = pos->x - pos->x_hotspot - param->viewport.x; int x_pos = pos->x - param->viewport.x;
int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y; int y_pos = pos->y - param->viewport.y;
int x_hotspot = pos->x_hotspot; int x_hotspot = pos->x_hotspot;
int y_hotspot = pos->y_hotspot; int y_hotspot = pos->y_hotspot;
int src_x_offset = x_pos - pos->x_hotspot;
int src_y_offset = y_pos - pos->y_hotspot;
int cursor_height = (int)hubp->curs_attr.height; int cursor_height = (int)hubp->curs_attr.height;
int cursor_width = (int)hubp->curs_attr.width; int cursor_width = (int)hubp->curs_attr.width;
uint32_t dst_x_offset; uint32_t dst_x_offset;
...@@ -994,18 +996,26 @@ void hubp2_cursor_set_position( ...@@ -994,18 +996,26 @@ void hubp2_cursor_set_position(
if (hubp->curs_attr.address.quad_part == 0) if (hubp->curs_attr.address.quad_part == 0)
return; return;
// Rotated cursor width/height and hotspots tweaks for offset calculation // Transform cursor width / height and hotspots for offset calculations
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) { if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
swap(cursor_height, cursor_width); swap(cursor_height, cursor_width);
swap(x_hotspot, y_hotspot);
if (param->rotation == ROTATION_ANGLE_90) { if (param->rotation == ROTATION_ANGLE_90) {
src_x_offset = pos->x - pos->y_hotspot - param->viewport.x; // hotspot = (-y, x)
src_y_offset = pos->y - pos->x_hotspot - param->viewport.y; src_x_offset = x_pos - (cursor_width - x_hotspot);
src_y_offset = y_pos - y_hotspot;
} else if (param->rotation == ROTATION_ANGLE_270) {
// hotspot = (y, -x)
src_x_offset = x_pos - x_hotspot;
src_y_offset = y_pos - (cursor_height - y_hotspot);
} }
} else if (param->rotation == ROTATION_ANGLE_180) { } else if (param->rotation == ROTATION_ANGLE_180) {
// hotspot = (-x, -y)
if (!param->mirror) if (!param->mirror)
src_x_offset = pos->x - param->viewport.x; src_x_offset = x_pos - (cursor_width - x_hotspot);
src_y_offset = pos->y - param->viewport.y; src_y_offset = y_pos - (cursor_height - y_hotspot);
} }
dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0; dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
...@@ -1042,8 +1052,8 @@ void hubp2_cursor_set_position( ...@@ -1042,8 +1052,8 @@ void hubp2_cursor_set_position(
CURSOR_Y_POSITION, pos->y); CURSOR_Y_POSITION, pos->y);
REG_SET_2(CURSOR_HOT_SPOT, 0, REG_SET_2(CURSOR_HOT_SPOT, 0,
CURSOR_HOT_SPOT_X, x_hotspot, CURSOR_HOT_SPOT_X, pos->x_hotspot,
CURSOR_HOT_SPOT_Y, y_hotspot); CURSOR_HOT_SPOT_Y, pos->y_hotspot);
REG_SET(CURSOR_DST_OFFSET, 0, REG_SET(CURSOR_DST_OFFSET, 0,
CURSOR_DST_X_OFFSET, dst_x_offset); CURSOR_DST_X_OFFSET, dst_x_offset);
...@@ -1052,8 +1062,8 @@ void hubp2_cursor_set_position( ...@@ -1052,8 +1062,8 @@ void hubp2_cursor_set_position(
hubp->pos.cur_ctl.bits.cur_enable = cur_en; hubp->pos.cur_ctl.bits.cur_enable = cur_en;
hubp->pos.position.bits.x_pos = pos->x; hubp->pos.position.bits.x_pos = pos->x;
hubp->pos.position.bits.y_pos = pos->y; hubp->pos.position.bits.y_pos = pos->y;
hubp->pos.hot_spot.bits.x_hot = x_hotspot; hubp->pos.hot_spot.bits.x_hot = pos->x_hotspot;
hubp->pos.hot_spot.bits.y_hot = y_hotspot; hubp->pos.hot_spot.bits.y_hot = pos->y_hotspot;
hubp->pos.dst_offset.bits.dst_x_offset = dst_x_offset; hubp->pos.dst_offset.bits.dst_x_offset = dst_x_offset;
/* Cursor Rectangle Cache /* Cursor Rectangle Cache
* Cursor bitmaps have different hotspot values * Cursor bitmaps have different hotspot values
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment