[PATCH xf86-video-amdgpu 1/2] Fix VT switching with ShadowFB
Michel Dänzer
michel at daenzer.net
Thu Oct 19 16:03:28 UTC 2017
From: Michel Dänzer <michel.daenzer at amd.com>
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)
Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
src/amdgpu_kms.c | 154 +++++++++++++++++++++++++++++++++----------------------
1 file changed, 94 insertions(+), 60 deletions(-)
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 6fe43264c..e3d7d71cf 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);
--
2.14.2
More information about the amd-gfx
mailing list