summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2018-11-22 19:02:20 +0100
committerMichel Dänzer <michel@daenzer.net>2018-12-13 12:40:40 +0100
commit0d60233d26ec70d4e1faa343b438e33829c6d5e4 (patch)
tree38b862552835b5e700619d5fadbd64ff4e88e20d
parentb04697de5270e8e45744a7025c24df1f454a4cf0 (diff)
Use two HW cursor buffers per CRTC
Switch to the other buffer when xf86_config->cursor changes. Avoids these issues possible when re-using the same buffer: * The HW may intermittently display a mix of the old and new cursor images. * If the hotspot changes, the HW may intermittently display the new cursor image at the location corresponding to the old image's hotspot. Bugzilla: https://bugs.freedesktop.org/108832 Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--src/amdgpu_kms.c27
-rw-r--r--src/drmmode_display.c22
-rw-r--r--src/drmmode_display.h5
3 files changed, 38 insertions, 16 deletions
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index fad2382..4cd46f2 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -2275,25 +2275,28 @@ static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen)
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
int cpp = info->pixel_bytes;
int cursor_size;
- int c;
+ int c, i;
cursor_size = info->cursor_w * info->cursor_h * 4;
cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE);
for (c = 0; c < xf86_config->num_crtc; c++) {
drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
- if (!drmmode_crtc->cursor_buffer) {
- drmmode_crtc->cursor_buffer = amdgpu_bo_open(pAMDGPUEnt->pDev,
- cursor_size, 0,
- AMDGPU_GEM_DOMAIN_VRAM);
- if (!(drmmode_crtc->cursor_buffer)) {
- ErrorF("Failed to allocate cursor buffer memory\n");
- return FALSE;
- }
+ for (i = 0; i < 2; i++) {
+ if (!drmmode_crtc->cursor_buffer[i]) {
+ drmmode_crtc->cursor_buffer[i] =
+ amdgpu_bo_open(pAMDGPUEnt->pDev,
+ cursor_size, 0,
+ AMDGPU_GEM_DOMAIN_VRAM);
+
+ if (!(drmmode_crtc->cursor_buffer[i])) {
+ ErrorF("Failed to allocate cursor buffer memory\n");
+ return FALSE;
+ }
- if (amdgpu_bo_cpu_map(drmmode_crtc->cursor_buffer->bo.amdgpu,
- &drmmode_crtc->cursor_buffer->cpu_ptr)) {
- ErrorF("Failed to map cursor buffer memory\n");
+ if (amdgpu_bo_cpu_map(drmmode_crtc->cursor_buffer[i]->bo.amdgpu,
+ &drmmode_crtc->cursor_buffer[i]->cpu_ptr))
+ ErrorF("Failed to map cursor buffer memory\n");
}
}
}
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 84d9a48..92cf543 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1633,17 +1633,24 @@ drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied,
static void drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- uint32_t *ptr = (uint32_t *) (drmmode_crtc->cursor_buffer->cpu_ptr);
ScrnInfoPtr pScrn = crtc->scrn;
AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+ unsigned id = drmmode_crtc->cursor_id;
Bool premultiplied = TRUE;
Bool apply_gamma = TRUE;
uint32_t argb;
+ uint32_t *ptr;
if ((crtc->scrn->depth != 24 && crtc->scrn->depth != 32) ||
drmmode_cm_enabled(&info->drmmode))
apply_gamma = FALSE;
+ if (drmmode_crtc->cursor &&
+ XF86_CRTC_CONFIG_PTR(pScrn)->cursor != drmmode_crtc->cursor)
+ id ^= 1;
+
+ ptr = (uint32_t *) (drmmode_crtc->cursor_buffer[id]->cpu_ptr);
+
#if XF86_CRTC_VERSION < 7
if (crtc->driverIsPerformingTransform) {
uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h;
@@ -1681,6 +1688,11 @@ retry:
ptr[i] = cpu_to_le32(argb);
}
}
+
+ if (id != drmmode_crtc->cursor_id) {
+ drmmode_crtc->cursor_id = id;
+ crtc->funcs->show_cursor(crtc);
+ }
}
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
@@ -1705,7 +1717,7 @@ static void drmmode_hide_cursor(xf86CrtcPtr crtc)
drmModeSetCursor(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
info->cursor_w, info->cursor_h);
-
+ drmmode_crtc->cursor = NULL;
}
static void drmmode_show_cursor(xf86CrtcPtr crtc)
@@ -1714,6 +1726,8 @@ static void drmmode_show_cursor(xf86CrtcPtr crtc)
AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ struct amdgpu_buffer *cursor_buffer =
+ drmmode_crtc->cursor_buffer[drmmode_crtc->cursor_id];
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
CursorPtr cursor = xf86_config->cursor;
int xhot = cursor->bits->xhot;
@@ -1721,9 +1735,11 @@ static void drmmode_show_cursor(xf86CrtcPtr crtc)
static Bool use_set_cursor2 = TRUE;
struct drm_mode_cursor2 arg;
+ drmmode_crtc->cursor = xf86_config->cursor;
+
memset(&arg, 0, sizeof(arg));
- if (!amdgpu_bo_get_handle(drmmode_crtc->cursor_buffer, &arg.handle)) {
+ if (!amdgpu_bo_get_handle(cursor_buffer, &arg.handle)) {
ErrorF("failed to get BO handle for cursor\n");
return;
}
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 87b301e..2fb97df 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -108,11 +108,14 @@ typedef struct {
drmModeCrtcPtr mode_crtc;
int hw_id;
+ CursorPtr cursor;
int cursor_x;
int cursor_y;
int cursor_xhot;
int cursor_yhot;
- struct amdgpu_buffer *cursor_buffer;
+ unsigned cursor_id;
+ struct amdgpu_buffer *cursor_buffer[2];
+
struct drmmode_scanout rotate;
struct drmmode_scanout scanout[2];
DamagePtr scanout_damage;