/***** * miHandleValidateExposures(pWin) * starting at pWin, draw background in any windows that have exposure * regions, translate the regions, restore any backing store, * and then send any regions still exposed to the client *****/ void miHandleValidateExposures(WindowPtr pWin) { WindowPtr pChild; ValidatePtr val; WindowExposuresProcPtr WindowExposures; pChild = pWin; WindowExposures = pChild->drawable.pScreen->WindowExposures; while (1) { if ((val = pChild->valdata)) { if (RegionNotEmpty(&val->after.borderExposed)) miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER); RegionUninit(&val->after.borderExposed); (*WindowExposures) (pChild, &val->after.exposed, NullRegion); RegionUninit(&val->after.exposed); free(val); pChild->valdata = NULL; if (pChild->firstChild) { pChild = pChild->firstChild; continue; } } while (!pChild->nextSib && (pChild != pWin)) pChild = pChild->parent; if (pChild == pWin) break; pChild = pChild->nextSib; } }
static void ephyrInternalDamageRedisplay(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; EphyrScrPriv *scrpriv = screen->driver; RegionPtr pRegion; if (!scrpriv || !scrpriv->pDamage) return; pRegion = DamageRegion(scrpriv->pDamage); if (RegionNotEmpty(pRegion)) { int nbox; BoxPtr pbox; if (ephyr_glamor) { ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion); } else { nbox = RegionNumRects(pRegion); pbox = RegionRects(pRegion); while (nbox--) { hostx_paint_rect(screen, pbox->x1, pbox->y1, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } } DamageEmpty(scrpriv->pDamage); } }
static Bool xf86RotateRedisplay(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DamagePtr damage = xf86_config->rotation_damage; RegionPtr region; if (!damage) return FALSE; xf86RotatePrepare(pScreen); region = DamageRegion(damage); if (RegionNotEmpty(region)) { int c; SourceValidateProcPtr SourceValidate; /* * SourceValidate is used by the software cursor code * to pull the cursor off of the screen when reading * bits from the frame buffer. Bypassing this function * leaves the software cursor in place */ SourceValidate = pScreen->SourceValidate; pScreen->SourceValidate = NULL; for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; if (crtc->transform_in_use && crtc->enabled) { RegionRec crtc_damage; /* compute portion of damage that overlaps crtc */ RegionInit(&crtc_damage, &crtc->bounds, 1); RegionIntersect(&crtc_damage, &crtc_damage, region); /* update damaged region */ if (RegionNotEmpty(&crtc_damage)) xf86RotateCrtcRedisplay(crtc, &crtc_damage); RegionUninit(&crtc_damage); } } pScreen->SourceValidate = SourceValidate; DamageEmpty(damage); } return TRUE; }
static void shadowRedisplay(ScreenPtr pScreen) { shadowBuf(pScreen); RegionPtr pRegion; if (!pBuf || !pBuf->pDamage || !pBuf->update) return; pRegion = DamageRegion(pBuf->pDamage); if (RegionNotEmpty(pRegion)) { (*pBuf->update) (pScreen, pBuf); DamageEmpty(pBuf->pDamage); } }
/** * Returns TRUE if the pixmap is dirty (has been modified in its current * location compared to the other), or lacks a private for tracking * dirtiness. */ static Bool exaPixmapIsDirty(PixmapPtr pPix) { ExaPixmapPriv(pPix); if (pExaPixmap == NULL) EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE); if (!pExaPixmap->pDamage) return FALSE; return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) || !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB); }
static void rdpValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr d) { rdpGCRec *priv; int wrap; RegionPtr pRegion; LLOGLN(10, ("rdpValidateGC:")); GC_FUNC_PROLOGUE(pGC); pGC->funcs->ValidateGC(pGC, changes, d); if (g_wrapPixmap) { wrap = 1; } else { wrap = (d->type == DRAWABLE_WINDOW) && ((WindowPtr)d)->viewable; if (wrap) { if (pGC->subWindowMode == IncludeInferiors) { pRegion = &(((WindowPtr)d)->borderClip); } else { pRegion = &(((WindowPtr)d)->clipList); } wrap = RegionNotEmpty(pRegion); } } priv->ops = 0; if (wrap) { priv->ops = pGC->ops; } GC_FUNC_EPILOGUE(pGC); }
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; }
/* return 2, draw using clip */ int rdp_get_clip(RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC) { WindowPtr pWindow; RegionPtr temp; BoxRec box; int rv; rv = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { switch (pGC->clientClipType) { case CT_NONE: rv = 1; break; case CT_REGION: rv = 2; RegionCopy(pRegion, pGC->clientClip); break; default: rdpLog("unimp clip type %d\n", pGC->clientClipType); break; } if (rv == 2) /* check if the clip is the entire pixmap */ { box.x1 = 0; box.y1 = 0; box.x2 = pDrawable->width; box.y2 = pDrawable->height; if (RegionContainsRect(pRegion, &box) == rgnIN) { rv = 1; } } } else if (pDrawable->type == DRAWABLE_WINDOW) { pWindow = (WindowPtr)pDrawable; if (pWindow->viewable) { if (pGC->subWindowMode == IncludeInferiors) { temp = &pWindow->borderClip; } else { temp = &pWindow->clipList; } if (RegionNotEmpty(temp)) { switch (pGC->clientClipType) { case CT_NONE: rv = 2; RegionCopy(pRegion, temp); break; case CT_REGION: rv = 2; RegionCopy(pRegion, pGC->clientClip); RegionTranslate(pRegion, pDrawable->x + pGC->clipOrg.x, pDrawable->y + pGC->clipOrg.y); RegionIntersect(pRegion, pRegion, temp); break; default: rdpLog("unimp clip type %d\n", pGC->clientClipType); break; } if (rv == 2) /* check if the clip is the entire screen */ { box.x1 = 0; box.y1 = 0; box.x2 = g_rdpScreen.width; box.y2 = g_rdpScreen.height; if (RegionContainsRect(pRegion, &box) == rgnIN) { rv = 1; } } } } } return rv; }
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; }
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); } }
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; }
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) { 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) { PixmapRec tmp; 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; 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; }