Esempio n. 1
0
int
ProcXFixesCombineRegion(ClientPtr client)
{
    RegionPtr pSource1, pSource2, pDestination;

    REQUEST(xXFixesCombineRegionReq);

    REQUEST_SIZE_MATCH(xXFixesCombineRegionReq);
    VERIFY_REGION(pSource1, stuff->source1, client, DixReadAccess);
    VERIFY_REGION(pSource2, stuff->source2, client, DixReadAccess);
    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);

    switch (stuff->xfixesReqType) {
    case X_XFixesUnionRegion:
        if (!RegionUnion(pDestination, pSource1, pSource2))
            return BadAlloc;
        break;
    case X_XFixesIntersectRegion:
        if (!RegionIntersect(pDestination, pSource1, pSource2))
            return BadAlloc;
        break;
    case X_XFixesSubtractRegion:
        if (!RegionSubtract(pDestination, pSource1, pSource2))
            return BadAlloc;
        break;
    }

    return Success;
}
Esempio n. 2
0
void
miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
{
    WindowPtr pChild;

    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
        if (pChild->drawable.depth == depth)
            RegionUnion(pReg, pReg, &pChild->borderClip);

        if (pChild->firstChild)
            miSegregateChildren(pChild, pReg, depth);
    }
}
Esempio n. 3
0
static void
shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
    ScreenPtr pScreen = closure;
    shadowBufPtr pBuf = (shadowBufPtr)
        dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey);

    /* Register the damaged region, use DamageReportNone below when we
     * want to break BC below... */
    RegionUnion(&pDamage->damage, &pDamage->damage, pRegion);

    /*
     * BC hack.  In 7.0 and earlier several drivers would inspect the
     * 'damage' member directly, so we have to keep it existing.
     */
    RegionCopy(&pBuf->damage, pRegion);
}
Esempio n. 4
0
int
ProcXFixesExpandRegion (ClientPtr client)
{
    RegionPtr	pSource, pDestination;
    REQUEST (xXFixesExpandRegionReq);
    BoxPtr	pTmp;
    BoxPtr	pSrc;
    int		nBoxes;
    int		i;

    REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
    
    nBoxes = RegionNumRects(pSource);
    pSrc = RegionRects(pSource);
    if (nBoxes)
    {
	pTmp = malloc(nBoxes * sizeof (BoxRec));
	if (!pTmp)
	    return BadAlloc;
	for (i = 0; i < nBoxes; i++)
	{
	    pTmp[i].x1 = pSrc[i].x1 - stuff->left;
	    pTmp[i].x2 = pSrc[i].x2 + stuff->right;
	    pTmp[i].y1 = pSrc[i].y1 - stuff->top;
	    pTmp[i].y2 = pSrc[i].y2 + stuff->bottom;
	}
	RegionEmpty(pDestination);
	for (i = 0; i < nBoxes; i++)
	{
	    RegionRec	r;
	    RegionInit(&r, &pTmp[i], 0);
	    RegionUnion(pDestination, pDestination, &r);
	}
	free(pTmp);
    }
    return Success;
}
Esempio n. 5
0
static void
ExaSrcValidate(DrawablePtr pDrawable,
               int x, int y, int width, int height, unsigned int subWindowMode)
{
    ScreenPtr pScreen = pDrawable->pScreen;

    ExaScreenPriv(pScreen);
    PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);
    BoxRec box;
    RegionRec reg;
    RegionPtr dst;
    int xoff, yoff;

    if (pExaScr->srcPix == pPix)
        dst = &pExaScr->srcReg;
    else if (pExaScr->maskPix == pPix)
        dst = &pExaScr->maskReg;
    else
        return;

    exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);

    box.x1 = x + xoff;
    box.y1 = y + yoff;
    box.x2 = box.x1 + width;
    box.y2 = box.y1 + height;

    RegionInit(&reg, &box, 1);
    RegionUnion(dst, dst, &reg);
    RegionUninit(&reg);

    if (pExaScr->SavedSourceValidate) {
        swap(pExaScr, pScreen, SourceValidate);
        pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
        swap(pExaScr, pScreen, SourceValidate);
    }
}
Esempio n. 6
0
static void
localFreeOffscreenArea(FBAreaPtr area)
{
    FBManagerPtr offman;
    FBLinkPtr pLink, pLinkPrev = NULL;
    RegionRec FreedRegion;
    ScreenPtr pScreen;

    pScreen = area->pScreen;
    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);
    pLink = offman->UsedAreas;
    if (!pLink)
        return;

    while (&(pLink->area) != area) {
        pLinkPrev = pLink;
        pLink = pLink->next;
        if (!pLink)
            return;
    }

    /* put the area back into the pool */
    RegionInit(&FreedRegion, &(pLink->area.box), 1);
    RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedRegion);
    RegionUninit(&FreedRegion);

    if (pLinkPrev)
        pLinkPrev->next = pLink->next;
    else
        offman->UsedAreas = pLink->next;

    free(pLink);
    offman->NumUsedAreas--;

    SendCallFreeBoxCallbacks(offman);
}
Esempio n. 7
0
static Bool
exaFillRegionSolid(DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
                   CARD32 planemask, CARD32 alu, Bool hasClientClip)
{
    ExaScreenPriv(pDrawable->pScreen);
    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);

    ExaPixmapPriv(pPixmap);
    int xoff, yoff;
    Bool ret = FALSE;

    exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
    RegionTranslate(pRegion, xoff, yoff);

    if (pExaScr->fallback_counter || pExaPixmap->accel_blocked)
        goto out;

    if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[1];

        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
                                                alu,
                                                hasClientClip) ? NULL : pRegion;

        exaDoMigration(pixmaps, 1, TRUE);
    }

    if (exaPixmapHasGpuCopy(pPixmap) &&
        (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) {
        int nbox;
        BoxPtr pBox;

        nbox = RegionNumRects(pRegion);
        pBox = RegionRects(pRegion);

        while (nbox--) {
            (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
                                     pBox->y2);
            pBox++;
        }
        (*pExaScr->info->DoneSolid) (pPixmap);
        exaMarkSync(pDrawable->pScreen);

        if (pExaPixmap->pDamage &&
            pExaPixmap->sys_ptr && pDrawable->type == DRAWABLE_PIXMAP &&
            pDrawable->width == 1 && pDrawable->height == 1 &&
            pDrawable->bitsPerPixel != 24) {
            RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);

            switch (pDrawable->bitsPerPixel) {
            case 32:
                *(CARD32 *) pExaPixmap->sys_ptr = pixel;
                break;
            case 16:
                *(CARD16 *) pExaPixmap->sys_ptr = pixel;
                break;
            case 8:
            case 4:
            case 1:
                *(CARD8 *) pExaPixmap->sys_ptr = pixel;
            }

            RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, pRegion);
            RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, pRegion);
            RegionSubtract(pending_damage, pending_damage, pRegion);
        }

        ret = TRUE;
    }

 out:
    RegionTranslate(pRegion, -xoff, -yoff);

    return ret;
}
Esempio n. 8
0
static Bool
localResizeOffscreenArea(FBAreaPtr resize, int w, int h)
{
    FBManagerPtr offman;
    ScreenPtr pScreen;
    BoxRec OrigArea;
    RegionRec FreedReg;
    FBAreaPtr area = NULL;
    FBLinkPtr pLink, newLink, pLinkPrev = NULL;

    pScreen = resize->pScreen;
    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);
    /* find this link */
    if (!(pLink = offman->UsedAreas))
        return FALSE;

    while (&(pLink->area) != resize) {
        pLinkPrev = pLink;
        pLink = pLink->next;
        if (!pLink)
            return FALSE;
    }

    OrigArea.x1 = resize->box.x1;
    OrigArea.x2 = resize->box.x2;
    OrigArea.y1 = resize->box.y1;
    OrigArea.y2 = resize->box.y2;

    /* if it's smaller, this is easy */

    if ((w <= (resize->box.x2 - resize->box.x1)) &&
        (h <= (resize->box.y2 - resize->box.y1))) {
        RegionRec NewReg;

        resize->box.x2 = resize->box.x1 + w;
        resize->box.y2 = resize->box.y1 + h;

        if ((resize->box.y2 == OrigArea.y2) && (resize->box.x2 == OrigArea.x2))
            return TRUE;

        RegionInit(&FreedReg, &OrigArea, 1);
        RegionInit(&NewReg, &(resize->box), 1);
        RegionSubtract(&FreedReg, &FreedReg, &NewReg);
        RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
        RegionUninit(&FreedReg);
        RegionUninit(&NewReg);

        SendCallFreeBoxCallbacks(offman);

        return TRUE;
    }

    /* otherwise we remove the old region */

    RegionInit(&FreedReg, &OrigArea, 1);
    RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &FreedReg);

    /* remove the old link */
    if (pLinkPrev)
        pLinkPrev->next = pLink->next;
    else
        offman->UsedAreas = pLink->next;

    /* and try to add a new one */

    if ((area = AllocateArea(offman, w, h, resize->granularity,
                             resize->MoveAreaCallback,
                             resize->RemoveAreaCallback,
                             resize->devPrivate.ptr))) {

        /* copy data over to our link and replace the new with old */
        memcpy(resize, area, sizeof(FBArea));

        pLinkPrev = NULL;
        newLink = offman->UsedAreas;

        while (&(newLink->area) != area) {
            pLinkPrev = newLink;
            newLink = newLink->next;
        }

        if (pLinkPrev)
            pLinkPrev->next = newLink->next;
        else
            offman->UsedAreas = newLink->next;

        pLink->next = offman->UsedAreas;
        offman->UsedAreas = pLink;

        free(newLink);

        /* AllocateArea added one but we really only exchanged one */
        offman->NumUsedAreas--;
    }
    else {
        /* reinstate the old region */
        RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &FreedReg);
        RegionUninit(&FreedReg);

        pLink->next = offman->UsedAreas;
        offman->UsedAreas = pLink;
        return FALSE;
    }

    RegionUninit(&FreedReg);

    SendCallFreeBoxCallbacks(offman);

    return TRUE;
}
Esempio n. 9
0
static FBAreaPtr
AllocateArea(FBManagerPtr offman,
             int w, int h,
             int granularity,
             MoveAreaCallbackProcPtr moveCB,
             RemoveAreaCallbackProcPtr removeCB, void *privData)
{
    ScreenPtr pScreen = offman->pScreen;
    FBLinkPtr link = NULL;
    FBAreaPtr area = NULL;
    RegionRec NewReg;
    int i, x = 0, num;
    BoxPtr boxp;

    if (granularity <= 1)
        granularity = 0;

    boxp = RegionRects(offman->FreeBoxes);
    num = RegionNumRects(offman->FreeBoxes);

    /* look through the free boxes */
    for (i = 0; i < num; i++, boxp++) {
        x = boxp->x1;
        if (granularity > 1)
            x = ((x + granularity - 1) / granularity) * granularity;

        if (((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w))
            continue;

        link = malloc(sizeof(FBLink));
        if (!link)
            return NULL;

        area = &(link->area);
        link->next = offman->UsedAreas;
        offman->UsedAreas = link;
        offman->NumUsedAreas++;
        break;
    }

    /* try to boot a removeable one out if we are not expendable ourselves */
    if (!area && !removeCB) {
        link = offman->UsedAreas;

        while (link) {
            if (!link->area.RemoveAreaCallback) {
                link = link->next;
                continue;
            }

            boxp = &(link->area.box);
            x = boxp->x1;
            if (granularity > 1)
                x = ((x + granularity - 1) / granularity) * granularity;

            if (((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) {
                link = link->next;
                continue;
            }

            /* bye, bye */
            (*link->area.RemoveAreaCallback) (&link->area);
            RegionInit(&NewReg, &(link->area.box), 1);
            RegionUnion(offman->FreeBoxes, offman->FreeBoxes, &NewReg);
            RegionUninit(&NewReg);

            area = &(link->area);
            break;
        }
    }

    if (area) {
        area->pScreen = pScreen;
        area->granularity = granularity;
        area->box.x1 = x;
        area->box.x2 = x + w;
        area->box.y1 = boxp->y1;
        area->box.y2 = boxp->y1 + h;
        area->MoveAreaCallback = moveCB;
        area->RemoveAreaCallback = removeCB;
        area->devPrivate.ptr = privData;

        RegionInit(&NewReg, &(area->box), 1);
        RegionSubtract(offman->FreeBoxes, offman->FreeBoxes, &NewReg);
        RegionUninit(&NewReg);
    }

    return area;
}
/**
 * If the pixmap is currently dirty, this copies at least the dirty area from
 * FB to system or vice versa.  Both areas must be allocated.
 */
static void
exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
             Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
                               char *sys, int sys_pitch), int fallback_index,
             void (*sync) (ScreenPtr pScreen))
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaPixmapPriv(pPixmap);
    RegionPtr damage = DamageRegion(pExaPixmap->pDamage);
    RegionRec CopyReg;
    Bool save_use_gpu_copy;
    int save_pitch;
    BoxPtr pBox;
    int nbox;
    Bool access_prepared = FALSE;
    Bool need_sync = FALSE;

    /* Damaged bits are valid in current copy but invalid in other one */
    if (pExaPixmap->use_gpu_copy) {
        RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
        RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
    }
    else {
        RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
        RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
    }

    RegionEmpty(damage);

    /* Copy bits valid in source but not in destination */
    RegionNull(&CopyReg);
    RegionSubtract(&CopyReg, pValidSrc, pValidDst);

    if (migrate->as_dst) {
        ExaScreenPriv(pPixmap->drawable.pScreen);

        /* XXX: The pending damage region will be marked as damaged after the
         * operation, so it should serve as an upper bound for the region that
         * needs to be synchronized for the operation. Unfortunately, this
         * causes corruption in some cases, e.g. when starting compiz. See
         * https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
         */
        if (pExaScr->optimize_migration) {
            RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);

#if DEBUG_MIGRATE
            if (RegionNil(pending_damage)) {
                static Bool firsttime = TRUE;

                if (firsttime) {
                    ErrorF("%s: Pending damage region empty!\n", __func__);
                    firsttime = FALSE;
                }
            }
#endif

            /* Try to prevent destination valid region from growing too many
             * rects by filling it up to the extents of the union of the
             * destination valid region and the pending damage region.
             */
            if (RegionNumRects(pValidDst) > 10) {
                BoxRec box;
                BoxPtr pValidExt, pDamageExt;
                RegionRec closure;

                pValidExt = RegionExtents(pValidDst);
                pDamageExt = RegionExtents(pending_damage);

                box.x1 = min(pValidExt->x1, pDamageExt->x1);
                box.y1 = min(pValidExt->y1, pDamageExt->y1);
                box.x2 = max(pValidExt->x2, pDamageExt->x2);
                box.y2 = max(pValidExt->y2, pDamageExt->y2);

                RegionInit(&closure, &box, 0);
                RegionIntersect(&CopyReg, &CopyReg, &closure);
            }
            else
                RegionIntersect(&CopyReg, &CopyReg, pending_damage);
        }

        /* The caller may provide a region to be subtracted from the calculated
         * dirty region. This is to avoid migration of bits that don't
         * contribute to the result of the operation.
         */
        if (migrate->pReg)
            RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
    }
    else {
        /* The caller may restrict the region to be migrated for source pixmaps
         * to what's relevant for the operation.
         */
        if (migrate->pReg)
            RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
    }

    pBox = RegionRects(&CopyReg);
    nbox = RegionNumRects(&CopyReg);

    save_use_gpu_copy = pExaPixmap->use_gpu_copy;
    save_pitch = pPixmap->devKind;
    pExaPixmap->use_gpu_copy = TRUE;
    pPixmap->devKind = pExaPixmap->fb_pitch;

    while (nbox--) {
        pBox->x1 = max(pBox->x1, 0);
        pBox->y1 = max(pBox->y1, 0);
        pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
        pBox->y2 = min(pBox->y2, pPixmap->drawable.height);

        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
            continue;

        if (!transfer || !transfer(pPixmap,
                                   pBox->x1, pBox->y1,
                                   pBox->x2 - pBox->x1,
                                   pBox->y2 - pBox->y1,
                                   (char *) (pExaPixmap->sys_ptr
                                             + pBox->y1 * pExaPixmap->sys_pitch
                                             +
                                             pBox->x1 *
                                             pPixmap->drawable.bitsPerPixel /
                                             8), pExaPixmap->sys_pitch)) {
            if (!access_prepared) {
                ExaDoPrepareAccess(pPixmap, fallback_index);
                access_prepared = TRUE;
            }
            if (fallback_index == EXA_PREPARE_DEST) {
                exaMemcpyBox(pPixmap, pBox,
                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
                             pPixmap->devPrivate.ptr, pPixmap->devKind);
            }
            else {
                exaMemcpyBox(pPixmap, pBox,
                             pPixmap->devPrivate.ptr, pPixmap->devKind,
                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
            }
        }
        else
            need_sync = TRUE;

        pBox++;
    }

    pExaPixmap->use_gpu_copy = save_use_gpu_copy;
    pPixmap->devKind = save_pitch;

    /* Try to prevent source valid region from growing too many rects by
     * removing parts of it which are also in the destination valid region.
     * Removing anything beyond that would lead to data loss.
     */
    if (RegionNumRects(pValidSrc) > 20)
        RegionSubtract(pValidSrc, pValidSrc, pValidDst);

    /* The copied bits are now valid in destination */
    RegionUnion(pValidDst, pValidDst, &CopyReg);

    RegionUninit(&CopyReg);

    if (access_prepared)
        exaFinishAccess(&pPixmap->drawable, fallback_index);
    else if (need_sync && sync)
        sync(pPixmap->drawable.pScreen);
}
Esempio n. 11
0
/*ARGSUSED*/
int
miValidateTree (
    WindowPtr		pParent,    /* Parent to validate */
    WindowPtr		pChild,     /* First child of pParent that was
				     * affected */
    VTKind		kind        /* What kind of configuration caused call */
    )
{
    RegionRec	  	totalClip;  /* Total clipping region available to
				     * the marked children. pParent's clipList
				     * merged with the borderClips of all
				     * the marked children. */
    RegionRec	  	childClip;  /* The new borderClip for the current
				     * child */
    RegionRec		childUnion; /* the space covered by borderSize for
				     * all marked children */
    RegionRec		exposed;    /* For intermediate calculations */
    ScreenPtr		pScreen;
    WindowPtr		pWin;
    Bool		overlap;
    int			viewvals;
    Bool		forward;

    pScreen = pParent->drawable.pScreen;
    if (pChild == NullWindow)
	pChild = pParent->firstChild;

    RegionNull(&childClip);
    RegionNull(&exposed);

    /*
     * compute the area of the parent window occupied
     * by the marked children + the parent itself.  This
     * is the area which can be divied up among the marked
     * children in their new configuration.
     */
    RegionNull(&totalClip);
    viewvals = 0;
    if (RegionBroken(&pParent->clipList) &&
	!RegionBroken(&pParent->borderClip))
    {
	kind = VTBroken;
	/*
	 * When rebuilding clip lists after out of memory,
	 * assume everything is busted.
	 */
	forward = TRUE;
	RegionCopy(&totalClip, &pParent->borderClip);
	RegionIntersect(&totalClip, &totalClip, &pParent->winSize);
	
	for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib)
	{
	    if (pWin->viewable && !TreatAsTransparent (pWin))
		RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
	}
	for (pWin = pChild; pWin; pWin = pWin->nextSib)
	    if (pWin->valdata && pWin->viewable)
		viewvals++;
	
	RegionEmpty(&pParent->clipList);
    }
    else 
    {
	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
	{
	    forward = TRUE;
	    for (pWin = pChild; pWin; pWin = pWin->nextSib)
	    {
		if (pWin->valdata)
		{
		    RegionPtr	pBorderClip = &pWin->borderClip;
#ifdef COMPOSITE
		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
#endif
		    RegionAppend(&totalClip, pBorderClip );
		    if (pWin->viewable)
			viewvals++;
		}
	    }
	}
	else
	{
	    forward = FALSE;
	    pWin = pParent->lastChild;
	    while (1)
	    {
		if (pWin->valdata)
		{
		    RegionPtr	pBorderClip = &pWin->borderClip;
#ifdef COMPOSITE
		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
#endif
		    RegionAppend(&totalClip, pBorderClip );
		    if (pWin->viewable)
			viewvals++;
		}
		if (pWin == pChild)
		    break;
		pWin = pWin->prevSib;
	    }
	}
	RegionValidate(&totalClip, &overlap);
    }

    /*
     * Now go through the children of the root and figure their new
     * borderClips from the totalClip, passing that off to miComputeClips
     * to handle recursively. Once that's done, we remove the child
     * from the totalClip to clip any siblings below it.
     */

    overlap = TRUE;
    if (kind != VTStack)
    {
	RegionUnion(&totalClip, &totalClip, &pParent->clipList);
	if (viewvals > 1)
	{
	    /*
	     * precompute childUnion to discover whether any of them
	     * overlap.  This seems redundant, but performance studies
	     * have demonstrated that the cost of this loop is
	     * lower than the cost of multiple Subtracts in the
	     * loop below.
	     */
	    RegionNull(&childUnion);
	    if (forward)
	    {
		for (pWin = pChild; pWin; pWin = pWin->nextSib)
		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
			RegionAppend(&childUnion,
						   &pWin->borderSize);
	    }
	    else
	    {
		pWin = pParent->lastChild;
		while (1)
		{
		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
			RegionAppend(&childUnion,
						   &pWin->borderSize);
		    if (pWin == pChild)
			break;
		    pWin = pWin->prevSib;
		}
	    }
	    RegionValidate(&childUnion, &overlap);
	    if (overlap)
		RegionUninit(&childUnion);
	}
    }

    for (pWin = pChild;
	 pWin != NullWindow;
	 pWin = pWin->nextSib)
    {
	if (pWin->viewable) {
	    if (pWin->valdata) {
		RegionIntersect(&childClip,
					&totalClip,
 					&pWin->borderSize);
		miComputeClips (pWin, pScreen, &childClip, kind, &exposed);
		if (overlap && !TreatAsTransparent (pWin))
		{
		    RegionSubtract(&totalClip,
				       	   &totalClip,
				       	   &pWin->borderSize);
		}
	    } else if (pWin->visibility == VisibilityNotViewable) {
		miTreeObscured(pWin);
	    }
	} else {
	    if (pWin->valdata) {
		RegionEmpty(&pWin->clipList);
		if (pScreen->ClipNotify)
		    (* pScreen->ClipNotify) (pWin, 0, 0);
		RegionEmpty(&pWin->borderClip);
		pWin->valdata = NULL;
	    }
	}
    }

    RegionUninit(&childClip);
    if (!overlap)
    {
	RegionSubtract(&totalClip, &totalClip, &childUnion);
	RegionUninit(&childUnion);
    }

    RegionNull(&pParent->valdata->after.exposed);
    RegionNull(&pParent->valdata->after.borderExposed);

    /*
     * each case below is responsible for updating the
     * clipList and serial number for the parent window
     */

    switch (kind) {
    case VTStack:
	break;
    default:
	/*
	 * totalClip contains the new clipList for the parent. Figure out
	 * exposures and obscures as per miComputeClips and reset the parent's
	 * clipList.
	 */
	RegionSubtract(&pParent->valdata->after.exposed,
			       &totalClip, &pParent->clipList);
	/* fall through */
    case VTMap:
	RegionCopy(&pParent->clipList, &totalClip);
	pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
	break;
    }

    RegionUninit(&totalClip);
    RegionUninit(&exposed);
    if (pScreen->ClipNotify)
	(*pScreen->ClipNotify) (pParent, 0, 0);
    return 1;
}
Esempio n. 12
0
static int
RegionOperate(ClientPtr client,
              WindowPtr pWin,
              int kind,
              RegionPtr *destRgnp,
              RegionPtr srcRgn, int op, int xoff, int yoff, CreateDftPtr create)
{
    if (srcRgn && (xoff || yoff))
        RegionTranslate(srcRgn, xoff, yoff);
    if (!pWin->parent) {
        if (srcRgn)
            RegionDestroy(srcRgn);
        return Success;
    }

    /* May/30/2001:
     * The shape.PS specs say if src is None, existing shape is to be
     * removed (and so the op-code has no meaning in such removal);
     * see shape.PS, page 3, ShapeMask.
     */
    if (srcRgn == NULL) {
        if (*destRgnp != NULL) {
            RegionDestroy(*destRgnp);
            *destRgnp = 0;
            /* go on to remove shape and generate ShapeNotify */
        }
        else {
            /* May/30/2001:
             * The target currently has no shape in effect, so nothing to
             * do here.  The specs say that ShapeNotify is generated whenever
             * the client region is "modified"; since no modification is done
             * here, we do not generate that event.  The specs does not say
             * "it is an error to request removal when there is no shape in
             * effect", so we return good status.
             */
            return Success;
        }
    }
    else
        switch (op) {
        case ShapeSet:
            if (*destRgnp)
                RegionDestroy(*destRgnp);
            *destRgnp = srcRgn;
            srcRgn = 0;
            break;
        case ShapeUnion:
            if (*destRgnp)
                RegionUnion(*destRgnp, *destRgnp, srcRgn);
            break;
        case ShapeIntersect:
            if (*destRgnp)
                RegionIntersect(*destRgnp, *destRgnp, srcRgn);
            else {
                *destRgnp = srcRgn;
                srcRgn = 0;
            }
            break;
        case ShapeSubtract:
            if (!*destRgnp)
                *destRgnp = (*create) (pWin);
            RegionSubtract(*destRgnp, *destRgnp, srcRgn);
            break;
        case ShapeInvert:
            if (!*destRgnp)
                *destRgnp = RegionCreate((BoxPtr) 0, 0);
            else
                RegionSubtract(*destRgnp, srcRgn, *destRgnp);
            break;
        default:
            client->errorValue = op;
            return BadValue;
        }
    if (srcRgn)
        RegionDestroy(srcRgn);
    (*pWin->drawable.pScreen->SetShape) (pWin, kind);
    SendShapeNotify(pWin, kind);
    return Success;
}
Esempio n. 13
0
void
miSlideAndSizeWindow(WindowPtr pWin,
                     int x, int y,
                     unsigned int w, unsigned int h, WindowPtr pSib)
{
    WindowPtr pParent;
    Bool WasViewable = (Bool) (pWin->viewable);
    unsigned short width = pWin->drawable.width, height = pWin->drawable.height;
    short oldx = pWin->drawable.x, oldy = pWin->drawable.y;
    int bw = wBorderWidth(pWin);
    short dw, dh;
    DDXPointRec oldpt;
    RegionPtr oldRegion = NULL;
    Bool anyMarked = FALSE;
    ScreenPtr pScreen;
    WindowPtr pFirstChange;
    WindowPtr pChild;
    RegionPtr gravitate[StaticGravity + 1];
    unsigned g;
    int nx, ny;                 /* destination x,y */
    int newx, newy;             /* new inner window position */
    RegionPtr pRegion = NULL;
    RegionPtr destClip;         /* portions of destination already written */
    RegionPtr oldWinClip = NULL;        /* old clip list for window */
    RegionPtr borderVisible = NullRegion;       /* visible area of the border */
    Bool shrunk = FALSE;        /* shrunk in an inner dimension */
    Bool moved = FALSE;         /* window position changed */
    WindowPtr pLayerWin;

    /* if this is a root window, can't be resized */
    if (!(pParent = pWin->parent))
        return;

    pScreen = pWin->drawable.pScreen;
    newx = pParent->drawable.x + x + bw;
    newy = pParent->drawable.y + y + bw;
    if (WasViewable) {
        anyMarked = FALSE;
        /*
         * save the visible region of the window
         */
        oldRegion = RegionCreate(NullBox, 1);
        RegionCopy(oldRegion, &pWin->winSize);

        /*
         * categorize child windows into regions to be moved
         */
        for (g = 0; g <= StaticGravity; g++)
            gravitate[g] = (RegionPtr) NULL;
        for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
            g = pChild->winGravity;
            if (g != UnmapGravity) {
                if (!gravitate[g])
                    gravitate[g] = RegionCreate(NullBox, 1);
                RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip);
            }
            else {
                UnmapWindow(pChild, TRUE);
                anyMarked = TRUE;
            }
        }
        anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);

        oldWinClip = NULL;
        if (pWin->bitGravity != ForgetGravity) {
            oldWinClip = RegionCreate(NullBox, 1);
            RegionCopy(oldWinClip, &pWin->clipList);
        }
        /*
         * if the window is changing size, borderExposed
         * can't be computed correctly without some help.
         */
        if (pWin->drawable.height > h || pWin->drawable.width > w)
            shrunk = TRUE;

        if (newx != oldx || newy != oldy)
            moved = TRUE;

        if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
            HasBorder(pWin)) {
            borderVisible = RegionCreate(NullBox, 1);
            /* for tiled borders, we punt and draw the whole thing */
            if (pWin->borderIsPixel || !moved) {
                if (shrunk || moved)
                    RegionSubtract(borderVisible,
                                   &pWin->borderClip, &pWin->winSize);
                else
                    RegionCopy(borderVisible, &pWin->borderClip);
            }
        }
    }
    pWin->origin.x = x + bw;
    pWin->origin.y = y + bw;
    pWin->drawable.height = h;
    pWin->drawable.width = w;

    x = pWin->drawable.x = newx;
    y = pWin->drawable.y = newy;

    SetWinSize(pWin);
    SetBorderSize(pWin);

    dw = (int) w - (int) width;
    dh = (int) h - (int) height;
    ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);

    /* let the hardware adjust background and border pixmaps, if any */
    (*pScreen->PositionWindow) (pWin, x, y);

    pFirstChange = MoveWindowInStack(pWin, pSib);

    if (WasViewable) {
        pRegion = RegionCreate(NullBox, 1);

        if (pLayerWin == pWin)
            anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange,
                                                            NULL);
        else
            anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin,
                                                            NULL);

        if (pWin->valdata) {
            pWin->valdata->before.resized = TRUE;
            pWin->valdata->before.borderVisible = borderVisible;
        }

        if (anyMarked)
            (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, VTOther);
        /*
         * the entire window is trashed unless bitGravity
         * recovers portions of it
         */
        RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
    }

    GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);

    if (WasViewable) {
        /* avoid the border */
        if (HasBorder(pWin)) {
            int offx, offy, dx, dy;

            /* kruft to avoid double translates for each gravity */
            offx = 0;
            offy = 0;
            for (g = 0; g <= StaticGravity; g++) {
                if (!gravitate[g])
                    continue;

                /* align winSize to gravitate[g].
                 * winSize is in new coordinates,
                 * gravitate[g] is still in old coordinates */
                GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);

                dx = (oldx - nx) - offx;
                dy = (oldy - ny) - offy;
                if (dx || dy) {
                    RegionTranslate(&pWin->winSize, dx, dy);
                    offx += dx;
                    offy += dy;
                }
                RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize);
            }
            /* get winSize back where it belongs */
            if (offx || offy)
                RegionTranslate(&pWin->winSize, -offx, -offy);
        }
        /*
         * add screen bits to the appropriate bucket
         */

        if (oldWinClip) {
            /*
             * clip to new clipList
             */
            RegionCopy(pRegion, oldWinClip);
            RegionTranslate(pRegion, nx - oldx, ny - oldy);
            RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
            /*
             * don't step on any gravity bits which will be copied after this
             * region.  Note -- this assumes that the regions will be copied
             * in gravity order.
             */
            for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
                if (gravitate[g])
                    RegionSubtract(oldWinClip, oldWinClip, gravitate[g]);
            }
            RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
            g = pWin->bitGravity;
            if (!gravitate[g])
                gravitate[g] = oldWinClip;
            else {
                RegionUnion(gravitate[g], gravitate[g], oldWinClip);
                RegionDestroy(oldWinClip);
            }
        }

        /*
         * move the bits on the screen
         */

        destClip = NULL;

        for (g = 0; g <= StaticGravity; g++) {
            if (!gravitate[g])
                continue;

            GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);

            oldpt.x = oldx + (x - nx);
            oldpt.y = oldy + (y - ny);

            /* Note that gravitate[g] is *translated* by CopyWindow */

            /* only copy the remaining useful bits */

            RegionIntersect(gravitate[g], gravitate[g], oldRegion);

            /* clip to not overwrite already copied areas */

            if (destClip) {
                RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
                RegionSubtract(gravitate[g], gravitate[g], destClip);
                RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
            }

            /* and move those bits */

            if (oldpt.x != x || oldpt.y != y
#ifdef COMPOSITE
                || pWin->redirectDraw
#endif
                ) {
                (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt,
                                                       gravitate[g]);
            }

            /* remove any overwritten bits from the remaining useful bits */

            RegionSubtract(oldRegion, oldRegion, gravitate[g]);

            /*
             * recompute exposed regions of child windows
             */

            for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
                if (pChild->winGravity != g)
                    continue;
                RegionIntersect(pRegion, &pChild->borderClip, gravitate[g]);
                TraverseTree(pChild, miRecomputeExposures, (void *) pRegion);
            }

            /*
             * remove the successfully copied regions of the
             * window from its exposed region
             */

            if (g == pWin->bitGravity)
                RegionSubtract(&pWin->valdata->after.exposed,
                               &pWin->valdata->after.exposed, gravitate[g]);
            if (!destClip)
                destClip = gravitate[g];
            else {
                RegionUnion(destClip, destClip, gravitate[g]);
                RegionDestroy(gravitate[g]);
            }
        }

        RegionDestroy(oldRegion);
        RegionDestroy(pRegion);
        if (destClip)
            RegionDestroy(destClip);
        if (anyMarked)
            (*pScreen->HandleExposures) (pLayerWin->parent);
        if (anyMarked && pScreen->PostValidateTree)
            (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange,
                                          VTOther);
    }
    if (pWin->realized)
        WindowsRestructured();
}
Esempio n. 14
0
void
miWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
{
    RegionPtr exposures = prgn;

    if ((prgn && !RegionNil(prgn)) ||
        (exposures && !RegionNil(exposures)) || other_exposed) {
        RegionRec expRec;
        int clientInterested;

        /*
         * Restore from backing-store FIRST.
         */
        clientInterested =
            (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask;
        if (other_exposed) {
            if (exposures) {
                RegionUnion(other_exposed, exposures, other_exposed);
                if (exposures != prgn)
                    RegionDestroy(exposures);
            }
            exposures = other_exposed;
        }
        if (clientInterested && exposures &&
            (RegionNumRects(exposures) > RECTLIMIT)) {
            /*
             * If we have LOTS of rectangles, we decide to take the extents
             * and force an exposure on that.  This should require much less
             * work overall, on both client and server.  This is cheating, but
             * isn't prohibited by the protocol ("spontaneous combustion" :-).
             */
            BoxRec box;

            box = *RegionExtents(exposures);
            if (exposures == prgn) {
                exposures = &expRec;
                RegionInit(exposures, &box, 1);
                RegionReset(prgn, &box);
            }
            else {
                RegionReset(exposures, &box);
                RegionUnion(prgn, prgn, exposures);
            }
            /* miPaintWindow doesn't clip, so we have to */
            RegionIntersect(prgn, prgn, &pWin->clipList);
        }
        if (prgn && !RegionNil(prgn))
            miPaintWindow(pWin, prgn, PW_BACKGROUND);
        if (clientInterested && exposures && !RegionNil(exposures))
            miSendExposures(pWin, exposures,
                            pWin->drawable.x, pWin->drawable.y);
        if (exposures == &expRec) {
            RegionUninit(exposures);
        }
        else if (exposures && exposures != prgn && exposures != other_exposed)
            RegionDestroy(exposures);
        if (prgn)
            RegionEmpty(prgn);
    }
    else if (exposures && exposures != prgn)
        RegionDestroy(exposures);
}
Esempio n. 15
0
int
draw_item_pack(PixmapPtr pix, rdpPixmapRec *priv)
{
    struct rdp_draw_item *di;
    struct rdp_draw_item *di_prev;

#if 1

    /* look for repeating draw types */
    if (priv->draw_item_head != 0)
    {
        if (priv->draw_item_head->next != 0)
        {
            di_prev = priv->draw_item_head;
            di = priv->draw_item_head->next;

            while (di != 0)
            {
                if ((di_prev->type == RDI_IMGLL) && (di->type == RDI_IMGLL))
                {
                    LLOGLN(10, ("draw_item_pack: packing RDI_IMGLL"));
                    RegionUnion(di_prev->reg, di_prev->reg, di->reg);
                    draw_item_remove(priv, di);
                    di = di_prev->next;
                }
                else if ((di_prev->type == RDI_IMGLY) && (di->type == RDI_IMGLY))
                {
                    LLOGLN(10, ("draw_item_pack: packing RDI_IMGLY"));
                    RegionUnion(di_prev->reg, di_prev->reg, di->reg);
                    draw_item_remove(priv, di);
                    di = di_prev->next;
                }
                else
                {
                    di_prev = di;
                    di = di_prev->next;
                }
            }
        }
    }

#endif
#if 1

    /* subtract regions */
    if (priv->draw_item_tail != 0)
    {
        if (priv->draw_item_tail->prev != 0)
        {
            di = priv->draw_item_tail;

            while (di->prev != 0)
            {
                /* skip subtract flag
                 * draw items like line can't be used to clear(subtract) previous
                 * draw items since they are not opaque
                 * eg they can not be the 'S' in 'D = M - S'
                 * the region for line draw items is the clip region */
                if ((di->flags & 1) == 0)
                {
                    di_prev = di->prev;

                    while (di_prev != 0)
                    {
                        /* D = M - S */
                        RegionSubtract(di_prev->reg, di_prev->reg, di->reg);
                        di_prev = di_prev->prev;
                    }
                }

                di = di->prev;
            }
        }
    }

#endif
#if 1
    /* remove draw items with empty regions */
    di = priv->draw_item_head;
    di_prev = 0;

    while (di != 0)
    {
        if (!RegionNotEmpty(di->reg))
        {
            LLOGLN(10, ("draw_item_pack: removing empty item type %d", di->type));
            draw_item_remove(priv, di);
            di = di_prev == 0 ? priv->draw_item_head : di_prev->next;
        }
        else
        {
            di_prev = di;
            di = di->next;
        }
    }

#endif
    return 0;
}