From: Michel Dänzer <michel.daen...@amd.com>

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)

Signed-off-by: Michel Dänzer <michel.daen...@amd.com>
---
 src/drmmode_display.c | 18 +++++++++++++++---
 src/drmmode_display.h |  5 ++++-
 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 bec309e5e..d433e0611 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 49893ab04..2c2c3d57f 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 27a02109a..bb6885fb9 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);
     }
 
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to