All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michel Dänzer" <michel-otUistvHUpPR7s880joybQ@public.gmane.org>
To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Subject: [PATCH xf86-video-ati 5/6] Make all active CRTCs scan out an all-black framebuffer in LeaveVT
Date: Mon, 28 Aug 2017 18:23:42 +0900	[thread overview]
Message-ID: <20170828092343.27742-6-michel@daenzer.net> (raw)
In-Reply-To: <20170828092343.27742-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>

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

And destroy all other FBs. This is so that other DRM masters can only
get access to this all-black FB, not to any other FB we created, while
we're switched away and not DRM master.

Fixes: 55e513b978b2 ("Use reference counting for tracking KMS
                      framebuffer lifetimes")
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 src/drmmode_display.c |  4 +--
 src/drmmode_display.h |  4 +++
 src/radeon_kms.c      | 98 +++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 98 insertions(+), 8 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 791d59986..ba170ee64 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -536,7 +536,7 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
 	}
 }
 
-static void
+void
 drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
 {
 	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
@@ -558,7 +558,7 @@ drmmode_scanout_free(ScrnInfoPtr scrn)
 		drmmode_crtc_scanout_free(xf86_config->crtc[c]->driver_private);
 }
 
-static PixmapPtr
+PixmapPtr
 drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
 			    int width, int height)
 {
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 00b5e8119..ace059dcc 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -216,6 +216,10 @@ extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
 extern void drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
 					 struct drmmode_scanout *scanout);
 extern void drmmode_scanout_free(ScrnInfoPtr scrn);
+void drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc);
+PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc,
+				      struct drmmode_scanout *scanout,
+				      int width, int height);
 
 extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode);
 extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index ca2d36d04..5410c4208 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -32,6 +32,7 @@
 #include <sys/ioctl.h>
 /* Driver data structures */
 #include "radeon.h"
+#include "radeon_bo_helper.h"
 #include "radeon_drm_queue.h"
 #include "radeon_glamor.h"
 #include "radeon_reg.h"
@@ -1158,9 +1159,10 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
     (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
     pScreen->BlockHandler = RADEONBlockHandler_KMS;
 
-    if (!pScrn->vtSema) {
-	radeon_cs_flush_indirect(pScrn);
-
+    if (!xf86ScreenToScrn(radeon_master_screen(pScreen))->vtSema) {
+	/* Unreference the all-black FB created by RADEONLeaveVT_KMS. After
+	 * this, there should be no FB left created by this driver.
+	 */
 	for (c = 0; c < xf86_config->num_crtc; c++) {
 	    drmmode_crtc_private_ptr drmmode_crtc =
 		xf86_config->crtc[c]->driver_private;
@@ -2472,21 +2474,105 @@ Bool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL)
 }
 
 
+static void
+pixmap_unref_fb(void *value, XID id, void *cdata)
+{
+    PixmapPtr pixmap = value;
+    RADEONEntPtr pRADEONEnt = cdata;
+    struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pixmap);
+
+    if (fb_ptr)
+	drmmode_fb_reference(pRADEONEnt->fd, fb_ptr, NULL);
+}
+
 void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL)
 {
     SCRN_INFO_PTR(arg);
     RADEONInfoPtr  info  = RADEONPTR(pScrn);
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+    ScreenPtr pScreen = pScrn->pScreen;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    struct drmmode_scanout black_scanout = { .pixmap = NULL, .bo = NULL };
+    xf86CrtcPtr crtc;
+    drmmode_crtc_private_ptr drmmode_crtc;
+    unsigned w = 0, h = 0;
+    int i;
 
     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
 		   "RADEONLeaveVT_KMS\n");
 
