[PATCH] composite: Don't bother copying the pixmap for ForgetGravity windows (v2)

Jasper St. Pierre jstpierre at mecheye.net
Thu Apr 23 15:01:28 PDT 2015


The compositor sync protocol helps that tremendously, where the client
actually tells the compositor when it can start to use the new pixmap.
I tested with xcompmgr and nautilus, and couldn't see any flickering,
which tells me that clients are actually plenty fast enough already.

But yeah, you might see flickering in a worst case scenario. I'd argue
that isn't much better than the current NorthWestGravity behavior
where we lop off the bottom/right edge of the window. There's no true
way to solve this properly besides a Wayland-approach where the client
just presents the compositor a correctly-sized, finished pixmap.

On Thu, Apr 23, 2015 at 2:13 PM, Aaron Plattner <aplattner at nvidia.com> wrote:
> Does this cause flickering when resizing windows and the compositor reads
> the new window pixmap before the app has a chance to respond to the events?
>
>
> On 04/23/2015 01:24 PM, Jasper St. Pierre wrote:
>>
>> If a window has ForgetGravity in its bitGravity, that very likely
>> means it will repaint on the ConfigureNotify / Expose event, and thus
>> we don't have to copy the old pixmap into the new pixmap, we can simply
>> leave it blank.
>>
>> Preventing this copy is super simple to do and a big win on small
>> devices where these blits can be expensive.
>>
>> A better approach would be to actually obey BitGravity correctly rather
>> than assume NorthWestGravity always, but this is a big speedup for the
>> common case.
>>
>> v2: Check all subwindows to make sure they are also ForgetGravity
>>
>> Cc: Adam Jackson <ajax at redhat.com>
>> Signed-off-by: Jasper St. Pierre <jstpierre at mecheye.net>
>> ---
>>   composite/compalloc.c | 109
>> +++++++++++++++++++++++++++++---------------------
>>   1 file changed, 63 insertions(+), 46 deletions(-)
>>
>> diff --git a/composite/compalloc.c b/composite/compalloc.c
>> index 8daded0..40bf873 100644
>> --- a/composite/compalloc.c
>> +++ b/composite/compalloc.c
>> @@ -526,6 +526,21 @@ compUnredirectOneSubwindow(WindowPtr pParent,
>> WindowPtr pWin)
>>       return Success;
>>   }
>>
>> +static Bool
>> +needsPixmapCopy(WindowPtr pWin)
>> +{
>> +    WindowPtr pChild;
>> +
>> +    if (pWin->bitGravity != ForgetGravity)
>> +        return TRUE;
>> +
>> +    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
>> +        if (needsPixmapCopy(pChild))
>> +            return TRUE;
>> +
>> +    return FALSE;
>> +}
>> +
>>   static PixmapPtr
>>   compNewPixmap(WindowPtr pWin, int x, int y, int w, int h)
>>   {
>> @@ -542,54 +557,56 @@ compNewPixmap(WindowPtr pWin, int x, int y, int w,
>> int h)
>>       pPixmap->screen_x = x;
>>       pPixmap->screen_y = y;
>>
>> -    if (pParent->drawable.depth == pWin->drawable.depth) {
>> -        GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
>> -
>> -        if (pGC) {
>> -            ChangeGCVal val;
>> -
>> -            val.val = IncludeInferiors;
>> -            ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
>> -            ValidateGC(&pPixmap->drawable, pGC);
>> -            (*pGC->ops->CopyArea) (&pParent->drawable,
>> -                                   &pPixmap->drawable,
>> -                                   pGC,
>> -                                   x - pParent->drawable.x,
>> -                                   y - pParent->drawable.y, w, h, 0, 0);
>> -            FreeScratchGC(pGC);
>> +    if (needsPixmapCopy(pWin)) {
>> +        if (pParent->drawable.depth == pWin->drawable.depth) {
>> +            GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
>> +
>> +            if (pGC) {
>> +                ChangeGCVal val;
>> +
>> +                val.val = IncludeInferiors;
>> +                ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
>> +                ValidateGC(&pPixmap->drawable, pGC);
>> +                (*pGC->ops->CopyArea) (&pParent->drawable,
>> +                                       &pPixmap->drawable,
>> +                                       pGC,
>> +                                       x - pParent->drawable.x,
>> +                                       y - pParent->drawable.y, w, h, 0,
>> 0);
>> +                FreeScratchGC(pGC);
>> +            }
>>           }
>> -    }
>> -    else {
>> -        PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
>> -        PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
>> -        XID inferiors = IncludeInferiors;
>> -        int error;
>> -
>> -        PicturePtr pSrcPicture = CreatePicture(None,
>> -                                               &pParent->drawable,
>> -                                               pSrcFormat,
>> -                                               CPSubwindowMode,
>> -                                               &inferiors,
>> -                                               serverClient, &error);
>> -
>> -        PicturePtr pDstPicture = CreatePicture(None,
>> -                                               &pPixmap->drawable,
>> -                                               pDstFormat,
>> -                                               0, 0,
>> -                                               serverClient, &error);
>> -
>> -        if (pSrcPicture && pDstPicture) {
>> -            CompositePicture(PictOpSrc,
>> -                             pSrcPicture,
>> -                             NULL,
>> -                             pDstPicture,
>> -                             x - pParent->drawable.x,
>> -                             y - pParent->drawable.y, 0, 0, 0, 0, w, h);
>> +        else {
>> +            PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
>> +            PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
>> +            XID inferiors = IncludeInferiors;
>> +            int error;
>> +
>> +            PicturePtr pSrcPicture = CreatePicture(None,
>> +                                                   &pParent->drawable,
>> +                                                   pSrcFormat,
>> +                                                   CPSubwindowMode,
>> +                                                   &inferiors,
>> +                                                   serverClient, &error);
>> +
>> +            PicturePtr pDstPicture = CreatePicture(None,
>> +                                                   &pPixmap->drawable,
>> +                                                   pDstFormat,
>> +                                                   0, 0,
>> +                                                   serverClient, &error);
>> +
>> +            if (pSrcPicture && pDstPicture) {
>> +                CompositePicture(PictOpSrc,
>> +                                 pSrcPicture,
>> +                                 NULL,
>> +                                 pDstPicture,
>> +                                 x - pParent->drawable.x,
>> +                                 y - pParent->drawable.y, 0, 0, 0, 0, w,
>> h);
>> +            }
>> +            if (pSrcPicture)
>> +                FreePicture(pSrcPicture, 0);
>> +            if (pDstPicture)
>> +                FreePicture(pDstPicture, 0);
>>           }
>> -        if (pSrcPicture)
>> -            FreePicture(pSrcPicture, 0);
>> -        if (pDstPicture)
>> -            FreePicture(pDstPicture, 0);
>>       }
>>       return pPixmap;
>>   }
>
>
> --
> Aaron



-- 
  Jasper


More information about the xorg-devel mailing list