All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH xf86-video-amdgpu 01/12] Add explicit AMDGPU_DRM_QUEUE_ERROR define
@ 2016-09-08 10:02 Michel Dänzer
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
  0 siblings, 1 reply; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

Should make the amdgpu_drm_queue_alloc error handling clearer, and gets
rid of a compile warning about it returning NULL.

(Ported from radeon commit a37af701768b12d86868a831a79f1e02ee4968cf)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_dri2.c      | 4 ++--
 src/amdgpu_drm_queue.c | 7 ++++---
 src/amdgpu_drm_queue.h | 2 ++
 src/amdgpu_kms.c       | 4 ++--
 src/amdgpu_present.c   | 2 +-
 src/drmmode_display.c  | 2 +-
 6 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 1cbf1eb..31ac3f3 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -1035,7 +1035,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       wait_info, amdgpu_dri2_frame_event_handler,
 					       amdgpu_dri2_frame_event_abort);
-	if (!drm_queue_seq) {
+	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM queue event entry failed.\n");
 		goto out_complete;
@@ -1183,7 +1183,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       swap_info, amdgpu_dri2_frame_event_handler,
 					       amdgpu_dri2_frame_event_abort);
-	if (!drm_queue_seq) {
+	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM queue entry failed.\n");
 		goto blit_fallback;
diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index 562a11a..e8810fd 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -92,10 +92,11 @@ amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 
 	e = calloc(1, sizeof(struct amdgpu_drm_queue_entry));
 	if (!e)
-		return NULL;
+		return AMDGPU_DRM_QUEUE_ERROR;
+
+	if (_X_UNLIKELY(amdgpu_drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR))
+		amdgpu_drm_queue_seq++;
 
-	if (!amdgpu_drm_queue_seq)
-		amdgpu_drm_queue_seq = 1;
 	e->seq = amdgpu_drm_queue_seq++;
 	e->client = client;
 	e->crtc = crtc;
diff --git a/src/amdgpu_drm_queue.h b/src/amdgpu_drm_queue.h
index b4d4009..36ee900 100644
--- a/src/amdgpu_drm_queue.h
+++ b/src/amdgpu_drm_queue.h
@@ -31,6 +31,8 @@
 
 #include <xf86Crtc.h>
 
+#define AMDGPU_DRM_QUEUE_ERROR 0
+
 #define AMDGPU_DRM_QUEUE_CLIENT_DEFAULT serverClient
 #define AMDGPU_DRM_QUEUE_ID_DEFAULT ~0ULL
 
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index d9f15a4..9f023cf 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -426,7 +426,7 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 					       drmmode_crtc,
 					       amdgpu_scanout_update_handler,
 					       amdgpu_scanout_update_abort);
-	if (!drm_queue_seq) {
+	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "amdgpu_drm_queue_alloc failed for scanout update\n");
 		return;
@@ -480,7 +480,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       drmmode_crtc, NULL,
 					       amdgpu_scanout_flip_abort);
-	if (!drm_queue_seq) {
+	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM event queue entry failed.\n");
 		return;
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index edfccb1..192c410 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -170,7 +170,7 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 					       event_id, event,
 					       amdgpu_present_vblank_handler,
 					       amdgpu_present_vblank_abort);
-	if (!drm_queue_seq) {
+	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		free(event);
 		return BadAlloc;
 	}
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index fdd5922..3063fac 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2537,7 +2537,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 						       flipdata,
 						       drmmode_flip_handler,
 						       drmmode_flip_abort);
-		if (!drm_queue_seq) {
+		if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "Allocating DRM queue event entry failed.\n");
 			goto error;
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 02/12] Use EventCallback to avoid flushing every time in the FlushCallback
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 03/12] Keep track of damage event related flushes per-client Michel Dänzer
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

We only need to flush for XDamageNotify events.

Significantly reduces compositing slowdown due to flushing overhead, in
particular with glamor.

(Ported from radeon commit 9a1afbf61fbb2827c86bd86d295fa0848980d60b)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_drv.h    |  2 ++
 src/amdgpu_glamor.c |  3 ++-
 src/amdgpu_kms.c    | 77 ++++++++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 66 insertions(+), 16 deletions(-)

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 60aa0be..d2b3a6b 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -209,6 +209,8 @@ typedef struct {
 
 	/* accel */
 	PixmapPtr fbcon_pixmap;
+	int callback_event_type;
+	uint_fast32_t callback_needs_flush;
 	uint_fast32_t gpu_flushed;
 	uint_fast32_t gpu_synced;
 	Bool use_glamor;
diff --git a/src/amdgpu_glamor.c b/src/amdgpu_glamor.c
index 62831d0..d29b096 100644
--- a/src/amdgpu_glamor.c
+++ b/src/amdgpu_glamor.c
@@ -460,8 +460,9 @@ void amdgpu_glamor_flush(ScrnInfoPtr pScrn)
 
 	if (info->use_glamor) {
 		glamor_block_handler(pScrn->pScreen);
-		info->gpu_flushed++;
 	}
+
+	info->gpu_flushed++;
 }
 
 void amdgpu_glamor_finish(ScrnInfoPtr pScrn)
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 9f023cf..b1f6bd7 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -50,6 +50,8 @@
 #include <X11/extensions/dpms.h>
 #endif
 
+#include <X11/extensions/damageproto.h>
+
 #include "amdgpu_chipinfo_gen.h"
 #include "amdgpu_bo_helper.h"
 #include "amdgpu_pixmap.h"
@@ -163,8 +165,51 @@ amdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
 	shadowUpdatePacked(pScreen, pBuf);
 }
 
+static Bool
+callback_needs_flush(AMDGPUInfoPtr info)
+{
+	return (int)(info->callback_needs_flush - info->gpu_flushed) > 0;
+}
+
+static void
+amdgpu_event_callback(CallbackListPtr *list,
+		      pointer user_data, pointer call_data)
+{
+	EventInfoRec *eventinfo = call_data;
+	ScrnInfoPtr pScrn = user_data;
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+	int i;
+
+	if (callback_needs_flush(info))
+		return;
+
+	/* Don't let gpu_flushed get too far ahead of callback_needs_flush,
+	 * in order to prevent false positives in callback_needs_flush()
+	 */
+	info->callback_needs_flush = info->gpu_flushed;
+	
+	for (i = 0; i < eventinfo->count; i++) {
+		if (eventinfo->events[i].u.u.type == info->callback_event_type) {
+			info->callback_needs_flush++;
+			return;
+		}
+	}
+}
+
+static void
+amdgpu_flush_callback(CallbackListPtr *list,
+		      pointer user_data, pointer call_data)
+{
+	ScrnInfoPtr pScrn = user_data;
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+
+	if (pScrn->vtSema && callback_needs_flush(info))
+		amdgpu_glamor_flush(pScrn);
+}
+
 static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 {
+	ExtensionEntry *damage_ext = CheckExtension("DAMAGE");
 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 	PixmapPtr pixmap;
@@ -217,6 +262,19 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 	if (info->use_glamor)
 		amdgpu_glamor_create_screen_resources(pScreen);
 
+	info->callback_event_type = -1;
+	if (damage_ext) {
+		info->callback_event_type = damage_ext->eventBase + XDamageNotify;
+
+		if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
+			return FALSE;
+
+		if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) {
+			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+			return FALSE;
+		}
+	}
+
 	return TRUE;
 }
 
@@ -542,17 +600,6 @@ static void AMDGPUBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL)
 	drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
 }
 
-static void
-amdgpu_flush_callback(CallbackListPtr * list,
-		      pointer user_data, pointer call_data)
-{
-	ScrnInfoPtr pScrn = user_data;
-
-	if (pScrn->vtSema) {
-		amdgpu_glamor_flush(pScrn);
-	}
-}
-
 /* This is called by AMDGPUPreInit to set up the default visual */
 static Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn)
 {
@@ -1108,7 +1155,10 @@ static Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
 	drmmode_uevent_fini(pScrn, &info->drmmode);
 	amdgpu_drm_queue_close(pScrn);
 
-	DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+	if (info->callback_event_type != -1) {
+		DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
+		DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+	}
 
 	amdgpu_sync_close(pScreen);
 	amdgpu_drop_drm_master(pScrn);
@@ -1347,9 +1397,6 @@ Bool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 	info->BlockHandler = pScreen->BlockHandler;
 	pScreen->BlockHandler = AMDGPUBlockHandler_oneshot;
 
-	if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
-		return FALSE;
-
 	info->CreateScreenResources = pScreen->CreateScreenResources;
 	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
 
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 03/12] Keep track of damage event related flushes per-client
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 02/12] Use EventCallback to avoid flushing every time in the FlushCallback Michel Dänzer
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 04/12] Wait for pending flips to complete before turning off an output or CRTC Michel Dänzer
                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

This further reduces the compositing slowdown due to flushing overhead,
by only flushing when the X server actually sends XDamageNotify events
to a client, and there hasn't been a flush yet in the meantime.

(Ported from radeon commit 121a6de72da5fcf9a32408eff36b2235f3dfbcfe)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_drv.h |  5 ++++-
 src/amdgpu_kms.c | 41 +++++++++++++++++++++++++++++++++--------
 2 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index d2b3a6b..fc6a79d 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -185,6 +185,10 @@ struct amdgpu_buffer {
 	uint32_t flags;
 };
 
