[PATCH xf86-video-ati] Fix VT switching with ShadowFB

Deucher, Alexander Alexander.Deucher at amd.com
Tue Oct 3 16:01:57 UTC 2017


> -----Original Message-----
> From: amd-gfx [mailto:amd-gfx-bounces at lists.freedesktop.org] On Behalf
> Of Michel Dänzer
> Sent: Tuesday, October 03, 2017 6:55 AM
> To: amd-gfx at lists.freedesktop.org
> Subject: [PATCH xf86-video-ati] Fix VT switching with ShadowFB
> 
> 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: 06a465484101 ("Make all active CRTCs scan out an all-black
>                       framebuffer in LeaveVT")
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>

Reviewed-by: Alex Deucher <alexander.deucher at 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list