void rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs) { RegionRec clip_reg; RegionPtr tmpRegion; int cd; int lw; int extra; int i; int num_clips; int got_id; xRectangle* rects; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec* pDstPriv; LLOGLN(10, ("rdpPolyArc:")); rects = 0; if (narcs > 0) { rects = (xRectangle*)g_malloc(narcs * sizeof(xRectangle), 0); lw = pGC->lineWidth; if (lw == 0) { lw = 1; } extra = lw / 2; for (i = 0; i < narcs; i++) { rects[i].x = (parcs[i].x - extra) + pDrawable->x; rects[i].y = (parcs[i].y - extra) + pDrawable->y; rects[i].width = parcs[i].width + lw; rects[i].height = parcs[i].height + lw; } } /* do original call */ rdpPolyArcOrg(pDrawable, pGC, narcs, parcs); got_id = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); if (XRDP_IS_OS(pDstPriv)) { rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { if (pDrawable->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDrawable; if (pDstWnd->viewable) { rdpup_get_screen_image_rect(&id); got_id = 1; } } } if (!got_id) { g_free(rects); return; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDrawable, pGC); if (cd == 1) { if (rects != 0) { tmpRegion = RegionFromRects(narcs, rects, CT_NONE); num_clips = REGION_NUM_RECTS(tmpRegion); if (num_clips > 0) { rdpup_begin_update(); for (i = num_clips - 1; i >= 0; i--) { box = REGION_RECTS(tmpRegion)[i]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } RegionDestroy(tmpRegion); } } else if (cd == 2) { if (rects != 0) { tmpRegion = RegionFromRects(narcs, rects, CT_NONE); RegionIntersect(tmpRegion, tmpRegion, &clip_reg); num_clips = REGION_NUM_RECTS(tmpRegion); if (num_clips > 0) { rdpup_begin_update(); for (i = num_clips - 1; i >= 0; i--) { box = REGION_RECTS(tmpRegion)[i]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } RegionDestroy(tmpRegion); } } RegionUninit(&clip_reg); g_free(rects); rdpup_switch_os_surface(-1); }
void rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs) { RegionRec clip_reg; RegionPtr tmpRegion; int cd; int lw; int extra; int i; int num_clips; int got_id; int dirty_type; int post_process; int reset_surface; xRectangle *rects; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; LLOGLN(10, ("rdpPolyFillArc:")); rects = 0; if (narcs > 0) { rects = (xRectangle *)g_malloc(narcs * sizeof(xRectangle), 0); lw = pGC->lineWidth; if (lw == 0) { lw = 1; } extra = lw / 2; for (i = 0; i < narcs; i++) { rects[i].x = (parcs[i].x - extra) + pDrawable->x; rects[i].y = (parcs[i].y - extra) + pDrawable->y; rects[i].width = parcs[i].width + lw; rects[i].height = parcs[i].height + lw; } } /* do original call */ rdpPolyFillArcOrg(pDrawable, pGC, narcs, parcs); dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; got_id = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpPolyFillArc: getting dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; dirty_type = RDI_IMGLY; } else { rdpup_switch_os_surface(pDstPriv->rdpindex); reset_surface = 1; rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } } else { if (pDrawable->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDrawable; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(10, ("rdpPolyFillArc: getting dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { g_free(rects); return; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDrawable, pGC); if (cd == 1) { if (rects != 0) { tmpRegion = RegionFromRects(narcs, rects, CT_NONE); num_clips = REGION_NUM_RECTS(tmpRegion); if (num_clips > 0) { if (dirty_type != 0) { draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYFILLARC); } else if (got_id) { rdpup_begin_update(); for (i = num_clips - 1; i >= 0; i--) { box = REGION_RECTS(tmpRegion)[i]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } } RegionDestroy(tmpRegion); } } else if (cd == 2) { if (rects != 0) { tmpRegion = RegionFromRects(narcs, rects, CT_NONE); RegionIntersect(tmpRegion, tmpRegion, &clip_reg); num_clips = REGION_NUM_RECTS(tmpRegion); if (num_clips > 0) { if (dirty_type != 0) { draw_item_add_img_region(pDirtyPriv, tmpRegion, GXcopy, dirty_type, TAG_POLYFILLARC); } else if (got_id) { rdpup_begin_update(); for (i = num_clips - 1; i >= 0; i--) { box = REGION_RECTS(tmpRegion)[i]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } } RegionDestroy(tmpRegion); } } RegionUninit(&clip_reg); g_free(rects); if (reset_surface) { rdpup_switch_os_surface(-1); } }
void rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { RegionRec reg; RegionRec reg1; int num_clips; int cd; int j; int got_id; int dirty_type; int post_process; int reset_surface; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; LLOGLN(10, ("rdpImageGlyphBlt:")); if (nglyph != 0) { GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); } /* do original call */ rdpImageGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; got_id = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpImageGlyphBlt: gettig dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; dirty_type = RDI_IMGLL; } else { rdpup_switch_os_surface(pDstPriv->rdpindex); reset_surface = 1; rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } } else { if (pDrawable->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDrawable; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(0, ("rdpImageGlyphBlt: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { return; } RegionInit(®, NullBox, 0); if (nglyph == 0) { cd = 0; } else { cd = rdp_get_clip(®, pDrawable, pGC); } if (cd == 1) { if (dirty_type != 0) { RegionInit(®1, &box, 0); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, TAG_IMAGEGLYPHBLT); RegionUninit(®1); } else if (got_id) { rdpup_begin_update(); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_end_update(); } } else if (cd == 2) { RegionInit(®1, &box, 0); RegionIntersect(®, ®, ®1); num_clips = REGION_NUM_RECTS(®); if (num_clips > 0) { if (dirty_type != 0) { draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type, TAG_IMAGEGLYPHBLT); } else if (got_id) { rdpup_begin_update(); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(®)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } } RegionUninit(®1); } RegionUninit(®); if (reset_surface) { rdpup_switch_os_surface(-1); } return; }
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; }
void rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { RegionRec reg; RegionRec reg1; int num_clips; int cd; int j; int post_process; BoxRec box; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; LLOGLN(10, ("rdpPolyGlyphBlt:")); if (nglyph != 0) { GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); } /* do original call */ rdpPolyGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); post_process = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr) pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); } else { if (pDrawable->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr) pDrawable; if (pDstWnd->viewable) { post_process = 1; } } } if (!post_process) return; RegionInit(®, NullBox, 0); if (nglyph == 0) { cd = 0; } else { cd = rdp_get_clip(®, pDrawable, pGC); } if (cd == 1) { rdpup_begin_update(); rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_end_update(); } else if (cd == 2) { RegionInit(®1, &box, 0); RegionIntersect(®, ®, ®1); num_clips = REGION_NUM_RECTS(®); if (num_clips > 0) { rdpup_begin_update(); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(®)[j]; rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } RegionUninit(®1); } RegionUninit(®); return; }
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); }
/** * 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; }
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(); }
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; } }
void rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle* prectInit) { int j; int cd; int num_clips; RegionRec clip_reg; RegionPtr fill_reg; BoxRec box; int got_id; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec* pDstPriv; LLOGLN(10, ("rdpPolyFillRect:")); /* make a copy of rects */ fill_reg = RegionFromRects(nrectFill, prectInit, CT_NONE); /* do original call */ rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit); got_id = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); if (XRDP_IS_OS(pDstPriv)) { rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { if (pDrawable->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDrawable; if (pDstWnd->viewable) { rdpup_get_screen_image_rect(&id); got_id = 1; } } } if (!got_id) { RegionDestroy(fill_reg); return; } RegionTranslate(fill_reg, pDrawable->x, pDrawable->y); RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDrawable, pGC); if (cd == 1) /* no clip */ { rdpup_begin_update(); if (pGC->fillStyle == 0 && /* solid fill */ (pGC->alu == GXclear || pGC->alu == GXset || pGC->alu == GXinvert || pGC->alu == GXnoop || pGC->alu == GXand || pGC->alu == GXcopy /*|| pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ { rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_opcode(pGC->alu); for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) { box = REGION_RECTS(fill_reg)[j]; rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_set_opcode(GXcopy); } else /* non solid fill */ { for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--) { box = REGION_RECTS(fill_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } rdpup_end_update(); } else if (cd == 2) /* clip */ { RegionIntersect(&clip_reg, &clip_reg, fill_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { rdpup_begin_update(); if (pGC->fillStyle == 0 && /* solid fill */ (pGC->alu == GXclear || pGC->alu == GXset || pGC->alu == GXinvert || pGC->alu == GXnoop || pGC->alu == GXand || pGC->alu == GXcopy /*|| pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */ { rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_opcode(pGC->alu); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_set_opcode(GXcopy); } else /* non solid fill */ { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } rdpup_end_update(); } } RegionUninit(&clip_reg); RegionDestroy(fill_reg); rdpup_switch_os_surface(-1); }
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); }
/* tested with pGC->lineWidth = 0, 1, 2, 4 and opcodes 3 and 6 */ void rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects) { RegionRec clip_reg; RegionPtr fill_reg; int num_clips; int cd; int lw; int i; int j; int up; int down; int got_id; int dirty_type; int post_process; int reset_surface; xRectangle *regRects; xRectangle *r; xRectangle *rect1; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; LLOGLN(10, ("rdpPolyRectangle:")); /* make a copy of rects */ rect1 = (xRectangle *)g_malloc(sizeof(xRectangle) * nrects, 0); for (i = 0; i < nrects; i++) { rect1[i] = rects[i]; } /* do original call */ rdpPolyRectangleOrg(pDrawable, pGC, nrects, rects); dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; got_id = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpPolyRectangle: gettig dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; dirty_type = RDI_IMGLL; } else { rdpup_switch_os_surface(pDstPriv->rdpindex); reset_surface = 1; rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } } else { if (pDrawable->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDrawable; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(0, ("rdpPolyRectangle: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { g_free(rect1); return; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDrawable, pGC); regRects = 0; if ((cd != 0) && (nrects > 0)) { regRects = (xRectangle *)g_malloc(nrects * 4 * sizeof(xRectangle), 0); lw = pGC->lineWidth; if (lw < 1) { lw = 1; } up = lw / 2; down = 1 + (lw - 1) / 2; for (i = 0; i < nrects; i++) { r = regRects + i * 4; r->x = (rect1[i].x + pDrawable->x) - up; r->y = (rect1[i].y + pDrawable->y) - up; r->width = rect1[i].width + up + down; r->height = lw; r++; r->x = (rect1[i].x + pDrawable->x) - up; r->y = (rect1[i].y + pDrawable->y) + down; r->width = lw; r->height = MAX(rect1[i].height - (up + down), 0); r++; r->x = ((rect1[i].x + rect1[i].width) + pDrawable->x) - up; r->y = (rect1[i].y + pDrawable->y) + down; r->width = lw; r->height = MAX(rect1[i].height - (up + down), 0); r++; r->x = (rect1[i].x + pDrawable->x) - up; r->y = ((rect1[i].y + rect1[i].height) + pDrawable->y) - up; r->width = rect1[i].width + up + down; r->height = lw; } } if (cd == 1) { if (regRects != 0) { if (dirty_type != 0) { fill_reg = RegionFromRects(nrects * 4, regRects, CT_NONE); if (pGC->lineStyle == LineSolid) { draw_item_add_fill_region(pDirtyPriv, fill_reg, pGC->fgPixel, pGC->alu); } else { draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, dirty_type); } RegionDestroy(fill_reg); } else if (got_id) { rdpup_begin_update(); if (pGC->lineStyle == LineSolid) { rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_opcode(pGC->alu); for (i = 0; i < nrects * 4; i++) { r = regRects + i; rdpup_fill_rect(r->x, r->y, r->width, r->height); } rdpup_set_opcode(GXcopy); } else { for (i = 0; i < nrects * 4; i++) { r = regRects + i; rdpup_send_area(&id, r->x, r->y, r->width, r->height); } } rdpup_end_update(); } } } else if (cd == 2) { if (regRects != 0) { fill_reg = RegionFromRects(nrects * 4, regRects, CT_NONE); RegionIntersect(&clip_reg, &clip_reg, fill_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { if (dirty_type != 0) { if (pGC->lineStyle == LineSolid) { draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel, pGC->alu); } else { draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type); } } else if (got_id) { rdpup_begin_update(); if (pGC->lineStyle == LineSolid) { rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_opcode(pGC->alu); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_set_opcode(GXcopy); } else { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } rdpup_end_update(); } } RegionDestroy(fill_reg); } } RegionUninit(&clip_reg); g_free(regRects); g_free(rect1); if (reset_surface) { rdpup_switch_os_surface(-1); } }
bool sna_video_clip_helper(ScrnInfoPtr scrn, struct sna_video *video, struct sna_video_frame *frame, xf86CrtcPtr * crtc_ret, BoxPtr dst, short src_x, short src_y, short drw_x, short drw_y, short src_w, short src_h, short drw_w, short drw_h, RegionPtr reg) { bool ret; RegionRec crtc_region_local; RegionPtr crtc_region = reg; INT32 x1, x2, y1, y2; xf86CrtcPtr crtc; x1 = src_x; x2 = src_x + src_w; y1 = src_y; y2 = src_y + src_h; dst->x1 = drw_x; dst->x2 = drw_x + drw_w; dst->y1 = drw_y; dst->y2 = drw_y + drw_h; /* * For overlay video, compute the relevant CRTC and * clip video to that */ crtc = sna_covering_crtc(scrn, dst, video->desired_crtc); /* For textured video, we don't actually want to clip at all. */ if (crtc && !video->textured) { crtc_region_local.extents = crtc->bounds; crtc_region_local.data = NULL; crtc_region = &crtc_region_local; RegionIntersect(crtc_region, crtc_region, reg); } *crtc_ret = crtc; ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2, crtc_region, frame->width, frame->height); if (crtc_region != reg) RegionUninit(crtc_region); frame->src.x1 = x1 >> 16; frame->src.y1 = y1 >> 16; frame->src.x2 = (x2 + 0xffff) >> 16; frame->src.y2 = (y2 + 0xffff) >> 16; frame->image.x1 = frame->src.x1 & ~1; frame->image.x2 = ALIGN(frame->src.x2, 2); if (is_planar_fourcc(frame->id)) { frame->image.y1 = frame->src.y1 & ~1; frame->image.y2 = ALIGN(frame->src.y2, 2); } else { frame->image.y1 = frame->src.y1; frame->image.y2 = frame->src.y2; } return ret; }
RegionPtr rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane) { RegionPtr rv; RegionRec clip_reg; RegionRec box_reg; int cd; int num_clips; int j; int post_process; BoxRec box; BoxPtr pbox; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; LLOGLN(10, ("rdpCopyPlane:")); /* do original call */ rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); post_process = 0; if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr) pDst; pDstPriv = GETPIXPRIV(pDstPixmap); } else { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr) pDst; if (pDstWnd->viewable) { post_process = 1; } } } if (!post_process) return rv; RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { rdp_send_area_update(pDst->x + dstx, pDst->y + dsty, w, h); } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips < 10) { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdp_send_area_update(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } else { pbox = RegionExtents(&clip_reg); rdp_send_area_update(pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); } RegionUninit(&box_reg); } } RegionUninit(&clip_reg); return rv; }
/*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 winCopyWindowNativeGDI(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { DDXPointPtr pptSrc; DDXPointPtr ppt; RegionPtr prgnDst; BoxPtr pBox; int dx, dy; int i, nbox; WindowPtr pwinRoot; BoxPtr pBoxDst; ScreenPtr pScreen = pWin->drawable.pScreen; winScreenPriv(pScreen); /* Get a pointer to the root window */ pwinRoot = pWin->drawable.pScreen->root; /* Create a region for the destination */ prgnDst = RegionCreate(NULL, 1); /* Calculate the shift from the source to the destination */ dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; /* Translate the region from the destination to the source? */ RegionTranslate(prgnSrc, -dx, -dy); RegionIntersect(prgnDst, &pWin->borderClip, prgnSrc); /* Get a pointer to the first box in the region to be copied */ pBox = RegionRects(prgnDst); /* Get the number of boxes in the region */ nbox = RegionNumRects(prgnDst); /* Allocate source points for each box */ if (!(pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) return; /* Set an iterator pointer */ ppt = pptSrc; /* Calculate the source point of each box? */ for (i = nbox; --i >= 0; ppt++, pBox++) { ppt->x = pBox->x1 + dx; ppt->y = pBox->y1 + dy; } /* Setup loop pointers again */ pBoxDst = RegionRects(prgnDst); ppt = pptSrc; /* BitBlt each source to the destination point */ for (i = nbox; --i >= 0; pBoxDst++, ppt++) { BitBlt(pScreenPriv->hdcScreen, pBoxDst->x1, pBoxDst->y1, pBoxDst->x2 - pBoxDst->x1, pBoxDst->y2 - pBoxDst->y1, pScreenPriv->hdcScreen, ppt->x, ppt->y, SRCCOPY); } /* Cleanup the regions, etc. */ free(pptSrc); RegionDestroy(prgnDst); }
static void exaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { ExaScreenPriv (pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); ExaPixmapPriv (pPixmap); register BoxPtr pbox; BoxPtr pextent; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1, fullY2; int partX1, partX2, partY1, partY2; int xoff, yoff; int xorg, yorg; int n; RegionPtr pReg = RegionFromRects(nrect, prect, CT_UNSORTED); /* Compute intersection of rects and clip region */ RegionTranslate(pReg, pDrawable->x, pDrawable->y); RegionIntersect(pReg, pClip, pReg); if (!RegionNumRects(pReg)) { goto out; } exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); if (pExaScr->fallback_counter || pExaScr->swappedOut || pExaPixmap->accel_blocked) { goto fallback; } /* For ROPs where overlaps don't matter, convert rectangles to region and * call exaFillRegion{Solid,Tiled}. */ if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop || pGC->alu == GXcopyInverted || pGC->alu == GXset)) { if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? pGC->fgPixel : pGC->tile.pixel, pGC->planemask, pGC->alu, pGC->clientClipType)) || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, pGC->planemask, pGC->alu, pGC->clientClipType))) { goto out; } } if (pGC->fillStyle != FillSolid && !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { goto fallback; } if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap; pixmaps[0].pReg = NULL; exaDoMigration (pixmaps, 1, TRUE); } if (!exaPixmapHasGpuCopy (pPixmap) || !(*pExaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { fallback: ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); goto out; } xorg = pDrawable->x; yorg = pDrawable->y; pextent = RegionExtents(pClip); extentX1 = pextent->x1; extentY1 = pextent->y1; extentX2 = pextent->x2; extentY2 = pextent->y2; while (nrect--) { fullX1 = prect->x + xorg; fullY1 = prect->y + yorg; fullX2 = fullX1 + (int) prect->width; fullY2 = fullY1 + (int) prect->height; prect++; if (fullX1 < extentX1) fullX1 = extentX1; if (fullY1 < extentY1) fullY1 = extentY1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullY2 > extentY2) fullY2 = extentY2; if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) continue; n = RegionNumRects (pClip); if (n == 1) { (*pExaScr->info->Solid) (pPixmap, fullX1 + xoff, fullY1 + yoff, fullX2 + xoff, fullY2 + yoff); } else { pbox = RegionRects(pClip); /* * clip the rectangle to each box in the clip region * this is logically equivalent to calling Intersect(), * but rectangles may overlap each other here. */ while(n--) { partX1 = pbox->x1; if (partX1 < fullX1) partX1 = fullX1; partY1 = pbox->y1; if (partY1 < fullY1) partY1 = fullY1; partX2 = pbox->x2; if (partX2 > fullX2) partX2 = fullX2; partY2 = pbox->y2; if (partY2 > fullY2) partY2 = fullY2; pbox++; if (partX1 < partX2 && partY1 < partY2) { (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); } } } } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); out: RegionUninit(pReg); RegionDestroy(pReg); }
/** * 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); }
/* it looks like all the antialias draws go through here */ void rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { BoxRec box; PictureScreenPtr ps; RegionRec reg1; RegionRec reg2; DrawablePtr p; int j; int num_clips; int got_id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec* pDstPriv; struct image_data id; LLOGLN(10, ("rdpComposite:")); ps = GetPictureScreen(g_pScreen); ps->Composite = g_rdpScreen.Composite; ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); ps->Composite = rdpComposite; p = pDst->pDrawable; got_id = 0; if (p->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)p; pDstPriv = GETPIXPRIV(pDstPixmap); if (XRDP_IS_OS(pDstPriv)) { rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { if (p->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)p; if (pDstWnd->viewable) { rdpup_get_screen_image_rect(&id); got_id = 1; } } } if (!got_id) { return; } if (pDst->clientClipType == CT_REGION) { box.x1 = p->x + xDst; box.y1 = p->y + yDst; box.x2 = box.x1 + width; box.y2 = box.y1 + height; RegionInit(®1, &box, 0); RegionInit(®2, NullBox, 0); RegionCopy(®2, pDst->clientClip); RegionTranslate(®2, p->x + pDst->clipOrigin.x, p->y + pDst->clipOrigin.y); RegionIntersect(®1, ®1, ®2); num_clips = REGION_NUM_RECTS(®1); if (num_clips > 0) { rdpup_begin_update(); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(®1)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } RegionUninit(®1); RegionUninit(®2); } else { box.x1 = p->x + xDst; box.y1 = p->y + yDst; box.x2 = box.x1 + width; box.y2 = box.y1 + height; rdpup_begin_update(); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_end_update(); } rdpup_switch_os_surface(-1); }
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; }
/* 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; }
RegionPtr rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane) { RegionPtr rv; RegionRec clip_reg; RegionRec box_reg; int cd; int num_clips; int j; int got_id; BoxRec box; BoxPtr pbox; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec* pDstPriv; LLOGLN(10, ("rdpCopyPlane:")); /* do original call */ rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); got_id = 0; if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (XRDP_IS_OS(pDstPriv)) { rdpup_switch_os_surface(pDstPriv->rdpindex); rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { rdpup_get_screen_image_rect(&id); got_id = 1; } } } if (!got_id) { return rv; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { rdpup_begin_update(); rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); rdpup_end_update(); } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { rdpup_begin_update(); box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips < 10) { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } else { pbox = RegionExtents(&clip_reg); rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); } RegionUninit(&box_reg); rdpup_end_update(); } } RegionUninit(&clip_reg); return rv; }
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; }
void miComputeCompositeClip(GCPtr pGC, DrawablePtr pDrawable) { if (pDrawable->type == DRAWABLE_WINDOW) { WindowPtr pWin = (WindowPtr) pDrawable; RegionPtr pregWin; Bool freeTmpClip, freeCompClip; if (pGC->subWindowMode == IncludeInferiors) { pregWin = NotClippedByChildren(pWin); freeTmpClip = TRUE; } else { pregWin = &pWin->clipList; freeTmpClip = FALSE; } freeCompClip = pGC->freeCompClip; /* * if there is no client clip, we can get by with just keeping the * pointer we got, and remembering whether or not should destroy (or * maybe re-use) it later. this way, we avoid unnecessary copying of * regions. (this wins especially if many clients clip by children * and have no client clip.) */ if (!pGC->clientClip) { if (freeCompClip) RegionDestroy(pGC->pCompositeClip); pGC->pCompositeClip = pregWin; pGC->freeCompClip = freeTmpClip; } else { /* * we need one 'real' region to put into the composite clip. if * pregWin the current composite clip are real, we can get rid of * one. if pregWin is real and the current composite clip isn't, * use pregWin for the composite clip. if the current composite * clip is real and pregWin isn't, use the current composite * clip. if neither is real, create a new region. */ RegionTranslate(pGC->clientClip, pDrawable->x + pGC->clipOrg.x, pDrawable->y + pGC->clipOrg.y); if (freeCompClip) { RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip); if (freeTmpClip) RegionDestroy(pregWin); } else if (freeTmpClip) { RegionIntersect(pregWin, pregWin, pGC->clientClip); pGC->pCompositeClip = pregWin; } else { pGC->pCompositeClip = RegionCreate(NullBox, 0); RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip); } pGC->freeCompClip = TRUE; RegionTranslate(pGC->clientClip, -(pDrawable->x + pGC->clipOrg.x), -(pDrawable->y + pGC->clipOrg.y)); } } /* end of composite clip for a window */ else { BoxRec pixbounds; /* XXX should we translate by drawable.x/y here ? */ /* If you want pixmaps in offscreen memory, yes */ pixbounds.x1 = pDrawable->x; pixbounds.y1 = pDrawable->y; pixbounds.x2 = pDrawable->x + pDrawable->width; pixbounds.y2 = pDrawable->y + pDrawable->height; if (pGC->freeCompClip) { RegionReset(pGC->pCompositeClip, &pixbounds); } else { pGC->freeCompClip = TRUE; pGC->pCompositeClip = RegionCreate(&pixbounds, 1); } if (pGC->clientClip) { if (pDrawable->x || pDrawable->y) { RegionTranslate(pGC->clientClip, pDrawable->x + pGC->clipOrg.x, pDrawable->y + pGC->clipOrg.y); RegionIntersect(pGC->pCompositeClip, pGC->pCompositeClip, pGC->clientClip); RegionTranslate(pGC->clientClip, -(pDrawable->x + pGC->clipOrg.x), -(pDrawable->y + pGC->clipOrg.y)); } else { RegionTranslate(pGC->pCompositeClip, -pGC->clipOrg.x, -pGC->clipOrg.y); RegionIntersect(pGC->pCompositeClip, pGC->pCompositeClip, pGC->clientClip); RegionTranslate(pGC->pCompositeClip, pGC->clipOrg.x, pGC->clipOrg.y); } } } /* end of composite clip for pixmap */ } /* end miComputeCompositeClip */
/** Transfer \a pBits image to back-end server associated with \a * pDrawable's screen. If primitive subdivision optimization is * enabled, then only transfer the sections of \a pBits that are * visible (i.e., not-clipped) to the back-end server. */ void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) { DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); XImage *img; if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; img = XCreateImage(dmxScreen->beDisplay, dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, depth, format, leftPad, pBits, w, h, BitmapPad(dmxScreen->beDisplay), (format == ZPixmap) ? PixmapBytePad(w, depth) : BitmapBytePad(w+leftPad)); if (img) { Drawable draw; DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); if (dmxSubdividePrimitives && pGC->pCompositeClip) { RegionPtr pSubImages; RegionPtr pClip; BoxRec box; BoxPtr pBox; int nBox; box.x1 = x; box.y1 = y; box.x2 = x + w; box.y2 = y + h; pSubImages = RegionCreate(&box, 1); pClip = RegionCreate(NullBox, 1); RegionCopy(pClip, pGC->pCompositeClip); RegionTranslate(pClip, -pDrawable->x, -pDrawable->y); RegionIntersect(pSubImages, pSubImages, pClip); nBox = RegionNumRects(pSubImages); pBox = RegionRects(pSubImages); while (nBox--) { XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img, pBox->x1 - box.x1, pBox->y1 - box.y1, pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1); pBox++; } RegionDestroy(pClip); RegionDestroy(pSubImages); } else { XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img, 0, 0, x, y, w, h); } XFree(img); /* Use XFree instead of XDestroyImage * because pBits is passed in from the * caller. */ dmxSync(dmxScreen, FALSE); } else { /* Error -- this should not happen! */ } }
RegionPtr rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { RegionPtr rv; RegionRec clip_reg; RegionRec box_reg; RegionRec reg1; int num_clips; int cd; int j; int can_do_screen_blt; int got_id; int dirty_type; int post_process; int reset_surface; struct image_data id; BoxRec box; BoxPtr pbox; PixmapPtr pSrcPixmap; PixmapPtr pDstPixmap; rdpPixmapRec *pSrcPriv; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; WindowPtr pDstWnd; WindowPtr pSrcWnd; LLOGLN(10, ("rdpCopyArea: x %d y %d w %d h %d", dstx, dsty, w, h)); if (pSrc->type == DRAWABLE_WINDOW) { pSrcWnd = (WindowPtr)pSrc; if (pSrcWnd->viewable) { rdpup_check_dirty_screen(&g_screenPriv); if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { can_do_screen_blt = pGC->alu == GXcopy; if (can_do_screen_blt) { return rdpCopyAreaWndToWnd(pSrcWnd, pDstWnd, pGC, srcx, srcy, w, h, dstx, dsty); } } } else if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { can_do_screen_blt = pGC->alu == GXcopy; if (can_do_screen_blt) { rdpup_check_dirty(pDstPixmap, pDstPriv); return rdpCopyAreaWndToPixmap(pSrcWnd, pDstPixmap, pDstPriv, pGC, srcx, srcy, w, h, dstx, dsty); } } else { LLOGLN(10, ("rdpCopyArea: 1")); } } } } if (pSrc->type == DRAWABLE_PIXMAP) { pSrcPixmap = (PixmapPtr)pSrc; pSrcPriv = GETPIXPRIV(pSrcPixmap); if (xrdp_is_os(pSrcPixmap, pSrcPriv)) { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { rdpup_check_dirty_screen(&g_screenPriv); rdpup_check_dirty(pSrcPixmap, pSrcPriv); return rdpCopyAreaPixmapToWnd(pSrcPixmap, pSrcPriv, pDstWnd, pGC, srcx, srcy, w, h, dstx, dsty); } } else if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { if (g_can_do_pix_to_pix) { rdpup_check_dirty(pSrcPixmap, pSrcPriv); rdpup_check_dirty(pDstPixmap, pDstPriv); return rdpCopyAreaPixmapToPixmap(pSrcPixmap, pSrcPriv, pDstPixmap, pDstPriv, pGC, srcx, srcy, w, h, dstx, dsty); } } else { LLOGLN(10, ("rdpCopyArea: 4")); } } } else { LLOGLN(10, ("rdpCopyArea: 2")); } } /* do original call */ rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; got_id = 0; if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpCopyArea: gettig dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; dirty_type = RDI_IMGLL; } else { rdpup_switch_os_surface(pDstPriv->rdpindex); reset_surface = 1; rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { LLOGLN(10, ("rdpCopyArea: 3")); } } else { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(10, ("rdpCopyArea: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { return rv; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { if (dirty_type != 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(®1, &box, 0); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, 1); RegionUninit(®1); } else if (got_id) { rdpup_begin_update(); rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); rdpup_end_update(); } } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { if (dirty_type != 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 1); RegionUninit(&box_reg); } else if (got_id) { rdpup_begin_update(); box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips < 10) { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } else { pbox = RegionExtents(&clip_reg); rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); } RegionUninit(&box_reg); rdpup_end_update(); } } } RegionUninit(&clip_reg); if (reset_surface) { rdpup_switch_os_surface(-1); } return rv; }
/* *----------------------------------------------------------------------- * 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 miValidatePicture (PicturePtr pPicture, Mask mask) { DrawablePtr pDrawable = pPicture->pDrawable; if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) || (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) { if (pDrawable->type == DRAWABLE_WINDOW) { WindowPtr pWin = (WindowPtr) pDrawable; RegionPtr pregWin; Bool freeTmpClip, freeCompClip; if (pPicture->subWindowMode == IncludeInferiors) { pregWin = NotClippedByChildren(pWin); freeTmpClip = TRUE; } else { pregWin = &pWin->clipList; freeTmpClip = FALSE; } freeCompClip = pPicture->freeCompClip; /* * if there is no client clip, we can get by with just keeping the * pointer we got, and remembering whether or not should destroy * (or maybe re-use) it later. this way, we avoid unnecessary * copying of regions. (this wins especially if many clients clip * by children and have no client clip.) */ if (pPicture->clientClipType == CT_NONE) { if (freeCompClip) RegionDestroy(pPicture->pCompositeClip); pPicture->pCompositeClip = pregWin; pPicture->freeCompClip = freeTmpClip; } else { /* * we need one 'real' region to put into the composite clip. if * pregWin the current composite clip are real, we can get rid of * one. if pregWin is real and the current composite clip isn't, * use pregWin for the composite clip. if the current composite * clip is real and pregWin isn't, use the current composite * clip. if neither is real, create a new region. */ RegionTranslate(pPicture->clientClip, pDrawable->x + pPicture->clipOrigin.x, pDrawable->y + pPicture->clipOrigin.y); if (freeCompClip) { RegionIntersect(pPicture->pCompositeClip, pregWin, pPicture->clientClip); if (freeTmpClip) RegionDestroy(pregWin); } else if (freeTmpClip) { RegionIntersect(pregWin, pregWin, pPicture->clientClip); pPicture->pCompositeClip = pregWin; } else { pPicture->pCompositeClip = RegionCreate(NullBox, 0); RegionIntersect(pPicture->pCompositeClip, pregWin, pPicture->clientClip); } pPicture->freeCompClip = TRUE; RegionTranslate(pPicture->clientClip, -(pDrawable->x + pPicture->clipOrigin.x), -(pDrawable->y + pPicture->clipOrigin.y)); } } /* end of composite clip for a window */ else { BoxRec pixbounds; /* XXX should we translate by drawable.x/y here ? */ /* If you want pixmaps in offscreen memory, yes */ pixbounds.x1 = pDrawable->x; pixbounds.y1 = pDrawable->y; pixbounds.x2 = pDrawable->x + pDrawable->width; pixbounds.y2 = pDrawable->y + pDrawable->height; if (pPicture->freeCompClip) { RegionReset(pPicture->pCompositeClip, &pixbounds); } else { pPicture->freeCompClip = TRUE; pPicture->pCompositeClip = RegionCreate(&pixbounds, 1); } if (pPicture->clientClipType == CT_REGION) { if(pDrawable->x || pDrawable->y) { RegionTranslate(pPicture->clientClip, pDrawable->x + pPicture->clipOrigin.x, pDrawable->y + pPicture->clipOrigin.y); RegionIntersect(pPicture->pCompositeClip, pPicture->pCompositeClip, pPicture->clientClip); RegionTranslate(pPicture->clientClip, -(pDrawable->x + pPicture->clipOrigin.x), -(pDrawable->y + pPicture->clipOrigin.y)); } else { RegionTranslate(pPicture->pCompositeClip, -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); RegionIntersect(pPicture->pCompositeClip, pPicture->pCompositeClip, pPicture->clientClip); RegionTranslate(pPicture->pCompositeClip, pPicture->clipOrigin.x, pPicture->clipOrigin.y); } } } /* end of composite clip for pixmap */ } }
/* it looks like all the antialias draws go through here */ void rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { BoxRec box; PictureScreenPtr ps; RegionRec reg1; RegionRec reg2; DrawablePtr p; int dirty_type; int j; int num_clips; int post_process; int reset_surface; int got_id; int lx; int ly; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; struct image_data id; LLOGLN(10, ("rdpComposite:")); ps = GetPictureScreen(g_pScreen); ps->Composite = g_rdpScreen.Composite; ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); ps->Composite = rdpComposite; p = pDst->pDrawable; dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; got_id = 0; if (p->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)p; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpComposite: gettig dirty")); pDstPriv->is_dirty = 1; dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY; pDirtyPriv = pDstPriv; } else { rdpup_switch_os_surface(pDstPriv->rdpindex); reset_surface = 1; rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; LLOGLN(10, ("rdpComposite: offscreen")); } } } else { if (p->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)p; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(0, ("rdpComposite: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; LLOGLN(10, ("rdpComposite: screen")); } } } } if (!post_process) { return; } if (pDst->clientClipType == CT_REGION) { box.x1 = p->x + xDst; box.y1 = p->y + yDst; box.x2 = box.x1 + width; box.y2 = box.y1 + height; RegionInit(®1, &box, 0); RegionInit(®2, NullBox, 0); RegionCopy(®2, pDst->clientClip); lx = p->x + pDst->clipOrigin.x; ly = p->y + pDst->clipOrigin.y; RegionTranslate(®2, lx, ly); RegionIntersect(®1, ®1, ®2); if (dirty_type != 0) { draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); } else if (got_id) { num_clips = REGION_NUM_RECTS(®1); if (num_clips > 0) { rdpup_begin_update(); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(®1)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } } RegionUninit(®1); RegionUninit(®2); } else { box.x1 = p->x + xDst; box.y1 = p->y + yDst; box.x2 = box.x1 + width; box.y2 = box.y1 + height; if (dirty_type != 0) { RegionInit(®1, &box, 0); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); RegionUninit(®1); } else if (got_id) { rdpup_begin_update(); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_end_update(); } } if (reset_surface) { rdpup_switch_os_surface(-1); } }