+struct amdgpu_client_priv {
+	uint_fast32_t needs_flush;
+};
+
 typedef struct {
 	EntityInfoPtr pEnt;
 	pciVideoPtr PciInfo;
@@ -210,7 +214,6 @@ typedef struct {
 	/* accel */
 	PixmapPtr fbcon_pixmap;
 	int callback_event_type;
-	uint_fast32_t callback_needs_flush;
 	uint_fast32_t gpu_flushed;
 	uint_fast32_t gpu_synced;
 	Bool use_glamor;
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index b1f6bd7..d557313 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -39,6 +39,7 @@
 
 #include "amdgpu_version.h"
 #include "shadow.h"
+#include <xf86Priv.h>
 
 #include "amdpciids.h"
 
@@ -58,6 +59,8 @@
 
 #include <gbm.h>
 
+static DevScreenPrivateKeyRec amdgpu_client_private_key;
+
 extern SymTabRec AMDGPUChipsets[];
 static Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen);
 
@@ -166,9 +169,9 @@ amdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
 }
 
 static Bool
-callback_needs_flush(AMDGPUInfoPtr info)
+callback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv)
 {
-	return (int)(info->callback_needs_flush - info->gpu_flushed) > 0;
+	return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
 }
 
 static void
@@ -177,20 +180,30 @@ amdgpu_event_callback(CallbackListPtr *list,
 {
 	EventInfoRec *eventinfo = call_data;
 	ScrnInfoPtr pScrn = user_data;
+	ScreenPtr pScreen = pScrn->pScreen;
+	struct amdgpu_client_priv *client_priv =
+		dixLookupScreenPrivate(&eventinfo->client->devPrivates,
+				       &amdgpu_client_private_key, pScreen);
+	struct amdgpu_client_priv *server_priv =
+		dixLookupScreenPrivate(&serverClient->devPrivates,
+				       &amdgpu_client_private_key, pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 	int i;
 
-	if (callback_needs_flush(info))
+	if (callback_needs_flush(info, client_priv) ||
+	    callback_needs_flush(info, server_priv))
 		return;
 
-	/* Don't let gpu_flushed get too far ahead of callback_needs_flush,
-	 * in order to prevent false positives in callback_needs_flush()
+	/* Don't let gpu_flushed get too far ahead of needs_flush, in order
+	 * to prevent false positives in callback_needs_flush()
 	 */
-	info->callback_needs_flush = info->gpu_flushed;
+	client_priv->needs_flush = info->gpu_flushed;
+	server_priv->needs_flush = info->gpu_flushed;
 	
 	for (i = 0; i < eventinfo->count; i++) {
 		if (eventinfo->events[i].u.u.type == info->callback_event_type) {
-			info->callback_needs_flush++;
+			client_priv->needs_flush++;
+			server_priv->needs_flush++;
 			return;
 		}
 	}
@@ -201,9 +214,14 @@ amdgpu_flush_callback(CallbackListPtr *list,
 		      pointer user_data, pointer call_data)
 {
 	ScrnInfoPtr pScrn = user_data;
+	ScreenPtr pScreen = pScrn->pScreen;
+	ClientPtr client = call_data ? call_data : serverClient;
+	struct amdgpu_client_priv *client_priv =
+		dixLookupScreenPrivate(&client->devPrivates,
+				       &amdgpu_client_private_key, pScreen);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
 
-	if (pScrn->vtSema && callback_needs_flush(info))
+	if (pScrn->vtSema && callback_needs_flush(info, client_priv))
 		amdgpu_glamor_flush(pScrn);
 }
 
@@ -273,6 +291,13 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
 			return FALSE;
 		}
+
+		if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen,
+						 PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) {
+			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
+			DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
+			return FALSE;
+		}
 	}
 
 	return TRUE;
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 04/12] Wait for pending flips to complete before turning off an output or CRTC
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 02/12] Use EventCallback to avoid flushing every time in the FlushCallback Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 03/12] Keep track of damage event related flushes per-client Michel Dänzer
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 05/12] Use drmmode_crtc_scanout_* helpers for RandR 1.4 scanout pixmaps Michel Dänzer
                     ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

At least with older kernels, the flip may never complete otherwise,
which can result in us hanging in drmmode_set_mode_major.

Fixes: https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-ati/+bug/1577170

(Ported from radeon commits 9090309e057dc703d1a5bffd88e6cae14108cfc3,
 e520ce0ec0adf91ddce5c932d4b3f9477fd49304,
 a36fdaff40d5b4795a1400c348a80eee94892212 and
 4bd2d01552f18153afa03a8947b22eebf3d67c6b)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c      |  6 ++---
 src/amdgpu_present.c  |  4 +--
 src/amdgpu_video.c    |  2 +-
 src/drmmode_display.c | 73 +++++++++++++++++++++++++++++++++++++++++----------
 src/drmmode_display.h |  3 +++
 5 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index d557313..1bce781 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -366,7 +366,7 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
 	BoxRec extents;
 
 	if (!xf86_crtc->enabled ||
-	    drmmode_crtc->dpms_mode != DPMSModeOn ||
+	    drmmode_crtc->pending_dpms_mode != DPMSModeOn ||
 	    !drmmode_crtc->scanout[scanout_id].pixmap)
 		return FALSE;
 
@@ -485,7 +485,7 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 	if (!xf86_crtc->enabled ||
 	    drmmode_crtc->scanout_update_pending ||
 	    !drmmode_crtc->scanout[0].pixmap ||
-	    drmmode_crtc->dpms_mode != DPMSModeOn)
+	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
 		return;
 
 	pDamage = drmmode_crtc->scanout[0].damage;
@@ -537,7 +537,7 @@ amdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
 	drmmode_crtc_private_ptr drmmode_crtc = event_data;
 
 	drmmode_crtc->scanout_update_pending = FALSE;
-	drmmode_crtc->flip_pending = FALSE;
+	drmmode_clear_pending_flip(crtc);
 }
 
 static void
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index 192c410..e36778c 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -235,7 +235,7 @@ amdgpu_present_check_unflip(ScrnInfoPtr scrn)
 		    drmmode_crtc->scanout[0].bo)
 			return FALSE;
 
-		if (drmmode_crtc->dpms_mode == DPMSModeOn)
+		if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
 			num_crtcs_on++;
 	}
 
@@ -376,7 +376,7 @@ modeset:
 		if (!crtc->enabled)
 			continue;
 
-		if (drmmode_crtc->dpms_mode == DPMSModeOn)
+		if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
 			crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
 						    crtc->x, crtc->y);
 		else
diff --git a/src/amdgpu_video.c b/src/amdgpu_video.c
index 8f9a2b9..3f441e7 100644
--- a/src/amdgpu_video.c
+++ b/src/amdgpu_video.c
@@ -67,7 +67,7 @@ static int amdgpu_box_area(BoxPtr box)
 Bool amdgpu_crtc_is_enabled(xf86CrtcPtr crtc)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-	return drmmode_crtc->dpms_mode == DPMSModeOn;
+	return drmmode_crtc->pending_dpms_mode == DPMSModeOn;
 }
 
 xf86CrtcPtr
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3063fac..491599f 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -249,9 +249,15 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	CARD64 ust;
 	int ret;
 
+	drmmode_crtc->pending_dpms_mode = mode;
+
 	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
 		drmVBlank vbl;
 
+		/* Wait for any pending flip to finish */
+		if (drmmode_crtc->flip_pending)
+			return;
+
 		/*
 		 * On->Off transition: record the last vblank time,
 		 * sequence number and frame period.
@@ -309,10 +315,14 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
 
 	/* Disable unused CRTCs and enable/disable active CRTCs */
-	if (!crtc->enabled || mode != DPMSModeOn)
+	if (!crtc->enabled || mode != DPMSModeOn) {
+		/* Wait for any pending flip to finish */
+		if (drmmode_crtc->flip_pending)
+			return;
+
 		drmModeSetCrtc(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
 			       0, 0, 0, NULL, 0, NULL);
-	else if (drmmode_crtc->dpms_mode != DPMSModeOn)
+	} else if (drmmode_crtc->dpms_mode != DPMSModeOn)
 		crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
 					    crtc->x, crtc->y);
 }
@@ -1171,6 +1181,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
 	    drmModeGetCrtc(pAMDGPUEnt->fd, mode_res->crtcs[num]);
 	drmmode_crtc->drmmode = drmmode;
 	drmmode_crtc->dpms_mode = DPMSModeOff;
+	drmmode_crtc->pending_dpms_mode = DPMSModeOff;
 	crtc->driver_private = drmmode_crtc;
 	drmmode_crtc_hw_id(crtc);
 
@@ -1298,9 +1309,16 @@ static void drmmode_output_dpms(xf86OutputPtr output, int mode)
 	if (!koutput)
 		return;
 
-	if (mode != DPMSModeOn && crtc)
+	if (mode != DPMSModeOn && crtc) {
+		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
 		drmmode_do_crtc_dpms(crtc, mode);
 
+		/* Wait for any pending flip to finish */
+		if (drmmode_crtc->flip_pending)
+			return;
+	}
+
 	drmModeConnectorSetProperty(pAMDGPUEnt->fd, koutput->connector_id,
 				    drmmode_output->dpms_enum_id, mode);
 
@@ -2002,26 +2020,50 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 	drmmode_xf86crtc_resize
 };
 
