[PATCH xf86-video-amdgpu 2/2] Keep track of how many SW cursors are visible on each screen

Michel Dänzer michel at daenzer.net
Fri Dec 22 17:39:44 UTC 2017


From: Michel Dänzer <michel.daenzer at amd.com>

And use this to determine when we cannot use page flipping for DRI
clients. We previously did this based on whether the HW cursor cannot
be used on at least one CRTC, which had at least two issues:

* Even while the HW cursor cannot be used, no SW cursor may actually be
  visible (e.g. because all cursors are disabled), in which case we can
  use page flipping for DRI clients anyway
* Even while the HW cursor can be used, there may be SW cursors visible
  from non-core pointer devices, in which case we cannot use page
  flipping for DRI clients anyway

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/amdgpu_dri2.c     |  2 +-
 src/amdgpu_drv.h      | 13 +++++++++++++
 src/amdgpu_kms.c      | 28 +++++++++++++++++++++++++++
 src/amdgpu_present.c  |  2 +-
 src/drmmode_display.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/drmmode_display.h |  4 ++++
 6 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index a8ccd22ba..4ffa34676 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -603,7 +603,7 @@ can_flip(xf86CrtcPtr crtc, DrawablePtr draw,
 
 	if (draw->type != DRAWABLE_WINDOW ||
 	    !info->allowPageFlip ||
-	    info->hwcursor_disabled ||
+	    info->sprites_visible > 0 ||
 	    info->drmmode.present_flipping ||
 	    !pScrn->vtSema ||
 	    !DRI2CanFlip(draw))
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 055c3c3e9..72975d597 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -234,6 +234,13 @@ struct amdgpu_client_priv {
 	uint_fast32_t needs_flush;
 };
 
+struct amdgpu_device_priv {
+	CursorPtr cursor;
+	Bool sprite_visible;
+};
+
+extern DevScreenPrivateKeyRec amdgpu_device_private_key;
+
 typedef struct {
 	EntityInfoPtr pEnt;
 	struct pci_device *PciInfo;
@@ -274,6 +281,12 @@ 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);
+
+	/* Number of SW cursor currently visible on this screen */
+	int sprites_visible;
 
 	Bool IsSecondary;
 
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 58531bf33..49044f514 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -37,6 +37,7 @@
 #include "amdgpu_glamor.h"
 #include "amdgpu_probe.h"
 #include "micmap.h"
+#include "mipointrst.h"
 
 #include "amdgpu_version.h"
 #include "shadow.h"
@@ -62,6 +63,7 @@
 #include <gbm.h>
 
 static DevScreenPrivateKeyRec amdgpu_client_private_key;
+DevScreenPrivateKeyRec amdgpu_device_private_key;
 
 static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen);
 
@@ -1532,6 +1534,23 @@ static Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen)
 	/* Cursor setup */
 	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
 
+	if (info->allowPageFlip) {
+		miPointerScreenPtr PointPriv =
+			dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
+
+		if (!dixRegisterScreenPrivateKey(&amdgpu_device_private_key, pScreen,
+						 PRIVATE_DEVICE,
+						 sizeof(struct amdgpu_device_priv))) {
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n");
+			return FALSE;
+		}
+
+		info->SetCursor = PointPriv->spriteFuncs->SetCursor;
+		info->MoveCursor = PointPriv->spriteFuncs->MoveCursor;
+		PointPriv->spriteFuncs->SetCursor = drmmode_sprite_set_cursor;
+		PointPriv->spriteFuncs->MoveCursor = drmmode_sprite_move_cursor;
+	}
+
 	if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
 		return TRUE;
 
@@ -1701,6 +1720,15 @@ static Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen)
 	amdgpu_glamor_fini(pScreen);
 	pScrn->vtSema = FALSE;
 	xf86ClearPrimInitDone(info->pEnt->index);
+
+	if (info->allowPageFlip) {
+		miPointerScreenPtr PointPriv =
+			dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
+
+		PointPriv->spriteFuncs->SetCursor = info->SetCursor;
+		PointPriv->spriteFuncs->MoveCursor = info->MoveCursor;
+	}
+
 	pScreen->BlockHandler = info->BlockHandler;
 	pScreen->CloseScreen = info->CloseScreen;
 	return pScreen->CloseScreen(pScreen);
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index cef93c068..4e74bfac9 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -273,7 +273,7 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	if (!info->allowPageFlip)
 		return FALSE;
 
-	if (info->hwcursor_disabled)
+	if (info->sprites_visible > 0)
 		return FALSE;
 
 	if (info->drmmode.dri2_flipping)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 55551eea7..047179449 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -34,6 +34,7 @@
 #include <time.h>
 #include "cursorstr.h"
 #include "damagestr.h"
+#include "inputstr.h"
 #include "list.h"
 #include "micmap.h"
 #include "xf86cmap.h"
@@ -2431,6 +2432,57 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 		drmmode_crtc_scanout_free(config->crtc[c]->driver_private);
 }
 
+static void drmmode_sprite_do_set_cursor(struct amdgpu_device_priv *device_priv,
+					 ScrnInfoPtr scrn, int x, int y)
+{
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	CursorPtr cursor = device_priv->cursor;
+	Bool sprite_visible = device_priv->sprite_visible;
+
+	if (cursor) {
+		x -= cursor->bits->xhot;
+		y -= cursor->bits->yhot;
+
+		device_priv->sprite_visible =
+			x < scrn->virtualX && y < scrn->virtualY &&
+			(x + cursor->bits->width > 0) &&
+			(y + cursor->bits->height > 0);
+	} else {
+		device_priv->sprite_visible = FALSE;
+	}
+
+	info->sprites_visible += device_priv->sprite_visible - sprite_visible;
+}
+
+void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+			       CursorPtr pCursor, int x, int y)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	struct amdgpu_device_priv *device_priv =
+		dixLookupScreenPrivate(&pDev->devPrivates,
+				       &amdgpu_device_private_key, pScreen);
+
+	device_priv->cursor = pCursor;
+	drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
+
+	info->SetCursor(pDev, pScreen, pCursor, x, y);
+}
+
+void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x,
+				int y)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	struct amdgpu_device_priv *device_priv =
+		dixLookupScreenPrivate(&pDev->devPrivates,
+				       &amdgpu_device_private_key, pScreen);
+
+	drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
+
+	info->MoveCursor(pDev, pScreen, x, y);
+}
+
 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 03134f0c9..4e6f70776 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -198,6 +198,10 @@ 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);
-- 
2.15.1



More information about the amd-gfx mailing list