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

We were clobbering entries in mi's global miSpritePointerFuncs struct,
which cannot work correctly with multiple primary screens. Instead,
assign a pointer to our own wrapper struct to PointPriv->spriteFuncs.

Fixes crashes with multiple primary screens.

Fixes: 69e20839bfeb ("Keep track of how many SW cursors are visible on
                      each screen")
Reported-by: Mario Kleiner <mario.kleiner...@gmail.com>
Signed-off-by: Michel Dänzer <michel.daen...@amd.com>
---
 src/amdgpu_drv.h      |  4 +---
 src/amdgpu_kms.c      | 14 ++++--------
 src/drmmode_display.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++-----
 src/drmmode_display.h |  7 +++---
 4 files changed, 63 insertions(+), 23 deletions(-)

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 40157262e..acf697730 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -281,9 +281,7 @@ typedef struct {
        CreateScreenResourcesProcPtr CreateScreenResources;
        CreateWindowProcPtr CreateWindow;
        WindowExposuresProcPtr WindowExposures;
-       void (*SetCursor) (DeviceIntPtr pDev, ScreenPtr pScreen,
-                          CursorPtr pCursor, int x, int y);
-       void (*MoveCursor) (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
+       miPointerSpriteFuncPtr SpriteFuncs;
 
        /* Number of SW cursors currently visible on this screen */
        int sprites_visible;
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 90e1f2531..b287fcc6e 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -1551,12 +1551,8 @@ static Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen)
                        return FALSE;
                }
 
-               if (PointPriv->spriteFuncs->SetCursor != 
drmmode_sprite_set_cursor) {
-                       info->SetCursor = PointPriv->spriteFuncs->SetCursor;
-                       info->MoveCursor = PointPriv->spriteFuncs->MoveCursor;
-                       PointPriv->spriteFuncs->SetCursor = 
drmmode_sprite_set_cursor;
-                       PointPriv->spriteFuncs->MoveCursor = 
drmmode_sprite_move_cursor;
-               }
+               info->SpriteFuncs = PointPriv->spriteFuncs;
+               PointPriv->spriteFuncs = &drmmode_sprite_funcs;
        }
 
        if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
@@ -1733,10 +1729,8 @@ static Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen)
                miPointerScreenPtr PointPriv =
                        dixLookupPrivate(&pScreen->devPrivates, 
miPointerScreenKey);
 
-               if (PointPriv->spriteFuncs->SetCursor == 
drmmode_sprite_set_cursor) {
-                       PointPriv->spriteFuncs->SetCursor = info->SetCursor;
-                       PointPriv->spriteFuncs->MoveCursor = info->MoveCursor;
-               }
+               if (PointPriv->spriteFuncs == &drmmode_sprite_funcs)
+                       PointPriv->spriteFuncs = info->SpriteFuncs;
        }
 
        pScreen->BlockHandler = info->BlockHandler;
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 746e52aa7..3513c1f93 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -37,6 +37,7 @@
 #include "inputstr.h"
 #include "list.h"
 #include "micmap.h"
+#include "mipointrst.h"
 #include "xf86cmap.h"
 #include "xf86Priv.h"
 #include "sarea.h"
@@ -2550,8 +2551,8 @@ static void drmmode_sprite_do_set_cursor(struct 
amdgpu_device_priv *device_priv,
        info->sprites_visible += device_priv->sprite_visible - sprite_visible;
 }
 
-void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
-                              CursorPtr pCursor, int x, int y)
+static void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                     CursorPtr pCursor, int x, int y)
 {
        ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
        AMDGPUInfoPtr info = AMDGPUPTR(scrn);
@@ -2562,11 +2563,11 @@ void drmmode_sprite_set_cursor(DeviceIntPtr pDev, 
ScreenPtr pScreen,
        device_priv->cursor = pCursor;
        drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
 
-       info->SetCursor(pDev, pScreen, pCursor, x, y);
+       info->SpriteFuncs->SetCursor(pDev, pScreen, pCursor, x, y);
 }
 
-void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x,
-                               int y)
+static void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                      int x, int y)
 {
        ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
        AMDGPUInfoPtr info = AMDGPUPTR(scrn);
@@ -2576,9 +2577,57 @@ void drmmode_sprite_move_cursor(DeviceIntPtr pDev, 
ScreenPtr pScreen, int x,
 
        drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
 
-       info->MoveCursor(pDev, pScreen, x, y);
+       info->SpriteFuncs->MoveCursor(pDev, pScreen, x, y);
 }
 
+static Bool drmmode_sprite_realize_realize_cursor(DeviceIntPtr pDev,
+                                                 ScreenPtr pScreen,
+                                                 CursorPtr pCursor)
+{
+       ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+
+       return info->SpriteFuncs->RealizeCursor(pDev, pScreen, pCursor);
+}
+
+static Bool drmmode_sprite_realize_unrealize_cursor(DeviceIntPtr pDev,
+                                                   ScreenPtr pScreen,
+                                                   CursorPtr pCursor)
+{
+       ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+
+       return info->SpriteFuncs->UnrealizeCursor(pDev, pScreen, pCursor);
+}
+
+static Bool drmmode_sprite_device_cursor_initialize(DeviceIntPtr pDev,
+                                                   ScreenPtr pScreen)
+{
+       ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+
+       return info->SpriteFuncs->DeviceCursorInitialize(pDev, pScreen);
+}
+
+static void drmmode_sprite_device_cursor_cleanup(DeviceIntPtr pDev,
+                                                ScreenPtr pScreen)
+{
+       ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+
+       info->SpriteFuncs->DeviceCursorCleanup(pDev, pScreen);
+}
+
+miPointerSpriteFuncRec drmmode_sprite_funcs = {
+       .RealizeCursor = drmmode_sprite_realize_realize_cursor,
+       .UnrealizeCursor = drmmode_sprite_realize_unrealize_cursor,
+       .SetCursor = drmmode_sprite_set_cursor,
+       .MoveCursor = drmmode_sprite_move_cursor,
+       .DeviceCursorInitialize = drmmode_sprite_device_cursor_initialize,
+       .DeviceCursorCleanup = drmmode_sprite_device_cursor_cleanup,
+};
+
+       
 void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id,
                        struct amdgpu_buffer *bo)
 {
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 4e6f70776..2aa56723d 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -198,10 +198,6 @@ extern int drmmode_page_flip_target_relative(AMDGPUEntPtr 
pAMDGPUEnt,
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp);
 extern void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 extern void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
-extern void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
-                                     CursorPtr pCursor, int x, int y);
-extern void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
int x,
-                                      int y);
 extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id,
                               struct amdgpu_buffer *bo);
 void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int 
y);
@@ -239,4 +235,7 @@ Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType 
type,
                         uint64_t *ust, uint32_t *result_seq);
 
 
+miPointerSpriteFuncRec drmmode_sprite_funcs;
+
+
 #endif
-- 
2.16.2

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

Reply via email to