-    radeon_drop_drm_master(pScrn);
+    /* Compute maximum scanout dimensions of active CRTCs */
+    for (i = 0; i < xf86_config->num_crtc; i++) {
+	crtc = xf86_config->crtc[i];
+	drmmode_crtc = crtc->driver_private;
+
+	if (!drmmode_crtc->fb)
+	    continue;
+
+	w = max(w, crtc->mode.HDisplay);
+	h = max(h, crtc->mode.VDisplay);
+    }
+
+    /* Make all active CRTCs scan out from an all-black framebuffer */
+    if (w > 0 && h > 0) {
+	if (drmmode_crtc_scanout_create(crtc, &black_scanout, w, h)) {
+	    struct drmmode_fb *black_fb =
+		radeon_pixmap_get_fb(black_scanout.pixmap);
+
+	    radeon_pixmap_clear(black_scanout.pixmap);
+	    radeon_cs_flush_indirect(pScrn);
+	    radeon_bo_wait(black_scanout.bo);
+
+	    for (i = 0; i < xf86_config->num_crtc; i++) {
+		crtc = xf86_config->crtc[i];
+		drmmode_crtc = crtc->driver_private;
+
+		if (drmmode_crtc->fb) {
+		    if (black_fb) {
+			drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0);
+		    } else {
+			drmModeSetCrtc(pRADEONEnt->fd,
+				       drmmode_crtc->mode_crtc->crtc_id, 0, 0,
+				       0, NULL, 0, NULL);
+			drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
+					     NULL);
+		    }
+
+		    if (pScrn->is_gpu) {
+			if (drmmode_crtc->scanout[0].pixmap)
+			    pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap,
+					    None, pRADEONEnt);
+			if (drmmode_crtc->scanout[1].pixmap)
+			    pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap,
+					    None, pRADEONEnt);
+		    } else {
+			drmmode_crtc_scanout_free(drmmode_crtc);
+		    }
+		}
+	    }
+	}
+    }
 
     xf86RotateFreeShadow(pScrn);
-    if (!pScrn->is_gpu)
-	drmmode_scanout_free(pScrn);
+    drmmode_crtc_scanout_destroy(&info->drmmode, &black_scanout);
+
+    /* Unreference FBs of all pixmaps. After this, the only FB remaining
+     * should be the all-black one being scanned out by active CRTCs
+     */
+    for (i = 0; i < currentMaxClients; i++) {
+	if (i > 0 &&
+	    (!clients[i] || clients[i]->clientState != ClientStateRunning))
+            continue;
+
+	FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb,
+				  pRADEONEnt);
+    }
+    pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pRADEONEnt);
 
     xf86_hide_cursors (pScrn);
+
+    radeon_drop_drm_master(pScrn);
+
     info->accel_state->XInited3D = FALSE;
     info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
 
-- 
2.14.1

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

  parent reply	other threads:[~2017-08-28  9:23 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-28  9:23 [PATCH xf86-video-ati 0/6] Harden against other DRM masters Michel Dänzer
     [not found] ` <20170828092343.27742-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
2017-08-28  9:23   ` [PATCH xf86-video-ati 1/6] Create radeon_pixmap_clear helper Michel Dänzer
2017-08-28  9:23   ` [PATCH xf86-video-ati 2/6] Create drmmode_set_mode helper Michel Dänzer
2017-08-28  9:23   ` [PATCH xf86-video-ati 3/6] Create radeon_pixmap_get_fb_ptr helper Michel Dänzer
2017-08-28  9:23   ` [PATCH xf86-video-ati 4/6] Create radeon_master_screen helper Michel Dänzer
2017-08-28  9:23   ` Michel Dänzer [this message]
     [not found]     ` <20170828092343.27742-6-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
2017-08-29 10:56       ` [PATCH xf86-video-ati 5/6] Make all active CRTCs scan out an all-black framebuffer in LeaveVT Emil Velikov
     [not found]         ` <CACvgo52+5yVkKdwDMSdGnbM2C-Z-wUt3NdewP8oystW6=LVn2Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-08-30  8:04           ` Michel Dänzer
     [not found]             ` <8d6d0c04-7994-3b7a-6db6-cac8d8be3a4c-otUistvHUpPR7s880joybQ@public.gmane.org>
2017-08-30 10:27               ` Emil Velikov
     [not found]                 ` <CACvgo51bzkmjadyRqH+7quMt6VOW=tp24h3Gv3iDNdEhKDN1nQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-08-31  2:35                   ` Michel Dänzer
2017-08-28  9:23   ` [PATCH xf86-video-ati 6/6] Remove drmmode_scanout_free Michel Dänzer
2017-08-28 17:09   ` [PATCH xf86-video-ati 0/6] Harden against other DRM masters Deucher, Alexander

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170828092343.27742-6-michel@daenzer.net \
    --to=michel-otuistvhuppr7s880joybq@public.gmane.org \
    --cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.