+void
+drmmode_clear_pending_flip(xf86CrtcPtr crtc)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	drmmode_crtc->flip_pending = FALSE;
+
+	if (!crtc->enabled ||
+	    (drmmode_crtc->pending_dpms_mode != DPMSModeOn &&
+	     drmmode_crtc->dpms_mode != drmmode_crtc->pending_dpms_mode)) {
+		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+		int o;
+
+		for (o = 0; o < xf86_config->num_output; o++) {
+			xf86OutputPtr output = xf86_config->output[o];
+
+			if (output->crtc != crtc)
+				continue;
+
+			drmmode_output_dpms(output, drmmode_crtc->pending_dpms_mode);
+		}
+
+		drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode);
+	}
+}
+
 static void
 drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
 {
-	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	drmmode_flipdata_ptr flipdata = event_data;
 
 	if (--flipdata->flip_count == 0) {
-		if (flipdata->fe_crtc)
-			crtc = flipdata->fe_crtc;
-		flipdata->abort(crtc, flipdata->event_data);
+		if (!flipdata->fe_crtc)
+			flipdata->fe_crtc = crtc;
+		flipdata->abort(flipdata->fe_crtc, flipdata->event_data);
 		free(flipdata);
 	}
 
-	drmmode_crtc->flip_pending = FALSE;
+	drmmode_clear_pending_flip(crtc);
 }
 
 static void
 drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data)
 {
-	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
 	drmmode_flipdata_ptr flipdata = event_data;
 
@@ -2033,11 +2075,14 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 	}
 
 	if (--flipdata->flip_count == 0) {
-		/* Deliver cached msc, ust from reference crtc to flip event handler */
+		/* Deliver MSC & UST from reference/current CRTC to flip event
+		 * handler
+		 */
 		if (flipdata->fe_crtc)
-			crtc = flipdata->fe_crtc;
-		flipdata->handler(crtc, flipdata->fe_frame, flipdata->fe_usec,
-				  flipdata->event_data);
+			flipdata->handler(flipdata->fe_crtc, flipdata->fe_frame,
+					  flipdata->fe_usec, flipdata->event_data);
+		else
+			flipdata->handler(crtc, frame, usec, flipdata->event_data);
 
 		/* Release framebuffer */
 		drmModeRmFB(pAMDGPUEnt->fd, flipdata->old_fb_id);
@@ -2045,7 +2090,7 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 		free(flipdata);
 	}
 
-	drmmode_crtc->flip_pending = FALSE;
+	drmmode_clear_pending_flip(crtc);
 }
 
 #if HAVE_NOTIFY_FD
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 2e62a8c..14fbcfc 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -88,6 +88,8 @@ typedef struct {
 	unsigned scanout_id;
 	Bool scanout_update_pending;
 	int dpms_mode;
+	/* For when a flip is pending when DPMS off requested */
+	int pending_dpms_mode;
 	CARD64 dpms_last_ust;
 	uint32_t dpms_last_seq;
 	int dpms_last_fps;
@@ -147,6 +149,7 @@ extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
 
 extern int drmmode_get_crtc_id(xf86CrtcPtr crtc);
 extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe);
+extern void drmmode_clear_pending_flip(xf86CrtcPtr crtc);
 Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			PixmapPtr new_front, uint64_t id, void *data,
 			int ref_crtc_hw_id, amdgpu_drm_handler_proc handler,
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 05/12] Use drmmode_crtc_scanout_* helpers for RandR 1.4 scanout pixmaps
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 04/12] Wait for pending flips to complete before turning off an output or CRTC Michel Dänzer
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 06/12] Handle RandR 1.4 slave dirty updates via amdgpu_drm_queue Michel Dänzer
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

This should allow using multiple CRTCs via RandR 1.4 even with xserver
< 1.17. It also simplifies the code a little, and paves the way for
following changes.

(Ported from radeon commits 4cfa4615f79f64062e5e771cd45dd7048f48b4f6
 and a92c27484703abc7c410b6ae0e4b8d1efbbb8e6f)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c      | 19 ++++++++-----
 src/drmmode_display.c | 76 +++++++++++++++------------------------------------
 src/drmmode_display.h |  1 -
 3 files changed, 34 insertions(+), 62 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 1bce781..9670c3f 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -595,15 +595,20 @@ static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
 	(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
 	pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
 
-	for (c = 0; c < xf86_config->num_crtc; c++) {
-		if (info->tear_free)
-			amdgpu_scanout_flip(pScreen, info, xf86_config->crtc[c]);
-		else if (info->shadow_primary
+#ifdef AMDGPU_PIXMAP_SHARING
+	if (!pScreen->isGPU)
+#endif
+	{
+		for (c = 0; c < xf86_config->num_crtc; c++) {
+			if (info->tear_free)
+				amdgpu_scanout_flip(pScreen, info, xf86_config->crtc[c]);
+			else if (info->shadow_primary
 #if XF86_CRTC_VERSION >= 4
-				 || xf86_config->crtc[c]->driverIsPerformingTransform
+					 || xf86_config->crtc[c]->driverIsPerformingTransform
 #endif
-			)
-			amdgpu_scanout_update(xf86_config->crtc[c]);
+				)
+				amdgpu_scanout_update(xf86_config->crtc[c]);
+		}
 	}
 
 	if (info->use_glamor)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 491599f..a8ee5f0 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -705,18 +705,22 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		fb_id = drmmode->fb_id;
 #ifdef AMDGPU_PIXMAP_SHARING
 		if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
-			x = drmmode_crtc->prime_pixmap_x;
-			y = 0;
+			fb_id = drmmode_crtc->scanout[0].fb_id;
+			x = y = 0;
 		} else
 #endif
 		if (drmmode_crtc->rotate.fb_id) {
 			fb_id = drmmode_crtc->rotate.fb_id;
 			x = y = 0;
-		} else if (info->tear_free ||
+		} else if (
+#ifdef AMDGPU_PIXMAP_SHARING
+			   !pScreen->isGPU &&
+#endif
+			   (info->tear_free ||
 #if XF86_CRTC_VERSION >= 4
-			   crtc->driverIsPerformingTransform ||
+			    crtc->driverIsPerformingTransform ||
 #endif
-			   info->shadow_primary) {
+			    info->shadow_primary)) {
 			for (i = 0; i < (info->tear_free ? 2 : 1); i++) {
 				drmmode_crtc_scanout_create(crtc,
 							    &drmmode_crtc->scanout[i],
@@ -1058,66 +1062,30 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
 #ifdef AMDGPU_PIXMAP_SHARING
 static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 {
-	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
-	PixmapPtr screenpix = screen->GetScreenPixmap(screen);
-	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-	int c, total_width = 0, max_height = 0, this_x = 0;
 
 	if (!ppix) {
 		if (crtc->randr_crtc->scanout_pixmap)
-			PixmapStopDirtyTracking(crtc->
-						randr_crtc->scanout_pixmap,
-						screenpix);
-		drmmode_crtc->prime_pixmap_x = 0;
+			PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap,
+						drmmode_crtc->scanout[0].pixmap);
+		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+					     &drmmode_crtc->scanout[0]);
 		return TRUE;
 	}
 
-	/* iterate over all the attached crtcs -
-	   work out bounding box */
-	for (c = 0; c < xf86_config->num_crtc; c++) {
-		xf86CrtcPtr iter = xf86_config->crtc[c];
-		if (!iter->enabled && iter != crtc)
-			continue;
-		if (iter == crtc) {
-			this_x = total_width;
-			total_width += ppix->drawable.width;
-			if (max_height < ppix->drawable.height)
-				max_height = ppix->drawable.height;
-		} else {
-			total_width += iter->mode.HDisplay;
-			if (max_height < iter->mode.VDisplay)
-				max_height = iter->mode.VDisplay;
-		}
-#if !defined(HAS_DIRTYTRACKING_ROTATION) && !defined(HAS_DIRTYTRACKING2)
-		if (iter != crtc) {
-			ErrorF
-			    ("Cannot do multiple crtcs without X server dirty tracking 2 interface\n");
-			return FALSE;
-		}
-#endif
-	}
-
-	if (total_width != screenpix->drawable.width ||
-	    max_height != screenpix->drawable.height) {
-		Bool ret;
-		ret =
-		    drmmode_xf86crtc_resize(crtc->scrn, total_width,
-					    max_height);
-		if (ret == FALSE)
-			return FALSE;
+	if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[0],
+					 ppix->drawable.width,
+					 ppix->drawable.height))
+		return FALSE;
 
-		screenpix = screen->GetScreenPixmap(screen);
-		screen->width = screenpix->drawable.width = total_width;
-		screen->height = screenpix->drawable.height = max_height;
-	}
-	drmmode_crtc->prime_pixmap_x = this_x;
 #ifdef HAS_DIRTYTRACKING_ROTATION
-	PixmapStartDirtyTracking(ppix, screenpix, 0, 0, this_x, 0, RR_Rotate_0);
+	PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[0].pixmap,
+				 0, 0, 0, 0, RR_Rotate_0);
 #elif defined(HAS_DIRTYTRACKING2)
-	PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0);
+	PixmapStartDirtyTracking2(ppix, drmmode_crtc->scanout[0].pixmap,
+				  0, 0, 0, 0);
 #else
