diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2017-10-19 16:20:03 +0200 |
---|---|---|
committer | Michel Dänzer <michel.daenzer@amd.com> | 2017-10-19 16:20:03 +0200 |
commit | 55396cc45c9aae3b1985ced1044b6b93064667c3 (patch) | |
tree | ea2393e5cdb6f03173fa1eaf9d60fa5f64827ee2 | |
parent | 2f72be038d22c54620e436af30121dd89f79a003 (diff) |
Fix VT switching with ShadowFB
We were trying to call acceleration specific functions from LeaveVT.
Instead, memset the scanout buffer to all 0 in LeaveVT and allocate a
new one in EnterVT.
Bugzilla: https://bugs.freedesktop.org/102948
Fixes: c16ff42f927d ("Make all active CRTCs scan out an all-black
framebuffer in LeaveVT")
(Ported from radeon commit 34da04daec82077571558ac3fe1ec0c1203a01ad)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | src/amdgpu_kms.c | 154 |
1 files changed, 94 insertions, 60 deletions
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c index 6fe4326..e3d7d71 100644 --- a/src/amdgpu_kms.c +++ b/src/amdgpu_kms.c @@ -1941,6 +1941,33 @@ Bool AMDGPUEnterVT_KMS(ScrnInfoPtr pScrn) amdgpu_set_drm_master(pScrn); + if (info->shadow_fb) { + int pitch; + struct amdgpu_buffer *front_buffer = + amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX, + pScrn->virtualY, pScrn->depth, + AMDGPU_CREATE_PIXMAP_LINEAR, + pScrn->bitsPerPixel, + &pitch); + + if (front_buffer) { + if (amdgpu_bo_map(pScrn, front_buffer) == 0) { + memset(front_buffer->cpu_ptr, 0, pitch * pScrn->virtualY); + amdgpu_bo_unref(&info->front_buffer); + info->front_buffer = front_buffer; + } else { + amdgpu_bo_unref(&front_buffer); + front_buffer = NULL; + } + } + + if (!front_buffer) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to allocate new scanout BO after VT switch, " + "other DRM masters may see screen contents\n"); + } + } + pScrn->vtSema = TRUE; if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE)) @@ -1963,84 +1990,91 @@ pixmap_unref_fb(void *value, XID id, void *cdata) void AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn) { AMDGPUInfoPtr info = AMDGPUPTR(pScrn); - AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(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, AMDGPU_LOGLEVEL_DEBUG, "AMDGPULeaveVT_KMS\n"); - /* 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); - } + if (!info->shadow_fb) { + AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); + 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; + + /* 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; - /* 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 = - amdgpu_pixmap_get_fb(black_scanout.pixmap); + w = max(w, crtc->mode.HDisplay); + h = max(h, crtc->mode.VDisplay); + } - amdgpu_pixmap_clear(black_scanout.pixmap); - amdgpu_glamor_finish(pScrn); + /* 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 = + amdgpu_pixmap_get_fb(black_scanout.pixmap); - for (i = 0; i < xf86_config->num_crtc; i++) { - crtc = xf86_config->crtc[i]; - drmmode_crtc = crtc->driver_private; + amdgpu_pixmap_clear(black_scanout.pixmap); + amdgpu_glamor_finish(pScrn); - if (drmmode_crtc->fb) { - if (black_fb) { - drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0); - } else { - drmModeSetCrtc(pAMDGPUEnt->fd, - drmmode_crtc->mode_crtc->crtc_id, 0, 0, - 0, NULL, 0, NULL); - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, - NULL); - } + for (i = 0; i < xf86_config->num_crtc; i++) { + crtc = xf86_config->crtc[i]; + drmmode_crtc = crtc->driver_private; - if (pScrn->is_gpu) { - if (drmmode_crtc->scanout[0].pixmap) - pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap, - None, pAMDGPUEnt); - if (drmmode_crtc->scanout[1].pixmap) - pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap, - None, pAMDGPUEnt); - } else { - drmmode_crtc_scanout_free(drmmode_crtc); + if (drmmode_crtc->fb) { + if (black_fb) { + drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0); + } else { + drmModeSetCrtc(pAMDGPUEnt->fd, + drmmode_crtc->mode_crtc->crtc_id, 0, + 0, 0, NULL, 0, NULL); + drmmode_fb_reference(pAMDGPUEnt->fd, + &drmmode_crtc->fb, NULL); + } + + if (pScrn->is_gpu) { + if (drmmode_crtc->scanout[0].pixmap) + pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap, + None, pAMDGPUEnt); + if (drmmode_crtc->scanout[1].pixmap) + pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap, + None, pAMDGPUEnt); + } else { + drmmode_crtc_scanout_free(drmmode_crtc); + } } } } } - } - xf86RotateFreeShadow(pScrn); - drmmode_crtc_scanout_destroy(&info->drmmode, &black_scanout); + xf86RotateFreeShadow(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; + /* 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, + pAMDGPUEnt); + } - FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb, - pAMDGPUEnt); + pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pAMDGPUEnt); + } else { + memset(info->front_buffer->cpu_ptr, 0, pScrn->virtualX * + info->pixel_bytes * pScrn->virtualY); } - pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pAMDGPUEnt); TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen); |