summaryrefslogtreecommitdiff
path: root/src/amdgpu_kms.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2017-08-30 17:17:49 +0900
committerMichel Dänzer <michel.daenzer@amd.com>2017-08-30 17:17:49 +0900
commit456e5841233a8a79c23ad13649bbdaf8428b50f3 (patch)
tree13ab19e1a4dd6dd93699e599261d8e4d5fef85ff /src/amdgpu_kms.c
parent639076efb06cdf13a211a8df1acb00c3908992b9 (diff)
Use a timer for unreferencing the all-black FB
The timer fires 1 second after LeaveVT. This gives the next DRM master enough time to set up scanout of its own buffers. Fixes prolonged intermittent black screen when switching from Xorg to e.g. the GDM Wayland mode login VT. Fixes: c16ff42f927d ("Make all active CRTCs scan out an all-black framebuffer in LeaveVT") (Ported from radeon commit 9d9c565c84601f4c6c73ad769f86491088683f7a) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src/amdgpu_kms.c')
-rw-r--r--src/amdgpu_kms.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index c3613eb..d82ead2 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -1044,7 +1044,6 @@ static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
{
SCREEN_PTR(arg);
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
- AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
int c;
@@ -1053,21 +1052,8 @@ static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
- if (!xf86ScreenToScrn(amdgpu_master_screen(pScreen))->vtSema) {
- /* Unreference the all-black FB created by AMDGPULeaveVT_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;
-
- drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
- NULL);
- }
-
+ if (!xf86ScreenToScrn(amdgpu_master_screen(pScreen))->vtSema)
return;
- }
if (!amdgpu_is_gpu_screen(pScreen))
{
@@ -1629,6 +1615,30 @@ static void amdgpu_drop_drm_master(ScrnInfoPtr pScrn)
}
+static
+CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data)
+{
+ ScreenPtr screen = data;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ if (xf86ScreenToScrn(amdgpu_master_screen(screen))->vtSema)
+ return 0;
+
+ /* Unreference the all-black FB created by AMDGPULeaveVT_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;
+
+ drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, NULL);
+ }
+
+ return 0;
+}
static Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode)
{
@@ -2061,6 +2071,8 @@ void AMDGPULeaveVT_KMS(VT_FUNC_ARGS_DECL)
}
pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pAMDGPUEnt);
+ TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen);
+
xf86_hide_cursors(pScrn);
amdgpu_drop_drm_master(pScrn);