static int ProcDamageSubtract (ClientPtr client) { REQUEST(xDamageSubtractReq); DamageExtPtr pDamageExt; RegionPtr pRepair; RegionPtr pParts; REQUEST_SIZE_MATCH(xDamageSubtractReq); VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess); VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, SecurityWriteAccess); VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, SecurityWriteAccess); if (pDamageExt->level != DamageReportRawRegion) { DamagePtr pDamage = pDamageExt->pDamage; if (pRepair) { if (pParts) REGION_INTERSECT (prScreen, pParts, DamageRegion (pDamage), pRepair); if (DamageSubtract (pDamage, pRepair)) DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt); } else { if (pParts) REGION_COPY (prScreen, pParts, DamageRegion (pDamage)); DamageEmpty (pDamage); } } return (client->noClientException); }
static void miColorRects (PicturePtr pDst, PicturePtr pClipPict, xRenderColor *color, int nRect, xRectangle *rects, int xoff, int yoff) { ScreenPtr pScreen = pDst->pDrawable->pScreen; CARD32 pixel; GCPtr pGC; CARD32 tmpval[5]; RegionPtr pClip; unsigned long mask; miRenderColorToPixel (pDst->pFormat, color, &pixel); pGC = GetScratchGC (pDst->pDrawable->depth, pScreen); if (!pGC) return; tmpval[0] = GXcopy; tmpval[1] = pixel; tmpval[2] = pDst->subWindowMode; mask = GCFunction | GCForeground | GCSubwindowMode; if (pClipPict->clientClipType == CT_REGION) { tmpval[3] = pDst->clipOrigin.x - xoff; tmpval[4] = pDst->clipOrigin.y - yoff; mask |= GCClipXOrigin|GCClipYOrigin; pClip = REGION_CREATE (pScreen, NULL, 1); REGION_COPY (pScreen, pClip, (RegionPtr) pClipPict->clientClip); (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0); } ChangeGC (pGC, mask, tmpval); ValidateGC (pDst->pDrawable, pGC); if (xoff || yoff) { int i; for (i = 0; i < nRect; i++) { rects[i].x -= xoff; rects[i].y -= yoff; } } (*pGC->ops->PolyFillRect) (pDst->pDrawable, pGC, nRect, rects); if (xoff || yoff) { int i; for (i = 0; i < nRect; i++) { rects[i].x += xoff; rects[i].y += yoff; } } FreeScratchGC (pGC); }
/** * Vertically invert a region. */ static void InvertRegion(RegionPtr reg, int height) { const BoxPtr b = REGION_RECTS(reg); const int n = REGION_NUM_RECTS(reg); int i; RegionRec newRegion; miRegionInit(&newRegion, NULL, 0); CRASSERT(miValidRegion(reg)); for (i = 0; i < n; i++) { BoxRec invBox; RegionRec invReg; invBox.x1 = b[i].x1; invBox.y1 = height - b[i].y2; invBox.x2 = b[i].x2; invBox.y2 = height - b[i].y1; CRASSERT(invBox.y1 <= invBox.y2); miRegionInit(&invReg, &invBox, 1); REGION_UNION(&newRegion, &newRegion, &invReg); REGION_UNINIT(&invReg); } CRASSERT(miValidRegion(&newRegion)); REGION_COPY(reg, &newRegion); REGION_UNINIT(&newRegion); }
static void vivante_dri2_CopyRegion(DrawablePtr drawable, RegionPtr pRegion, DRI2BufferPtr dstBuf, DRI2BufferPtr srcBuf) { ScreenPtr screen = drawable->pScreen; DrawablePtr src = vivante_dri2_get_drawable(srcBuf, drawable); DrawablePtr dst = vivante_dri2_get_drawable(dstBuf, drawable); RegionPtr clip; GCPtr gc; gc = GetScratchGC(dst->depth, screen); if (!gc) return; clip = REGION_CREATE(screen, NULL, 0); REGION_COPY(screen, clip, pRegion); gc->funcs->ChangeClip(gc, CT_REGION, clip, 0); ValidateGC(dst, gc); /* * FIXME: wait for scanline to be outside the region to be copied... * that is an interesting problem for Dove/GAL stuff because they're * independent, and there's no way for the GPU to know where the * scan position is. For now, just do the copy anyway. */ gc->ops->CopyArea(src, dst, gc, 0, 0, drawable->width, drawable->height, 0, 0); FreeScratchGC(gc); }
int ProcXFixesSetRegion (ClientPtr client) { int things; RegionPtr pRegion, pNew; REQUEST (xXFixesSetRegionReq); REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq); VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq); if (things & 4) return BadLength; things >>= 3; pNew = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED); if (!pNew) return BadAlloc; if (!REGION_COPY (0, pRegion, pNew)) { REGION_DESTROY (0, pNew); return BadAlloc; } REGION_DESTROY (0, pNew); return(client->noClientException); }
void compFreePixmap (WindowPtr pWin) { ScreenPtr pScreen = pWin->drawable.pScreen; PixmapPtr pRedirectPixmap, pParentPixmap; CompWindowPtr cw = GetCompWindow (pWin); if (cw->damageRegistered) { DamageUnregister (&pWin->drawable, cw->damage); cw->damageRegistered = FALSE; DamageEmpty (cw->damage); } /* * Move the parent-constrained border clip region back into * the window so that ValidateTree will handle the unmap * case correctly. Unmap adds the window borderClip to the * parent exposed area; regions beyond the parent cause crashes */ REGION_COPY (pScreen, &pWin->borderClip, &cw->borderClip); pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin); pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); pWin->redirectDraw = RedirectDrawNone; compSetPixmap (pWin, pParentPixmap); (*pScreen->DestroyPixmap) (pRedirectPixmap); }
Bool xf86InitFBManagerRegion( ScreenPtr pScreen, RegionPtr FullRegion ){ FBManagerPtr offman; if(REGION_NIL(FullRegion)) return FALSE; if(xf86FBGeneration != serverGeneration) { if((xf86FBScreenIndex = AllocateScreenPrivateIndex()) < 0) return FALSE; xf86FBGeneration = serverGeneration; } if(!xf86RegisterOffscreenManager(pScreen, &xf86FBManFuncs)) return FALSE; offman = xalloc(sizeof(FBManager)); if(!offman) return FALSE; pScreen->devPrivates[xf86FBScreenIndex].ptr = (pointer)offman; offman->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = xf86FBCloseScreen; offman->InitialBoxes = REGION_CREATE(pScreen, NULL, 1); offman->FreeBoxes = REGION_CREATE(pScreen, NULL, 1); REGION_COPY(pScreen, offman->InitialBoxes, FullRegion); REGION_COPY(pScreen, offman->FreeBoxes, FullRegion); offman->pScreen = pScreen; offman->UsedAreas = NULL; offman->LinearAreas = NULL; offman->NumUsedAreas = 0; offman->NumCallbacks = 0; offman->FreeBoxesUpdateCallback = NULL; offman->devPrivates = NULL; return TRUE; }
/** * Get list of dirty rects in current virtual frame buffer. * This is the union of all Cr/GL windows. * NOTE: Called from vnc server thread. * \return GL_TRUE if any dirty rects, GL_FALSE if no dirty rects * If GL_TRUE is returned, the serverBuffer will be set and will be in a * locked state. */ GLboolean vncspuGetDirtyRects(RegionPtr region) { vnc_spu.serverBuffer = DequeueBufferNoBlock(&vnc_spu.filledQueue); if (vnc_spu.serverBuffer) { ScreenBuffer *b = vnc_spu.serverBuffer; if (REGION_NUM_RECTS(&b->dirtyRegion) > 0) { REGION_COPY(region, &b->dirtyRegion); REGION_EMPTY(&b->dirtyRegion) return GL_TRUE; }
int ProcXFixesCopyRegion (ClientPtr client) { RegionPtr pSource, pDestination; REQUEST (xXFixesCopyRegionReq); VERIFY_REGION(pSource, stuff->source, client, DixReadAccess); VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess); if (!REGION_COPY(pScreen, pDestination, pSource)) return BadAlloc; return(client->noClientException); }
RegionPtr XFixesRegionCopy (RegionPtr pRegion) { RegionPtr pNew = REGION_CREATE (0, REGION_EXTENTS(0, pRegion), REGION_NUM_RECTS(pRegion)); if (!pNew) return 0; if (!REGION_COPY (0, pNew, pRegion)) { REGION_DESTROY (0, pNew); return 0; } return pNew; }
/* Do ordinary copy */ static void MaliDRI2CopyRegion_copy(DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) { GCPtr pGC; RegionPtr copyRegion; ScreenPtr pScreen = pDraw->pScreen; MaliDRI2BufferPrivatePtr privates; PixmapPtr pScratchPixmap; privates = (MaliDRI2BufferPrivatePtr)pSrcBuffer->driverPrivate; // DebugMsg("Enter MaliDRI2CopyRegion buf_name:%d\n",pSrcBuffer->name); /* #ifdef HAVE_LIBUMP_CACHE_CONTROL if (privates->handle != UMP_INVALID_MEMORY_HANDLE) { // That's a normal UMP allocation, not a wrapped framebuffer ump_cache_operations_control(UMP_CACHE_OP_START); ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_CPU); ump_cache_operations_control(UMP_CACHE_OP_FINISH); } #endif */ pGC = GetScratchGC(pDraw->depth, pScreen); pScratchPixmap = GetScratchPixmapHeader(pScreen, privates->width, privates->height, privates->depth, pSrcBuffer->cpp * 8, pSrcBuffer->pitch, privates->addr + pSrcBuffer->flags); copyRegion = REGION_CREATE(pScreen, NULL, 0); REGION_COPY(pScreen, copyRegion, pRegion); (*pGC->funcs->ChangeClip)(pGC, CT_REGION, copyRegion, 0); ValidateGC(pDraw, pGC); (*pGC->ops->CopyArea)((DrawablePtr)pScratchPixmap, pDraw, pGC, 0, 0, pDraw->width, pDraw->height, 0, 0); FreeScratchPixmapHeader(pScratchPixmap); FreeScratchGC(pGC); /* #ifdef HAVE_LIBUMP_CACHE_CONTROL if (privates->handle != UMP_INVALID_MEMORY_HANDLE) { // That's a normal UMP allocation, not a wrapped framebuffer ump_cache_operations_control(UMP_CACHE_OP_START); ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_MALI); ump_cache_operations_control(UMP_CACHE_OP_FINISH); } #endif */ }
static void shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure) { ScreenPtr pScreen = closure; shadowBufPtr pBuf = pScreen->devPrivates[shadowScrPrivateIndex].ptr; /* Register the damaged region, use DamageReportNone below when we * want to break BC below... */ REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pRegion); /* * BC hack. In 7.0 and earlier several drivers would inspect the * 'damage' member directly, so we have to keep it existing. */ REGION_COPY(pScreen, &pBuf->damage, pRegion); }
static void MaliDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) { GCPtr pGC; RegionPtr copyRegion; ScreenPtr pScreen = pDraw->pScreen; MaliDRI2BufferPrivatePtr privates; PixmapPtr pScratchPixmap; privates = (MaliDRI2BufferPrivatePtr)pSrcBuffer->driverPrivate; if (privates->depth != pDraw->depth) { ErrorF("MaliDRI2CopyRegion: privates->depth != pDraw->depth (%d vs. %d)\n", privates->depth, pDraw->depth); return; } //ErrorF("MaliDRI2CopyRegion dstbuf=%p srcbuf=%p, depth=%d\n", pDstBuffer, pSrcBuffer, privates->depth); ump_cache_operations_control(UMP_CACHE_OP_START); ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_CPU); ump_cache_operations_control(UMP_CACHE_OP_FINISH); pGC = GetScratchGC(pDraw->depth, pScreen); pScratchPixmap = GetScratchPixmapHeader(pScreen, privates->width, privates->height, privates->depth, pSrcBuffer->cpp * 8, pSrcBuffer->pitch, privates->addr); copyRegion = REGION_CREATE(pScreen, NULL, 0); REGION_COPY(pScreen, copyRegion, pRegion); (*pGC->funcs->ChangeClip)(pGC, CT_REGION, copyRegion, 0); ValidateGC(pDraw, pGC); (*pGC->ops->CopyArea)(pScratchPixmap, pDraw, pGC, 0, 0, pDraw->width, pDraw->height, 0, 0); FreeScratchPixmapHeader(pScratchPixmap); FreeScratchGC(pGC); ump_cache_operations_control(UMP_CACHE_OP_START); ump_switch_hw_usage_secure_id(pSrcBuffer->name, UMP_USED_BY_MALI); ump_cache_operations_control(UMP_CACHE_OP_FINISH); }
static void ShadowCopyWindow( WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgn ){ ScreenPtr pScreen = pWin->drawable.pScreen; ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); int num = 0; RegionRec rgnDst; if (pPriv->vtSema) { REGION_NULL(pWin->drawable.pScreen, &rgnDst); REGION_COPY(pWin->drawable.pScreen, &rgnDst, prgn); REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst, pWin->drawable.x - ptOldOrg.x, pWin->drawable.y - ptOldOrg.y); REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, &rgnDst); if ((num = REGION_NUM_RECTS(&rgnDst))) { if(pPriv->preRefresh) (*pPriv->preRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst)); } else { REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); } } pScreen->CopyWindow = pPriv->CopyWindow; (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn); pScreen->CopyWindow = ShadowCopyWindow; if (num) { if (pPriv->postRefresh) (*pPriv->postRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst)); REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); } }
void cfb8_32WidCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWin->drawable.pScreen; cfb8_32WidScreenPtr pScreenPriv = CFB8_32WID_GET_SCREEN_PRIVATE(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; PixmapPtr pPixChildren; DDXPointPtr ppt, pptSrc; RegionRec rgnDst, rgnOther, rgnPixmap; BoxPtr pbox; int i, nbox, dx, dy, other_bpp; REGION_NULL(pScreen, &rgnDst); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); if ((nbox = REGION_NUM_RECTS(&rgnDst)) == 0) { /* Nothing to render. */ REGION_UNINIT(pScreen, &rgnDst); return; } /* First, copy the WID plane for the whole area. */ pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)); if(pptSrc) { pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } pScreenPriv->WIDOps->WidCopyArea((DrawablePtr)pScreenPriv->pixWid, &rgnDst, pptSrc); DEALLOCATE_LOCAL(pptSrc); } /* Next, we copy children which have a different * bpp than pWin into a temporary pixmap. We will * toss this pixmap back onto the framebuffer before * we return. */ if (pWin->drawable.bitsPerPixel == 8) other_bpp = pScrn->bitsPerPixel; else other_bpp = 8; REGION_NULL(pScreen, &rgnOther); SegregateChildrenBpp(pWin, &rgnOther, 0, other_bpp, pWin->drawable.bitsPerPixel); pPixChildren = NULL; if (REGION_NOTEMPTY(pScreen, &rgnOther)) { REGION_INTERSECT(pScreen, &rgnOther, &rgnOther, prgnSrc); nbox = REGION_NUM_RECTS(&rgnOther); if (nbox) { int width = rgnOther.extents.x2 - rgnOther.extents.x1; int height = rgnOther.extents.y2 - rgnOther.extents.y1; int depth = (other_bpp == 8) ? 8 : pScrn->depth; if (other_bpp == 8) pPixChildren = cfbCreatePixmap(pScreen, width, height, depth); else pPixChildren = cfb32CreatePixmap(pScreen, width, height, depth); } if (nbox && pPixChildren && (pptSrc = (DDXPointPtr) ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) { pbox = REGION_RECTS(&rgnOther); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } REGION_NULL(pScreen, &rgnPixmap); REGION_COPY(pScreen, &rgnPixmap, &rgnOther); REGION_TRANSLATE(pScreen, &rgnPixmap, -(rgnOther.extents.x1), -(rgnOther.extents.y1)); if (other_bpp == 8) cfbDoBitbltCopy((DrawablePtr)pScreenPriv->pix8, (DrawablePtr)pPixChildren, GXcopy, &rgnPixmap, pptSrc, ~0L); else cfb32DoBitbltCopy((DrawablePtr)pScreenPriv->pix32, (DrawablePtr)pPixChildren, GXcopy, &rgnPixmap, pptSrc, ~0L); REGION_UNINIT(pScreen, &rgnPixmap); DEALLOCATE_LOCAL(pptSrc); } REGION_SUBTRACT(pScreen, &rgnDst, &rgnDst, &rgnOther); } /* Now copy the parent along with all child windows using the same depth. */ nbox = REGION_NUM_RECTS(&rgnDst); if(nbox && (pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) { pbox = REGION_RECTS(&rgnDst); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } if (pWin->drawable.bitsPerPixel == 8) cfbDoBitbltCopy((DrawablePtr)pScreenPriv->pix8, (DrawablePtr)pScreenPriv->pix8, GXcopy, &rgnDst, pptSrc, ~0L); else cfb32DoBitbltCopy((DrawablePtr)pScreenPriv->pix32, (DrawablePtr)pScreenPriv->pix32, GXcopy, &rgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } REGION_UNINIT(pScreen, &rgnDst); if (pPixChildren) { nbox = REGION_NUM_RECTS(&rgnOther); pptSrc = (DDXPointPtr) ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)); if (pptSrc) { pbox = REGION_RECTS(&rgnOther); for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { ppt->x = pbox->x1 - rgnOther.extents.x1; ppt->y = pbox->y1 - rgnOther.extents.y1; } if (other_bpp == 8) cfbDoBitbltCopy((DrawablePtr)pPixChildren, (DrawablePtr)pScreenPriv->pix8, GXcopy, &rgnOther, pptSrc, ~0L); else cfb32DoBitbltCopy((DrawablePtr)pPixChildren, (DrawablePtr)pScreenPriv->pix32, GXcopy, &rgnOther, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } if (other_bpp == 8) cfbDestroyPixmap(pPixChildren); else cfb32DestroyPixmap(pPixChildren); } REGION_UNINIT(pScreen, &rgnOther); }
void nouveau_dri2_copy_region2(ScreenPtr pScreen, DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) { struct nouveau_dri2_buffer *src = nouveau_dri2_buffer(pSrcBuffer); struct nouveau_dri2_buffer *dst = nouveau_dri2_buffer(pDstBuffer); NVPtr pNv = NVPTR(xf86ScreenToScrn(pScreen)); RegionPtr pCopyClip; GCPtr pGC; DrawablePtr src_draw, dst_draw; Bool translate = FALSE; int off_x = 0, off_y = 0; src_draw = &src->ppix->drawable; dst_draw = &dst->ppix->drawable; #if 0 ErrorF("attachments src %d, dst %d, drawable %p %p pDraw %p\n", src->base.attachment, dst->base.attachment, src_draw, dst_draw, pDraw); #endif if (src->base.attachment == DRI2BufferFrontLeft) src_draw = pDraw; if (dst->base.attachment == DRI2BufferFrontLeft) { #ifdef NOUVEAU_PIXMAP_SHARING if (pDraw->pScreen != pScreen) { dst_draw = DRI2UpdatePrime(pDraw, pDstBuffer); if (!dst_draw) return; } else #endif dst_draw = pDraw; if (dst_draw != pDraw) translate = TRUE; } if (translate && pDraw->type == DRAWABLE_WINDOW) { #ifdef COMPOSITE PixmapPtr pPix = get_drawable_pixmap(pDraw); off_x = -pPix->screen_x; off_y = -pPix->screen_y; #endif off_x += pDraw->x; off_y += pDraw->y; } pGC = GetScratchGC(pDraw->depth, pScreen); pCopyClip = REGION_CREATE(pScreen, NULL, 0); REGION_COPY(pScreen, pCopyClip, pRegion); if (translate) { REGION_TRANSLATE(pScreen, pCopyClip, off_x, off_y); } pGC->funcs->ChangeClip(pGC, CT_REGION, pCopyClip, 0); ValidateGC(dst_draw, pGC); /* If this is a full buffer swap or frontbuffer flush, throttle on * the previous one. */ if (dst->base.attachment == DRI2BufferFrontLeft && REGION_NUM_RECTS(pRegion) == 1) { BoxPtr extents = REGION_EXTENTS(pScreen, pRegion); if (extents->x1 == 0 && extents->y1 == 0 && extents->x2 == pDraw->width && extents->y2 == pDraw->height) { PixmapPtr fpix = get_drawable_pixmap(dst_draw); struct nouveau_bo *bo = nouveau_pixmap_bo(fpix); if (bo) nouveau_bo_wait(bo, NOUVEAU_BO_RD, pNv->client); } } pGC->ops->CopyArea(src_draw, dst_draw, pGC, 0, 0, pDraw->width, pDraw->height, off_x, off_y); FreeScratchGC(pGC); }
static Bool localQueryLargestOffscreenArea( ScreenPtr pScreen, int *width, int *height, int granularity, int preferences, int severity ){ FBManagerPtr offman; RegionPtr newRegion = NULL; BoxPtr pbox; int nbox; int x, w, h, area, oldArea; *width = *height = oldArea = 0; if(granularity <= 1) granularity = 0; if((preferences < 0) || (preferences > 3)) return FALSE; offman = pScreen->devPrivates[xf86FBScreenIndex].ptr; if(severity < 0) severity = 0; if(severity > 2) severity = 2; switch(severity) { case 2: if(offman->NumUsedAreas) { FBLinkPtr pLink; RegionRec tmpRegion; newRegion = REGION_CREATE(pScreen, NULL, 1); REGION_COPY(pScreen, newRegion, offman->InitialBoxes); pLink = offman->UsedAreas; while(pLink) { if(!pLink->area.RemoveAreaCallback) { REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1); REGION_SUBTRACT(pScreen, newRegion, newRegion, &tmpRegion); REGION_UNINIT(pScreen, &tmpRegion); } pLink = pLink->next; } nbox = REGION_NUM_RECTS(newRegion); pbox = REGION_RECTS(newRegion); break; } case 1: if(offman->NumUsedAreas) { FBLinkPtr pLink; RegionRec tmpRegion; newRegion = REGION_CREATE(pScreen, NULL, 1); REGION_COPY(pScreen, newRegion, offman->FreeBoxes); pLink = offman->UsedAreas; while(pLink) { if(pLink->area.RemoveAreaCallback) { REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1); REGION_APPEND(pScreen, newRegion, &tmpRegion); REGION_UNINIT(pScreen, &tmpRegion); } pLink = pLink->next; } nbox = REGION_NUM_RECTS(newRegion); pbox = REGION_RECTS(newRegion); break; } default: nbox = REGION_NUM_RECTS(offman->FreeBoxes); pbox = REGION_RECTS(offman->FreeBoxes); break; } while(nbox--) { x = pbox->x1; if(granularity) { int tmp = x % granularity; if(tmp) x += (granularity - tmp); } w = pbox->x2 - x; h = pbox->y2 - pbox->y1; area = w * h; if(w > 0) { Bool gotIt = FALSE; switch(preferences) { case FAVOR_AREA_THEN_WIDTH: if((area > oldArea) || ((area == oldArea) && (w > *width))) gotIt = TRUE; break; case FAVOR_AREA_THEN_HEIGHT: if((area > oldArea) || ((area == oldArea) && (h > *height))) gotIt = TRUE; break; case FAVOR_WIDTH_THEN_AREA: if((w > *width) || ((w == *width) && (area > oldArea))) gotIt = TRUE; break; case FAVOR_HEIGHT_THEN_AREA: if((h > *height) || ((h == *height) && (area > oldArea))) gotIt = TRUE; break; } if(gotIt) { *width = w; *height = h; oldArea = area; } } pbox++; } if(newRegion) REGION_DESTROY(pScreen, newRegion); return TRUE; }
/* *----------------------------------------------------------------------- * RootlessComputeClips -- * 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 RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, RegionPtr universe, VTKind kind, RegionPtr exposed) { int dx, dy; RegionRec childUniverse; register WindowPtr pChild; int oldVis, newVis; BoxRec borderSize; RegionRec childUnion; Bool overlap; RegionPtr borderVisible; Bool resized; /* * 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; oldVis = pParent->visibility; switch (RECT_IN_REGION( pScreen, universe, &borderSize)) { case rgnIN: newVis = VisibilityUnobscured; break; case rgnPART: newVis = VisibilityPartiallyObscured; { RegionPtr pBounding; if ((pBounding = wBoundingShape (pParent))) { switch (RootlessShapedWindowIn (pScreen, 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) { REGION_TRANSLATE( pScreen, &pChild->borderClip, dx, dy); REGION_TRANSLATE( pScreen, &pChild->clipList, dx, dy); pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; if (pScreen->ClipNotify) (* pScreen->ClipNotify) (pChild, dx, dy); } if (pChild->valdata) { REGION_NULL(pScreen, &pChild->valdata->after.borderExposed); if (HasParentRelativeBorder(pChild)) { REGION_SUBTRACT(pScreen, &pChild->valdata->after.borderExposed, &pChild->borderClip, &pChild->winSize); } REGION_NULL(pScreen, &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. */ REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy); REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy); } break; case VTBroken: REGION_EMPTY (pScreen, &pParent->borderClip); REGION_EMPTY (pScreen, &pParent->clipList); break; } borderVisible = pParent->valdata->before.borderVisible; resized = pParent->valdata->before.resized; REGION_NULL(pScreen, &pParent->valdata->after.borderExposed); REGION_NULL(pScreen, &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 */ REGION_SUBTRACT( pScreen, exposed, universe, borderVisible); REGION_DESTROY( pScreen, borderVisible); } else { REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip); } if (HasParentRelativeBorder(pParent) && (dx || dy)) { REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, universe, &pParent->winSize); } else { REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, exposed, &pParent->winSize); } REGION_COPY( pScreen, &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. */ REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize); } else REGION_COPY( pScreen, &pParent->borderClip, universe); if ((pChild = pParent->firstChild) && pParent->mapped) { REGION_NULL(pScreen, &childUniverse); REGION_NULL(pScreen, &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) REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); } } else { for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) { if (pChild->viewable) REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); } } REGION_VALIDATE( pScreen, &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. */ REGION_INTERSECT( pScreen, &childUniverse, universe, &pChild->borderSize); RootlessComputeClips (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) REGION_SUBTRACT( pScreen, universe, universe, &pChild->borderSize); } } if (!overlap) REGION_SUBTRACT( pScreen, universe, universe, &childUnion); REGION_UNINIT( pScreen, &childUnion); REGION_UNINIT( pScreen, &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) { REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe); } else if (newVis != VisibilityFullyObscured && newVis != VisibilityNotViewable) { REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed, universe, &pParent->clipList); } /* * One last thing: backing storage. We have to try to save what parts of * the window are about to be obscured. We can just subtract the universe * from the old clipList and get the areas that were in the old but aren't * in the new and, hence, are about to be obscured. */ if (pParent->backStorage && !resized) { REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe); (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy); } /* HACK ALERT - copying contents of regions, instead of regions */ { RegionRec tmp; tmp = pParent->clipList; pParent->clipList = *universe; *universe = tmp; } #ifdef NOTDEF REGION_COPY( pScreen, &pParent->clipList, universe); #endif pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; if (pScreen->ClipNotify) (* pScreen->ClipNotify) (pParent, dx, dy); }
static void send_update(void) { CL_SLOT *cl = (CL_SLOT *)cur_slot; BoxRec fb_rect; RegionRec fb_region, clip_region, outer_region; CARD8 msg_hdr[4] = { 0, 0, 0, 1 }; CARD8 rect_hdr[12]; int num_copy_rects, num_pending_rects, num_all_rects; int raw_bytes = 0, hextile_bytes = 0; int i, idx, rev_order; static int counter = 0; #ifdef NETLOGGER aio_set_serial_number(&cl->s, cl->serial_number); #endif counter++; vncspuLog(1, "Begin send update %d", counter); CRASSERT(vnc_spu.serverBuffer); /*crDebug("Enter send_update to %s", cur_slot->name);*/ /* check if clipping has changed since we got the pixels and update * the pending region if needed. */ if (NewClip) { /*crDebug("Getting updated cliprects");*/ vncspuGetScreenRects(&cl->pending_region); num_pending_rects = REGION_NUM_RECTS(&cl->pending_region); /*crDebug("Now, %d rects", num_pending_rects);*/ if (num_pending_rects == 0 && cl->enable_frame_sync) { /* always need to send _something_ for framesync to work */ BoxRec b; b.x1 = 0; b.y1 = 0; b.x2 = 1; b.y2 = 1; REGION_UNINIT(&cl->pending_region); REGION_INIT(&cl->pending_region, &b, 1); } NewClip = 0; } /*PrintRegion("Sending", &cl->pending_region);*/ /* Process framebuffer size change. */ if (cl->newfbsize_pending) { /* Update framebuffer size, clear newfbsize_pending flag. */ cl->fb_width = g_screen_info.width; cl->fb_height = g_screen_info.height; cl->newfbsize_pending = 0; log_write(LL_DEBUG, "Applying new framebuffer size (%dx%d) to %s", (int)cl->fb_width, (int)cl->fb_height, cur_slot->name); /* In any case, mark all the framebuffer contents as changed. */ fb_rect.x1 = 0; fb_rect.y1 = 0; fb_rect.x2 = cl->fb_width; fb_rect.y2 = cl->fb_height; REGION_INIT(&fb_region, &fb_rect, 1); REGION_COPY(&cl->pending_region, &fb_region); REGION_UNINIT(&fb_region); REGION_EMPTY(&cl->copy_region); /* If NewFBSize is supported by the client, send only NewFBSize pseudo-rectangle, pixel data will be sent in the next update. */ if (cl->enable_newfbsize) { send_newfbsize(); vncspuUnlockFrameBuffer(); return; } } else { /* Exclude CopyRect areas covered by pending_region. */ REGION_SUBTRACT(&cl->copy_region, &cl->copy_region, &cl->pending_region); } #if 00 if (cl->enable_cliprects_enc && cl->new_cliprects) { send_new_cliprects(); vncspuUnlockFrameBuffer(); cl->new_cliprects = 0; return; } #endif /* Clip regions to the rectangle requested by the client. */ REGION_INIT(&clip_region, &cl->update_rect, 1); REGION_INTERSECT(&cl->pending_region, &cl->pending_region, &clip_region); if (REGION_NOTEMPTY(&cl->copy_region)) { REGION_INTERSECT(&cl->copy_region, &cl->copy_region, &clip_region); REGION_INIT(&outer_region, NullBox, 8); REGION_COPY(&outer_region, &cl->copy_region); REGION_TRANSLATE(&clip_region, cl->copy_dx, cl->copy_dy); REGION_INTERSECT(&cl->copy_region, &cl->copy_region, &clip_region); REGION_SUBTRACT(&outer_region, &outer_region, &cl->copy_region); REGION_UNION(&cl->pending_region, &cl->pending_region, &outer_region); REGION_UNINIT(&outer_region); } REGION_UNINIT(&clip_region); /* Reduce the number of rectangles if possible. */ if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { region_pack(&cl->pending_region, 32); } else { region_pack(&cl->pending_region, 12); } /* Compute the number of rectangles in regions. */ num_pending_rects = REGION_NUM_RECTS(&cl->pending_region); num_copy_rects = REGION_NUM_RECTS(&cl->copy_region); num_all_rects = num_pending_rects + num_copy_rects; if (num_all_rects == 0) { vncspuUnlockFrameBuffer(); return; } log_write(LL_DEBUG, "Sending framebuffer update (min %d rects) to %s", num_all_rects, cur_slot->name); /* Prepare and send FramebufferUpdate message header. */ /* FIXME: Enable Tight encoding even if LastRect is not supported. */ /* FIXME: Do not send LastRect if all the rectangles are CopyRect. */ if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { buf_put_CARD16(&msg_hdr[2], 0xFFFF); } else { buf_put_CARD16(&msg_hdr[2], num_all_rects); } aio_write(NULL, msg_hdr, 4); /* Determine the order in which CopyRect rectangles should be sent. */ rev_order = (cl->copy_dy > 0 || (cl->copy_dy == 0 && cl->copy_dx > 0)); /* For each CopyRect rectangle: */ for (i = 0; i < num_copy_rects; i++) { FB_RECT rect; AIO_BLOCK *block; idx = (rev_order) ? num_copy_rects - i - 1 : i; rect.x = REGION_RECTS(&cl->copy_region)[idx].x1; rect.y = REGION_RECTS(&cl->copy_region)[idx].y1; rect.w = REGION_RECTS(&cl->copy_region)[idx].x2 - rect.x; rect.h = REGION_RECTS(&cl->copy_region)[idx].y2 - rect.y; rect.src_x = rect.x - cl->copy_dx; rect.src_y = rect.y - cl->copy_dy; rect.enc = RFB_ENCODING_COPYRECT; log_write(LL_DEBUG, "Sending CopyRect rectangle %dx%d at %d,%d to %s", (int)rect.w, (int)rect.h, (int)rect.x, (int)rect.y, cur_slot->name); /* Prepare the CopyRect rectangle. */ block = rfb_encode_copyrect_block(cl, &rect); /* Send the rectangle. FIXME: Check for block == NULL? */ aio_write_nocopy(NULL, block); } if (cl->enc_prefer == RFB_ENCODING_TIGHT) { /* needed for successful caching of zlib-compressed data (tight) */ rfb_reset_tight_encoder(cl); } if (num_pending_rects) { /* Lock around fb access so other thread doesn't change contents while * we're encoding. */ #ifdef NETLOGGER if (vnc_spu.netlogger_url) { NL_info("vncspu", "spu.encode.begin", "NODE=s NUMBER=i", vnc_spu.hostname, cl->serial_number); } #endif /* For each of the usual pending rectangles: */ for (i = 0; i < num_pending_rects; i++) { FB_RECT rect; AIO_BLOCK *block; /* crDebug("sending rect %d of %d: %d, %d .. %d, %d", i, num_pending_rects, REGION_RECTS(&cl->pending_region)[i].x1, REGION_RECTS(&cl->pending_region)[i].y1, REGION_RECTS(&cl->pending_region)[i].x2, REGION_RECTS(&cl->pending_region)[i].y2); */ rect.x = REGION_RECTS(&cl->pending_region)[i].x1; rect.y = REGION_RECTS(&cl->pending_region)[i].y1; rect.w = REGION_RECTS(&cl->pending_region)[i].x2 - rect.x; rect.h = REGION_RECTS(&cl->pending_region)[i].y2 - rect.y; log_write(LL_DEBUG, "Sending rectangle %dx%d at %d,%d to %s enc 0x%x", (int)rect.w, (int)rect.h, (int)rect.x, (int)rect.y, cur_slot->name, cl->enc_prefer); if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { /* Use Tight encoding */ rect.enc = RFB_ENCODING_TIGHT; /* lock to prevent glReadPixels in other thread changing data */ rfb_encode_tight(cl, &rect); continue; /* Important! */ } else if (cl->enc_prefer == RFB_ENCODING_RAW24) { rect.enc = RFB_ENCODING_RAW24; block = rfb_encode_raw24_block(cl, &rect); } else if ( cl->enc_prefer != RFB_ENCODING_RAW && cl->enc_enable[RFB_ENCODING_HEXTILE] ) { /* Use Hextile encoding */ rect.enc = RFB_ENCODING_HEXTILE; block = rfb_encode_hextile_block(cl, &rect); if (block != NULL) { hextile_bytes += block->data_size; raw_bytes += rect.w * rect.h * (cl->format.bits_pixel / 8); } } else { /* Use Raw encoding */ rect.enc = RFB_ENCODING_RAW; if (vnc_spu.half_rez) { block = rfb_encode_raw_block_halfrez(cl, &rect); } else { block = rfb_encode_raw_block(cl, &rect); } } /* Send the rectangle. FIXME: Check for block == NULL? */ aio_write_nocopy(NULL, block); } } /* if num_pending_rects */ REGION_EMPTY(&cl->pending_region); REGION_EMPTY(&cl->copy_region); /* Send LastRect marker. */ if (cl->enc_prefer == RFB_ENCODING_TIGHT && cl->enable_lastrect) { FB_RECT rect; rect.x = rect.y = rect.w = rect.h = 0; rect.enc = RFB_ENCODING_LASTRECT; put_rect_header(rect_hdr, &rect); aio_write(NULL, rect_hdr, 12); } /* Set the last block's callback function */ /* All prev blocks had NULL callbacks */ assert(cur_slot->outqueue_last); if (cur_slot->outqueue_last) { cur_slot->outqueue_last->func = wf_client_update_finished; } /* Something has been queued for sending. */ cl->update_in_progress = 1; cl->update_requested = 0; #ifdef NETLOGGER if (vnc_spu.netlogger_url) { NL_info("vncspu", "spu.encode.end", "NODE=s NUMBER=i", vnc_spu.hostname, cl->serial_number); } aio_set_serial_number(&cl->s, 0); #endif vncspuUnlockFrameBuffer(); /* encoder done with buffer */ /*crDebug("Leave send_update");*/ vncspuLog(1, "End send update %d", counter); }
static void xf86SetRootClip (ScreenPtr pScreen, Bool enable) { #if XORG < 19 WindowPtr pWin = WindowTable[pScreen->myNum]; #else WindowPtr pWin = pScreen->root; #endif WindowPtr pChild; Bool WasViewable = (Bool)(pWin->viewable); Bool anyMarked = FALSE; #if XORG < 110 RegionPtr pOldClip = NULL, bsExposed; #ifdef DO_SAVE_UNDERS Bool dosave = FALSE; #endif #endif WindowPtr pLayerWin; BoxRec box; if (WasViewable) { for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { (void) (*pScreen->MarkOverlappedWindows)(pChild, pChild, &pLayerWin); } (*pScreen->MarkWindow) (pWin); anyMarked = TRUE; if (pWin->valdata) { if (HasBorder (pWin)) { RegionPtr borderVisible; borderVisible = REGION_CREATE(pScreen, NullBox, 1); REGION_SUBTRACT(pScreen, borderVisible, &pWin->borderClip, &pWin->winSize); pWin->valdata->before.borderVisible = borderVisible; } pWin->valdata->before.resized = TRUE; } } /* * Use REGION_BREAK to avoid optimizations in ValidateTree * that assume the root borderClip can't change well, normally * it doesn't...) */ if (enable) { box.x1 = 0; box.y1 = 0; box.x2 = pScreen->width; box.y2 = pScreen->height; REGION_INIT (pScreen, &pWin->winSize, &box, 1); REGION_INIT (pScreen, &pWin->borderSize, &box, 1); if (WasViewable) REGION_RESET(pScreen, &pWin->borderClip, &box); pWin->drawable.width = pScreen->width; pWin->drawable.height = pScreen->height; REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); } else { REGION_EMPTY(pScreen, &pWin->borderClip); REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); } ResizeChildrenWinSize (pWin, 0, 0, 0, 0); if (WasViewable) { #if XORG < 110 if (pWin->backStorage) { pOldClip = REGION_CREATE(pScreen, NullBox, 1); REGION_COPY(pScreen, pOldClip, &pWin->clipList); } #endif if (pWin->firstChild) { anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, pWin->firstChild, (WindowPtr *)NULL); } else { (*pScreen->MarkWindow) (pWin); anyMarked = TRUE; } #if XORG < 110 && defined(DO_SAVE_UNDERS) if (DO_SAVE_UNDERS(pWin)) { dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); } #endif /* DO_SAVE_UNDERS */ if (anyMarked) (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); } #if XORG < 110 if (pWin->backStorage && ((pWin->backingStore == Always) || WasViewable)) { if (!WasViewable) pOldClip = &pWin->clipList; /* a convenient empty region */ bsExposed = (*pScreen->TranslateBackingStore) (pWin, 0, 0, pOldClip, pWin->drawable.x, pWin->drawable.y); if (WasViewable) REGION_DESTROY(pScreen, pOldClip); if (bsExposed) { RegionPtr valExposed = NullRegion; if (pWin->valdata) valExposed = &pWin->valdata->after.exposed; (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); if (valExposed) REGION_EMPTY(pScreen, valExposed); REGION_DESTROY(pScreen, bsExposed); } } #endif if (WasViewable) { if (anyMarked) (*pScreen->HandleExposures)(pWin); #if XORG < 110 && defined(DO_SAVE_UNDERS) if (dosave) (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); #endif /* DO_SAVE_UNDERS */ if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); } if (pWin->realized) WindowsRestructured (); FlushAllOutput (); }
// fixme this is ugly // Xprint/ValTree.c doesn't work, but maybe that method can? int RootlessMiValidateTree (WindowPtr pRoot, /* Parent to validate */ WindowPtr pChild, /* First child of pRoot that was * affected */ VTKind kind /* What kind of configuration caused call */) { RegionRec childClip; /* The new borderClip for the current * child */ RegionRec exposed; /* For intermediate calculations */ register ScreenPtr pScreen; register WindowPtr pWin; pScreen = pRoot->drawable.pScreen; if (pChild == NullWindow) pChild = pRoot->firstChild; REGION_NULL(pScreen, &childClip); REGION_NULL(pScreen, &exposed); if (REGION_BROKEN (pScreen, &pRoot->clipList) && !REGION_BROKEN (pScreen, &pRoot->borderClip)) { // fixme this might not work, but hopefully doesn't happen anyway. kind = VTBroken; REGION_EMPTY (pScreen, &pRoot->clipList); ErrorF("ValidateTree: BUSTED!\n"); } /* * Recursively compute the clips for all children of the root. * They don't clip against each other or the root itself, so * childClip is always reset to that child's size. */ for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) { if (pWin->viewable) { if (pWin->valdata) { REGION_COPY( pScreen, &childClip, &pWin->borderSize); RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed); } else if (pWin->visibility == VisibilityNotViewable) { RootlessTreeObscured(pWin); } } else { if (pWin->valdata) { REGION_EMPTY( pScreen, &pWin->clipList); if (pScreen->ClipNotify) (* pScreen->ClipNotify) (pWin, 0, 0); REGION_EMPTY( pScreen, &pWin->borderClip); pWin->valdata = (ValidatePtr)NULL; } } } REGION_UNINIT(pScreen, &childClip); /* The root is never clipped by its children, so nothing on the root is ever exposed by moving or mapping its children. */ REGION_NULL(pScreen, &pRoot->valdata->after.exposed); REGION_NULL(pScreen, &pRoot->valdata->after.borderExposed); return 1; }
void miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind) { WindowPtr pParent; Bool WasViewable = (Bool)(pWin->viewable); short bw; RegionPtr oldRegion = NULL; DDXPointRec oldpt; Bool anyMarked = FALSE; ScreenPtr pScreen; WindowPtr windowToValidate; WindowPtr pLayerWin; /* if this is a root window, can't be moved */ if (!(pParent = pWin->parent)) return ; pScreen = pWin->drawable.pScreen; bw = wBorderWidth (pWin); oldpt.x = pWin->drawable.x; oldpt.y = pWin->drawable.y; if (WasViewable) { oldRegion = REGION_CREATE(pScreen, NullBox, 1); REGION_COPY(pScreen, oldRegion, &pWin->borderClip); anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); } pWin->origin.x = x + (int)bw; pWin->origin.y = y + (int)bw; x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; SetWinSize (pWin); SetBorderSize (pWin); (*pScreen->PositionWindow)(pWin, x, y); windowToValidate = MoveWindowInStack(pWin, pNextSib); ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); if (WasViewable) { if (pLayerWin == pWin) anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL); else anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, NULL); if (anyMarked) { (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); REGION_DESTROY(pScreen, oldRegion); /* XXX need to retile border if ParentRelative origin */ (*pScreen->HandleExposures)(pLayerWin->parent); } if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); } if (pWin->realized) WindowsRestructured (); }
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 = REGION_CREATE(pScreen, NullBox, 1); REGION_COPY(pScreen, 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] = REGION_CREATE(pScreen, NullBox, 1); REGION_UNION(pScreen, 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 = REGION_CREATE(pScreen, NullBox, 1); REGION_COPY(pScreen, 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 = REGION_CREATE(pScreen, NullBox, 1); /* for tiled borders, we punt and draw the whole thing */ if (pWin->borderIsPixel || !moved) { if (shrunk || moved) REGION_SUBTRACT(pScreen, borderVisible, &pWin->borderClip, &pWin->winSize); else REGION_COPY(pScreen, 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 = REGION_CREATE(pScreen, 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 */ REGION_COPY(pScreen, &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) { REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); offx += dx; offy += dy; } REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], &pWin->winSize); } /* get winSize back where it belongs */ if (offx || offy) REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); } /* * add screen bits to the appropriate bucket */ if (oldWinClip) { /* * clip to new clipList */ REGION_COPY(pScreen, pRegion, oldWinClip); REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); REGION_INTERSECT(pScreen, 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]) REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, gravitate[g]); } REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); g = pWin->bitGravity; if (!gravitate[g]) gravitate[g] = oldWinClip; else { REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); REGION_DESTROY(pScreen, 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 */ REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); /* clip to not overwrite already copied areas */ if (destClip) { REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); REGION_TRANSLATE(pScreen, 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 */ REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); /* * recompute exposed regions of child windows */ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { if (pChild->winGravity != g) continue; REGION_INTERSECT(pScreen, pRegion, &pChild->borderClip, gravitate[g]); TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); } /* * remove the successfully copied regions of the * window from its exposed region */ if (g == pWin->bitGravity) REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, &pWin->valdata->after.exposed, gravitate[g]); if (!destClip) destClip = gravitate[g]; else { REGION_UNION(pScreen, destClip, destClip, gravitate[g]); REGION_DESTROY(pScreen, gravitate[g]); } } REGION_DESTROY(pScreen, oldRegion); REGION_DESTROY(pScreen, pRegion); if (destClip) REGION_DESTROY(pScreen, destClip); if (anyMarked) (*pScreen->HandleExposures)(pLayerWin->parent); if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, VTOther); } if (pWin->realized) WindowsRestructured (); }
void KdSetRootClip (ScreenPtr pScreen, BOOL enable) { #ifndef FB_OLD_SCREEN WindowPtr pWin = WindowTable[pScreen->myNum]; WindowPtr pChild; Bool WasViewable; Bool anyMarked = FALSE; RegionPtr pOldClip = 0, bsExposed; #ifdef DO_SAVE_UNDERS Bool dosave = FALSE; #endif WindowPtr pLayerWin; BoxRec box; if (!pWin) return; WasViewable = (Bool)(pWin->viewable); if (WasViewable) { for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { (void) (*pScreen->MarkOverlappedWindows)(pChild, pChild, &pLayerWin); } (*pScreen->MarkWindow) (pWin); anyMarked = TRUE; if (pWin->valdata) { if (HasBorder (pWin)) { RegionPtr borderVisible; borderVisible = REGION_CREATE(pScreen, NullBox, 1); REGION_SUBTRACT(pScreen, borderVisible, &pWin->borderClip, &pWin->winSize); pWin->valdata->before.borderVisible = borderVisible; } pWin->valdata->before.resized = TRUE; } } if (enable) { box.x1 = 0; box.y1 = 0; box.x2 = pScreen->width; box.y2 = pScreen->height; pWin->drawable.width = pScreen->width; pWin->drawable.height = pScreen->height; REGION_INIT (pScreen, &pWin->winSize, &box, 1); REGION_INIT (pScreen, &pWin->borderSize, &box, 1); REGION_RESET(pScreen, &pWin->borderClip, &box); REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); } else { REGION_EMPTY(pScreen, &pWin->borderClip); REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); } ResizeChildrenWinSize (pWin, 0, 0, 0, 0); if (WasViewable) { if (pWin->backStorage) { pOldClip = REGION_CREATE(pScreen, NullBox, 1); REGION_COPY(pScreen, pOldClip, &pWin->clipList); } if (pWin->firstChild) { anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, pWin->firstChild, (WindowPtr *)NULL); } else { (*pScreen->MarkWindow) (pWin); anyMarked = TRUE; } #ifdef DO_SAVE_UNDERS if (DO_SAVE_UNDERS(pWin)) { dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); } #endif /* DO_SAVE_UNDERS */ if (anyMarked) (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); } if (pWin->backStorage && ((pWin->backingStore == Always) || WasViewable)) { if (!WasViewable) pOldClip = &pWin->clipList; /* a convenient empty region */ bsExposed = (*pScreen->TranslateBackingStore) (pWin, 0, 0, pOldClip, pWin->drawable.x, pWin->drawable.y); if (WasViewable) REGION_DESTROY(pScreen, pOldClip); if (bsExposed) { RegionPtr valExposed = NullRegion; if (pWin->valdata) valExposed = &pWin->valdata->after.exposed; (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); if (valExposed) REGION_EMPTY(pScreen, valExposed); REGION_DESTROY(pScreen, bsExposed); } } if (WasViewable) { if (anyMarked) (*pScreen->HandleExposures)(pWin); #ifdef DO_SAVE_UNDERS if (dosave) (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); #endif /* DO_SAVE_UNDERS */ if (anyMarked && pScreen->PostValidateTree) (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); } if (pWin->realized) WindowsRestructured (); #endif /* !FB_OLD_SCREEN */ }
void I915DisplayVideoTextured(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, int id, RegionPtr dstRegion, short width, short height, int video_pitch, int video_pitch2, short src_w, short src_h, short drw_w, short drw_h, PixmapPtr pixmap) { intel_screen_private *intel = intel_get_screen_private(scrn); uint32_t format, ms3, s5, tiling; BoxPtr pbox = REGION_RECTS(dstRegion); int nbox_total = REGION_NUM_RECTS(dstRegion); int nbox_this_time; int dxo, dyo, pix_xoff, pix_yoff; PixmapPtr target; #if 0 ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height, video_pitch); #endif dxo = dstRegion->extents.x1; dyo = dstRegion->extents.y1; if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048 || !intel_uxa_check_pitch_3d(pixmap)) { ScreenPtr screen = pixmap->drawable.pScreen; target = screen->CreatePixmap(screen, dstRegion->extents.x2 - dxo, dstRegion->extents.y2 - dyo, pixmap->drawable.depth, CREATE_PIXMAP_USAGE_SCRATCH); if (target == NULL) return; if (intel_uxa_get_pixmap_bo(target) == NULL) { screen->DestroyPixmap(target); return; } pix_xoff = -dxo; pix_yoff = -dyo; } else { target = pixmap; /* Set up the offset for translating from the given region * (in screen coordinates) to the backing pixmap. */ #ifdef COMPOSITE pix_xoff = -target->screen_x + target->drawable.x; pix_yoff = -target->screen_y + target->drawable.y; #else pix_xoff = 0; pix_yoff = 0; #endif } #define BYTES_FOR_BOXES(n) ((200 + (n) * 20) * 4) #define BOXES_IN_BYTES(s) ((((s)/4) - 200) / 20) #define BATCH_BYTES(p) ((p)->batch_bo->size - 16) while (nbox_total) { nbox_this_time = nbox_total; if (BYTES_FOR_BOXES(nbox_this_time) > BATCH_BYTES(intel)) nbox_this_time = BOXES_IN_BYTES(BATCH_BYTES(intel)); nbox_total -= nbox_this_time; intel_batch_start_atomic(scrn, 200 + 20 * nbox_this_time); IntelEmitInvarientState(scrn); intel->last_3d = LAST_3D_VIDEO; /* draw rect -- just clipping */ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); OUT_BATCH(DRAW_DITHER_OFS_X(pixmap->drawable.x & 3) | DRAW_DITHER_OFS_Y(pixmap->drawable.y & 3)); OUT_BATCH(0x00000000); /* ymin, xmin */ /* ymax, xmax */ OUT_BATCH((target->drawable.width - 1) | (target->drawable.height - 1) << 16); OUT_BATCH(0x00000000); /* yorigin, xorigin */ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(5) | I1_LOAD_S(6) | 2); OUT_BATCH(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) | S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) | S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT)); s5 = 0x0; if (intel->cpp == 2) s5 |= S5_COLOR_DITHER_ENABLE; OUT_BATCH(s5); /* S5 - enable bits */ OUT_BATCH((2 << S6_DEPTH_TEST_FUNC_SHIFT) | (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) | (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE | (2 << S6_TRISTRIP_PV_SHIFT)); OUT_BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD); OUT_BATCH(0x00000000); OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); if (intel->cpp == 2) format = COLR_BUF_RGB565; else format = COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER; OUT_BATCH(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8) | format); /* front buffer, pitch, offset */ if (intel_uxa_pixmap_tiled(target)) { tiling = BUF_3D_TILED_SURFACE; if (intel_uxa_get_pixmap_private(target)->tiling == I915_TILING_Y) tiling |= BUF_3D_TILE_WALK_Y; } else tiling = 0; OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling | BUF_3D_PITCH(intel_pixmap_pitch(target))); OUT_RELOC_PIXMAP(target, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); if (!is_planar_fourcc(id)) { FS_LOCALS(); OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | 4); OUT_BATCH(0x0000001); /* constant 0 */ /* constant 0: brightness/contrast */ OUT_BATCH_F(adaptor_priv->brightness / 128.0); OUT_BATCH_F(adaptor_priv->contrast / 255.0); OUT_BATCH_F(0.0); OUT_BATCH_F(0.0); OUT_BATCH(_3DSTATE_SAMPLER_STATE | 3); OUT_BATCH(0x00000001); OUT_BATCH(SS2_COLORSPACE_CONVERSION | (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (0 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); OUT_BATCH(_3DSTATE_MAP_STATE | 3); OUT_BATCH(0x00000001); /* texture map #1 */ if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->YBufOffset); else OUT_BATCH(adaptor_priv->YBufOffset); ms3 = MAPSURF_422; switch (id) { case FOURCC_YUY2: ms3 |= MT_422_YCRCB_NORMAL; break; case FOURCC_UYVY: ms3 |= MT_422_YCRCB_SWAPY; break; } ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); FS_BEGIN(); i915_fs_dcl(FS_S0); i915_fs_dcl(FS_T0); i915_fs_texld(FS_OC, FS_S0, FS_T0); if (adaptor_priv->brightness != 0) { i915_fs_add(FS_OC, i915_fs_operand_reg(FS_OC), i915_fs_operand(FS_C0, X, X, X, ZERO)); } FS_END(); } else { FS_LOCALS(); /* For the planar formats, we set up three samplers -- * one for each plane, in a Y8 format. Because I * couldn't get the special PLANAR_TO_PACKED * shader setup to work, I did the manual pixel shader: * * y' = y - .0625 * u' = u - .5 * v' = v - .5; * * r = 1.1643 * y' + 0.0 * u' + 1.5958 * v' * g = 1.1643 * y' - 0.39173 * u' - 0.81290 * v' * b = 1.1643 * y' + 2.017 * u' + 0.0 * v' * * register assignment: * r0 = (y',u',v',0) * r1 = (y,y,y,y) * r2 = (u,u,u,u) * r3 = (v,v,v,v) * OC = (r,g,b,1) */ OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | (22 - 2)); OUT_BATCH(0x000001f); /* constants 0-4 */ /* constant 0: normalization offsets */ OUT_BATCH_F(-0.0625); OUT_BATCH_F(-0.5); OUT_BATCH_F(-0.5); OUT_BATCH_F(0.0); /* constant 1: r coefficients */ OUT_BATCH_F(1.1643); OUT_BATCH_F(0.0); OUT_BATCH_F(1.5958); OUT_BATCH_F(0.0); /* constant 2: g coefficients */ OUT_BATCH_F(1.1643); OUT_BATCH_F(-0.39173); OUT_BATCH_F(-0.81290); OUT_BATCH_F(0.0); /* constant 3: b coefficients */ OUT_BATCH_F(1.1643); OUT_BATCH_F(2.017); OUT_BATCH_F(0.0); OUT_BATCH_F(0.0); /* constant 4: brightness/contrast */ OUT_BATCH_F(adaptor_priv->brightness / 128.0); OUT_BATCH_F(adaptor_priv->contrast / 255.0); OUT_BATCH_F(0.0); OUT_BATCH_F(0.0); OUT_BATCH(_3DSTATE_SAMPLER_STATE | 9); OUT_BATCH(0x00000007); /* sampler 0 */ OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (0 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); /* sampler 1 */ OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (1 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); /* sampler 2 */ OUT_BATCH((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); OUT_BATCH((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT) | (2 << SS3_TEXTUREMAP_INDEX_SHIFT) | SS3_NORMALIZED_COORDS); OUT_BATCH(0x00000000); OUT_BATCH(_3DSTATE_MAP_STATE | 9); OUT_BATCH(0x00000007); if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->YBufOffset); else OUT_BATCH(adaptor_priv->YBufOffset); ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); /* check to see if Y has special pitch than normal * double u/v pitch, e.g i915 XvMC hw requires at * least 1K alignment, so Y pitch might * be same as U/V's.*/ if (video_pitch2) OUT_BATCH(((video_pitch2 / 4) - 1) << MS4_PITCH_SHIFT); else OUT_BATCH(((video_pitch * 2 / 4) - 1) << MS4_PITCH_SHIFT); if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->UBufOffset); else OUT_BATCH(adaptor_priv->UBufOffset); ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); if (adaptor_priv->buf) OUT_RELOC(adaptor_priv->buf, I915_GEM_DOMAIN_SAMPLER, 0, adaptor_priv->VBufOffset); else OUT_BATCH(adaptor_priv->VBufOffset); ms3 = MAPSURF_8BIT | MT_8BIT_I8; ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; OUT_BATCH(ms3); OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT); FS_BEGIN(); /* Declare samplers */ i915_fs_dcl(FS_S0); /* Y */ i915_fs_dcl(FS_S1); /* U */ i915_fs_dcl(FS_S2); /* V */ i915_fs_dcl(FS_T0); /* normalized coords */ /* Load samplers to temporaries. */ i915_fs_texld(FS_R1, FS_S0, FS_T0); i915_fs_texld(FS_R2, FS_S1, FS_T0); i915_fs_texld(FS_R3, FS_S2, FS_T0); /* Move the sampled YUV data in R[123] to the first * 3 channels of R0. */ i915_fs_mov_masked(FS_R0, MASK_X, i915_fs_operand_reg(FS_R1)); i915_fs_mov_masked(FS_R0, MASK_Y, i915_fs_operand_reg(FS_R2)); i915_fs_mov_masked(FS_R0, MASK_Z, i915_fs_operand_reg(FS_R3)); /* Normalize the YUV data */ i915_fs_add(FS_R0, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C0)); /* dot-product the YUV data in R0 by the vectors of * coefficients for calculating R, G, and B, storing * the results in the R, G, or B channels of the output * color. The OC results are implicitly clamped * at the end of the program. */ i915_fs_dp3(FS_OC, MASK_X, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C1)); i915_fs_dp3(FS_OC, MASK_Y, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C2)); i915_fs_dp3(FS_OC, MASK_Z, i915_fs_operand_reg(FS_R0), i915_fs_operand_reg(FS_C3)); /* Set alpha of the output to 1.0, by wiring W to 1 * and not actually using the source. */ i915_fs_mov_masked(FS_OC, MASK_W, i915_fs_operand_one()); if (adaptor_priv->brightness != 0) { i915_fs_add(FS_OC, i915_fs_operand_reg(FS_OC), i915_fs_operand(FS_C4, X, X, X, ZERO)); } FS_END(); } OUT_BATCH(PRIM3D_RECTLIST | (12 * nbox_this_time - 1)); while (nbox_this_time--) { int box_x1 = pbox->x1; int box_y1 = pbox->y1; int box_x2 = pbox->x2; int box_y2 = pbox->y2; float src_scale_x, src_scale_y; pbox++; src_scale_x = ((float)src_w / width) / drw_w; src_scale_y = ((float)src_h / height) / drw_h; /* vertex data - rect list consists of bottom right, * bottom left, and top left vertices. */ /* bottom right */ OUT_BATCH_F(box_x2 + pix_xoff); OUT_BATCH_F(box_y2 + pix_yoff); OUT_BATCH_F((box_x2 - dxo) * src_scale_x); OUT_BATCH_F((box_y2 - dyo) * src_scale_y); /* bottom left */ OUT_BATCH_F(box_x1 + pix_xoff); OUT_BATCH_F(box_y2 + pix_yoff); OUT_BATCH_F((box_x1 - dxo) * src_scale_x); OUT_BATCH_F((box_y2 - dyo) * src_scale_y); /* top left */ OUT_BATCH_F(box_x1 + pix_xoff); OUT_BATCH_F(box_y1 + pix_yoff); OUT_BATCH_F((box_x1 - dxo) * src_scale_x); OUT_BATCH_F((box_y1 - dyo) * src_scale_y); } intel_batch_end_atomic(scrn); } if (target != pixmap) { GCPtr gc; gc = GetScratchGC(pixmap->drawable.depth, pixmap->drawable.pScreen); if (gc) { gc->subWindowMode = ClipByChildren; if (REGION_NUM_RECTS(dstRegion) > 1) { RegionPtr tmp; tmp = REGION_CREATE(pixmap->drawable.pScreen, NULL, 0); if (tmp) { REGION_COPY(pixmap->drawable.pScreen, tmp, dstRegion); gc->funcs->ChangeClip(gc, CT_REGION, tmp, 0); } } ValidateGC(&pixmap->drawable, gc); gc->ops->CopyArea(&target->drawable, &pixmap->drawable, gc, 0, 0, target->drawable.width, target->drawable.height, -pix_xoff, -pix_yoff); FreeScratchGC(gc); } target->drawable.pScreen->DestroyPixmap(target); } intel_uxa_debug_flush(scrn); }
static void PclDoArc( DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc *pArcs, void (*DoIt)(FILE *, PclContextPrivPtr, double, double, xArc)) { char t[80]; FILE *outFile; int nbox, i; BoxPtr pbox; BoxRec r; RegionPtr drawRegion, region, transClip; short fudge; int xoffset, yoffset; XpContextPtr pCon; PclContextPrivPtr pConPriv; xRectangle repro; if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) return; fudge = 3 * pGC->lineWidth; pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); pConPriv = (PclContextPrivPtr) pCon->devPrivates[PclContextPrivateIndex].ptr; XpGetReproductionArea( pCon, &repro ); /* * Generate the PCL code to draw the collection of arcs, by * defining it as a macro which uses the HP-GL/2 arc drawing * function. */ xoffset = pDrawable->x; yoffset = pDrawable->y; for( i = 0; i < nArcs; i++ ) { xArc Arc = pArcs[i]; double b, X, Y, ratio; double angle1; MACRO_START( outFile, pConPriv ); SAVE_PCL( outFile, pConPriv, "\033%0B" ); /* Calculate the start of the arc */ if( ( Arc.angle1 / 64 ) % 360 == 90 ) { X = 0; Y = -Arc.height / 2.0; } else if( ( Arc.angle1 / 64 ) % 360 == 270 ) { X = 0; Y = Arc.height / 2.0; } else { /* Convert the angle to radians */ angle1 = ( Arc.angle1 / 64.0 ) * 3.141592654 / 180.0; b = (Arc.height / 2.0); X = b * cos( angle1 ); Y = -b * sin( angle1 ); } /* Change the coordinate system to scale the ellipse */ ratio = (double)Arc.height / (double)Arc.width; sprintf( t, "SC%.2f,%.2f,%d,%d;", (repro.x - Arc.width / 2 - xoffset - Arc.x) * ratio, (repro.x - Arc.width / 2 - xoffset - Arc.x + repro.width) * ratio, repro.y - Arc.height / 2 - yoffset - Arc.y + repro.height, repro.y - Arc.height / 2 - yoffset - Arc.y); SAVE_PCL( outFile, pConPriv, t ); DoIt( outFile, pConPriv, X, Y, Arc ); /* Build the bounding box */ r.x1 = -Arc.width / 2 - fudge; r.y1 = -Arc.height / 2 - fudge; r.x2 = Arc.width / 2 + fudge; r.y2 = Arc.height / 2 + fudge; drawRegion = REGION_CREATE( pGC->pScreen, &r, 0 ); SAVE_PCL( outFile, pConPriv, "\033%0A" ); MACRO_END( outFile ); /* * Intersect the bounding box with the clip region. */ region = REGION_CREATE( pGC->pScreen, NULL, 0 ); transClip = REGION_CREATE( pGC->pScreen, NULL, 0 ); REGION_COPY( pGC->pScreen, transClip, pGC->pCompositeClip ); REGION_TRANSLATE( pGC->pScreen, transClip, -(xoffset + Arc.x + Arc.width / 2), -(yoffset + Arc.y + Arc.height / 2) ); REGION_INTERSECT( pGC->pScreen, region, drawRegion, transClip ); /* * For each rectangle in the clip region, set the HP-GL/2 "input * window" and render the collection of arcs to it. */ pbox = REGION_RECTS( region ); nbox = REGION_NUM_RECTS( region ); PclSendData(outFile, pConPriv, pbox, nbox, ratio); /* * Restore the coordinate system */ sprintf( t, "\033%%0BSC%d,%d,%d,%d;\033%%0A", repro.x, repro.x + repro.width, repro.y + repro.height, repro.y ); SEND_PCL( outFile, t ); /* * Clean up the temporary regions */ REGION_DESTROY( pGC->pScreen, drawRegion ); REGION_DESTROY( pGC->pScreen, region ); REGION_DESTROY( pGC->pScreen, transClip ); } }
static void winReshapePRootless (WindowPtr pWin) { int nRects; ScreenPtr pScreen = pWin->drawable.pScreen; RegionRec rrNewShape; BoxPtr pShape, pRects, pEnd; HRGN hRgn, hRgnRect; winWindowPriv(pWin); #if CYGDEBUG ErrorF ("winReshapePRootless ()\n"); #endif /* Bail if the window is the root window */ if (pWin->parent == NULL) return; /* Bail if the window is not top level */ if (pWin->parent->parent != NULL) return; /* Free any existing window region stored in the window privates */ if (pWinPriv->hRgn != NULL) { DeleteObject (pWinPriv->hRgn); pWinPriv->hRgn = NULL; } /* Bail if the window has no bounding region defined */ if (!wBoundingShape (pWin)) return; REGION_NULL(pScreen, &rrNewShape); REGION_COPY(pScreen, &rrNewShape, wBoundingShape(pWin)); REGION_TRANSLATE(pScreen, &rrNewShape, pWin->borderWidth, pWin->borderWidth); nRects = REGION_NUM_RECTS(&rrNewShape); pShape = REGION_RECTS(&rrNewShape); if (nRects > 0) { /* Create initial empty Windows region */ hRgn = CreateRectRgn (0, 0, 0, 0); /* Loop through all rectangles in the X region */ for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) { /* Create a Windows region for the X rectangle */ hRgnRect = CreateRectRgn (pRects->x1, pRects->y1, pRects->x2, pRects->y2); if (hRgnRect == NULL) { ErrorF("winReshapePRootless - CreateRectRgn() failed\n"); } /* Merge the Windows region with the accumulated region */ if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) { ErrorF("winReshapePRootless - CombineRgn() failed\n"); } /* Delete the temporary Windows region */ DeleteObject (hRgnRect); } /* Save a handle to the composite region in the window privates */ pWinPriv->hRgn = hRgn; } REGION_UNINIT(pScreen, &rrNewShape); return; }
Bool exaHWCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown) { ExaScreenPriv (pDstDrawable->pScreen); PixmapPtr pSrcPixmap, pDstPixmap; ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap; int src_off_x, src_off_y; int dst_off_x, dst_off_y; RegionPtr srcregion = NULL, dstregion = NULL; xRectangle *rects; Bool ret = TRUE; /* avoid doing copy operations if no boxes */ if (nbox == 0) return TRUE; pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); pDstPixmap = exaGetDrawablePixmap (pDstDrawable); exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); rects = xalloc(nbox * sizeof(xRectangle)); if (rects) { int i; int ordering; for (i = 0; i < nbox; i++) { rects[i].x = pbox[i].x1 + dx + src_off_x; rects[i].y = pbox[i].y1 + dy + src_off_y; rects[i].width = pbox[i].x2 - pbox[i].x1; rects[i].height = pbox[i].y2 - pbox[i].y1; } /* This must match the miRegionCopy() logic for reversing rect order */ if (nbox == 1 || (dx > 0 && dy > 0) || (pDstDrawable != pSrcDrawable && (pDstDrawable->type != DRAWABLE_WINDOW || pSrcDrawable->type != DRAWABLE_WINDOW))) ordering = CT_YXBANDED; else ordering = CT_UNSORTED; srcregion = RECTS_TO_REGION(pScreen, nbox, rects, ordering); xfree(rects); if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, pGC->fillStyle, pGC->alu, pGC->clientClipType)) { dstregion = REGION_CREATE(pScreen, NullBox, 0); REGION_COPY(pScreen, dstregion, srcregion); REGION_TRANSLATE(pScreen, dstregion, dst_off_x - dx - src_off_x, dst_off_y - dy - src_off_y); } } pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap); pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap); /* Check whether the accelerator can use this pixmap. * If the pitch of the pixmaps is out of range, there's nothing * we can do but fall back to software rendering. */ if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH || pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH) goto fallback; /* If the width or the height of either of the pixmaps * is out of range, check whether the boxes are actually out of the * addressable range as well. If they aren't, we can still do * the copying in hardware. */ if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { int i; for (i = 0; i < nbox; i++) { /* src */ if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX || (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY) goto fallback; /* dst */ if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX || (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY) goto fallback; } } if (pExaScr->do_migration) { ExaMigrationRec pixmaps[2]; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pDstPixmap; pixmaps[0].pReg = dstregion; pixmaps[1].as_dst = FALSE; pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pSrcPixmap; pixmaps[1].pReg = srcregion; exaDoMigration (pixmaps, 2, TRUE); } /* Mixed directions must be handled specially if the card is lame */ if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && reverse != upsidedown) { if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) goto out; goto fallback; } if (exaPixmapIsOffscreen(pDstPixmap)) { /* Normal blitting. */ if (exaPixmapIsOffscreen(pSrcPixmap)) { if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1, pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) { goto fallback; } while (nbox--) { (*pExaScr->info->Copy) (pDstPixmap, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (*pExaScr->info->DoneCopy) (pDstPixmap); exaMarkSync (pDstDrawable->pScreen); /* UTS: mainly for SHM PutImage's secondary path. */ } else if (pSrcExaPixmap->sys_ptr) { int bpp = pSrcDrawable->bitsPerPixel; int src_stride = exaGetPixmapPitch(pSrcPixmap); CARD8 *src = NULL; if (!pExaScr->info->UploadToScreen) goto fallback; if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) goto fallback; if (pSrcDrawable->bitsPerPixel < 8) goto fallback; if (pGC && !(pGC->alu == GXcopy && EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask))) goto fallback; while (nbox--) { src = pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + src_off_y) * src_stride + (pbox->x1 + dx + src_off_x) * (bpp / 8); if (!pExaScr->info->UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (char *) src, src_stride)) goto fallback; pbox++; } } else goto fallback; } else goto fallback; goto out; fallback: ret = FALSE; out: if (dstregion) { REGION_UNINIT(pScreen, dstregion); REGION_DESTROY(pScreen, dstregion); } if (srcregion) { REGION_UNINIT(pScreen, srcregion); REGION_DESTROY(pScreen, srcregion); } return ret; }
void winReshapeMultiWindow (WindowPtr pWin) { int nRects; RegionRec rrNewShape; BoxPtr pShape, pRects, pEnd; HRGN hRgn, hRgnRect; winWindowPriv(pWin); #if CYGDEBUG winDebug ("winReshape ()\n"); #endif /* Bail if the window is the root window */ if (pWin->parent == NULL) return; /* Bail if the window is not top level */ if (pWin->parent->parent != NULL) return; /* Bail if Windows window handle is invalid */ if (pWinPriv->hWnd == NULL) return; /* Free any existing window region stored in the window privates */ if (pWinPriv->hRgn != NULL) { DeleteObject (pWinPriv->hRgn); pWinPriv->hRgn = NULL; } /* Bail if the window has no bounding region defined */ if (!wBoundingShape (pWin)) return; REGION_NULL(pWin->drawable.pScreen, &rrNewShape); REGION_COPY(pWin->drawable.pScreen, &rrNewShape, wBoundingShape(pWin)); REGION_TRANSLATE(pWin->drawable.pScreen, &rrNewShape, pWin->borderWidth, pWin->borderWidth); nRects = REGION_NUM_RECTS(&rrNewShape); pShape = REGION_RECTS(&rrNewShape); /* Don't do anything if there are no rectangles in the region */ if (nRects > 0) { RECT rcClient; RECT rcWindow; int iOffsetX, iOffsetY; /* Get client rectangle */ if (!GetClientRect (pWinPriv->hWnd, &rcClient)) { ErrorF ("winReshape - GetClientRect failed, bailing: %d\n", (int) GetLastError ()); return; } /* Translate client rectangle coords to screen coords */ /* NOTE: Only transforms top and left members */ ClientToScreen (pWinPriv->hWnd, (LPPOINT) &rcClient); /* Get window rectangle */ if (!GetWindowRect (pWinPriv->hWnd, &rcWindow)) { ErrorF ("winReshape - GetWindowRect failed, bailing: %d\n", (int) GetLastError ()); return; } /* Calculate offset from window upper-left to client upper-left */ iOffsetX = rcClient.left - rcWindow.left; iOffsetY = rcClient.top - rcWindow.top; /* Create initial Windows region for title bar */ /* FIXME: Mean, nasty, ugly hack!!! */ hRgn = CreateRectRgn (0, 0, rcWindow.right, iOffsetY); if (hRgn == NULL) { ErrorF ("winReshape - Initial CreateRectRgn (%d, %d, %d, %d) " "failed: %d\n", 0, 0, (int) rcWindow.right, iOffsetY, (int) GetLastError ()); } /* Loop through all rectangles in the X region */ for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) { /* Create a Windows region for the X rectangle */ hRgnRect = CreateRectRgn (pRects->x1 + iOffsetX, pRects->y1 + iOffsetY, pRects->x2 + iOffsetX, pRects->y2 + iOffsetY); if (hRgnRect == NULL) { ErrorF ("winReshape - Loop CreateRectRgn (%d, %d, %d, %d) " "failed: %d\n" "\tx1: %d x2: %d xOff: %d y1: %d y2: %d yOff: %d\n", pRects->x1 + iOffsetX, pRects->y1 + iOffsetY, pRects->x2 + iOffsetX, pRects->y2 + iOffsetY, (int) GetLastError (), pRects->x1, pRects->x2, iOffsetX, pRects->y1, pRects->y2, iOffsetY); } /* Merge the Windows region with the accumulated region */ if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) { ErrorF ("winReshape - CombineRgn () failed: %d\n", (int) GetLastError ()); } /* Delete the temporary Windows region */ DeleteObject (hRgnRect); } /* Save a handle to the composite region in the window privates */ pWinPriv->hRgn = hRgn; } REGION_UNINIT(pWin->drawable.pScreen, &rrNewShape); return; }
Bool saa_hw_copy_nton(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown) { ScreenPtr pScreen = pDstDrawable->pScreen; struct saa_screen_priv *sscreen = saa_screen(pDstDrawable->pScreen); struct saa_driver *driver = sscreen->driver; PixmapPtr pSrcPixmap, pDstPixmap; struct saa_pixmap *src_spix, *dst_spix; int src_off_x, src_off_y; int dst_off_x, dst_off_y; RegionRec dst_reg, *src_reg; int ordering; Bool ret = TRUE; (void)pScreen; /* avoid doing copy operations if no boxes */ if (nbox == 0) return TRUE; pSrcPixmap = saa_get_pixmap(pSrcDrawable, &src_off_x, &src_off_y); pDstPixmap = saa_get_pixmap(pDstDrawable, &dst_off_x, &dst_off_y); src_spix = saa_pixmap(pSrcPixmap); dst_spix = saa_pixmap(pDstPixmap); if (src_spix->auth_loc != saa_loc_driver || dst_spix->auth_loc != saa_loc_driver) return FALSE; ordering = (nbox == 1 || (dx > 0 && dy > 0) || (pDstDrawable != pSrcDrawable && (pDstDrawable->type != DRAWABLE_WINDOW || pSrcDrawable->type != DRAWABLE_WINDOW))) ? CT_YXBANDED : CT_UNSORTED; src_reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering); if (!src_reg) return FALSE; REGION_NULL(pScreen, &dst_reg); REGION_COPY(pScreen, &dst_reg, src_reg); REGION_TRANSLATE(pScreen, src_reg, dx + src_off_x, dy + src_off_y); REGION_TRANSLATE(pScreen, &dst_reg, dst_off_x, dst_off_y); if (!(driver->copy_prepare) (driver, pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1, pGC ? pGC->alu : GXcopy, src_reg, pGC ? pGC->planemask : FB_ALLONES)) { goto fallback; } while (nbox--) { (driver->copy) (driver, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; } (driver->copy_done) (driver); saa_pixmap_dirty(pDstPixmap, TRUE, &dst_reg); goto out; fallback: ret = FALSE; out: REGION_UNINIT(pScreen, &dst_reg); REGION_DESTROY(pScreen, src_reg); return ret; }