[PATCH xserver] cursor: add hw cursor support for prime

Hans de Goede hdegoede at redhat.com
Mon Sep 5 13:42:34 UTC 2016


Hi,

Subject should have contained v4, resending so that we've
the right version in patchwork. Sorry.

Regards,

Hans


On 05-09-16 15:37, Hans de Goede wrote:
> 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;
> +}
>


More information about the xorg-devel mailing list