-	PixmapStartDirtyTracking(ppix, screenpix, 0, 0);
+	PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[0].pixmap, 0, 0);
 #endif
 	return TRUE;
 }
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 14fbcfc..e739382 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -94,7 +94,6 @@ typedef struct {
 	uint32_t dpms_last_seq;
 	int dpms_last_fps;
 	uint32_t interpolated_vblanks;
-	int prime_pixmap_x;
 
 	/* Modeset needed for DPMS on */
 	Bool need_modeset;
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 06/12] Handle RandR 1.4 slave dirty updates via amdgpu_drm_queue
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
                     ` (3 preceding siblings ...)
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 05/12] Use drmmode_crtc_scanout_* helpers for RandR 1.4 scanout pixmaps Michel Dänzer
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 07/12] Track damage accurately for RandR 1.4 slave scanout Michel Dänzer
                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

This reduces PCIe bandwidth usage and tearing.

(Ported from radeon commit ad0a0656dd0e74683e6d7789decba827aa29c221)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 93 insertions(+), 3 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 9670c3f..aaaee1a 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -304,8 +304,10 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 }
 
 #ifdef AMDGPU_PIXMAP_SHARING
-static void redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
+static void
+redisplay_dirty(PixmapDirtyUpdatePtr dirty)
 {
+	ScrnInfoPtr scrn = xf86ScreenToScrn(dirty->src->drawable.pScreen);
 	RegionRec pixregion;
 
 	PixmapRegionInit(&pixregion, dirty->slave_dst);
@@ -316,8 +318,94 @@ static void redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
 	PixmapSyncDirtyHelper(dirty, &pixregion);
 #endif
 
+	amdgpu_glamor_flush(scrn);
 	DamageRegionProcessPending(&dirty->slave_dst->drawable);
 	RegionUninit(&pixregion);
+
+	DamageEmpty(dirty->damage);
+}
+
+static void
+amdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	drmmode_crtc->scanout_update_pending = FALSE;
+}
+
+void
+amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
+				    void *event_data)
+{
+	ScrnInfoPtr scrn = crtc->scrn;
+	ScreenPtr screen = scrn->pScreen;
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap;
+	PixmapDirtyUpdatePtr dirty;
+
+	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
+		if (dirty->src == scanoutpix &&
+		    dirty->slave_dst == drmmode_crtc->scanout[0].pixmap) {
+			redisplay_dirty(dirty);
+			break;
+		}
+	}
+
+	drmmode_crtc->scanout_update_pending = FALSE;
+}
+
+static void
+amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
+{
+	ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	xf86CrtcPtr xf86_crtc = NULL;
+	drmmode_crtc_private_ptr drmmode_crtc = NULL;
+	uintptr_t drm_queue_seq;
+	drmVBlank vbl;
+	int c;
+
+	/* Find the CRTC which is scanning out from this slave pixmap */
+	for (c = 0; c < xf86_config->num_crtc; c++) {
+		xf86_crtc = xf86_config->crtc[c];
+		drmmode_crtc = xf86_crtc->driver_private;
+		if (drmmode_crtc->scanout[0].pixmap == dirty->slave_dst)
+			break;
+	}
+
+	if (c == xf86_config->num_crtc ||
+	    !xf86_crtc->enabled ||
+	    drmmode_crtc->scanout_update_pending ||
+	    !drmmode_crtc->scanout[0].pixmap ||
+	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+		return;
+
+	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
+					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
+					       AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL,
+					       amdgpu_prime_scanout_update_handler,
+					       amdgpu_prime_scanout_update_abort);
+	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "amdgpu_drm_queue_alloc failed for PRIME update\n");
+		return;
+	}
+
+	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
+	vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
+	vbl.request.sequence = 1;
+	vbl.request.signal = drm_queue_seq;
+	if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "drmWaitVBlank failed for PRIME update: %s\n",
+			   strerror(errno));
+		amdgpu_drm_abort_entry(drm_queue_seq);
+		return;
+	}
+
+	drmmode_crtc->scanout_update_pending = TRUE;
 }
 
 static void amdgpu_dirty_update(ScreenPtr screen)
@@ -331,8 +419,10 @@ static void amdgpu_dirty_update(ScreenPtr screen)
 	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
 		region = DamageRegion(ent->damage);
 		if (RegionNotEmpty(region)) {
-			redisplay_dirty(screen, ent);
-			DamageEmpty(ent->damage);
+			if (screen->isGPU)
+				amdgpu_prime_scanout_update(ent);
+			else
+				redisplay_dirty(ent);
 		}
 	}
 }
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 07/12] Track damage accurately for RandR 1.4 slave scanout
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
                     ` (4 preceding siblings ...)
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 06/12] Handle RandR 1.4 slave dirty updates via amdgpu_drm_queue Michel Dänzer
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 08/12] Only copy from screen pixmap to shared pixmap on demand for " Michel Dänzer
                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

This further reduces the PCIe bandwidth usage.

(Ported from radeon commit b0867063abb197b9134166706d99fcbe5f204bb5,
 plus leak fix from 5a57005178fc13b6f7e513458ca6dae72a3e5783)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 72 insertions(+), 11 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index aaaee1a..0342ef8 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -304,23 +304,77 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 }
 
 #ifdef AMDGPU_PIXMAP_SHARING
+static RegionPtr
+dirty_region(PixmapDirtyUpdatePtr dirty)
+{
+	RegionPtr damageregion = DamageRegion(dirty->damage);
+	RegionPtr dstregion;
+
+#ifdef HAS_DIRTYTRACKING_ROTATION
+	if (dirty->rotation != RR_Rotate_0) {
+		BoxPtr boxes = RegionRects(damageregion);
+		int nboxes = RegionNumRects(damageregion);
+		xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
+		int dst_w = dirty->slave_dst->drawable.width;
+		int dst_h = dirty->slave_dst->drawable.height;
+		int nrects = 0;
+		BoxRec box;
+		int i;
+
+		for (i = 0; i < nboxes; i++) {
+			box.x1 = boxes[i].x1;
+			box.x2 = boxes[i].x2;
+			box.y1 = boxes[i].y1;
+			box.y2 = boxes[i].y2;
+			pixman_f_transform_bounds(&dirty->f_inverse, &box);
+
+			box.x1 = max(box.x1, 0);
+			box.y1 = max(box.y1, 0);
+			box.x2 = min(box.x2, dst_w);
+			box.y2 = min(box.y2, dst_h);
+			if (box.x1 >= box.x2 || box.y1 >= box.y2)
+				continue;
+
+			rects[nrects].x = box.x1;
+			rects[nrects].y = box.y1;
+			rects[nrects].width = box.x2 - box.x1;
+			rects[nrects].height = box.y2 - box.y1;
+			nrects++;
+		}
+		dstregion = RegionFromRects(nrects, rects, CT_UNSORTED);
+		free(rects);
+	} else
+#endif
+	{
+		RegionRec pixregion;
+
+		dstregion = RegionDuplicate(damageregion);
+		RegionTranslate(dstregion, -dirty->x, -dirty->y);
+		PixmapRegionInit(&pixregion, dirty->slave_dst);
+		RegionIntersect(dstregion, dstregion, &pixregion);
+		RegionUninit(&pixregion);
+	}
+
+	return dstregion;
+}
+
 static void
-redisplay_dirty(PixmapDirtyUpdatePtr dirty)
+redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(dirty->src->drawable.pScreen);
-	RegionRec pixregion;
 
-	PixmapRegionInit(&pixregion, dirty->slave_dst);
-	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
+	if (dirty->slave_dst->master_pixmap)
+		DamageRegionAppend(&dirty->slave_dst->drawable, region);
+
 #ifdef HAS_DIRTYTRACKING_ROTATION
 	PixmapSyncDirtyHelper(dirty);
 #else
-	PixmapSyncDirtyHelper(dirty, &pixregion);
+	PixmapSyncDirtyHelper(dirty, region);
 #endif
 
 	amdgpu_glamor_flush(scrn);
-	DamageRegionProcessPending(&dirty->slave_dst->drawable);
-	RegionUninit(&pixregion);
+	if (dirty->slave_dst->master_pixmap)
+		DamageRegionProcessPending(&dirty->slave_dst->drawable);
 
 	DamageEmpty(dirty->damage);
 }
@@ -346,7 +400,10 @@ amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t u
 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
 		if (dirty->src == scanoutpix &&
 		    dirty->slave_dst == drmmode_crtc->scanout[0].pixmap) {
-			redisplay_dirty(dirty);
+			RegionPtr region = dirty_region(dirty);
+
+			redisplay_dirty(dirty, region);
+			RegionDestroy(region);
 			break;
 		}
 	}
@@ -410,20 +467,24 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 
 static void amdgpu_dirty_update(ScreenPtr screen)
 {
-	RegionPtr region;
 	PixmapDirtyUpdatePtr ent;
 
 	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
 		return;
 
 	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
-		region = DamageRegion(ent->damage);
+		RegionPtr region = dirty_region(ent);
+
 		if (RegionNotEmpty(region)) {
 			if (screen->isGPU)
 				amdgpu_prime_scanout_update(ent);
 			else
-				redisplay_dirty(ent);
+				redisplay_dirty(ent, region);
+		} else {
+			DamageEmpty(ent->damage);
 		}
+
+		RegionDestroy(region);
 	}
 }
 #endif
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 08/12] Only copy from screen pixmap to shared pixmap on demand for slave scanout
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
                     ` (5 preceding siblings ...)
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 07/12] Track damage accurately for RandR 1.4 slave scanout Michel Dänzer
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 09/12] Factor out transform_region helper Michel Dänzer
  2016-09-08 10:03   ` [PATCH xf86-video-amdgpu 10/12] Move up amdgpu_scanout_extents_intersect Michel Dänzer
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

Only copy once for each time we update the corresponding scanout pixmap.
This can significantly reduce the bandwidth usage when there are
frequent updates to the screen pixmap.

This initial implementation only works when both the master and slave
screens use this driver.

(Ported from radeon commit 99232f64db52812a843cd616d263d3a6b90eef3d)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 70 insertions(+), 13 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 0342ef8..5e3d322 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -363,6 +363,9 @@ redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(dirty->src->drawable.pScreen);
 
+	if (RegionNil(region))
+		goto out;
+
 	if (dirty->slave_dst->master_pixmap)
 		DamageRegionAppend(&dirty->slave_dst->drawable, region);
 
@@ -376,6 +379,7 @@ redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
 	if (dirty->slave_dst->master_pixmap)
 		DamageRegionProcessPending(&dirty->slave_dst->drawable);
 
+out:
 	DamageEmpty(dirty->damage);
 }
 
@@ -388,6 +392,39 @@ amdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
 }
 
 void
