Skip to content

Commit e640536

Browse files
dgaliffiAMDalexdeucher
authored andcommitted
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: Martin Leung <[email protected]> Acked-by: Brian Chang <[email protected]> Signed-off-by: David Galiffi <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 1a97a13 commit e640536

File tree

3 files changed

+64
-30
lines changed

3 files changed

+64
-30
lines changed

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -436,34 +436,48 @@ void dpp1_set_cursor_position(
436436
uint32_t height)
437437
{
438438
struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
439-
int src_x_offset = pos->x - pos->x_hotspot - param->viewport.x;
440-
int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y;
439+
int x_pos = pos->x - param->viewport.x;
440+
int y_pos = pos->y - param->viewport.y;
441+
int x_hotspot = pos->x_hotspot;
442+
int y_hotspot = pos->y_hotspot;
443+
int src_x_offset = x_pos - pos->x_hotspot;
444+
int src_y_offset = y_pos - pos->y_hotspot;
445+
int cursor_height = (int)height;
446+
int cursor_width = (int)width;
441447
uint32_t cur_en = pos->enable ? 1 : 0;
442448

443-
// Cursor width/height and hotspots need to be rotated for offset calculation
449+
// Transform cursor width / height and hotspots for offset calculations
444450
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
445-
swap(width, height);
451+
swap(cursor_height, cursor_width);
452+
swap(x_hotspot, y_hotspot);
453+
446454
if (param->rotation == ROTATION_ANGLE_90) {
447-
src_x_offset = pos->x - pos->y_hotspot - param->viewport.x;
448-
src_y_offset = pos->y - pos->x_hotspot - param->viewport.y;
455+
// hotspot = (-y, x)
456+
src_x_offset = x_pos - (cursor_width - x_hotspot);
457+
src_y_offset = y_pos - y_hotspot;
458+
} else if (param->rotation == ROTATION_ANGLE_270) {
459+
// hotspot = (y, -x)
460+
src_x_offset = x_pos - x_hotspot;
461+
src_y_offset = y_pos - (cursor_height - y_hotspot);
449462
}
450463
} else if (param->rotation == ROTATION_ANGLE_180) {
464+
// hotspot = (-x, -y)
451465
if (!param->mirror)
452-
src_x_offset = pos->x - param->viewport.x;
466+
src_x_offset = x_pos - (cursor_width - x_hotspot);
453467

454-
src_y_offset = pos->y - param->viewport.y;
468+
src_y_offset = y_pos - (cursor_height - y_hotspot);
455469
}
456470

457471
if (src_x_offset >= (int)param->viewport.width)
458472
cur_en = 0; /* not visible beyond right edge*/
459473

460-
if (src_x_offset + (int)width <= 0)
474+
if (src_x_offset + cursor_width <= 0)
461475
cur_en = 0; /* not visible beyond left edge*/
462476

463477
if (src_y_offset >= (int)param->viewport.height)
464478
cur_en = 0; /* not visible beyond bottom edge*/
465479

466-
if (src_y_offset + (int)height <= 0)
480+
if (src_y_offset + cursor_height <= 0)
467481
cur_en = 0; /* not visible beyond top edge*/
468482

