> -----Original Message----- > From: amd-gfx [mailto:amd-gfx-boun...@lists.freedesktop.org] On Behalf > Of Michel Dänzer > Sent: Tuesday, October 03, 2017 6:55 AM > To: amd-gfx@lists.freedesktop.org > Subject: [PATCH xf86-video-ati] Fix VT switching with ShadowFB > > From: Michel Dänzer <michel.daen...@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: 06a465484101 ("Make all active CRTCs scan out an all-black > framebuffer in LeaveVT") > Signed-off-by: Michel Dänzer <michel.daen...@amd.com>
Reviewed-by: Alex Deucher <alexander.deuc...@amd.com> > --- > src/radeon_kms.c | 157 +++++++++++++++++++++++++++++++++----------- > ----------- > 1 file changed, 94 insertions(+), 63 deletions(-) > > diff --git a/src/radeon_kms.c b/src/radeon_kms.c > index 351af995..b982e425 100644 > --- a/src/radeon_kms.c > +++ b/src/radeon_kms.c > @@ -2423,6 +2423,31 @@ Bool RADEONEnterVT_KMS(ScrnInfoPtr pScrn) > > radeon_set_drm_master(pScrn); > > + if (info->r600_shadow_fb) { > + int base_align = drmmode_get_base_align(pScrn, info->pixel_bytes, > 0); > + struct radeon_bo *front_bo = radeon_bo_open(info->bufmgr, 0, > + info->front_bo->size, > + base_align, > + > RADEON_GEM_DOMAIN_VRAM, 0); > + > + if (front_bo) { > + if (radeon_bo_map(front_bo, 1) == 0) { > + memset(front_bo->ptr, 0, front_bo->size); > + radeon_bo_unref(info->front_bo); > + info->front_bo = front_bo; > + } else { > + radeon_bo_unref(front_bo); > + front_bo = NULL; > + } > + } > + > + if (!front_bo) { > + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, > + "Failed to allocate new scanout BO after VT switch, " > + "other DRM masters may see screen contents\n"); > + } > + } > + > info->accel_state->XInited3D = FALSE; > info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; > > @@ -2473,85 +2498,91 @@ pixmap_unref_fb(void *value, XID id, void > *cdata) > void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) > { > 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"); > > - /* 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 (!info->r600_shadow_fb) { > + RADEONEntPtr pRADEONEnt = RADEONEntPriv(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; > > - if (!drmmode_crtc->fb) > - continue; > + /* 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; > > - 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 (!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); > + 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); > - 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, > + pRADEONEnt); > + } > > - FindClientResourcesByType(clients[i], RT_PIXMAP, > pixmap_unref_fb, > - pRADEONEnt); > + pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, > pRADEONEnt); > + } else { > + memset(info->front_bo->ptr, 0, info->front_bo->size); > } > - pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, > pRADEONEnt); > > TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen); > > -- > 2.14.2 > > _______________________________________________ > 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