[PATCH v4 xserver] cursor: add hw cursor support for prime
Hans de Goede
hdegoede at redhat.com
Mon Sep 5 13:41:31 UTC 2016
From: Dave Airlie <airlied at gmail.com>
Currently with PRIME if we detect a secondary GPU,
we switch to using SW cursors, this isn't optimal,
esp for the intel/nvidia combinations, we have
no choice for the USB offload devices.
This patch checks on each slave screen if hw
cursors are enabled, and also calls set cursor
and move cursor on all screens.
Cc: Aaron Plattner <aplattner at nvidia.com>
Signed-off-by: Dave Airlie <airlied at redhat.com>
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
Changes in v4 (Hans de Goede):
-Fix crash when xf86ScreenSetCursor() gets called on a hot-plugged GPU
Changes in v3 (Hans de Goede):
-Re-indent xf86CursorScreenCheckHW
-Loop over slave-outputs instead of over pixmap_dirty_list, Aaron Plattner has
indicated that the nvidia driver does not use pixmap_dirty_list and with
the recent "randr/xf86: Add PRIME Synchronization / Double Buffer" changes
there may be 2 pixmaps pointing to the same GPU screen on the pixmap_dirty_list twice
-Make xf86CurrentCursor work when called on GPU screen pointers
(fixes the modesetting driver as outputslave crashing)
-Fix both hw and sw cursor showing at the same time when an usb slave-gpu is
present at cold plug time
Changes in v2:
-hotplugging causes the driver to try and register
the cursor private, however we can't register
these at runtime yet, we need to add support for
reallocation of cursor screen privates. However
all hotplugged devices currently don't support
HW cursors, so punt for now. This means GPUs
already in the system will get hw cursors
and USB ones won't which is all we care about
presently.
-drop list empty checks (Eric)
-fixup comments (Michel)
foo
foo
---
dix/dispatch.c | 4 ++
dix/privates.c | 9 ++++
hw/xfree86/ramdac/xf86Cursor.c | 20 ++++-----
hw/xfree86/ramdac/xf86CursorPriv.h | 1 +
hw/xfree86/ramdac/xf86HWCurs.c | 86 ++++++++++++++++++++++++++++++++++++--
include/privates.h | 3 ++
randr/randrstr.h | 6 +++
randr/rrcrtc.c | 19 +++++++++
8 files changed, 133 insertions(+), 15 deletions(-)
diff --git a/dix/dispatch.c b/dix/dispatch.c
index a3c2fbb..21c387e 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3965,6 +3965,10 @@ AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
update_desktop_dimensions();
+ if (!dixPrivatesCreated(PRIVATE_CURSOR))
+ dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen,
+ PRIVATE_CURSOR, 0);
+
return i;
}
diff --git a/dix/privates.c b/dix/privates.c
index 969d014..478f52c 100644
--- a/dix/privates.c
+++ b/dix/privates.c
@@ -783,3 +783,12 @@ dixResetPrivates(void)
global_keys[t].allocated = 0;
}
}
+
+Bool
+dixPrivatesCreated(DevPrivateType type)
+{
+ if (global_keys[type].created)
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index dda4349..afcce53 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -337,16 +337,9 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
return;
}
- if (infoPtr->pScrn->vtSema && xorg_list_is_empty(&pScreen->pixmap_dirty_list) &&
+ if (infoPtr->pScrn->vtSema &&
(ScreenPriv->ForceHWCursorCount ||
- ((
- cursor->bits->argb &&
- infoPtr->UseHWCursorARGB &&
- (*infoPtr->UseHWCursorARGB)(pScreen, cursor)) ||
- (cursor->bits->argb == 0 &&
- (cursor->bits->height <= infoPtr->MaxHeight) &&
- (cursor->bits->width <= infoPtr->MaxWidth) &&
- (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, cursor)))))) {
+ xf86CheckHWCursor(pScreen, cursor, infoPtr))) {
if (ScreenPriv->SWCursor) /* remove the SW cursor */
(*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen,
@@ -465,9 +458,12 @@ xf86ForceHWCursor(ScreenPtr pScreen, Bool on)
CursorPtr
xf86CurrentCursor(ScreenPtr pScreen)
{
- xf86CursorScreenPtr ScreenPriv =
- (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
- xf86CursorScreenKey);
+ xf86CursorScreenPtr ScreenPriv;
+
+ if (pScreen->is_output_slave)
+ pScreen = pScreen->current_master;
+
+ ScreenPriv = dixLookupPrivate(&pScreen->devPrivates, xf86CursorScreenKey);
return ScreenPriv->CurrentCursor;
}
diff --git a/hw/xfree86/ramdac/xf86CursorPriv.h b/hw/xfree86/ramdac/xf86CursorPriv.h
index f34c1c7..397d2a1 100644
--- a/hw/xfree86/ramdac/xf86CursorPriv.h
+++ b/hw/xfree86/ramdac/xf86CursorPriv.h
@@ -43,6 +43,7 @@ void xf86MoveCursor(ScreenPtr pScreen, int x, int y);
void xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed);
Bool xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr);
+Bool xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr);
extern _X_EXPORT DevPrivateKeyRec xf86CursorScreenKeyRec;
#define xf86CursorScreenKey (&xf86CursorScreenKeyRec)
diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
index 458781c..ccfcf4f 100644
--- a/hw/xfree86/ramdac/xf86HWCurs.c
+++ b/hw/xfree86/ramdac/xf86HWCurs.c
@@ -17,6 +17,7 @@
#include "cursorstr.h"
#include "mi.h"
#include "mipointer.h"
+#include "randrstr.h"
#include "xf86CursorPriv.h"
#include "servermd.h"
@@ -129,8 +130,42 @@ xf86ShowCursor(xf86CursorInfoPtr infoPtr)
return TRUE;
}
+static Bool
+xf86CursorScreenCheckHW(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
+{
+ return
+ (cursor->bits->argb && infoPtr->UseHWCursorARGB &&
+ infoPtr->UseHWCursorARGB(pScreen, cursor)) ||
+ (cursor->bits->argb == 0 &&
+ cursor->bits->height <= infoPtr->MaxHeight &&
+ cursor->bits->width <= infoPtr->MaxWidth &&
+ (!infoPtr->UseHWCursor || infoPtr->UseHWCursor(pScreen, cursor)));
+}
+
Bool
-xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
+xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
+{
+ ScreenPtr pSlave;
+
+ if (!xf86CursorScreenCheckHW(pScreen, cursor, infoPtr))
+ return FALSE;
+
+ /* ask each driver consuming a pixmap if it can support HW cursor */
+ xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
+ xf86CursorScreenPtr sPriv;
+
+ if (!RRHasScanoutPixmap(pSlave))
+ continue;
+
+ sPriv = dixLookupPrivate(&pSlave->devPrivates, xf86CursorScreenKey);
+ if (!xf86CursorScreenCheckHW(pSlave, cursor, sPriv->CursorInfoPtr))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static Bool
+xf86ScreenSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
{
xf86CursorScreenPtr ScreenPriv =
(xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
@@ -143,6 +178,10 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
return TRUE;
}
+ /* Hot plugged GPU's do not have a CursorScreenKey, force sw cursor */
+ if (!_dixGetScreenPrivateKey(CursorScreenKey, pScreen))
+ return FALSE;
+
bits =
dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen);
@@ -175,6 +214,31 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
}
+Bool
+xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
+{
+ ScreenPtr pSlave;
+
+ if (!xf86ScreenSetCursor(pScreen, pCurs, x, y))
+ return FALSE;
+
+ /* ask each slave driver to set the cursor. */
+ xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
+ if (!RRHasScanoutPixmap(pSlave))
+ continue;
+
+ if (!xf86ScreenSetCursor(pSlave, pCurs, x, y)) {
+ /*
+ * hide the master (and successfully set slave) cursors,
+ * otherwise both the hw and sw cursor will show.
+ */
+ xf86SetCursor(pScreen, NullCursor, x, y);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
void
xf86SetTransparentCursor(ScreenPtr pScreen)
{
@@ -197,8 +261,8 @@ xf86SetTransparentCursor(ScreenPtr pScreen)
xf86ShowCursor(infoPtr);
}
-void
-xf86MoveCursor(ScreenPtr pScreen, int x, int y)
+static void
+xf86ScreenMoveCursor(ScreenPtr pScreen, int x, int y)
{
xf86CursorScreenPtr ScreenPriv =
(xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
@@ -212,6 +276,22 @@ xf86MoveCursor(ScreenPtr pScreen, int x, int y)
}
void
+xf86MoveCursor(ScreenPtr pScreen, int x, int y)
+{
+ ScreenPtr pSlave;
+
+ xf86ScreenMoveCursor(pScreen, x, y);
+
+ /* ask each slave driver to move the cursor */
+ xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
+ if (!RRHasScanoutPixmap(pSlave))
+ continue;
+
+ xf86ScreenMoveCursor(pSlave, x, y);
+ }
+}
+
+void
xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
{
xf86CursorScreenPtr ScreenPriv =
diff --git a/include/privates.h b/include/privates.h
index 7d1461c..a2bb1a4 100644
--- a/include/privates.h
+++ b/include/privates.h
@@ -252,6 +252,9 @@ dixFreeScreenSpecificPrivates(ScreenPtr pScreen);
extern void
dixInitScreenSpecificPrivates(ScreenPtr pScreen);
+/* is this private created - so hotplug can avoid crashing */
+Bool dixPrivatesCreated(DevPrivateType type);
+
extern _X_EXPORT void *
_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,
unsigned size,
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 1baa912..706e9a7 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -726,6 +726,12 @@ extern _X_EXPORT Bool
RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable);
/*
+ * Return if the screen has any scanout_pixmap's attached
+ */
+extern _X_EXPORT Bool
+ RRHasScanoutPixmap(ScreenPtr pScreen);
+
+/*
* Crtc dispatch
*/
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 8fb2bca..7636591 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1945,3 +1945,22 @@ RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
return ret;
}
+
+Bool
+RRHasScanoutPixmap(ScreenPtr pScreen)
+{
+ rrScrPriv(pScreen);
+ int i;
+
+ if (!pScreen->is_output_slave)
+ return FALSE;
+
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+ if (crtc->scanout_pixmap)
+ return TRUE;
+ }
+
+ return FALSE;
+}
--
2.9.3
More information about the xorg-devel
mailing list