diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2018-11-22 19:02:20 +0100 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2018-12-13 12:40:40 +0100 |
commit | 0d60233d26ec70d4e1faa343b438e33829c6d5e4 (patch) | |
tree | 38b862552835b5e700619d5fadbd64ff4e88e20d | |
parent | b04697de5270e8e45744a7025c24df1f454a4cf0 (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.c | 27 | ||||
-rw-r--r-- | src/drmmode_display.c | 22 | ||||
-rw-r--r-- | src/drmmode_display.h | 5 |
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; |