Example #1
0
static int
miRecomputeExposures(WindowPtr pWin, void *value)
{                               /* must conform to VisitWindowProcPtr */
    RegionPtr pValid = (RegionPtr) value;

    if (pWin->valdata) {
#ifdef COMPOSITE
        /*
         * Redirected windows are not affected by parent window
         * gravity manipulations, so don't recompute their
         * exposed areas here.
         */
        if (pWin->redirectDraw != RedirectDrawNone)
            return WT_DONTWALKCHILDREN;
#endif
        /*
         * compute exposed regions of this window
         */
        RegionSubtract(&pWin->valdata->after.exposed, &pWin->clipList, pValid);
        /*
         * compute exposed regions of the border
         */
        RegionSubtract(&pWin->valdata->after.borderExposed,
                       &pWin->borderClip, &pWin->winSize);
        RegionSubtract(&pWin->valdata->after.borderExposed,
                       &pWin->valdata->after.borderExposed, pValid);
        return WT_WALKCHILDREN;
    }
    return WT_NOMATCH;
}
Example #2
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;
}
Example #3
0
void
miChangeBorderWidth(WindowPtr pWin, unsigned int width)
{
    int oldwidth;
    Bool anyMarked = FALSE;
    ScreenPtr pScreen;
    Bool WasViewable = (Bool) (pWin->viewable);
    Bool HadBorder;
    WindowPtr pLayerWin;

    oldwidth = wBorderWidth(pWin);
    if (oldwidth == width)
        return;
    HadBorder = HasBorder(pWin);
    pScreen = pWin->drawable.pScreen;
    if (WasViewable && width < oldwidth)
        anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);

    pWin->borderWidth = width;
    SetBorderSize(pWin);

    if (WasViewable) {
        if (width > oldwidth) {
            anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
                                                           &pLayerWin);
            /*
             * save the old border visible region to correctly compute
             * borderExposed.
             */
            if (pWin->valdata && HadBorder) {
                RegionPtr borderVisible;

                borderVisible = RegionCreate(NULL, 1);
                RegionSubtract(borderVisible,
                               &pWin->borderClip, &pWin->winSize);
                pWin->valdata->before.borderVisible = borderVisible;
            }
        }

        if (anyMarked) {
            (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
            (*pScreen->HandleExposures) (pLayerWin->parent);
        }
        if (anyMarked && pScreen->PostValidateTree)
            (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin,
                                          VTOther);
    }
    if (pWin->realized)
        WindowsRestructured();
}
Example #4
0
void
miSetShape(WindowPtr pWin, int kind)
{
    Bool WasViewable = (Bool) (pWin->viewable);
    ScreenPtr pScreen = pWin->drawable.pScreen;
    Bool anyMarked = FALSE;
    WindowPtr pLayerWin;

    if (kind != ShapeInput) {
        if (WasViewable) {
            anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin,
                                                           &pLayerWin);
            if (pWin->valdata) {
                if (HasBorder(pWin)) {
                    RegionPtr borderVisible;

                    borderVisible = RegionCreate(NullBox, 1);
                    RegionSubtract(borderVisible,
                                   &pWin->borderClip, &pWin->winSize);
                    pWin->valdata->before.borderVisible = borderVisible;
                }
                pWin->valdata->before.resized = TRUE;
            }
        }

        SetWinSize(pWin);
        SetBorderSize(pWin);

        ResizeChildrenWinSize(pWin, 0, 0, 0, 0);

        if (WasViewable) {
            anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);

            if (anyMarked)
                (*pScreen->ValidateTree) (pLayerWin->parent, NullWindow,
                                          VTOther);
        }

        if (WasViewable) {
            if (anyMarked)
                (*pScreen->HandleExposures) (pLayerWin->parent);
            if (anyMarked && pScreen->PostValidateTree)
                (*pScreen->PostValidateTree) (pLayerWin->parent, NullWindow,
                                              VTOther);
        }
    }
    if (pWin->realized)
        WindowsRestructured();
    CheckCursorConfinement(pWin);
}
Example #5
0
Bool
xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    RegionRec ScreenRegion;
    RegionRec FullRegion;
    BoxRec ScreenBox;
    Bool ret;

    ScreenBox.x1 = 0;
    ScreenBox.y1 = 0;
    ScreenBox.x2 = pScrn->virtualX;
    ScreenBox.y2 = pScrn->virtualY;

    if ((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) ||
        (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) {
        return FALSE;
    }

    if (FullBox->y2 < FullBox->y1)
        return FALSE;
    if (FullBox->x2 < FullBox->x1)
        return FALSE;

    RegionInit(&ScreenRegion, &ScreenBox, 1);
    RegionInit(&FullRegion, FullBox, 1);

    RegionSubtract(&FullRegion, &FullRegion, &ScreenRegion);

    ret = xf86InitFBManagerRegion(pScreen, &FullRegion);

    RegionUninit(&ScreenRegion);
    RegionUninit(&FullRegion);

    return ret;
}
Example #6
0
static Bool
localQueryLargestOffscreenArea(ScreenPtr pScreen,
                               int *width, int *height,
                               int granularity, int preferences, int severity)
{
    FBManagerPtr offman;
    RegionPtr newRegion = NULL;
    BoxPtr pbox;
    int nbox;
    int x, w, h, area, oldArea;

    *width = *height = oldArea = 0;

    if (granularity <= 1)
        granularity = 0;

    if ((preferences < 0) || (preferences > 3))
        return FALSE;

    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);
    if (severity < 0)
        severity = 0;
    if (severity > 2)
        severity = 2;

    switch (severity) {
    case 2:
        if (offman->NumUsedAreas) {
            FBLinkPtr pLink;
            RegionRec tmpRegion;

            newRegion = RegionCreate(NULL, 1);
            RegionCopy(newRegion, offman->InitialBoxes);
            pLink = offman->UsedAreas;

            while (pLink) {
                if (!pLink->area.RemoveAreaCallback) {
                    RegionInit(&tmpRegion, &(pLink->area.box), 1);
                    RegionSubtract(newRegion, newRegion, &tmpRegion);
                    RegionUninit(&tmpRegion);
                }
                pLink = pLink->next;
            }

            nbox = RegionNumRects(newRegion);
            pbox = RegionRects(newRegion);
            break;
        }
    case 1:
        if (offman->NumUsedAreas) {
            FBLinkPtr pLink;
            RegionRec tmpRegion;

            newRegion = RegionCreate(NULL, 1);
            RegionCopy(newRegion, offman->FreeBoxes);
            pLink = offman->UsedAreas;

            while (pLink) {
                if (pLink->area.RemoveAreaCallback) {
                    RegionInit(&tmpRegion, &(pLink->area.box), 1);
                    RegionAppend(newRegion, &tmpRegion);
                    RegionUninit(&tmpRegion);
                }
                pLink = pLink->next;
            }

            nbox = RegionNumRects(newRegion);
            pbox = RegionRects(newRegion);
            break;
        }
    default:
        nbox = RegionNumRects(offman->FreeBoxes);
        pbox = RegionRects(offman->FreeBoxes);
        break;
    }

    while (nbox--) {
        x = pbox->x1;
        if (granularity > 1)
            x = ((x + granularity - 1) / granularity) * granularity;

        w = pbox->x2 - x;
        h = pbox->y2 - pbox->y1;
        area = w * h;

        if (w > 0) {
            Bool gotIt = FALSE;

            switch (preferences) {
            case FAVOR_AREA_THEN_WIDTH:
                if ((area > oldArea) || ((area == oldArea) && (w > *width)))
                    gotIt = TRUE;
                break;
            case FAVOR_AREA_THEN_HEIGHT:
                if ((area > oldArea) || ((area == oldArea) && (h > *height)))
                    gotIt = TRUE;
                break;
            case FAVOR_WIDTH_THEN_AREA:
                if ((w > *width) || ((w == *width) && (area > oldArea)))
                    gotIt = TRUE;
                break;
            case FAVOR_HEIGHT_THEN_AREA:
                if ((h > *height) || ((h == *height) && (area > oldArea)))
                    gotIt = TRUE;
                break;
            }
            if (gotIt) {
                *width = w;
                *height = h;
                oldArea = area;
            }
        }
        pbox++;
    }

    if (newRegion)
        RegionDestroy(newRegion);

    return TRUE;
}
Example #7
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;
}
Example #8
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;
}
Example #9
0
Bool
xf86InitFBManagerArea(ScreenPtr pScreen, int PixelArea, int Verbosity)
{
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    xRectangle Rect[3];
    RegionPtr pRegion, pScreenRegion;
    int nRect;
    Bool ret = FALSE;

    if (PixelArea < (pScrn->displayWidth * pScrn->virtualY))
        return FALSE;

    Rect[0].x = Rect[0].y = 0;
    Rect[0].width = pScrn->displayWidth;
    Rect[0].height = PixelArea / pScrn->displayWidth;
    nRect = 1;

    /* Add a possible partial scanline */
    if ((Rect[1].height = Rect[1].width = PixelArea % pScrn->displayWidth)) {
        Rect[1].x = 0;
        Rect[1].y = Rect[0].height;
        Rect[1].height = 1;
        nRect++;
    }

    /* Factor out virtual resolution */
    pRegion = RegionFromRects(nRect, Rect, 0);
    if (pRegion) {
        if (!RegionNar(pRegion)) {
            Rect[2].x = Rect[2].y = 0;
            Rect[2].width = pScrn->virtualX;
            Rect[2].height = pScrn->virtualY;

            pScreenRegion = RegionFromRects(1, &Rect[2], 0);
            if (pScreenRegion) {
                if (!RegionNar(pScreenRegion)) {
                    RegionSubtract(pRegion, pRegion, pScreenRegion);

                    ret = xf86InitFBManagerRegion(pScreen, pRegion);

                    if (ret && xf86GetVerbosity() >= Verbosity) {
                        int scrnIndex = pScrn->scrnIndex;

                        xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
                                       "Largest offscreen areas (with overlaps):\n");

                        if (Rect[2].width < Rect[0].width) {
                            xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
                                           "\t%d x %d rectangle at %d,0\n",
                                           Rect[0].width - Rect[2].width,
                                           Rect[0].height, Rect[2].width);
                        }
                        if (Rect[2].width < Rect[1].width) {
                            xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
                                           "\t%d x %d rectangle at %d,0\n",
                                           Rect[1].width - Rect[2].width,
                                           Rect[0].height + Rect[1].height,
                                           Rect[2].width);
                        }
                        if (Rect[2].height < Rect[0].height) {
                            xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
                                           "\t%d x %d rectangle at 0,%d\n",
                                           Rect[0].width,
                                           Rect[0].height - Rect[2].height,
                                           Rect[2].height);
                        }
                        if (Rect[1].height) {
                            xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity,
                                           "\t%d x %d rectangle at 0,%d\n",
                                           Rect[1].width,
                                           Rect[0].height - Rect[2].height +
                                           Rect[1].height, Rect[2].height);
                        }
                    }
                }

                RegionDestroy(pScreenRegion);
            }
        }

        RegionDestroy(pRegion);
    }

    return ret;
}
/**
 * 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);
}
Example #11
0
/*
 *-----------------------------------------------------------------------
 * miComputeClips --
 *	Recompute the clipList, borderClip, exposed and borderExposed
 *	regions for pParent and its children. Only viewable windows are
 *	taken into account.
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	clipList, borderClip, exposed and borderExposed are altered.
 *	A VisibilityNotify event may be generated on the parent window.
 *
 *-----------------------------------------------------------------------
 */