+amdgpu_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
+{
+	ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen;
+	PixmapDirtyUpdatePtr ent;
+	RegionPtr region;
+
+	xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) {
+		if (ent->slave_dst != dirty->src)
+			continue;
+
+		region = dirty_region(ent);
+		redisplay_dirty(ent, region);
+		RegionDestroy(region);
+	}
+}
+
+static Bool
+master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
+{
+	ScrnInfoPtr master_scrn = xf86ScreenToScrn(dirty->src->master_pixmap->drawable.pScreen);
+
+	return master_scrn->driverName == scrn->driverName;
+}
+
+static Bool
+slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
+{
+	ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen);
+
+	return slave_scrn->driverName == scrn->driverName;
+}
+
+void
 amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
 				    void *event_data)
 {
@@ -400,8 +437,12 @@ amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t u
 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
 		if (dirty->src == scanoutpix &&
 		    dirty->slave_dst == drmmode_crtc->scanout[0].pixmap) {
-			RegionPtr region = dirty_region(dirty);
+			RegionPtr region;
+
+			if (master_has_sync_shared_pixmap(scrn, dirty))
+				amdgpu_sync_shared_pixmap(dirty);
 
+			region = dirty_region(dirty);
 			redisplay_dirty(dirty, region);
 			RegionDestroy(region);
 			break;
@@ -465,26 +506,42 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 	drmmode_crtc->scanout_update_pending = TRUE;
 }
 
-static void amdgpu_dirty_update(ScreenPtr screen)
+static void
+amdgpu_dirty_update(ScrnInfoPtr scrn)
 {
+	ScreenPtr screen = scrn->pScreen;
 	PixmapDirtyUpdatePtr ent;
-
-	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
-		return;
+	RegionPtr region;
 
 	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
-		RegionPtr region = dirty_region(ent);
+		if (screen->isGPU) {
+			PixmapDirtyUpdatePtr region_ent = ent;
+
+			if (master_has_sync_shared_pixmap(scrn, ent)) {
+				ScreenPtr master_screen = ent->src->master_pixmap->drawable.pScreen;
 
-		if (RegionNotEmpty(region)) {
-			if (screen->isGPU)
+				xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) {
+					if (region_ent->slave_dst == ent->src)
+						break;
+				}
+			}
+
+			region = dirty_region(region_ent);
+
+			if (RegionNotEmpty(region))
 				amdgpu_prime_scanout_update(ent);
 			else
-				redisplay_dirty(ent, region);
+				DamageEmpty(region_ent->damage);
+
+			RegionDestroy(region);
 		} else {
-			DamageEmpty(ent->damage);
-		}
+			if (slave_has_sync_shared_pixmap(scrn, ent))
+				continue;
 
-		RegionDestroy(region);
+			region = dirty_region(ent);
+			redisplay_dirty(ent, region);
+			RegionDestroy(region);
+		}
 	}
 }
 #endif
@@ -766,7 +823,7 @@ static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
 		amdgpu_glamor_flush(pScrn);
 
 #ifdef AMDGPU_PIXMAP_SHARING
-	amdgpu_dirty_update(pScreen);
+	amdgpu_dirty_update(pScrn);
 #endif
 }
 
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 09/12] Factor out transform_region helper
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
                     ` (6 preceding siblings ...)
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 08/12] Only copy from screen pixmap to shared pixmap on demand for " Michel Dänzer
@ 2016-09-08 10:02   ` Michel Dänzer
  2016-09-08 10:03   ` [PATCH xf86-video-amdgpu 10/12] Move up amdgpu_scanout_extents_intersect Michel Dänzer
  8 siblings, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:02 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

(Ported from radeon commit 5a57005178fc13b6f7e513458ca6dae72a3e5783)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c | 74 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 43 insertions(+), 31 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 5e3d322..c75d429 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -304,6 +304,45 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 }
 
 #ifdef AMDGPU_PIXMAP_SHARING
+
+static RegionPtr
+transform_region(RegionPtr region, struct pict_f_transform *transform,
+		 int w, int h)
+{
+	BoxPtr boxes = RegionRects(region);
+	int nboxes = RegionNumRects(region);
+	xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
+	RegionPtr transformed;
+	int nrects = 0;
+	BoxRec box;
+	int i;
+
+	for (i = 0; i < nboxes; i++) {
+		box.x1 = boxes[i].x1;
+		box.x2 = boxes[i].x2;
+		box.y1 = boxes[i].y1;
+		box.y2 = boxes[i].y2;
+		pixman_f_transform_bounds(transform, &box);
+
+		box.x1 = max(box.x1, 0);
+		box.y1 = max(box.y1, 0);
+		box.x2 = min(box.x2, w);
+		box.y2 = min(box.y2, h);
+		if (box.x1 >= box.x2 || box.y1 >= box.y2)
+			continue;
+
+		rects[nrects].x = box.x1;
+		rects[nrects].y = box.y1;
+		rects[nrects].width = box.x2 - box.x1;
+		rects[nrects].height = box.y2 - box.y1;
+		nrects++;
+	}
+
+	transformed = RegionFromRects(nrects, rects, CT_UNSORTED);
+	free(rects);
+	return transformed;
+}
+
 static RegionPtr
 dirty_region(PixmapDirtyUpdatePtr dirty)
 {
@@ -312,37 +351,10 @@ dirty_region(PixmapDirtyUpdatePtr dirty)
 
 #ifdef HAS_DIRTYTRACKING_ROTATION
 	if (dirty->rotation != RR_Rotate_0) {
-		BoxPtr boxes = RegionRects(damageregion);
-		int nboxes = RegionNumRects(damageregion);
-		xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
-		int dst_w = dirty->slave_dst->drawable.width;
-		int dst_h = dirty->slave_dst->drawable.height;
-		int nrects = 0;
-		BoxRec box;
-		int i;
-
-		for (i = 0; i < nboxes; i++) {
-			box.x1 = boxes[i].x1;
-			box.x2 = boxes[i].x2;
-			box.y1 = boxes[i].y1;
-			box.y2 = boxes[i].y2;
-			pixman_f_transform_bounds(&dirty->f_inverse, &box);
-
-			box.x1 = max(box.x1, 0);
-			box.y1 = max(box.y1, 0);
-			box.x2 = min(box.x2, dst_w);
-			box.y2 = min(box.y2, dst_h);
-			if (box.x1 >= box.x2 || box.y1 >= box.y2)
-				continue;
-
-			rects[nrects].x = box.x1;
-			rects[nrects].y = box.y1;
-			rects[nrects].width = box.x2 - box.x1;
-			rects[nrects].height = box.y2 - box.y1;
-			nrects++;
-		}
-		dstregion = RegionFromRects(nrects, rects, CT_UNSORTED);
-		free(rects);
+		dstregion = transform_region(damageregion,
+					     &dirty->f_inverse,
+					     dirty->slave_dst->drawable.width,
+					     dirty->slave_dst->drawable.height);
 	} else
 #endif
 	{
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 10/12] Move up amdgpu_scanout_extents_intersect
       [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
                     ` (7 preceding siblings ...)
  2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 09/12] Factor out transform_region helper Michel Dänzer
@ 2016-09-08 10:03   ` Michel Dänzer
       [not found]     ` <20160908100310.20051-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
  8 siblings, 1 reply; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:03 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

Will be needed higher up by the following changes. No functional change.

(Ported from radeon commit 2f6e5fb15f1a9ce523c85550e493f8bda9d0c00f)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index c75d429..7ec86fb 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -303,6 +303,23 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 	return TRUE;
 }
 
+static Bool
+amdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
+{
+	extents->x1 -= xf86_crtc->filter_width >> 1;
+	extents->x2 += xf86_crtc->filter_width >> 1;
+	extents->y1 -= xf86_crtc->filter_height >> 1;
+	extents->y2 += xf86_crtc->filter_height >> 1;
+	pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents);
+
+	extents->x1 = max(extents->x1, 0);
+	extents->y1 = max(extents->y1, 0);
+	extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay);
+	extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay);
+
+	return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
+}
+
 #ifdef AMDGPU_PIXMAP_SHARING
 
 static RegionPtr
@@ -559,23 +576,6 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
 #endif
 
 static Bool
-amdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
-{
-	extents->x1 -= xf86_crtc->filter_width >> 1;
-	extents->x2 += xf86_crtc->filter_width >> 1;
-	extents->y1 -= xf86_crtc->filter_height >> 1;
-	extents->y2 += xf86_crtc->filter_height >> 1;
-	pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents);
-
-	extents->x1 = max(extents->x1, 0);
-	extents->y1 = max(extents->y1, 0);
-	extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay);
-	extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay);
-
-	return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
-}
-
-static Bool
 amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 11/12] Synchronize scanout pixmaps for TearFree
       [not found]     ` <20160908100310.20051-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
@ 2016-09-08 10:03       ` Michel Dänzer
  2016-09-08 10:03       ` [PATCH xf86-video-amdgpu 12/12] Make TearFree effective with PRIME slave scanout Michel Dänzer
  1 sibling, 0 replies; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:03 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

Copy the damaged areas which are still valid in the other scanout pixmap
from there, then only copy the remaining damaged area from the screen
pixmap.

This is slightly more efficient (only needs one Damage record instead of
two, and only needs to copy each screen update across PCIe once with
ShadowPrimary and a discrete GPU), and will be significantly more
efficient for PRIME with the following change.

(Ported from radeon commit eda1f3df6aaed683036369fe8820da4dac3c2ae2)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c      | 80 ++++++++++++++++++++++++++++++++++++++++++---------
 src/drmmode_display.c | 80 +++++++++++++++++++++++++--------------------------
 src/drmmode_display.h |  3 +-
 3 files changed, 108 insertions(+), 55 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 7ec86fb..88b0be0 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -320,8 +320,6 @@ amdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
 	return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
 }
 
-#ifdef AMDGPU_PIXMAP_SHARING
-
 static RegionPtr
 transform_region(RegionPtr region, struct pict_f_transform *transform,
 		 int w, int h)
@@ -360,6 +358,62 @@ transform_region(RegionPtr region, struct pict_f_transform *transform,
 	return transformed;
 }
 
+static void
+amdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
+							int scanout_id)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+	DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
+	DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable;
+	RegionPtr last_region = &drmmode_crtc->scanout_last_region;
+	ScrnInfoPtr scrn = xf86_crtc->scrn;
+	ScreenPtr pScreen = scrn->pScreen;
+	RegionRec remaining;
+	RegionPtr sync_region = NULL;
+	BoxRec extents;
+	GCPtr gc;
+
+	if (RegionNil(last_region))
+		return;
+
+	RegionNull(&remaining);
+	RegionSubtract(&remaining, last_region, new_region);
+	if (RegionNil(&remaining))
+		goto uninit;
+
+	extents = *RegionExtents(&remaining);
+	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
+		goto uninit;
+
+#if XF86_CRTC_VERSION >= 4
+	if (xf86_crtc->driverIsPerformingTransform) {
+		sync_region = transform_region(&remaining,
+					       &xf86_crtc->f_framebuffer_to_crtc,
+					       dst->width, dst->height);
+	} else
+#endif /* XF86_CRTC_VERSION >= 4 */
+	{
+		sync_region = RegionDuplicate(&remaining);
+		RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y);
+	}
+
+	gc = GetScratchGC(dst->depth, pScreen);
+	if (gc) {
+		ValidateGC(dst, gc);
+		gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0);
+		sync_region = NULL;
+		gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0);
+		FreeScratchGC(gc);
+	}
+
+ uninit:
+	if (sync_region)
+		RegionDestroy(sync_region);
+	RegionUninit(&remaining);
+}
+
+#ifdef AMDGPU_PIXMAP_SHARING
+
 static RegionPtr
 dirty_region(PixmapDirtyUpdatePtr dirty)
 {
@@ -579,10 +633,11 @@ static Bool
 amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
-	DamagePtr pDamage;
-	RegionPtr pRegion;
+	RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
+	ScrnInfoPtr scrn = xf86_crtc->scrn;
+	ScreenPtr pScreen = scrn->pScreen;
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	DrawablePtr pDraw;
-	ScreenPtr pScreen;
 	BoxRec extents;
 
 	if (!xf86_crtc->enabled ||
@@ -590,21 +645,20 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
 	    !drmmode_crtc->scanout[scanout_id].pixmap)
 		return FALSE;
 
-	pDamage = drmmode_crtc->scanout[scanout_id].damage;
-	if (!pDamage)
-		return FALSE;
-
-	pRegion = DamageRegion(pDamage);
 	if (!RegionNotEmpty(pRegion))
 		return FALSE;
 
 	pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
-	pScreen = pDraw->pScreen;
 	extents = *RegionExtents(pRegion);
-	RegionEmpty(pRegion);
 	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
 		return FALSE;
 
+	if (info->tear_free) {
+		amdgpu_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
+		RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
+	}
+	RegionEmpty(pRegion);
+
 #if XF86_CRTC_VERSION >= 4
 	if (xf86_crtc->driverIsPerformingTransform) {
 		SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
@@ -708,7 +762,7 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
 		return;
 
-	pDamage = drmmode_crtc->scanout[0].damage;
+	pDamage = drmmode_crtc->scanout_damage;
 	if (!pDamage)
 		return;
 
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index a8ee5f0..1e4622d 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -462,10 +462,20 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
 		amdgpu_bo_unref(&scanout->bo);
 		scanout->bo = NULL;
 	}
+}
+
+static void
+drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
+{
+	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+				     &drmmode_crtc->scanout[0]);
+	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+				     &drmmode_crtc->scanout[1]);
 
-	if (scanout->damage) {
-		DamageDestroy(scanout->damage);
-		scanout->damage = NULL;
+	if (drmmode_crtc->scanout_damage) {
+		DamageDestroy(drmmode_crtc->scanout_damage);
+		drmmode_crtc->scanout_damage = NULL;
+		RegionUninit(&drmmode_crtc->scanout_last_region);
 	}
 }
 
@@ -475,15 +485,8 @@ drmmode_scanout_free(ScrnInfoPtr scrn)
 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
 	int c;
 
-	for (c = 0; c < xf86_config->num_crtc; c++) {
-		drmmode_crtc_private_ptr drmmode_crtc =
-			xf86_config->crtc[c]->driver_private;
-
-		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-					     &drmmode_crtc->scanout[0]);
-		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-					     &drmmode_crtc->scanout[1]);
-	}
+	for (c = 0; c < xf86_config->num_crtc; c++)
+		drmmode_crtc_scanout_free(xf86_config->crtc[c]->driver_private);
 }
 
 static void *
@@ -726,33 +729,31 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 							    &drmmode_crtc->scanout[i],
 							    mode->HDisplay,
 							    mode->VDisplay);
-
-				if (drmmode_crtc->scanout[i].pixmap) {
-					RegionPtr pRegion;
-					BoxPtr pBox;
-
-					if (!drmmode_crtc->scanout[i].damage) {
-						drmmode_crtc->scanout[i].damage =
-							DamageCreate(amdgpu_screen_damage_report,
-								     NULL, DamageReportRawRegion,
-								     TRUE, pScreen, NULL);
-						DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
-							       drmmode_crtc->scanout[i].damage);
-					}
-
-					pRegion = DamageRegion(drmmode_crtc->scanout[i].damage);
-					RegionUninit(pRegion);
-					pRegion->data = NULL;
-					pBox = RegionExtents(pRegion);
-					pBox->x1 = 0;
-					pBox->y1 = 0;
-					pBox->x2 = max(pBox->x2, pScrn->virtualX);
-					pBox->y2 = max(pBox->y2, pScrn->virtualY);
-				}
 			}
 
 			if (drmmode_crtc->scanout[0].pixmap &&
 			    (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) {
+				RegionPtr pRegion;
+				BoxPtr pBox;
+
+				if (!drmmode_crtc->scanout_damage) {
+					drmmode_crtc->scanout_damage =
+						DamageCreate(amdgpu_screen_damage_report,
+							     NULL, DamageReportRawRegion,
+							     TRUE, pScreen, NULL);
+					DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
+						       drmmode_crtc->scanout_damage);
+				}
+
+				pRegion = DamageRegion(drmmode_crtc->scanout_damage);
+				RegionUninit(pRegion);
+				pRegion->data = NULL;
+				pBox = RegionExtents(pRegion);
+				pBox->x1 = 0;
+				pBox->y1 = 0;
+				pBox->x2 = max(pBox->x2, pScrn->virtualX);
+				pBox->y2 = max(pBox->y2, pScrn->virtualY);
+
 				drmmode_crtc->scanout_id = 0;
 				fb_id = drmmode_crtc->scanout[0].fb_id;
 				x = y = 0;
@@ -840,10 +841,8 @@ done:
 	} else {
 		crtc->active = TRUE;
 
-		if (fb_id != drmmode_crtc->scanout[0].fb_id) {
-			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
-			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
-		}
+		if (fb_id != drmmode_crtc->scanout[0].fb_id)
+			drmmode_crtc_scanout_free(drmmode_crtc);
 	}
 
 	return ret;
@@ -1068,8 +1067,7 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 		if (crtc->randr_crtc->scanout_pixmap)
 			PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap,
 						drmmode_crtc->scanout[0].pixmap);
-		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-					     &drmmode_crtc->scanout[0]);
+		drmmode_crtc_scanout_free(drmmode_crtc);
 		return TRUE;
 	}
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index e739382..6c5542c 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -73,7 +73,6 @@ typedef struct {
 struct drmmode_scanout {
 	struct amdgpu_buffer *bo;
 	PixmapPtr pixmap;
-	DamagePtr damage;
 	unsigned fb_id;
 	int width, height;
 };
@@ -85,6 +84,8 @@ typedef struct {
 	struct amdgpu_buffer *cursor_buffer;
 	struct drmmode_scanout rotate;
 	struct drmmode_scanout scanout[2];
+	DamagePtr scanout_damage;
+	RegionRec scanout_last_region;
 	unsigned scanout_id;
 	Bool scanout_update_pending;
 	int dpms_mode;
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH xf86-video-amdgpu 12/12] Make TearFree effective with PRIME slave scanout
       [not found]     ` <20160908100310.20051-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
  2016-09-08 10:03       ` [PATCH xf86-video-amdgpu 11/12] Synchronize scanout pixmaps for TearFree Michel Dänzer
@ 2016-09-08 10:03       ` Michel Dänzer
       [not found]         ` <20160908100310.20051-3-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
  1 sibling, 1 reply; 13+ messages in thread
From: Michel Dänzer @ 2016-09-08 10:03 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

TearFree can now prevent tearing with any possible display
configuration.

Note that there may still be inter-GPU tearing if the primary GPU uses
a different driver.

(Ported from radeon commit 38797a33117222dadbc89e5f21ed8cd5deef9bea)

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/amdgpu_kms.c      | 112 ++++++++++++++++++++++++++++++++++++++++++++++----
 src/drmmode_display.c |  33 ++++++++++++---
 src/drmmode_display.h |   1 +
 3 files changed, 133 insertions(+), 13 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 88b0be0..a159c84 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -507,31 +507,56 @@ slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
 	return slave_scrn->driverName == scrn->driverName;
 }
 
-void
-amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
-				    void *event_data)
+static Bool
+amdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
 {
 	ScrnInfoPtr scrn = crtc->scrn;
 	ScreenPtr screen = scrn->pScreen;
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap;
 	PixmapDirtyUpdatePtr dirty;
+	Bool ret = FALSE;
 
 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
-		if (dirty->src == scanoutpix &&
-		    dirty->slave_dst == drmmode_crtc->scanout[0].pixmap) {
+		if (dirty->src == scanoutpix && dirty->slave_dst ==
+		    drmmode_crtc->scanout[scanout_id ^ info->tear_free].pixmap) {
 			RegionPtr region;
 
 			if (master_has_sync_shared_pixmap(scrn, dirty))
 				amdgpu_sync_shared_pixmap(dirty);
 
 			region = dirty_region(dirty);
+			if (RegionNil(region))
+				goto destroy;
+
+			if (info->tear_free) {
+				RegionTranslate(region, crtc->x, crtc->y);
+				amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id);
+				amdgpu_glamor_flush(scrn);
+				RegionCopy(&drmmode_crtc->scanout_last_region, region);
+				RegionTranslate(region, -crtc->x, -crtc->y);
+				dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap;
+			}
+
 			redisplay_dirty(dirty, region);
+			ret = TRUE;
+		destroy:
 			RegionDestroy(region);
 			break;
 		}
 	}
 
+	return ret;
+}
+
+void
+amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
+				     void *event_data)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	amdgpu_prime_scanout_do_update(crtc, 0);
 	drmmode_crtc->scanout_update_pending = FALSE;
 }
 
@@ -590,8 +615,75 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 }
 
 static void
+amdgpu_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = event_data;
+
+	drmmode_crtc->scanout_update_pending = FALSE;
+	drmmode_clear_pending_flip(crtc);
+}
+
+static void
+amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
+{
+	ScreenPtr screen = ent->slave_dst->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+	xf86CrtcPtr crtc = NULL;
+	drmmode_crtc_private_ptr drmmode_crtc = NULL;
+	uintptr_t drm_queue_seq;
+	unsigned scanout_id;
+	int c;
+
+	/* Find the CRTC which is scanning out from this slave pixmap */
+	for (c = 0; c < xf86_config->num_crtc; c++) {
+		crtc = xf86_config->crtc[c];
+		drmmode_crtc = crtc->driver_private;
+		scanout_id = drmmode_crtc->scanout_id;
+		if (drmmode_crtc->scanout[scanout_id].pixmap == ent->slave_dst)
+			break;
+	}
+
+	if (c == xf86_config->num_crtc ||
+	    !crtc->enabled ||
+	    drmmode_crtc->scanout_update_pending ||
+	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
+	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+		return;
+
+	scanout_id = drmmode_crtc->scanout_id ^ 1;
+	if (!amdgpu_prime_scanout_do_update(crtc, scanout_id))
+		return;
+
+	drm_queue_seq = amdgpu_drm_queue_alloc(crtc,
+					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
+					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
+					       drmmode_crtc, NULL,
+					       amdgpu_prime_scanout_flip_abort);
+	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+			   "Allocating DRM event queue entry failed for PRIME flip.\n");
+		return;
+	}
+
+	if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
+			    drmmode_crtc->scanout[scanout_id].fb_id,
+			    DRM_MODE_PAGE_FLIP_EVENT, (void*)drm_queue_seq)) {
+		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
+			   __func__, strerror(errno));
+		return;
+	}
+
+	drmmode_crtc->scanout_id = scanout_id;
+	drmmode_crtc->scanout_update_pending = TRUE;
+	drmmode_crtc->flip_pending = TRUE;
+}
+
+static void
 amdgpu_dirty_update(ScrnInfoPtr scrn)
 {
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	ScreenPtr screen = scrn->pScreen;
 	PixmapDirtyUpdatePtr ent;
 	RegionPtr region;
@@ -611,10 +703,14 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
 
 			region = dirty_region(region_ent);
 
-			if (RegionNotEmpty(region))
-				amdgpu_prime_scanout_update(ent);
-			else
+			if (RegionNotEmpty(region)) {
+				if (info->tear_free)
+					amdgpu_prime_scanout_flip(ent);
+				else
+					amdgpu_prime_scanout_update(ent);
+			} else {
 				DamageEmpty(region_ent->damage);
+			}
 
 			RegionDestroy(region);
 		} else {
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1e4622d..31aa1db 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -467,10 +467,19 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
 static void
 drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
 {
-	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-				     &drmmode_crtc->scanout[0]);
-	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-				     &drmmode_crtc->scanout[1]);
+	if (drmmode_crtc->flip_pending) {
+		drmmode_crtc->scanout_destroy[0] = drmmode_crtc->scanout[0];
+		drmmode_crtc->scanout[0].pixmap = NULL;
+		drmmode_crtc->scanout[0].bo = NULL;
+		drmmode_crtc->scanout_destroy[1] = drmmode_crtc->scanout[1];
+		drmmode_crtc->scanout[1].pixmap = NULL;
+		drmmode_crtc->scanout[1].bo = NULL;
+	} else {
+		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+					     &drmmode_crtc->scanout[0]);
+		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+					     &drmmode_crtc->scanout[1]);
+	}
 
 	if (drmmode_crtc->scanout_damage) {
 		DamageDestroy(drmmode_crtc->scanout_damage);
@@ -1062,11 +1071,12 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t * red, uint16_t * green,
 static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
 
 	if (!ppix) {
 		if (crtc->randr_crtc->scanout_pixmap)
 			PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap,
-						drmmode_crtc->scanout[0].pixmap);
+						drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap);
 		drmmode_crtc_scanout_free(drmmode_crtc);
 		return TRUE;
 	}
@@ -1076,6 +1086,14 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
 					 ppix->drawable.height))
 		return FALSE;
 
+	if (info->tear_free &&
+	    !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
+					 ppix->drawable.width,
+					 ppix->drawable.height)) {
+		drmmode_crtc_scanout_free(drmmode_crtc);
+		return FALSE;
+	}
+
 #ifdef HAS_DIRTYTRACKING_ROTATION
 	PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[0].pixmap,
 				 0, 0, 0, 0, RR_Rotate_0);
@@ -2010,6 +2028,11 @@ drmmode_clear_pending_flip(xf86CrtcPtr crtc)
 
 		drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode);
 	}
+
+	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+				     &drmmode_crtc->scanout_destroy[0]);
+	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+				     &drmmode_crtc->scanout_destroy[1]);
 }
 
 static void
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 6c5542c..4973bc2 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -84,6 +84,7 @@ typedef struct {
 	struct amdgpu_buffer *cursor_buffer;
 	struct drmmode_scanout rotate;
 	struct drmmode_scanout scanout[2];
+	struct drmmode_scanout scanout_destroy[2];
 	DamagePtr scanout_damage;
 	RegionRec scanout_last_region;
 	unsigned scanout_id;
-- 
2.9.3

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

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* RE: [PATCH xf86-video-amdgpu 12/12] Make TearFree effective with PRIME slave scanout
       [not found]         ` <20160908100310.20051-3-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
