[PATCH 07/18] Delay initial modeset until root window contents are prepared

Eric Anholt eric at anholt.net
Mon Aug 25 13:33:07 PDT 2014


Keith Packard <keithp at keithp.com> writes:

> Wait until the root window has been painted for the first time before
> doing the modeset. This avoids flashing black while the root window
> gets set up.
>
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
>  src/uxa/intel.h         |  2 ++
>  src/uxa/intel_display.c | 39 ++++++++++++++++++---------------------
>  src/uxa/intel_driver.c  | 33 ++++++++++++++++++++++++++++-----
>  3 files changed, 48 insertions(+), 26 deletions(-)
>
> diff --git a/src/uxa/intel.h b/src/uxa/intel.h
> index ceb20ea..c8bdaf3 100644
> --- a/src/uxa/intel.h
> +++ b/src/uxa/intel.h
> @@ -235,6 +235,8 @@ typedef struct intel_screen_private {
>  	void (*batch_flush) (struct intel_screen_private *intel);
>  	void (*batch_commit_notify) (struct intel_screen_private *intel);
>  
> +        Bool need_entervt;
> +
>  	struct _UxaDriver *uxa_driver;
>  	int uxa_flags;
>  	Bool need_sync;
> diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
> index c9e7669..9720fc3 100644
> --- a/src/uxa/intel_display.c
> +++ b/src/uxa/intel_display.c
> @@ -2300,7 +2300,7 @@ void intel_copy_fb(ScrnInfoPtr scrn)
>  	ScreenPtr pScreen = xf86ScrnToScreen(scrn);
>  	intel_screen_private *intel = intel_get_screen_private(scrn);
>  	PixmapPtr src, dst;
> -	unsigned int pitch = scrn->displayWidth * intel->cpp;
> +        GCPtr gc;
>  	struct intel_crtc *intel_crtc;
>  	int i, fbcon_id;
>  
> @@ -2320,30 +2320,27 @@ void intel_copy_fb(ScrnInfoPtr scrn)
>  	if (src == NULL)
>  		return;
>  
> -	/* We dont have a screen Pixmap yet */
> -	dst = intel_create_pixmap_for_bo(pScreen, intel->front_buffer,
> -					 scrn->virtualX, scrn->virtualY,
> -					 scrn->depth, scrn->bitsPerPixel,
> -					 pitch);
> +        dst = (*pScreen->GetScreenPixmap)(pScreen);
> +
>  	if (dst == NullPixmap)
>  		goto cleanup_src;
>  
> -	if (!intel->uxa_driver->prepare_copy(src, dst,
> -					     -1, -1,
> -					     GXcopy, FB_ALLONES))
> -		goto cleanup_dst;
> -
> -	intel->uxa_driver->copy(dst,
> -				0, 0,
> -				0, 0,
> -				scrn->virtualX, scrn->virtualY);
> -	intel->uxa_driver->done_copy(dst);
> -#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0)
> -	pScreen->canDoBGNoneRoot = TRUE;
> -#endif
> +        gc = GetScratchGC(scrn->depth, pScreen);
> +
> +        if (!gc)
> +                goto cleanup_src;
> +
> +        ValidateGC(&dst->drawable, gc);
> +
> +        (*gc->ops->CopyArea)(&src->drawable,
> +                             &dst->drawable,
> +                             gc,
> +                             0, 0,
> +                             scrn->virtualX, scrn->virtualY,
> +                             0, 0);
> +
> +        FreeScratchGC(gc);
>  
> -cleanup_dst:
> -	(*pScreen->DestroyPixmap)(dst);
>  cleanup_src:
>  	(*pScreen->DestroyPixmap)(src);
>  }
> diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c
> index a7ca906..d34c6d7 100644
> --- a/src/uxa/intel_driver.c
> +++ b/src/uxa/intel_driver.c
> @@ -165,7 +165,6 @@ static Bool i830CreateScreenResources(ScreenPtr screen)
>  	if (!intel_uxa_create_screen_resources(screen))
>  		return FALSE;
>  
> -	intel_copy_fb(scrn);
>  	return TRUE;
>  }
>  
> @@ -699,6 +698,29 @@ I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
>  
>  	screen->BlockHandler = intel->BlockHandler;
>  
> +        /* At server init time, get the root window bits from fbcon if
> +         * available and then update the protocol-level information
> +         * for both RandR and XINERAMA
> +         */
> +        if (intel->need_entervt) {
> +                intel->need_entervt = FALSE;
> +
> +                if (screen->root->backgroundState == None)
> +                        intel_copy_fb(scrn);

What guarantees that no important rendering has happened before the
first BlockHandler, which would get overridden by intel_copy_fb()?

> +                /* Must force it before EnterVT, so we are in control of VT and
> +                 * later memory should be bound when allocating, e.g rotate_mem */
> +                scrn->vtSema = TRUE;
> +
> +                if (!I830EnterVT(VT_FUNC_ARGS(0))) {
> +                        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
> +                                   "Failed to perform initial modeset.\n");
> +                        FatalError("Mode set failed\n");
> +                }
> +
> +                xf86RandR12CreateScreenResources(screen);

Delaying setting up things like pScreen->width/height and mmWidth/Height
until the first BlockHandler also seems really creepy.

> +        }
> +
>  	(*screen->BlockHandler) (BLOCKHANDLER_ARGS);

I expected this patch overall to be "delay the first call to the kernel
for the actual modeset/flip until blockhandler", but it looks like
"delay modesetting-related probing and initial root window rendering to
the first blockhandler", which I don't feel a good reason to trust.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg-devel/attachments/20140825/4a610f36/attachment.sig>


More information about the xorg-devel mailing list