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; }
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); } }
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); }
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; }
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(®, &box, 1); RegionUnion(dst, dst, ®); RegionUninit(®); if (pExaScr->SavedSourceValidate) { swap(pExaScr, pScreen, SourceValidate); pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode); swap(pExaScr, pScreen, SourceValidate); } }
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); }
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; }
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; }
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); }
/*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; }
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; }
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(); }
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); }
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; }