diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2018-12-21 18:04:21 +0100 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2018-12-28 12:10:19 +0100 |
commit | 803f872f7d4b2d80be434bb42ce64dfd295b122c (patch) | |
tree | e1e5fac1e873c792637306f311a2e3c0e5e419b3 | |
parent | 91e557f78ad261e76a1829f54722c2c0781742d2 (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
(Ported from amdgpu commit 0d60233d26ec70d4e1faa343b438e33829c6d5e4)
-rw-r--r-- | src/drmmode_display.c | 18 | ||||
-rw-r--r-- | src/drmmode_display.h | 5 | ||||
-rw-r--r-- | src/radeon_kms.c | 34 |
3 files changed, 37 insertions, 20 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index bec309e5..d433e061 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1122,13 +1122,18 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + unsigned id = drmmode_crtc->cursor_id; Bool premultiplied = TRUE; Bool apply_gamma = TRUE; uint32_t argb; uint32_t *ptr; + if (drmmode_crtc->cursor && + XF86_CRTC_CONFIG_PTR(pScrn)->cursor != drmmode_crtc->cursor) + id ^= 1; + /* cursor should be mapped already */ - ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); + ptr = (uint32_t *)(drmmode_crtc->cursor_bo[id]->ptr); if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) apply_gamma = FALSE; @@ -1170,6 +1175,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) @@ -1195,7 +1205,7 @@ drmmode_hide_cursor (xf86CrtcPtr crtc) drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, info->cursor_w, info->cursor_h); - + drmmode_crtc->cursor = NULL; } static void @@ -1212,9 +1222,11 @@ 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)); - arg.handle = drmmode_crtc->cursor_bo->handle; + arg.handle = drmmode_crtc->cursor_bo[drmmode_crtc->cursor_id]->handle; arg.flags = DRM_MODE_CURSOR_BO; arg.crtc_id = drmmode_crtc->mode_crtc->crtc_id; arg.width = info->cursor_w; diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 49893ab0..2c2c3d57 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -88,11 +88,14 @@ typedef struct { drmModeCrtcPtr mode_crtc; int hw_id; + CursorPtr cursor; int cursor_x; int cursor_y; int cursor_xhot; int cursor_yhot; - struct radeon_bo *cursor_bo; + unsigned cursor_id; + struct radeon_bo *cursor_bo[2]; + struct drmmode_scanout rotate; struct drmmode_scanout scanout[2]; DamagePtr scanout_damage; diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 27a02109..bb6885fb 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -2755,27 +2755,29 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen) { int cursor_size; - int c; + int c, i; cursor_size = info->cursor_w * info->cursor_h * 4; cursor_size = RADEON_ALIGN(cursor_size, RADEON_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_bo) { - drmmode_crtc->cursor_bo = radeon_bo_open(info->bufmgr, 0, - cursor_size, 0, - RADEON_GEM_DOMAIN_VRAM, 0); - if (!(drmmode_crtc->cursor_bo)) { - ErrorF("Failed to allocate cursor buffer memory\n"); - return FALSE; - } - - if (radeon_bo_map(drmmode_crtc->cursor_bo, 1)) { - ErrorF("Failed to map cursor buffer memory\n"); - } - } - } + for (i = 0; i < 2; i++) { + if (!drmmode_crtc->cursor_bo[i]) { + drmmode_crtc->cursor_bo[i] = + radeon_bo_open(info->bufmgr, 0, cursor_size, 0, + RADEON_GEM_DOMAIN_VRAM, 0); + + if (!(drmmode_crtc->cursor_bo[i])) { + ErrorF("Failed to allocate cursor buffer memory\n"); + return FALSE; + } + + if (radeon_bo_map(drmmode_crtc->cursor_bo[i], 1)) + ErrorF("Failed to map cursor buffer memory\n"); + } + } + } } if (!info->front_buffer) { @@ -2841,7 +2843,7 @@ void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_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_bo) + if (drmmode_crtc->cursor_bo[0]) new_fb_size += (64 * 4 * 64); } |