static void
miComputeClips (
    WindowPtr	pParent,
    ScreenPtr	pScreen,
    RegionPtr	universe,
    VTKind		kind,
    RegionPtr		exposed ) /* for intermediate calculations */
{
    int			dx,
			dy;
    RegionRec		childUniverse;
    WindowPtr		pChild;
    int     	  	oldVis, newVis;
    BoxRec		borderSize;
    RegionRec		childUnion;
    Bool		overlap;
    RegionPtr		borderVisible;
    /*
     * Figure out the new visibility of this window.
     * The extent of the universe should be the same as the extent of
     * the borderSize region. If the window is unobscured, this rectangle
     * will be completely inside the universe (the universe will cover it
     * completely). If the window is completely obscured, none of the
     * universe will cover the rectangle.
     */
    borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
    borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
    dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
    if (dx > 32767)
	dx = 32767;
    borderSize.x2 = dx;
    dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
    if (dy > 32767)
	dy = 32767;
    borderSize.y2 = dy;

#ifdef COMPOSITE
    /*
     * In redirected drawing case, reset universe to borderSize
     */
    if (pParent->redirectDraw != RedirectDrawNone)
    {
	if (miSetRedirectBorderClipProc)
	{
	    if (TreatAsTransparent (pParent))
		RegionEmpty(universe);
	    (*miSetRedirectBorderClipProc) (pParent, universe);
	}
	RegionCopy(universe, &pParent->borderSize);
    }
#endif

    oldVis = pParent->visibility;
    switch (RegionContainsRect(universe, &borderSize))
    {
	case rgnIN:
	    newVis = VisibilityUnobscured;
	    break;
	case rgnPART:
	    newVis = VisibilityPartiallyObscured;
	    {
		RegionPtr   pBounding;

		if ((pBounding = wBoundingShape (pParent)))
		{
		    switch (miShapedWindowIn (universe, pBounding,
					      &borderSize,
					      pParent->drawable.x,
 					      pParent->drawable.y))
		    {
		    case rgnIN:
			newVis = VisibilityUnobscured;
			break;
		    case rgnOUT:
			newVis = VisibilityFullyObscured;
			break;
		    }
		}
	    }
	    break;
	default:
	    newVis = VisibilityFullyObscured;
	    break;
    }
    pParent->visibility = newVis;
    if (oldVis != newVis &&
	((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
	SendVisibilityNotify(pParent);

    dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
    dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;

    /*
     * avoid computations when dealing with simple operations
     */

    switch (kind) {
    case VTMap:
    case VTStack:
    case VTUnmap:
	break;
    case VTMove:
	if ((oldVis == newVis) &&
	    ((oldVis == VisibilityFullyObscured) ||
	     (oldVis == VisibilityUnobscured)))
	{
	    pChild = pParent;
	    while (1)
	    {
		if (pChild->viewable)
		{
		    if (pChild->visibility != VisibilityFullyObscured)
		    {
			RegionTranslate(&pChild->borderClip,
						      dx, dy);
			RegionTranslate(&pChild->clipList,
						      dx, dy);
			pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
			if (pScreen->ClipNotify)
			    (* pScreen->ClipNotify) (pChild, dx, dy);

		    }
		    if (pChild->valdata)
		    {
			RegionNull(&pChild->valdata->after.borderExposed);
			if (HasParentRelativeBorder(pChild))
			{
			    RegionSubtract(&pChild->valdata->after.borderExposed,
					   &pChild->borderClip,
					   &pChild->winSize);
			}
			RegionNull(&pChild->valdata->after.exposed);
		    }
		    if (pChild->firstChild)
		    {
			pChild = pChild->firstChild;
			continue;
		    }
		}
		while (!pChild->nextSib && (pChild != pParent))
		    pChild = pChild->parent;
		if (pChild == pParent)
		    break;
		pChild = pChild->nextSib;
	    }
	    return;
	}
	/* fall through */
    default:
    	/*
     	 * To calculate exposures correctly, we have to translate the old
     	 * borderClip and clipList regions to the window's new location so there
     	 * is a correspondence between pieces of the new and old clipping regions.
     	 */
    	if (dx || dy) 
    	{
	    /*
	     * We translate the old clipList because that will be exposed or copied
	     * if gravity is right.
	     */
	    RegionTranslate(&pParent->borderClip, dx, dy);
	    RegionTranslate(&pParent->clipList, dx, dy);
    	} 
	break;
    case VTBroken:
	RegionEmpty(&pParent->borderClip);
	RegionEmpty(&pParent->clipList);
	break;
    }

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

    /*
     * Since the borderClip must not be clipped by the children, we do
     * the border exposure first...
     *
     * 'universe' is the window's borderClip. To figure the exposures, remove
     * the area that used to be exposed from the new.
     * This leaves a region of pieces that weren't exposed before.
     */

    if (HasBorder (pParent))
    {
    	if (borderVisible)
    	{
	    /*
	     * when the border changes shape, the old visible portions
	     * of the border will be saved by DIX in borderVisible --
	     * use that region and destroy it
	     */
	    RegionSubtract(exposed, universe, borderVisible);
	    RegionDestroy(borderVisible);
    	}
    	else
    	{
	    RegionSubtract(exposed, universe, &pParent->borderClip);
    	}
	if (HasParentRelativeBorder(pParent) && (dx || dy))
	    RegionSubtract(&pParent->valdata->after.borderExposed,
				  universe,
				  &pParent->winSize);
	else
	    RegionSubtract(&pParent->valdata->after.borderExposed,
			       exposed, &pParent->winSize);

	RegionCopy(&pParent->borderClip, universe);
    
    	/*
     	 * To get the right clipList for the parent, and to make doubly sure
     	 * that no child overlaps the parent's border, we remove the parent's
     	 * border from the universe before proceeding.
     	 */
    
	RegionIntersect(universe, universe, &pParent->winSize);
    }
    else
	RegionCopy(&pParent->borderClip, universe);
    
    if ((pChild = pParent->firstChild) && pParent->mapped)
    {
	RegionNull(&childUniverse);
	RegionNull(&childUnion);
	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
	{
	    for (; pChild; pChild = pChild->nextSib)
	    {
		if (pChild->viewable && !TreatAsTransparent(pChild))
		    RegionAppend(&childUnion, &pChild->borderSize);
	    }
	}
	else
	{
	    for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
	    {
		if (pChild->viewable && !TreatAsTransparent(pChild))
		    RegionAppend(&childUnion, &pChild->borderSize);
	    }
	}
	RegionValidate(&childUnion, &overlap);

	for (pChild = pParent->firstChild;
	     pChild;
	     pChild = pChild->nextSib)
 	{
	    if (pChild->viewable) {
		/*
		 * If the child is viewable, we want to remove its extents
		 * from the current universe, but we only re-clip it if
		 * it's been marked.
		 */
		if (pChild->valdata) {
		    /*
		     * Figure out the new universe from the child's
		     * perspective and recurse.
		     */
		    RegionIntersect(&childUniverse,
					    universe,
					    &pChild->borderSize);
		    miComputeClips (pChild, pScreen, &childUniverse, kind,
				    exposed);
		}
		/*
		 * Once the child has been processed, we remove its extents
		 * from the current universe, thus denying its space to any
		 * other sibling.
		 */
		if (overlap && !TreatAsTransparent (pChild))
		    RegionSubtract(universe, universe,
					  &pChild->borderSize);
	    }
	}
	if (!overlap)
	    RegionSubtract(universe, universe, &childUnion);
	RegionUninit(&childUnion);
	RegionUninit(&childUniverse);
    } /* if any children */

    /*
     * 'universe' now contains the new clipList for the parent window.
     *
     * To figure the exposure of the window we subtract the old clip from the
     * new, just as for the border.
     */

    if (oldVis == VisibilityFullyObscured ||
	oldVis == VisibilityNotViewable)
    {
	RegionCopy(&pParent->valdata->after.exposed, universe);
    }
    else if (newVis != VisibilityFullyObscured &&
	     newVis != VisibilityNotViewable)
    {
	RegionSubtract(&pParent->valdata->after.exposed,
			       universe, &pParent->clipList);
    }

    /* HACK ALERT - copying contents of regions, instead of regions */
    {
	RegionRec   tmp;

	tmp = pParent->clipList;
	pParent->clipList = *universe;
	*universe = tmp;
    }

#ifdef NOTDEF
    RegionCopy(&pParent->clipList, universe);
#endif

    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;

    if (pScreen->ClipNotify)
	(* pScreen->ClipNotify) (pParent, dx, dy);
}
Example #12
0
/* XaceCensorImage
 *
 * Called after pScreen->GetImage to prevent pieces or trusted windows from
 * being returned in image data from an untrusted window.
 *
 * Arguments:
 *	client is the client doing the GetImage.
 *      pVisibleRegion is the visible region of the window.
 *	widthBytesLine is the width in bytes of one horizontal line in pBuf.
 *	pDraw is the source window.
 *	x, y, w, h is the rectangle of image data from pDraw in pBuf.
 *	format is the format of the image data in pBuf: ZPixmap or XYPixmap.
 *	pBuf is the image data.
 *
 * Returns: nothing.
 *
 * Side Effects:
 *	Any part of the rectangle (x, y, w, h) that is outside the visible
 *	region of the window will be destroyed (overwritten) in pBuf.
 */
void
XaceCensorImage(ClientPtr client,
                RegionPtr pVisibleRegion,
                long widthBytesLine,
                DrawablePtr pDraw,
                int x, int y, int w, int h, unsigned int format, char *pBuf)
{
    RegionRec imageRegion;      /* region representing x,y,w,h */
    RegionRec censorRegion;     /* region to obliterate */
    BoxRec imageBox;
    int nRects;

    imageBox.x1 = x;
    imageBox.y1 = y;
    imageBox.x2 = x + w;
    imageBox.y2 = y + h;
    RegionInit(&imageRegion, &imageBox, 1);
    RegionNull(&censorRegion);

    /* censorRegion = imageRegion - visibleRegion */
    RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion);
    nRects = RegionNumRects(&censorRegion);
    if (nRects > 0) {           /* we have something to censor */
        GCPtr pScratchGC = NULL;
        PixmapPtr pPix = NULL;
        xRectangle *pRects = NULL;
        Bool failed = FALSE;
        int depth = 1;
        int bitsPerPixel = 1;
        int i;
        BoxPtr pBox;

        /* convert region to list-of-rectangles for PolyFillRect */

        pRects = malloc(nRects * sizeof(xRectangle));
        if (!pRects) {
            failed = TRUE;
            goto failSafe;
        }
        for (pBox = RegionRects(&censorRegion), i = 0; i < nRects; i++, pBox++) {
            pRects[i].x = pBox->x1;
            pRects[i].y = pBox->y1 - imageBox.y1;
            pRects[i].width = pBox->x2 - pBox->x1;
            pRects[i].height = pBox->y2 - pBox->y1;
        }

        /* use pBuf as a fake pixmap */

        if (format == ZPixmap) {
            depth = pDraw->depth;
            bitsPerPixel = pDraw->bitsPerPixel;
        }

        pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
                                      depth, bitsPerPixel,
                                      widthBytesLine, (pointer) pBuf);
        if (!pPix) {
            failed = TRUE;
            goto failSafe;
        }

        pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
        if (!pScratchGC) {
            failed = TRUE;
            goto failSafe;
        }

        ValidateGC(&pPix->drawable, pScratchGC);
        (*pScratchGC->ops->PolyFillRect) (&pPix->drawable,
                                          pScratchGC, nRects, pRects);

 failSafe:
        if (failed) {
            /* Censoring was not completed above.  To be safe, wipe out
             * all the image data so that nothing trusted gets out.
             */
            memset(pBuf, 0, (int) (widthBytesLine * h));
        }
        free(pRects);
        if (pScratchGC)
            FreeScratchGC(pScratchGC);
        if (pPix)
            FreeScratchPixmapHeader(pPix);
    }
    RegionUninit(&imageRegion);
    RegionUninit(&censorRegion);
}                               /* XaceCensorImage */
Example #13
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;
}
Example #14
0
RegionPtr
miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
                  GCPtr pGC, int srcx, int srcy, int width, int height,
                  int dstx, int dsty)
{
    RegionPtr prgnSrcClip;      /* drawable-relative source clip */
    RegionRec rgnSrcRec;
    RegionPtr prgnDstClip;      /* drawable-relative dest clip */
    RegionRec rgnDstRec;
    BoxRec srcBox;              /* unclipped source */
    RegionRec rgnExposed;       /* exposed region, calculated source-
                                   relative, made dst relative to
                                   intersect with visible parts of
                                   dest and send events to client,
                                   and then screen relative to paint
                                   the window background
                                 */
    WindowPtr pSrcWin;
    BoxRec expBox = { 0, };
    Bool extents;

    /* avoid work if we can */
    if (!pGC->graphicsExposures && pDstDrawable->type == DRAWABLE_PIXMAP)
        return NULL;

    srcBox.x1 = srcx;
    srcBox.y1 = srcy;
    srcBox.x2 = srcx + width;
    srcBox.y2 = srcy + height;

    if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
        BoxRec TsrcBox;

        TsrcBox.x1 = srcx + pSrcDrawable->x;
        TsrcBox.y1 = srcy + pSrcDrawable->y;
        TsrcBox.x2 = TsrcBox.x1 + width;
        TsrcBox.y2 = TsrcBox.y1 + height;
        pSrcWin = (WindowPtr) pSrcDrawable;
        if (pGC->subWindowMode == IncludeInferiors) {
            prgnSrcClip = NotClippedByChildren(pSrcWin);
            if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN) {
                RegionDestroy(prgnSrcClip);
                return NULL;
            }
        }
        else {
            if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
                return NULL;
            prgnSrcClip = &rgnSrcRec;
            RegionNull(prgnSrcClip);
            RegionCopy(prgnSrcClip, &pSrcWin->clipList);
        }
        RegionTranslate(prgnSrcClip, -pSrcDrawable->x, -pSrcDrawable->y);
    }
    else {
        BoxRec box;

        if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
            (srcBox.x2 <= pSrcDrawable->width) &&
            (srcBox.y2 <= pSrcDrawable->height))
            return NULL;

        box.x1 = 0;
        box.y1 = 0;
        box.x2 = pSrcDrawable->width;
        box.y2 = pSrcDrawable->height;
        prgnSrcClip = &rgnSrcRec;
        RegionInit(prgnSrcClip, &box, 1);
        pSrcWin = NULL;
    }

    if (pDstDrawable == pSrcDrawable) {
        prgnDstClip = prgnSrcClip;
    }
    else if (pDstDrawable->type != DRAWABLE_PIXMAP) {
        if (pGC->subWindowMode == IncludeInferiors) {
            prgnDstClip = NotClippedByChildren((WindowPtr) pDstDrawable);
        }
        else {
            prgnDstClip = &rgnDstRec;
            RegionNull(prgnDstClip);
            RegionCopy(prgnDstClip, &((WindowPtr) pDstDrawable)->clipList);
        }
        RegionTranslate(prgnDstClip, -pDstDrawable->x, -pDstDrawable->y);
    }
    else {
        BoxRec box;

        box.x1 = 0;
        box.y1 = 0;
        box.x2 = pDstDrawable->width;
        box.y2 = pDstDrawable->height;
        prgnDstClip = &rgnDstRec;
        RegionInit(prgnDstClip, &box, 1);
    }

    /* drawable-relative source region */
    RegionInit(&rgnExposed, &srcBox, 1);

    /* now get the hidden parts of the source box */
    RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);

    /* move them over the destination */
    RegionTranslate(&rgnExposed, dstx - srcx, dsty - srcy);

    /* intersect with visible areas of dest */
    RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);

    /* intersect with client clip region. */
    if (pGC->clientClip)
        RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);

    /*
     * 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" :-)
     * for windows.
     */
    extents = pGC->graphicsExposures &&
        (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
        (pDstDrawable->type != DRAWABLE_PIXMAP);
    if (pSrcWin) {
        RegionPtr region;

        if (!(region = wClipShape(pSrcWin)))
            region = wBoundingShape(pSrcWin);
        /*
         * If you try to CopyArea the extents of a shaped window, compacting the
         * exposed region will undo all our work!
         */
        if (extents && pSrcWin && region &&
            (RegionContainsRect(region, &srcBox) != rgnIN))
            extents = FALSE;
    }
    if (extents) {
        expBox = *RegionExtents(&rgnExposed);
        RegionReset(&rgnExposed, &expBox);
    }
    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
        (((WindowPtr) pDstDrawable)->backgroundState != None)) {
        WindowPtr pWin = (WindowPtr) pDstDrawable;

        /* make the exposed area screen-relative */
        RegionTranslate(&rgnExposed, pDstDrawable->x, pDstDrawable->y);

        if (extents) {
            /* PaintWindow doesn't clip, so we have to */
            RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
        }
        pDstDrawable->pScreen->PaintWindow((WindowPtr) pDstDrawable,
                                           &rgnExposed, PW_BACKGROUND);

        if (extents) {
            RegionReset(&rgnExposed, &expBox);
        }
        else
            RegionTranslate(&rgnExposed, -pDstDrawable->x, -pDstDrawable->y);
    }
    if (prgnDstClip == &rgnDstRec) {
        RegionUninit(prgnDstClip);
    }
    else if (prgnDstClip != prgnSrcClip) {
        RegionDestroy(prgnDstClip);
    }

    if (prgnSrcClip == &rgnSrcRec) {
        RegionUninit(prgnSrcClip);
    }
    else {
        RegionDestroy(prgnSrcClip);
    }

    if (pGC->graphicsExposures) {
        /* don't look */
        RegionPtr exposed = RegionCreate(NullBox, 0);

        *exposed = rgnExposed;
        return exposed;
    }
    else {
        RegionUninit(&rgnExposed);
        return NULL;
    }
}
Example #15
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();
}
Example #16
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;
}
Example #17
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;
}
Example #18
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;
}