469483
REG_UPDATE(CURSOR0_CONTROL,

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,10 +1179,12 @@ void hubp1_cursor_set_position(
11791179
const struct dc_cursor_mi_param *param)
11801180
{
11811181
struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
1182-
int src_x_offset = pos->x - pos->x_hotspot - param->viewport.x;
1183-
int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y;
1182+
int x_pos = pos->x - param->viewport.x;
1183+
int y_pos = pos->y - param->viewport.y;
11841184
int x_hotspot = pos->x_hotspot;
11851185
int y_hotspot = pos->y_hotspot;
1186+
int src_x_offset = x_pos - pos->x_hotspot;
1187+
int src_y_offset = y_pos - pos->y_hotspot;
11861188
int cursor_height = (int)hubp->curs_attr.height;
11871189
int cursor_width = (int)hubp->curs_attr.width;
11881190
uint32_t dst_x_offset;
@@ -1200,18 +1202,26 @@ void hubp1_cursor_set_position(
12001202
if (hubp->curs_attr.address.quad_part == 0)
12011203
return;
12021204

1203-
// Rotated cursor width/height and hotspots tweaks for offset calculation
1205+
// Transform cursor width / height and hotspots for offset calculations
12041206
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
12051207
swap(cursor_height, cursor_width);
1208+
swap(x_hotspot, y_hotspot);
1209+
12061210
if (param->rotation == ROTATION_ANGLE_90) {
1207-
src_x_offset = pos->x - pos->y_hotspot - param->viewport.x;
1208-
src_y_offset = pos->y - pos->x_hotspot - param->viewport.y;
1211+
// hotspot = (-y, x)
1212+
src_x_offset = x_pos - (cursor_width - x_hotspot);
1213+
src_y_offset = y_pos - y_hotspot;
1214+
} else if (param->rotation == ROTATION_ANGLE_270) {
1215+
// hotspot = (y, -x)
1216+
src_x_offset = x_pos - x_hotspot;
1217+
src_y_offset = y_pos - (cursor_height - y_hotspot);
12091218
}
12101219
} else if (param->rotation == ROTATION_ANGLE_180) {
1220+
// hotspot = (-x, -y)
12111221
if (!param->mirror)
1212-
src_x_offset = pos->x - param->viewport.x;
1222+
src_x_offset = x_pos - (cursor_width - x_hotspot);
12131223

1214-
src_y_offset = pos->y - param->viewport.y;
1224+
src_y_offset = y_pos - (cursor_height - y_hotspot);
12151225
}
12161226

12171227
dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
@@ -1248,8 +1258,8 @@ void hubp1_cursor_set_position(
12481258
CURSOR_Y_POSITION, pos->y);
12491259

12501260
REG_SET_2(CURSOR_HOT_SPOT, 0,
1251-
CURSOR_HOT_SPOT_X, x_hotspot,
1252-
CURSOR_HOT_SPOT_Y, y_hotspot);
1261+
CURSOR_HOT_SPOT_X, pos->x_hotspot,
1262+
CURSOR_HOT_SPOT_Y, pos->y_hotspot);
12531263

12541264
REG_SET(CURSOR_DST_OFFSET, 0,
12551265
CURSOR_DST_X_OFFSET, dst_x_offset);

drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -973,10 +973,12 @@ void hubp2_cursor_set_position(
973973
const struct dc_cursor_mi_param *param)
974974
{
975975
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
976-
int src_x_offset = pos->x - pos->x_hotspot - param->viewport.x;
977-
int src_y_offset = pos->y - pos->y_hotspot - param->viewport.y;
976+
int x_pos = pos->x - param->viewport.x;
977+
int y_pos = pos->y - param->viewport.y;
978978
int x_hotspot = pos->x_hotspot;
979979
int y_hotspot = pos->y_hotspot;
980+
int src_x_offset = x_pos - pos->x_hotspot;
981+
int src_y_offset = y_pos - pos->y_hotspot;
980982
int cursor_height = (int)hubp->curs_attr.height;
981983
int cursor_width = (int)hubp->curs_attr.width;
982984
uint32_t dst_x_offset;
@@ -994,18 +996,26 @@ void hubp2_cursor_set_position(
994996
if (hubp->curs_attr.address.quad_part == 0)
995997
return;
996998

997-
// Rotated cursor width/height and hotspots tweaks for offset calculation
999+
// Transform cursor width / height and hotspots for offset calculations
9981000
if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
9991001
swap(cursor_height, cursor_width);
1002+
swap(x_hotspot, y_hotspot);
1003+
10001004
if (param->rotation == ROTATION_ANGLE_90) {
1001-
src_x_offset = pos->x - pos->y_hotspot - param->viewport.x;
1002-
src_y_offset = pos->y - pos->x_hotspot - param->viewport.y;
1005+
// hotspot = (-y, x)
1006+
src_x_offset = x_pos - (cursor_width - x_hotspot);
1007+
src_y_offset = y_pos - y_hotspot;
1008+
} else if (param->rotation == ROTATION_ANGLE_270) {
1009+
// hotspot = (y, -x)
1010+
src_x_offset = x_pos - x_hotspot;
1011+
src_y_offset = y_pos - (cursor_height - y_hotspot);
10031012
}
10041013
} else if (param->rotation == ROTATION_ANGLE_180) {
1014+
// hotspot = (-x, -y)
10051015
if (!param->mirror)
1006-
src_x_offset = pos->x - param->viewport.x;
1016+
src_x_offset = x_pos - (cursor_width - x_hotspot);
10071017

1008-
src_y_offset = pos->y - param->viewport.y;
1018+
src_y_offset = y_pos - (cursor_height - y_hotspot);
10091019
}
10101020

10111021
dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
@@ -1042,8 +1052,8 @@ void hubp2_cursor_set_position(
10421052
CURSOR_Y_POSITION, pos->y);
10431053

10441054
REG_SET_2(CURSOR_HOT_SPOT, 0,
1045-
CURSOR_HOT_SPOT_X, x_hotspot,
1046-
CURSOR_HOT_SPOT_Y, y_hotspot);
1055+
CURSOR_HOT_SPOT_X, pos->x_hotspot,
1056+
CURSOR_HOT_SPOT_Y, pos->y_hotspot);
10471057

10481058
REG_SET(CURSOR_DST_OFFSET, 0,
10491059
CURSOR_DST_X_OFFSET, dst_x_offset);
@@ -1052,8 +1062,8 @@ void hubp2_cursor_set_position(
10521062
hubp->pos.cur_ctl.bits.cur_enable = cur_en;
10531063
hubp->pos.position.bits.x_pos = pos->x;
10541064
hubp->pos.position.bits.y_pos = pos->y;
1055-
hubp->pos.hot_spot.bits.x_hot = x_hotspot;
1056-
hubp->pos.hot_spot.bits.y_hot = y_hotspot;
1065+
hubp->pos.hot_spot.bits.x_hot = pos->x_hotspot;
1066+
hubp->pos.hot_spot.bits.y_hot = pos->y_hotspot;
10571067
hubp->pos.dst_offset.bits.dst_x_offset = dst_x_offset;
10581068
/* Cursor Rectangle Cache
10591069
* Cursor bitmaps have different hotspot values

0 commit comments

Comments
 (0)