void fbCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { RegionRec rgnDst; int dx, dy; PixmapPtr pPixmap = fbGetWindowPixmap(pWin); DrawablePtr pDrawable = &pPixmap->drawable; dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; RegionTranslate(prgnSrc, -dx, -dy); RegionNull(&rgnDst); RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); #ifdef COMPOSITE if (pPixmap->screen_x || pPixmap->screen_y) RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y); #endif miCopyRegion(pDrawable, pDrawable, 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); RegionUninit(&rgnDst); fbValidateDrawable(&pWin->drawable); }
static void ShadowCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgn) { ScreenPtr pScreen = pWin->drawable.pScreen; ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); int num = 0; RegionRec rgnDst; if (pPriv->vtSema) { RegionNull(&rgnDst); RegionCopy(&rgnDst, prgn); RegionTranslate(&rgnDst, pWin->drawable.x - ptOldOrg.x, pWin->drawable.y - ptOldOrg.y); RegionIntersect(&rgnDst, &pWin->borderClip, &rgnDst); if ((num = RegionNumRects(&rgnDst))) { if (pPriv->preRefresh) (*pPriv->preRefresh) (pPriv->pScrn, num, RegionRects(&rgnDst)); } else { RegionUninit(&rgnDst); } } pScreen->CopyWindow = pPriv->CopyWindow; (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn); pScreen->CopyWindow = ShadowCopyWindow; if (num) { if (pPriv->postRefresh) (*pPriv->postRefresh) (pPriv->pScrn, num, RegionRects(&rgnDst)); RegionUninit(&rgnDst); } }
void XAACopyWindow( WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc ) { DDXPointPtr pptSrc, ppt; RegionRec rgnDst; BoxPtr pbox; int dx, dy, nbox; WindowPtr pwinRoot; ScreenPtr pScreen = pWin->drawable.pScreen; XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); if(infoRec->pScrn->vtSema && infoRec->NeedToSync) { (*infoRec->Sync)(infoRec->pScrn); infoRec->NeedToSync = FALSE; } (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAACopyWindow); return; } pwinRoot = pScreen->root; RegionNull(&rgnDst); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; RegionTranslate(prgnSrc, -dx, -dy); RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); pbox = RegionRects(&rgnDst); nbox = RegionNumRects(&rgnDst); if(!nbox || !(pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec)))) { RegionUninit(&rgnDst); return; } ppt = pptSrc; while(nbox--) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; ppt++; pbox++; } infoRec->ScratchGC.planemask = ~0L; infoRec->ScratchGC.alu = GXcopy; XAADoBitBlt((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); free(pptSrc); RegionUninit(&rgnDst); }
/** * find if the remote window denoted by a_remote * is paired with an internal Window within the Xephyr server. * If the remove window is paired with an internal window, send an * expose event to the client insterested in the internal window expose event. * * Pairing happens when a drawable inside Xephyr is associated with * a GL surface in a DRI environment. * Look at the function ProcXF86DRICreateDrawable in ephyrdriext.c to * know a paired window is created. * * This is useful to make GL drawables (only windows for now) handle * expose events and send those events to clients. */ static void ephyrExposePairedWindow(int a_remote) { EphyrWindowPair *pair = NULL; RegionRec reg; ScreenPtr screen; if (!findWindowPairFromRemote(a_remote, &pair)) { EPHYR_LOG("did not find a pair for this window\n"); return; } screen = pair->local->drawable.pScreen; RegionNull(®); RegionCopy(®, &pair->local->clipList); screen->WindowExposures(pair->local, ®); RegionUninit(®); }
Bool shadowSetup(ScreenPtr pScreen) { shadowBufPtr pBuf; if (!dixRegisterPrivateKey(&shadowScrPrivateKeyRec, PRIVATE_SCREEN, 0)) return FALSE; if (!DamageSetup(pScreen)) return FALSE; pBuf = malloc(sizeof(shadowBufRec)); if (!pBuf) return FALSE; #ifdef BACKWARDS_COMPATIBILITY pBuf->pDamage = DamageCreate((DamageReportFunc) shadowReportFunc, (DamageDestroyFunc) NULL, DamageReportRawRegion, TRUE, pScreen, pScreen); #else pBuf->pDamage = DamageCreate((DamageReportFunc) NULL, (DamageDestroyFunc) NULL, DamageReportNone, TRUE, pScreen, pScreen); #endif if (!pBuf->pDamage) { free(pBuf); return FALSE; } wrap(pBuf, pScreen, CloseScreen); wrap(pBuf, pScreen, GetImage); pBuf->update = 0; pBuf->window = 0; pBuf->pPixmap = 0; pBuf->closure = 0; pBuf->randr = 0; #ifdef BACKWARDS_COMPATIBILITY RegionNull(&pBuf->damage); /* bc */ #endif dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf); return TRUE; }
bool sna_tiling_fill_boxes(struct sna *sna, CARD8 op, PictFormat format, const xRenderColor *color, PixmapPtr dst, struct kgem_bo *dst_bo, const BoxRec *box, int n) { RegionRec region, tile, this; struct kgem_bo *bo; int step; bool ret = false; pixman_region_init_rects(®ion, box, n); /* Use a small step to accommodate enlargement through tile alignment */ step = sna->render.max_3d_size; if (region.extents.x1 & (8*512 / dst->drawable.bitsPerPixel - 1) || region.extents.y1 & 63) step /= 2; while (step * step * 4 > sna->kgem.max_copy_tile_size) step /= 2; DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n", __FUNCTION__, op, (int)format, color->red, color->green, color->blue, color->alpha, step, n, region.extents.x1, region.extents.y1, region.extents.x2, region.extents.y2)); for (tile.extents.y1 = tile.extents.y2 = region.extents.y1; tile.extents.y2 < region.extents.y2; tile.extents.y1 = tile.extents.y2) { int y2 = tile.extents.y1 + step; if (y2 > region.extents.y2) y2 = region.extents.y2; tile.extents.y2 = y2; for (tile.extents.x1 = tile.extents.x2 = region.extents.x1; tile.extents.x2 < region.extents.x2; tile.extents.x1 = tile.extents.x2) { PixmapRec tmp; int x2 = tile.extents.x1 + step; if (x2 > region.extents.x2) x2 = region.extents.x2; tile.extents.x2 = x2; tile.data = NULL; RegionNull(&this); RegionIntersect(&this, ®ion, &tile); if (RegionNil(&this)) continue; tmp.drawable.width = this.extents.x2 - this.extents.x1; tmp.drawable.height = this.extents.y2 - this.extents.y1; tmp.drawable.depth = dst->drawable.depth; tmp.drawable.bitsPerPixel = dst->drawable.bitsPerPixel; tmp.devPrivate.ptr = NULL; bo = kgem_create_2d(&sna->kgem, tmp.drawable.width, tmp.drawable.height, dst->drawable.bitsPerPixel, kgem_choose_tiling(&sna->kgem, I915_TILING_X, tmp.drawable.width, tmp.drawable.height, dst->drawable.bitsPerPixel), CREATE_TEMPORARY); if (bo) { int16_t dx = this.extents.x1; int16_t dy = this.extents.y1; assert(kgem_bo_can_blt(&sna->kgem, bo)); if (!sna->render.copy_boxes(sna, GXcopy, dst, dst_bo, 0, 0, &tmp, bo, -dx, -dy, REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0)) goto err; RegionTranslate(&this, -dx, -dy); if (!sna->render.fill_boxes(sna, op, format, color, &tmp, bo, REGION_RECTS(&this), REGION_NUM_RECTS(&this))) goto err; if (!sna->render.copy_boxes(sna, GXcopy, &tmp, bo, 0, 0, dst, dst_bo, dx, dy, REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0)) goto err; kgem_bo_destroy(&sna->kgem, bo); } RegionUninit(&this); } } ret = true; goto done; err: kgem_bo_destroy(&sna->kgem, bo); RegionUninit(&this); done: pixman_region_fini(®ion); return ret; }
/** * If the pixmap has both a framebuffer and system memory copy, this function * asserts that both of them are the same. */ static Bool exaAssertNotDirty(PixmapPtr pPixmap) { ExaPixmapPriv(pPixmap); CARD8 *dst, *src; RegionRec ValidReg; int dst_pitch, src_pitch, cpp, y, nbox, save_pitch; BoxPtr pBox; Bool ret = TRUE, save_use_gpu_copy; if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL) return ret; RegionNull(&ValidReg); RegionIntersect(&ValidReg, &pExaPixmap->validFB, &pExaPixmap->validSys); nbox = RegionNumRects(&ValidReg); if (!nbox) goto out; pBox = RegionRects(&ValidReg); dst_pitch = pExaPixmap->sys_pitch; src_pitch = pExaPixmap->fb_pitch; cpp = pPixmap->drawable.bitsPerPixel / 8; save_use_gpu_copy = pExaPixmap->use_gpu_copy; save_pitch = pPixmap->devKind; pExaPixmap->use_gpu_copy = TRUE; pPixmap->devKind = pExaPixmap->fb_pitch; if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC)) goto skip; while (nbox--) { int rowbytes; 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; rowbytes = (pBox->x2 - pBox->x1) * cpp; src = (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch + pBox->x1 * cpp; dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp; for (y = pBox->y1; y < pBox->y2; y++, src += src_pitch, dst += dst_pitch) { if (memcmp(dst, src, rowbytes) != 0) { ret = FALSE; exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, pBox->y2); break; } } } skip: exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); pExaPixmap->use_gpu_copy = save_use_gpu_copy; pPixmap->devKind = save_pitch; out: RegionUninit(&ValidReg); 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); }
void XAAOverCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWin->drawable.pScreen; XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); ScrnInfoPtr pScrn = infoRec->pScrn; DDXPointPtr ppt, pptSrc; RegionRec rgnDst; BoxPtr pbox; int i, nbox, dx, dy; WindowPtr pRoot = pScreen->root; if (!pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { XAA_SCREEN_PROLOGUE(pScreen, CopyWindow); if (pScrn->vtSema && infoRec->NeedToSync) { (*infoRec->Sync) (pScrn); infoRec->NeedToSync = FALSE; } (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); XAA_SCREEN_EPILOGUE(pScreen, CopyWindow, XAAOverCopyWindow); return; } infoRec->ScratchGC.alu = GXcopy; infoRec->ScratchGC.planemask = ~0; RegionNull(&rgnDst); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; RegionTranslate(prgnSrc, -dx, -dy); RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); nbox = RegionNumRects(&rgnDst); if (nbox && (pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) { pbox = RegionRects(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } SWITCH_DEPTH(8); XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); if (pWin->drawable.bitsPerPixel != 8) { SWITCH_DEPTH(pScrn->depth); XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); } free(pptSrc); } RegionUninit(&rgnDst); if (pWin->drawable.depth == 8) { RegionNull(&rgnDst); miSegregateChildren(pWin, &rgnDst, pScrn->depth); if (RegionNotEmpty(&rgnDst)) { RegionIntersect(&rgnDst, &rgnDst, prgnSrc); nbox = RegionNumRects(&rgnDst); if (nbox && (pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) { pbox = RegionRects(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } SWITCH_DEPTH(pScrn->depth); XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); free(pptSrc); } } RegionUninit(&rgnDst); } }
/* * Redirect one window for one client */ int compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update) { CompWindowPtr cw = GetCompWindow(pWin); CompClientWindowPtr ccw; CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); WindowPtr pLayerWin = NULL; Bool anyMarked = FALSE; if (pWin == cs->pOverlayWin) { return Success; } if (!pWin->parent) return BadMatch; /* * Only one Manual update is allowed */ if (cw && update == CompositeRedirectManual) for (ccw = cw->clients; ccw; ccw = ccw->next) if (ccw->update == CompositeRedirectManual) return BadAccess; /* * Allocate per-client per-window structure * The client *could* allocate multiple, but while supported, * it is not expected to be common */ ccw = malloc(sizeof(CompClientWindowRec)); if (!ccw) return BadAlloc; ccw->id = FakeClientID(pClient->index); ccw->update = update; /* * Now make sure there's a per-window structure to hang this from */ if (!cw) { cw = malloc(sizeof(CompWindowRec)); if (!cw) { free(ccw); return BadAlloc; } cw->damage = DamageCreate(compReportDamage, compDestroyDamage, DamageReportNonEmpty, FALSE, pWin->drawable.pScreen, pWin); if (!cw->damage) { free(ccw); free(cw); return BadAlloc; } anyMarked = compMarkWindows(pWin, &pLayerWin); RegionNull(&cw->borderClip); cw->update = CompositeRedirectAutomatic; cw->clients = 0; cw->oldx = COMP_ORIGIN_INVALID; cw->oldy = COMP_ORIGIN_INVALID; cw->damageRegistered = FALSE; cw->damaged = FALSE; cw->pOldPixmap = NullPixmap; dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); } ccw->next = cw->clients; cw->clients = ccw; if (!AddResource(ccw->id, CompositeClientWindowType, pWin)) return BadAlloc; if (ccw->update == CompositeRedirectManual) { if (!anyMarked) anyMarked = compMarkWindows(pWin, &pLayerWin); if (cw->damageRegistered) { DamageUnregister(&pWin->drawable, cw->damage); cw->damageRegistered = FALSE; } cw->update = CompositeRedirectManual; } else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { if (!anyMarked) anyMarked = compMarkWindows(pWin, &pLayerWin); } if (!compCheckRedirect(pWin)) { FreeResource(ccw->id, RT_NONE); return BadAlloc; } if (anyMarked) compHandleMarkedWindows(pWin, pLayerWin); return Success; }
/* 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 */
RegionPtr miDoCopy(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut, miCopyProc copyProc, Pixel bitPlane, void *closure) { RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ Bool freeSrcClip = FALSE; RegionPtr prgnExposed = NULL; RegionRec rgnDst; int dx; int dy; int numRects; int box_x1; int box_y1; int box_x2; int box_y2; Bool fastSrc = FALSE; /* for fast clipping with pixmap source */ Bool fastDst = FALSE; /* for fast clipping with one rect dest */ Bool fastExpose = FALSE; /* for fast exposures with pixmap source */ /* Short cut for unmapped or fully clipped windows */ if (pDstDrawable->type == DRAWABLE_WINDOW && RegionNil(&((WindowPtr)pDstDrawable)->clipList)) { return NULL; } if (pSrcDrawable->pScreen->SourceValidate) { (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc, pGC->subWindowMode); } /* Compute source clip region */ if (pSrcDrawable->type == DRAWABLE_PIXMAP) { if ((pSrcDrawable == pDstDrawable) && (!pGC->clientClip)) prgnSrcClip = miGetCompositeClip(pGC); else fastSrc = TRUE; } else { if (pGC->subWindowMode == IncludeInferiors) { /* * XFree86 DDX empties the border clip when the * VT is inactive, make sure the region isn't empty */ if (!((WindowPtr) pSrcDrawable)->parent && RegionNotEmpty(&((WindowPtr) pSrcDrawable)->borderClip)) { /* * special case bitblt from root window in * IncludeInferiors mode; just like from a pixmap */ fastSrc = TRUE; } else if ((pSrcDrawable == pDstDrawable) && (!pGC->clientClip)) { prgnSrcClip = miGetCompositeClip(pGC); } else { prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable); freeSrcClip = TRUE; } } else { prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList; } } xIn += pSrcDrawable->x; yIn += pSrcDrawable->y; xOut += pDstDrawable->x; yOut += pDstDrawable->y; box_x1 = xIn; box_y1 = yIn; box_x2 = xIn + widthSrc; box_y2 = yIn + heightSrc; dx = xIn - xOut; dy = yIn - yOut; /* Don't create a source region if we are doing a fast clip */ if (fastSrc) { RegionPtr cclip; fastExpose = TRUE; /* * clip the source; if regions extend beyond the source size, * make sure exposure events get sent */ if (box_x1 < pSrcDrawable->x) { box_x1 = pSrcDrawable->x; fastExpose = FALSE; } if (box_y1 < pSrcDrawable->y) { box_y1 = pSrcDrawable->y; fastExpose = FALSE; } if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width; fastExpose = FALSE; } if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height; fastExpose = FALSE; } /* Translate and clip the dst to the destination composite clip */ box_x1 -= dx; box_x2 -= dx; box_y1 -= dy; box_y2 -= dy; /* If the destination composite clip is one rectangle we can do the clip directly. Otherwise we have to create a full blown region and call intersect */ cclip = miGetCompositeClip(pGC); if (RegionNumRects(cclip) == 1) { BoxPtr pBox = RegionRects(cclip); if (box_x1 < pBox->x1) box_x1 = pBox->x1; if (box_x2 > pBox->x2) box_x2 = pBox->x2; if (box_y1 < pBox->y1) box_y1 = pBox->y1; if (box_y2 > pBox->y2) box_y2 = pBox->y2; fastDst = TRUE; } } /* Check to see if the region is empty */ if (box_x1 >= box_x2 || box_y1 >= box_y2) { RegionNull(&rgnDst); } else { BoxRec box; box.x1 = box_x1; box.y1 = box_y1; box.x2 = box_x2; box.y2 = box_y2; RegionInit(&rgnDst, &box, 1); } /* Clip against complex source if needed */ if (!fastSrc) { RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip); RegionTranslate(&rgnDst, -dx, -dy); } /* Clip against complex dest if needed */ if (!fastDst) { RegionIntersect(&rgnDst, &rgnDst, miGetCompositeClip(pGC)); } /* Do bit blitting */ numRects = RegionNumRects(&rgnDst); if (numRects && widthSrc && heightSrc) miCopyRegion(pSrcDrawable, pDstDrawable, pGC, &rgnDst, dx, dy, copyProc, bitPlane, closure); /* Pixmap sources generate a NoExposed (we return NULL to do this) */ if (!fastExpose && pGC->fExpose) prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn - pSrcDrawable->x, yIn - pSrcDrawable->y, widthSrc, heightSrc, xOut - pDstDrawable->x, yOut - pDstDrawable->y); RegionUninit(&rgnDst); if (freeSrcClip) RegionDestroy(prgnSrcClip); return prgnExposed; }
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; } }
// fixme this is ugly // Xprint/ValTree.c doesn't work, but maybe that method can? int RootlessMiValidateTree (WindowPtr pRoot, /* Parent to validate */ WindowPtr pChild, /* First child of pRoot that was * affected */ VTKind kind /* What kind of configuration caused call */) { RegionRec childClip; /* The new borderClip for the current * child */ RegionRec exposed; /* For intermediate calculations */ register ScreenPtr pScreen; register WindowPtr pWin; pScreen = pRoot->drawable.pScreen; if (pChild == NullWindow) pChild = pRoot->firstChild; RegionNull(&childClip); RegionNull(&exposed); if (RegionBroken(&pRoot->clipList) && !RegionBroken(&pRoot->borderClip)) { // fixme this might not work, but hopefully doesn't happen anyway. kind = VTBroken; RegionEmpty(&pRoot->clipList); ErrorF("ValidateTree: BUSTED!\n"); } /* * Recursively compute the clips for all children of the root. * They don't clip against each other or the root itself, so * childClip is always reset to that child's size. */ for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) { if (pWin->viewable) { if (pWin->valdata) { RegionCopy(&childClip, &pWin->borderSize); RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed); } else if (pWin->visibility == VisibilityNotViewable) { RootlessTreeObscured(pWin); } } else { if (pWin->valdata) { RegionEmpty(&pWin->clipList); if (pScreen->ClipNotify) (* pScreen->ClipNotify) (pWin, 0, 0); RegionEmpty(&pWin->borderClip); pWin->valdata = NULL; } } } RegionUninit(&childClip); /* The root is never clipped by its children, so nothing on the root is ever exposed by moving or mapping its children. */ RegionNull(&pRoot->valdata->after.exposed); RegionNull(&pRoot->valdata->after.borderExposed); return 1; }
static bool sna_tiling_blt_copy_boxes__with_alpha(struct sna *sna, uint8_t alu, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, int bpp, int alpha_fixup, const BoxRec *box, int nbox) { RegionRec region, tile, this; struct kgem_bo *bo; int max_size, step; bool ret = false; if (wedged(sna) || !kgem_bo_can_blt(&sna->kgem, src_bo) || !kgem_bo_can_blt(&sna->kgem, dst_bo)) { /* XXX */ DBG(("%s: tiling blt fail: src?=%d, dst?=%d\n", __FUNCTION__, kgem_bo_can_blt(&sna->kgem, src_bo), kgem_bo_can_blt(&sna->kgem, dst_bo))); return false; } max_size = sna->kgem.aperture_high * PAGE_SIZE; max_size -= MAX(kgem_bo_size(src_bo), kgem_bo_size(dst_bo)); if (max_size <= 0) { DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__)); return false; } if (max_size > sna->kgem.max_copy_tile_size) max_size = sna->kgem.max_copy_tile_size; pixman_region_init_rects(®ion, box, nbox); /* Use a small step to accommodate enlargement through tile alignment */ step = sna->render.max_3d_size; if (region.extents.x1 & (8*512 / bpp - 1) || region.extents.y1 & 63) step /= 2; while (step * step * 4 > max_size) step /= 2; if (sna->kgem.gen < 033) step /= 2; /* accommodate severe fence restrictions */ if (step == 0) { DBG(("%s: tiles cannot fit into aperture\n", __FUNCTION__)); return false; } DBG(("%s (alu=%d), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n", __FUNCTION__, alu, step, nbox, region.extents.x1, region.extents.y1, region.extents.x2, region.extents.y2)); for (tile.extents.y1 = tile.extents.y2 = region.extents.y1; tile.extents.y2 < region.extents.y2; tile.extents.y1 = tile.extents.y2) { int y2 = tile.extents.y1 + step; if (y2 > region.extents.y2) y2 = region.extents.y2; tile.extents.y2 = y2; for (tile.extents.x1 = tile.extents.x2 = region.extents.x1; tile.extents.x2 < region.extents.x2; tile.extents.x1 = tile.extents.x2) { int w, h; int x2 = tile.extents.x1 + step; if (x2 > region.extents.x2) x2 = region.extents.x2; tile.extents.x2 = x2; tile.data = NULL; RegionNull(&this); RegionIntersect(&this, ®ion, &tile); if (RegionNil(&this)) continue; w = this.extents.x2 - this.extents.x1; h = this.extents.y2 - this.extents.y1; bo = kgem_create_2d(&sna->kgem, w, h, bpp, kgem_choose_tiling(&sna->kgem, I915_TILING_X, w, h, bpp), CREATE_TEMPORARY); if (bo) { int16_t dx = this.extents.x1; int16_t dy = this.extents.y1; assert(bo->pitch <= 8192); assert(bo->tiling != I915_TILING_Y); if (!sna_blt_copy_boxes(sna, GXcopy, src_bo, src_dx, src_dy, bo, -dx, -dy, bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this))) goto err; if (!sna_blt_copy_boxes__with_alpha(sna, alu, bo, -dx, -dy, dst_bo, dst_dx, dst_dy, bpp, alpha_fixup, REGION_RECTS(&this), REGION_NUM_RECTS(&this))) goto err; kgem_bo_destroy(&sna->kgem, bo); } RegionUninit(&this); } } ret = true; goto done; err: kgem_bo_destroy(&sna->kgem, bo); RegionUninit(&this); done: pixman_region_fini(®ion); return ret; }
/* *----------------------------------------------------------------------- * 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); }
void winReshapeMultiWindow(WindowPtr pWin) { int nRects; RegionRec rrNewShape; BoxPtr pShape, pRects, pEnd; HRGN hRgn, hRgnRect; winWindowPriv(pWin); winDebug("winReshape ()\n"); /* Bail if the window is the root window */ if (pWin->parent == NULL) return; /* Bail if the window is not top level */ if (pWin->parent->parent != NULL) return; /* Bail if Windows window handle is invalid */ if (pWinPriv->hWnd == NULL) return; /* Free any existing window region stored in the window privates */ if (pWinPriv->hRgn != NULL) { DeleteObject(pWinPriv->hRgn); pWinPriv->hRgn = NULL; } /* Bail if the window has no bounding region defined */ if (!wBoundingShape(pWin)) return; RegionNull(&rrNewShape); RegionCopy(&rrNewShape, wBoundingShape(pWin)); RegionTranslate(&rrNewShape, pWin->borderWidth, pWin->borderWidth); nRects = RegionNumRects(&rrNewShape); pShape = RegionRects(&rrNewShape); /* Don't do anything if there are no rectangles in the region */ if (nRects > 0) { RECT rcClient; RECT rcWindow; int iOffsetX, iOffsetY; /* Get client rectangle */ if (!GetClientRect(pWinPriv->hWnd, &rcClient)) { ErrorF("winReshape - GetClientRect failed, bailing: %d\n", (int) GetLastError()); return; } /* Translate client rectangle coords to screen coords */ /* NOTE: Only transforms top and left members */ ClientToScreen(pWinPriv->hWnd, (LPPOINT) &rcClient); /* Get window rectangle */ if (!GetWindowRect(pWinPriv->hWnd, &rcWindow)) { ErrorF("winReshape - GetWindowRect failed, bailing: %d\n", (int) GetLastError()); return; } /* Calculate offset from window upper-left to client upper-left */ iOffsetX = rcClient.left - rcWindow.left; iOffsetY = rcClient.top - rcWindow.top; /* Create initial Windows region for title bar */ /* FIXME: Mean, nasty, ugly hack!!! */ hRgn = CreateRectRgn(0, 0, rcWindow.right, iOffsetY); if (hRgn == NULL) { ErrorF("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) " "failed: %d\n", 0, 0, (int) rcWindow.right, iOffsetY, (int) GetLastError()); } /* Loop through all rectangles in the X region */ for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) { /* Create a Windows region for the X rectangle */ hRgnRect = CreateRectRgn(pRects->x1 + iOffsetX, pRects->y1 + iOffsetY, pRects->x2 + iOffsetX, pRects->y2 + iOffsetY); if (hRgnRect == NULL) { ErrorF("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) " "failed: %d\n" "\tx1: %d x2: %d xOff: %d y1: %d y2: %d yOff: %d\n", pRects->x1 + iOffsetX, pRects->y1 + iOffsetY, pRects->x2 + iOffsetX, pRects->y2 + iOffsetY, (int) GetLastError(), pRects->x1, pRects->x2, iOffsetX, pRects->y1, pRects->y2, iOffsetY); } /* Merge the Windows region with the accumulated region */ if (CombineRgn(hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) { ErrorF("winReshape - CombineRgn () failed: %d\n", (int) GetLastError()); } /* Delete the temporary Windows region */ DeleteObject(hRgnRect); } /* Save a handle to the composite region in the window privates */ pWinPriv->hRgn = hRgn; } RegionUninit(&rrNewShape); return; }
/*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 ProcWindowsWMFrameDraw(ClientPtr client) { REQUEST(xWindowsWMFrameDrawReq); WindowPtr pWin; win32RootlessWindowPtr pRLWinPriv; RECT rcNew; int nCmdShow, rc; RegionRec newShape; REQUEST_SIZE_MATCH(xWindowsWMFrameDrawReq); #if CYGMULTIWINDOW_DEBUG ErrorF("ProcWindowsWMFrameDraw\n"); #endif rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); if (rc != Success) return rc; #if CYGMULTIWINDOW_DEBUG ErrorF("ProcWindowsWMFrameDraw - Window found\n"); #endif pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow(pWin, TRUE); if (pRLWinPriv == 0) return BadWindow; #if CYGMULTIWINDOW_DEBUG ErrorF("ProcWindowsWMFrameDraw - HWND %p 0x%08x 0x%08x\n", pRLWinPriv->hWnd, (int) stuff->frame_style, (int) stuff->frame_style_ex); ErrorF("ProcWindowsWMFrameDraw - %d %d %d %d\n", stuff->ix, stuff->iy, stuff->iw, stuff->ih); #endif /* Store the origin, height, and width in a rectangle structure */ SetRect(&rcNew, stuff->ix, stuff->iy, stuff->ix + stuff->iw, stuff->iy + stuff->ih); /* * Calculate the required size of the Windows window rectangle, * given the size of the Windows window client area. */ AdjustWindowRectEx(&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex); /* Set the window extended style flags */ if (!SetWindowLongPtr(pRLWinPriv->hWnd, GWL_EXSTYLE, stuff->frame_style_ex)) { return BadValue; } /* Set the window standard style flags */ if (!SetWindowLongPtr(pRLWinPriv->hWnd, GWL_STYLE, stuff->frame_style)) { return BadValue; } /* Flush the window style */ if (!SetWindowPos(pRLWinPriv->hWnd, NULL, rcNew.left, rcNew.top, rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE)) { return BadValue; } if (!IsWindowVisible(pRLWinPriv->hWnd)) nCmdShow = SW_HIDE; else nCmdShow = SW_SHOWNA; ShowWindow(pRLWinPriv->hWnd, nCmdShow); if (wBoundingShape(pWin) != NULL) { /* wBoundingShape is relative to *inner* origin of window. Translate by borderWidth to get the outside-relative position. */ RegionNull(&newShape); RegionCopy(&newShape, wBoundingShape(pWin)); RegionTranslate(&newShape, pWin->borderWidth, pWin->borderWidth); winMWExtWMReshapeFrame(pRLWinPriv, &newShape); RegionUninit(&newShape); } #if CYGMULTIWINDOW_DEBUG ErrorF("ProcWindowsWMFrameDraw - done\n"); #endif return Success; }
static void winReshapeRootless(WindowPtr pWin) { int nRects; RegionRec rrNewShape; BoxPtr pShape, pRects, pEnd; HRGN hRgn, hRgnRect; winWindowPriv(pWin); winDebug("winReshapeRootless ()\n"); /* Bail if the window is the root window */ if (pWin->parent == NULL) return; /* Bail if the window is not top level */ if (pWin->parent->parent != NULL) return; /* Free any existing window region stored in the window privates */ if (pWinPriv->hRgn != NULL) { DeleteObject(pWinPriv->hRgn); pWinPriv->hRgn = NULL; } /* Bail if the window has no bounding region defined */ if (!wBoundingShape(pWin)) return; RegionNull(&rrNewShape); RegionCopy(&rrNewShape, wBoundingShape(pWin)); RegionTranslate(&rrNewShape, pWin->borderWidth, pWin->borderWidth); nRects = RegionNumRects(&rrNewShape); pShape = RegionRects(&rrNewShape); if (nRects > 0) { /* Create initial empty Windows region */ hRgn = CreateRectRgn(0, 0, 0, 0); /* Loop through all rectangles in the X region */ for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) { /* Create a Windows region for the X rectangle */ hRgnRect = CreateRectRgn(pRects->x1, pRects->y1, pRects->x2, pRects->y2); if (hRgnRect == NULL) { ErrorF("winReshapeRootless - CreateRectRgn() failed\n"); } /* Merge the Windows region with the accumulated region */ if (CombineRgn(hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) { ErrorF("winReshapeRootless - CombineRgn() failed\n"); } /* Delete the temporary Windows region */ DeleteObject(hRgnRect); } /* Save a handle to the composite region in the window privates */ pWinPriv->hRgn = hRgn; } RegionUninit(&rrNewShape); return; }
static Bool ExaPrepareCompositeReg(ScreenPtr pScreen, CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { RegionRec region; RegionPtr dstReg = NULL; RegionPtr srcReg = NULL; RegionPtr maskReg = NULL; PixmapPtr pSrcPix = NULL; PixmapPtr pMaskPix = NULL; PixmapPtr pDstPix; ExaScreenPriv(pScreen); Bool ret; RegionNull(®ion); if (pSrc->pDrawable) { pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); RegionNull(&pExaScr->srcReg); srcReg = &pExaScr->srcReg; pExaScr->srcPix = pSrcPix; if (pSrc != pDst) RegionTranslate(pSrc->pCompositeClip, -pSrc->pDrawable->x, -pSrc->pDrawable->y); } else pExaScr->srcPix = NULL; if (pMask && pMask->pDrawable) { pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); RegionNull(&pExaScr->maskReg); maskReg = &pExaScr->maskReg; pExaScr->maskPix = pMaskPix; if (pMask != pDst && pMask != pSrc) RegionTranslate(pMask->pCompositeClip, -pMask->pDrawable->x, -pMask->pDrawable->y); } else pExaScr->maskPix = NULL; RegionTranslate(pDst->pCompositeClip, -pDst->pDrawable->x, -pDst->pDrawable->y); pExaScr->SavedSourceValidate = ExaSrcValidate; swap(pExaScr, pScreen, SourceValidate); ret = miComputeCompositeRegion(®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); swap(pExaScr, pScreen, SourceValidate); RegionTranslate(pDst->pCompositeClip, pDst->pDrawable->x, pDst->pDrawable->y); if (pSrc->pDrawable && pSrc != pDst) RegionTranslate(pSrc->pCompositeClip, pSrc->pDrawable->x, pSrc->pDrawable->y); if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc) RegionTranslate(pMask->pCompositeClip, pMask->pDrawable->x, pMask->pDrawable->y); if (!ret) { if (srcReg) RegionUninit(srcReg); if (maskReg) RegionUninit(maskReg); return FALSE; } /** * Don't limit alphamaps readbacks for now until we've figured out how that * should be done. */ if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) pExaScr-> prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable), EXA_PREPARE_AUX_SRC, NULL); if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) pExaScr-> prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable), EXA_PREPARE_AUX_MASK, NULL); if (pSrcPix) pExaScr->prepare_access_reg(pSrcPix, EXA_PREPARE_SRC, srcReg); if (pMaskPix) pExaScr->prepare_access_reg(pMaskPix, EXA_PREPARE_MASK, maskReg); if (srcReg) RegionUninit(srcReg); if (maskReg) RegionUninit(maskReg); pDstPix = exaGetDrawablePixmap(pDst->pDrawable); if (!exaOpReadsDestination(op)) { int xoff; int yoff; exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &xoff, &yoff); RegionTranslate(®ion, pDst->pDrawable->x + xoff, pDst->pDrawable->y + yoff); dstReg = ®ion; } if (pDst->alphaMap && pDst->alphaMap->pDrawable) pExaScr-> prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable), EXA_PREPARE_AUX_DEST, dstReg); pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg); RegionUninit(®ion); return TRUE; }
static void XAACopyWindow8_32(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { DDXPointPtr pptSrc, ppt; RegionRec rgnDst; BoxPtr pbox; int dx, dy, nbox; WindowPtr pwinRoot; ScreenPtr pScreen = pWin->drawable.pScreen; XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); Bool doUnderlay = miOverlayCopyUnderlay(pScreen); RegionPtr borderClip = &pWin->borderClip; Bool freeReg = FALSE; if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt || (infoRec->ScreenToScreenBitBltFlags & NO_PLANEMASK)) { XAA_SCREEN_PROLOGUE(pScreen, CopyWindow); if (infoRec->pScrn->vtSema && infoRec->NeedToSync) { (*infoRec->Sync) (infoRec->pScrn); infoRec->NeedToSync = FALSE; } (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); XAA_SCREEN_EPILOGUE(pScreen, CopyWindow, XAACopyWindow8_32); return; } pwinRoot = pScreen->root; if (doUnderlay) freeReg = miOverlayCollectUnderlayRegions(pWin, &borderClip); RegionNull(&rgnDst); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; RegionTranslate(prgnSrc, -dx, -dy); RegionIntersect(&rgnDst, borderClip, prgnSrc); pbox = RegionRects(&rgnDst); nbox = RegionNumRects(&rgnDst); if (!nbox || !(pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) { RegionUninit(&rgnDst); return; } ppt = pptSrc; while (nbox--) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; ppt++; pbox++; } infoRec->ScratchGC.planemask = doUnderlay ? 0x00ffffff : 0xff000000; infoRec->ScratchGC.alu = GXcopy; XAADoBitBlt((DrawablePtr) pwinRoot, (DrawablePtr) pwinRoot, &(infoRec->ScratchGC), &rgnDst, pptSrc); free(pptSrc); RegionUninit(&rgnDst); if (freeReg) RegionDestroy(borderClip); }
/* * Redirect one window for one client */ int compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) { CompWindowPtr cw = GetCompWindow (pWin); CompClientWindowPtr ccw; Bool wasMapped = pWin->mapped; CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); if (pWin == cs->pOverlayWin) { return Success; } if (!pWin->parent) return BadMatch; /* * Only one Manual update is allowed */ if (cw && update == CompositeRedirectManual) for (ccw = cw->clients; ccw; ccw = ccw->next) if (ccw->update == CompositeRedirectManual) return BadAccess; /* * Allocate per-client per-window structure * The client *could* allocate multiple, but while supported, * it is not expected to be common */ ccw = malloc(sizeof (CompClientWindowRec)); if (!ccw) return BadAlloc; ccw->id = FakeClientID (pClient->index); ccw->update = update; /* * Now make sure there's a per-window structure to hang this from */ if (!cw) { cw = malloc(sizeof (CompWindowRec)); if (!cw) { free(ccw); return BadAlloc; } cw->damage = DamageCreate (compReportDamage, compDestroyDamage, DamageReportNonEmpty, FALSE, pWin->drawable.pScreen, pWin); if (!cw->damage) { free(ccw); free(cw); return BadAlloc; } if (wasMapped) { DisableMapUnmapEvents (pWin); UnmapWindow (pWin, FALSE); EnableMapUnmapEvents (pWin); } RegionNull(&cw->borderClip); cw->borderClipX = 0; cw->borderClipY = 0; cw->update = CompositeRedirectAutomatic; cw->clients = 0; cw->oldx = COMP_ORIGIN_INVALID; cw->oldy = COMP_ORIGIN_INVALID; cw->damageRegistered = FALSE; cw->damaged = FALSE; cw->pOldPixmap = NullPixmap; dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); } ccw->next = cw->clients; cw->clients = ccw; if (!AddResource (ccw->id, CompositeClientWindowType, pWin)) return BadAlloc; if (ccw->update == CompositeRedirectManual) { /* If the window was CompositeRedirectAutomatic, then * unmap the window so that the parent clip list will * be correctly recomputed. */ if (pWin->mapped) { DisableMapUnmapEvents (pWin); UnmapWindow (pWin, FALSE); EnableMapUnmapEvents (pWin); } if (cw->damageRegistered) { DamageUnregister (&pWin->drawable, cw->damage); cw->damageRegistered = FALSE; } cw->update = CompositeRedirectManual; } if (!compCheckRedirect (pWin)) { FreeResource (ccw->id, RT_NONE); return BadAlloc; } if (wasMapped && !pWin->mapped) { Bool overrideRedirect = pWin->overrideRedirect; pWin->overrideRedirect = TRUE; DisableMapUnmapEvents (pWin); MapWindow (pWin, pClient); EnableMapUnmapEvents (pWin); pWin->overrideRedirect = overrideRedirect; } return Success; }
bool sna_tiling_blt_copy_boxes(struct sna *sna, uint8_t alu, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, int bpp, const BoxRec *box, int nbox) { RegionRec region, tile, this; struct kgem_bo *bo; int step; bool ret = false; if (!kgem_bo_can_blt(&sna->kgem, src_bo) || !kgem_bo_can_blt(&sna->kgem, dst_bo)) { /* XXX */ DBG(("%s: tiling blt fail: src?=%d, dst?=%d\n", __FUNCTION__, kgem_bo_can_blt(&sna->kgem, src_bo), kgem_bo_can_blt(&sna->kgem, dst_bo))); return false; } pixman_region_init_rects(®ion, box, nbox); /* Use a small step to accommodate enlargement through tile alignment */ step = sna->render.max_3d_size; if (region.extents.x1 & (8*512 / bpp - 1) || region.extents.y1 & 63) step /= 2; while (step * step * 4 > sna->kgem.max_copy_tile_size) step /= 2; DBG(("%s (alu=%d), tile.size=%d, box=%dx[(%d, %d), (%d, %d)])\n", __FUNCTION__, alu, step, nbox, region.extents.x1, region.extents.y1, region.extents.x2, region.extents.y2)); for (tile.extents.y1 = tile.extents.y2 = region.extents.y1; tile.extents.y2 < region.extents.y2; tile.extents.y1 = tile.extents.y2) { tile.extents.y2 = tile.extents.y1 + step; if (tile.extents.y2 > region.extents.y2) tile.extents.y2 = region.extents.y2; for (tile.extents.x1 = tile.extents.x2 = region.extents.x1; tile.extents.x2 < region.extents.x2; tile.extents.x1 = tile.extents.x2) { int w, h; tile.extents.x2 = tile.extents.x1 + step; if (tile.extents.x2 > region.extents.x2) tile.extents.x2 = region.extents.x2; tile.data = NULL; RegionNull(&this); RegionIntersect(&this, ®ion, &tile); if (!RegionNotEmpty(&this)) continue; w = this.extents.x2 - this.extents.x1; h = this.extents.y2 - this.extents.y1; bo = kgem_create_2d(&sna->kgem, w, h, bpp, kgem_choose_tiling(&sna->kgem, I915_TILING_X, w, h, bpp), CREATE_TEMPORARY); if (bo) { int16_t dx = this.extents.x1; int16_t dy = this.extents.y1; assert(bo->pitch <= 8192); assert(bo->tiling != I915_TILING_Y); if (!sna_blt_copy_boxes(sna, alu, src_bo, src_dx, src_dy, bo, -dx, -dy, bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this))) goto err; if (!sna_blt_copy_boxes(sna, alu, bo, -dx, -dy, dst_bo, dst_dx, dst_dy, bpp, REGION_RECTS(&this), REGION_NUM_RECTS(&this))) goto err; kgem_bo_destroy(&sna->kgem, bo); } RegionUninit(&this); } } ret = true; goto done; err: kgem_bo_destroy(&sna->kgem, bo); RegionUninit(&this); done: pixman_region_fini(®ion); return ret; }