From 7b634067c13045671685a9f00bfbac626ed68f94 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 15 Jul 2015 10:15:51 +1000 Subject: xf86Cursor: Add hw cursor support for prime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Dave Airlie Signed-off-by: Hans de Goede Reviewed-by: Michel Dänzer Reviewed-by: Keith Packard --- dix/dispatch.c | 10 ++++++ hw/xfree86/ramdac/xf86Cursor.c | 2 +- hw/xfree86/ramdac/xf86HWCurs.c | 82 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/dix/dispatch.c b/dix/dispatch.c index a3c2fbb31..0edcfeea8 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -3965,6 +3965,16 @@ AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , update_desktop_dimensions(); + /* + * We cannot register the Screen PRIVATE_CURSOR key if cursors are already + * created, because dix/privates.c does not have relocation code for + * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can + * register the Screen PRIVATE_CURSOR key unconditionally. + */ + if (!dixPrivatesCreated(PRIVATE_CURSOR)) + dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, + PRIVATE_CURSOR, 0); + return i; } diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c index 623a65b33..afcce5353 100644 --- a/hw/xfree86/ramdac/xf86Cursor.c +++ b/hw/xfree86/ramdac/xf86Cursor.c @@ -337,7 +337,7 @@ 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 || xf86CheckHWCursor(pScreen, cursor, infoPtr))) { diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c index 1b85e6346..e8966ed35 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" @@ -119,8 +120,8 @@ xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr) return TRUE; } -Bool -xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr) +static Bool +xf86ScreenCheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr) { return (cursor->bits->argb && infoPtr->UseHWCursorARGB && @@ -132,7 +133,29 @@ xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr } Bool -xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) +xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr) +{ + ScreenPtr pSlave; + + if (!xf86ScreenCheckHWCursor(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 (!xf86ScreenCheckHWCursor(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, @@ -145,6 +168,14 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) return TRUE; } + /* + * Hot plugged GPU's do not have a CursorScreenKey, force sw cursor. + * This check can be removed once dix/privates.c gets relocation code for + * PRIVATE_CURSOR. Also see the related comment in AddGPUScreen(). + */ + if (!_dixGetScreenPrivateKey(CursorScreenKey, pScreen)) + return FALSE; + bits = dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen); @@ -177,6 +208,31 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) return TRUE; } +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) { @@ -199,8 +255,8 @@ xf86SetTransparentCursor(ScreenPtr pScreen) (*infoPtr->ShowCursor) (infoPtr->pScrn); } -void -xf86MoveCursor(ScreenPtr pScreen, int x, int y) +static void +xf86ScreenMoveCursor(ScreenPtr pScreen, int x, int y) { xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, @@ -213,6 +269,22 @@ xf86MoveCursor(ScreenPtr pScreen, int x, int y) (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, 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) { -- cgit v1.2.3