@ 2016-09-08 12:53           ` Deucher, Alexander
  0 siblings, 0 replies; 13+ messages in thread
From: Deucher, Alexander @ 2016-09-08 12:53 UTC (permalink / raw)
  To: 'Michel Dänzer', amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

> -----Original Message-----
> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On Behalf
> Of Michel Dänzer
> Sent: Thursday, September 08, 2016 6:03 AM
> To: amd-gfx@lists.freedesktop.org
> Subject: [PATCH xf86-video-amdgpu 12/12] Make TearFree effective with
> PRIME slave scanout
> 
> From: Michel Dänzer <michel.daenzer@amd.com>
> 
> TearFree can now prevent tearing with any possible display
> configuration.
> 
> Note that there may still be inter-GPU tearing if the primary GPU uses
> a different driver.
> 
> (Ported from radeon commit 38797a33117222dadbc89e5f21ed8cd5deef9bea)
> 
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

Series is:
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

> ---
>  src/amdgpu_kms.c      | 112
> ++++++++++++++++++++++++++++++++++++++++++++++----
>  src/drmmode_display.c |  33 ++++++++++++---
>  src/drmmode_display.h |   1 +
>  3 files changed, 133 insertions(+), 13 deletions(-)
> 
> diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
> index 88b0be0..a159c84 100644
> --- a/src/amdgpu_kms.c
> +++ b/src/amdgpu_kms.c
> @@ -507,31 +507,56 @@ slave_has_sync_shared_pixmap(ScrnInfoPtr scrn,
> PixmapDirtyUpdatePtr dirty)
>  	return slave_scrn->driverName == scrn->driverName;
>  }
> 
> -void
> -amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame,
> uint64_t usec,
> -				    void *event_data)
> +static Bool
> +amdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
>  {
>  	ScrnInfoPtr scrn = crtc->scrn;
>  	ScreenPtr screen = scrn->pScreen;
> +	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
>  	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
>  	PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap;
>  	PixmapDirtyUpdatePtr dirty;
> +	Bool ret = FALSE;
> 
>  	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
> -		if (dirty->src == scanoutpix &&
> -		    dirty->slave_dst == drmmode_crtc->scanout[0].pixmap) {
> +		if (dirty->src == scanoutpix && dirty->slave_dst ==
> +		    drmmode_crtc->scanout[scanout_id ^ info-
> >tear_free].pixmap) {
>  			RegionPtr region;
> 
>  			if (master_has_sync_shared_pixmap(scrn, dirty))
>  				amdgpu_sync_shared_pixmap(dirty);
> 
>  			region = dirty_region(dirty);
> +			if (RegionNil(region))
> +				goto destroy;
> +
> +			if (info->tear_free) {
> +				RegionTranslate(region, crtc->x, crtc->y);
> +				amdgpu_sync_scanout_pixmaps(crtc, region,
> scanout_id);
> +				amdgpu_glamor_flush(scrn);
> +				RegionCopy(&drmmode_crtc-
> >scanout_last_region, region);
> +				RegionTranslate(region, -crtc->x, -crtc->y);
> +				dirty->slave_dst = drmmode_crtc-
> >scanout[scanout_id].pixmap;
> +			}
> +
>  			redisplay_dirty(dirty, region);
> +			ret = TRUE;
> +		destroy:
>  			RegionDestroy(region);
>  			break;
>  		}
>  	}
> 
> +	return ret;
> +}
> +
> +void
> +amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame,
> uint64_t usec,
> +				     void *event_data)
> +{
> +	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +
> +	amdgpu_prime_scanout_do_update(crtc, 0);
>  	drmmode_crtc->scanout_update_pending = FALSE;
>  }
> 
> @@ -590,8 +615,75 @@
> amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
>  }
> 
>  static void
> +amdgpu_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
> +{
> +	drmmode_crtc_private_ptr drmmode_crtc = event_data;
> +
> +	drmmode_crtc->scanout_update_pending = FALSE;
> +	drmmode_clear_pending_flip(crtc);
> +}
> +
> +static void
> +amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
> +{
> +	ScreenPtr screen = ent->slave_dst->drawable.pScreen;
> +	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
> +	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
> +	xf86CrtcPtr crtc = NULL;
> +	drmmode_crtc_private_ptr drmmode_crtc = NULL;
> +	uintptr_t drm_queue_seq;
> +	unsigned scanout_id;
> +	int c;
> +
> +	/* Find the CRTC which is scanning out from this slave pixmap */
> +	for (c = 0; c < xf86_config->num_crtc; c++) {
> +		crtc = xf86_config->crtc[c];
> +		drmmode_crtc = crtc->driver_private;
> +		scanout_id = drmmode_crtc->scanout_id;
> +		if (drmmode_crtc->scanout[scanout_id].pixmap == ent-
> >slave_dst)
> +			break;
> +	}
> +
> +	if (c == xf86_config->num_crtc ||
> +	    !crtc->enabled ||
> +	    drmmode_crtc->scanout_update_pending ||
> +	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
> +	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
> +		return;
> +
> +	scanout_id = drmmode_crtc->scanout_id ^ 1;
> +	if (!amdgpu_prime_scanout_do_update(crtc, scanout_id))
> +		return;
> +
> +	drm_queue_seq = amdgpu_drm_queue_alloc(crtc,
> +
> AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
> +
> AMDGPU_DRM_QUEUE_ID_DEFAULT,
> +					       drmmode_crtc, NULL,
> +
> amdgpu_prime_scanout_flip_abort);
> +	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
> +		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
> +			   "Allocating DRM event queue entry failed for PRIME
> flip.\n");
> +		return;
> +	}
> +
> +	if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc-
> >mode_crtc->crtc_id,
> +			    drmmode_crtc->scanout[scanout_id].fb_id,
> +			    DRM_MODE_PAGE_FLIP_EVENT,
> (void*)drm_queue_seq)) {
> +		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue
> failed in %s: %s\n",
> +			   __func__, strerror(errno));
> +		return;
> +	}
> +
> +	drmmode_crtc->scanout_id = scanout_id;
> +	drmmode_crtc->scanout_update_pending = TRUE;
> +	drmmode_crtc->flip_pending = TRUE;
> +}
> +
> +static void
>  amdgpu_dirty_update(ScrnInfoPtr scrn)
>  {
> +	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
>  	ScreenPtr screen = scrn->pScreen;
>  	PixmapDirtyUpdatePtr ent;
>  	RegionPtr region;
> @@ -611,10 +703,14 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
> 
>  			region = dirty_region(region_ent);
> 
> -			if (RegionNotEmpty(region))
> -				amdgpu_prime_scanout_update(ent);
> -			else
> +			if (RegionNotEmpty(region)) {
> +				if (info->tear_free)
> +					amdgpu_prime_scanout_flip(ent);
> +				else
> +
> 	amdgpu_prime_scanout_update(ent);
> +			} else {
>  				DamageEmpty(region_ent->damage);
> +			}
> 
>  			RegionDestroy(region);
>  		} else {
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index 1e4622d..31aa1db 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -467,10 +467,19 @@ drmmode_crtc_scanout_destroy(drmmode_ptr
> drmmode,
>  static void
>  drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
>  {
> -	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> -				     &drmmode_crtc->scanout[0]);
> -	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> -				     &drmmode_crtc->scanout[1]);
> +	if (drmmode_crtc->flip_pending) {
> +		drmmode_crtc->scanout_destroy[0] = drmmode_crtc-
> >scanout[0];
> +		drmmode_crtc->scanout[0].pixmap = NULL;
> +		drmmode_crtc->scanout[0].bo = NULL;
> +		drmmode_crtc->scanout_destroy[1] = drmmode_crtc-
> >scanout[1];
> +		drmmode_crtc->scanout[1].pixmap = NULL;
> +		drmmode_crtc->scanout[1].bo = NULL;
> +	} else {
> +		drmmode_crtc_scanout_destroy(drmmode_crtc-
> >drmmode,
> +					     &drmmode_crtc->scanout[0]);
> +		drmmode_crtc_scanout_destroy(drmmode_crtc-
> >drmmode,
> +					     &drmmode_crtc->scanout[1]);
> +	}
> 
>  	if (drmmode_crtc->scanout_damage) {
>  		DamageDestroy(drmmode_crtc->scanout_damage);
> @@ -1062,11 +1071,12 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc,
> uint16_t * red, uint16_t * green,
>  static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
>  {
>  	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +	AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
> 
>  	if (!ppix) {
>  		if (crtc->randr_crtc->scanout_pixmap)
>  			PixmapStopDirtyTracking(crtc->randr_crtc-
> >scanout_pixmap,
> -						drmmode_crtc-
> >scanout[0].pixmap);
> +						drmmode_crtc-
> >scanout[drmmode_crtc->scanout_id].pixmap);
>  		drmmode_crtc_scanout_free(drmmode_crtc);
>  		return TRUE;
>  	}
> @@ -1076,6 +1086,14 @@ static Bool
> drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
>  					 ppix->drawable.height))
>  		return FALSE;
> 
> +	if (info->tear_free &&
> +	    !drmmode_crtc_scanout_create(crtc, &drmmode_crtc-
> >scanout[1],
> +					 ppix->drawable.width,
> +					 ppix->drawable.height)) {
> +		drmmode_crtc_scanout_free(drmmode_crtc);
> +		return FALSE;
> +	}
> +
>  #ifdef HAS_DIRTYTRACKING_ROTATION
>  	PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[0].pixmap,
>  				 0, 0, 0, 0, RR_Rotate_0);
> @@ -2010,6 +2028,11 @@ drmmode_clear_pending_flip(xf86CrtcPtr crtc)
> 
>  		drmmode_crtc_dpms(crtc, drmmode_crtc-
> >pending_dpms_mode);
>  	}
> +
> +	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> +				     &drmmode_crtc->scanout_destroy[0]);
> +	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> +				     &drmmode_crtc->scanout_destroy[1]);
>  }
> 
>  static void
> diff --git a/src/drmmode_display.h b/src/drmmode_display.h
> index 6c5542c..4973bc2 100644
> --- a/src/drmmode_display.h
> +++ b/src/drmmode_display.h
> @@ -84,6 +84,7 @@ typedef struct {
>  	struct amdgpu_buffer *cursor_buffer;
>  	struct drmmode_scanout rotate;
>  	struct drmmode_scanout scanout[2];
> +	struct drmmode_scanout scanout_destroy[2];
>  	DamagePtr scanout_damage;
>  	RegionRec scanout_last_region;
>  	unsigned scanout_id;
> --
> 2.9.3
> 
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-09-08 12:53 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-08 10:02 [PATCH xf86-video-amdgpu 01/12] Add explicit AMDGPU_DRM_QUEUE_ERROR define Michel Dänzer
     [not found] ` <20160908100242.19964-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 02/12] Use EventCallback to avoid flushing every time in the FlushCallback Michel Dänzer
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 03/12] Keep track of damage event related flushes per-client Michel Dänzer
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 04/12] Wait for pending flips to complete before turning off an output or CRTC Michel Dänzer
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 05/12] Use drmmode_crtc_scanout_* helpers for RandR 1.4 scanout pixmaps Michel Dänzer
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 06/12] Handle RandR 1.4 slave dirty updates via amdgpu_drm_queue Michel Dänzer
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 07/12] Track damage accurately for RandR 1.4 slave scanout Michel Dänzer
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 08/12] Only copy from screen pixmap to shared pixmap on demand for " Michel Dänzer
2016-09-08 10:02   ` [PATCH xf86-video-amdgpu 09/12] Factor out transform_region helper Michel Dänzer
2016-09-08 10:03   ` [PATCH xf86-video-amdgpu 10/12] Move up amdgpu_scanout_extents_intersect Michel Dänzer
     [not found]     ` <20160908100310.20051-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
2016-09-08 10:03       ` [PATCH xf86-video-amdgpu 11/12] Synchronize scanout pixmaps for TearFree Michel Dänzer
2016-09-08 10:03       ` [PATCH xf86-video-amdgpu 12/12] Make TearFree effective with PRIME slave scanout Michel Dänzer
     [not found]         ` <20160908100310.20051-3-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
2016-09-08 12:53           ` Deucher, Alexander

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.