summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2017-10-03 12:47:14 +0200
committerMichel Dänzer <michel.daenzer@amd.com>2017-10-03 12:51:05 +0200
commit34da04daec82077571558ac3fe1ec0c1203a01ad (patch)
tree10519ee29d9cbd79e13ad9a84d3344d13fc7d090 /src
parentf9aca8c1a7a423b9e738c88400ae821bdfbcdb1c (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: 06a465484101 ("Make all active CRTCs scan out an all-black framebuffer in LeaveVT") Signed-off-by: Michel Dänzer <michel.daenzer@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src')
-rw-r--r--src/radeon_kms.c157
1 files 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);