void CreatorDoHWBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask) { FFBPtr pFfb = GET_FFB_FROM_SCREEN (pSrc->pScreen); ffb_fbcPtr ffb = pFfb->regs; BoxPtr pboxTmp; DDXPointPtr pptTmp; int nbox; BoxPtr pboxNext, pboxBase, pbox; nbox = REGION_NUM_RECTS(prgnDst); pbox = REGION_RECTS(prgnDst); FFB_WRITE_ATTRIBUTES(pFfb, FFB_PPC_ACE_DISABLE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST, FFB_PPC_ACE_MASK|FFB_PPC_APE_MASK|FFB_PPC_CS_MASK, planemask, FFB_ROP_NEW, FFB_DRAWOP_BCOPY, pFfb->fg_cache, FFB_FBC_DEFAULT); /* need to blit rectangles in different orders, depending on the direction of copy so that an area isnt overwritten before it is blitted */ if (pptSrc->y < pbox->y1 && nbox > 1) { if (pptSrc->x < pbox->x1) { pboxTmp = pbox + nbox; pptTmp = pptSrc + nbox; while(nbox--) { pboxTmp--; pptTmp--; FFBFifo(pFfb, 6); FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x); FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1); FFB_WRITE64_3(&ffb->bh, (pboxTmp->y2 - pboxTmp->y1), (pboxTmp->x2 - pboxTmp->x1)); } } else { /* keep ordering in each band, reverse order of bands */ pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox) { /* for each band */ /* find first box in band */ while (pboxNext >= pbox && pboxBase->y1 == pboxNext->y1) pboxNext--; pboxTmp = pboxNext + 1; /* first box in band */ pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */ while (pboxTmp <= pboxBase) { /* for each box in band */ FFBFifo(pFfb, 6); FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x); FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1); FFB_WRITE64_3(&ffb->bh, (pboxTmp->y2 - pboxTmp->y1), (pboxTmp->x2 - pboxTmp->x1)); ++pboxTmp; ++pptTmp; } pboxBase = pboxNext; } } } else { if((pptSrc->x < pbox->x1) && (nbox > 1)) { pboxBase = pboxNext = pbox; while(pboxBase < pbox+nbox) { while((pboxNext<pbox+nbox) && (pboxNext->y1 == pboxBase->y1)) pboxNext++; pboxTmp = pboxNext; pptTmp = pptSrc + (pboxTmp - pbox); while(pboxTmp != pboxBase) { --pboxTmp; --pptTmp; FFBFifo(pFfb, 6); FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x); FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1); FFB_WRITE64_3(&ffb->bh, (pboxTmp->y2 - pboxTmp->y1), (pboxTmp->x2 - pboxTmp->x1)); } pboxBase = pboxNext; } } else { /* dont need to change order of anything */ pptTmp = pptSrc; pboxTmp = pbox; while (nbox--) { FFBFifo(pFfb, 6); FFB_WRITE64(&ffb->by, pptTmp->y, pptTmp->x); FFB_WRITE64_2(&ffb->dy, pboxTmp->y1, pboxTmp->x1); FFB_WRITE64_3(&ffb->bh, (pboxTmp->y2 - pboxTmp->y1), (pboxTmp->x2 - pboxTmp->x1)); pboxTmp++; pptTmp++; } } } pFfb->rp_active = 1; FFBSync(pFfb, ffb); }
void winShadowUpdateDDNL (ScreenPtr pScreen, shadowBufPtr pBuf) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; RegionPtr damage = &pBuf->damage; HRESULT ddrval = DD_OK; RECT rcDest, rcSrc; POINT ptOrigin; DWORD dwBox = REGION_NUM_RECTS (damage); BoxPtr pBox = REGION_RECTS (damage); HRGN hrgnTemp = NULL, hrgnCombined = NULL; /* * Return immediately if the app is not active * and we are fullscreen, or if we have a bad display depth */ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) || pScreenPriv->fBadDepth) return; /* Get the origin of the window in the screen coords */ ptOrigin.x = pScreenInfo->dwXOffset; ptOrigin.y = pScreenInfo->dwYOffset; MapWindowPoints (pScreenPriv->hwndScreen, HWND_DESKTOP, (LPPOINT)&ptOrigin, 1); /* * Handle small regions with multiple blits, * handle large regions by creating a clipping region and * doing a single blit constrained to that clipping region. */ if (pScreenInfo->dwClipUpdatesNBoxes == 0 || dwBox < pScreenInfo->dwClipUpdatesNBoxes) { /* Loop through all boxes in the damaged region */ while (dwBox--) { /* Assign damage box to source rectangle */ rcSrc.left = pBox->x1; rcSrc.top = pBox->y1; rcSrc.right = pBox->x2; rcSrc.bottom = pBox->y2; /* Calculate destination rectangle */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Blit the damaged areas */ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, &rcDest, pScreenPriv->pddsShadow4, &rcSrc, DDBLT_WAIT, NULL); if (FAILED (ddrval)) { ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () " "failed: %08x\n", ddrval); } /* Get a pointer to the next box */ ++pBox; } } else { BoxPtr pBoxExtents = REGION_EXTENTS (pScreen, damage); /* Compute a GDI region from the damaged region */ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); dwBox--; pBox++; while (dwBox--) { hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); DeleteObject (hrgnTemp); pBox++; } /* Install the GDI region as a clipping region */ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); DeleteObject (hrgnCombined); hrgnCombined = NULL; #if CYGDEBUG ErrorF ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n", pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2, pBoxExtents->y2); #endif /* Calculating a bounding box for the source is easy */ rcSrc.left = pBoxExtents->x1; rcSrc.top = pBoxExtents->y1; rcSrc.right = pBoxExtents->x2; rcSrc.bottom = pBoxExtents->y2; /* Calculating a bounding box for the destination is trickier */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Our Blt should be clipped to the invalidated region */ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, &rcDest, pScreenPriv->pddsShadow4, &rcSrc, DDBLT_WAIT, NULL); /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } }
void xglFillSpan (DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth) { RegionPtr pClip = pGC->pCompositeClip; BoxPtr pClipBox; BoxPtr pExtent = REGION_EXTENTS (pGC->pScreen, pClip); BoxRec part, full; BoxPtr heapBox = NULL; BoxRec stackBox[N_STACK_BOX]; int size = N_STACK_BOX; BoxPtr pBox = stackBox; int nClip, nBox = 0; while (n--) { full.x1 = ppt->x; full.y1 = ppt->y; full.x2 = full.x1 + *pwidth; full.y2 = full.y1 + 1; pwidth++; ppt++; if (full.x1 < pExtent->x1) full.x1 = pExtent->x1; if (full.y1 < pExtent->y1) full.y1 = pExtent->y1; if (full.x2 > pExtent->x2) full.x2 = pExtent->x2; if (full.y2 > pExtent->y2) full.y2 = pExtent->y2; if (full.x1 >= full.x2 || full.y1 >= full.y2) continue; nClip = REGION_NUM_RECTS (pClip); if (nClip == 1) { ADD_BOX (pBox, nBox, stackBox, heapBox, size, full); } else { pClipBox = REGION_RECTS (pClip); while (nClip--) { part = *pClipBox++; if (part.x1 < full.x1) part.x1 = full.x1; if (part.y1 < full.y1) part.y1 = full.y1; if (part.x2 > full.x2) part.x2 = full.x2; if (part.y2 > full.y2) part.y2 = full.y2; if (part.x1 < part.x2 && part.y1 < part.y2) ADD_BOX (pBox, nBox, stackBox, heapBox, size, part); } } } xglFillBox (pDrawable, pGC, pExtent->x1, pExtent->y1, pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, (heapBox) ? heapBox : stackBox, nBox); if (heapBox) xfree (heapBox); }
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 ); } }
RegionPtr XAABitBlt( DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, void (*doBitBlt)(DrawablePtr, DrawablePtr, GCPtr, RegionPtr, DDXPointPtr), unsigned long bitPlane ) { RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ RegionPtr prgnExposed; Bool freeSrcClip = FALSE; RegionRec rgnDst; DDXPointPtr pptSrc, ppt; DDXPointRec origDest; BoxPtr pbox; BoxRec fastBox; int i, dx, dy, numRects; xRectangle origSource; int fastClip = 0; /* for fast clipping with pixmap source */ int fastExpose = 0; /* for fast exposures with pixmap source */ origSource.x = srcx; origSource.y = srcy; origSource.width = width; origSource.height = height; origDest.x = dstx; origDest.y = dsty; if((pSrcDrawable != pDstDrawable) && pSrcDrawable->pScreen->SourceValidate) { (*pSrcDrawable->pScreen->SourceValidate) ( pSrcDrawable, srcx, srcy, width, height); } srcx += pSrcDrawable->x; srcy += pSrcDrawable->y; /* clip the source */ if (pSrcDrawable->type == DRAWABLE_PIXMAP) { if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) prgnSrcClip = pGC->pCompositeClip; else fastClip = 1; } else { /* Window */ if (pGC->subWindowMode == IncludeInferiors) { if (!((WindowPtr) pSrcDrawable)->parent) { /* * special case bitblt from root window in * IncludeInferiors mode; just like from a pixmap */ fastClip = 1; } else if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) { prgnSrcClip = pGC->pCompositeClip; } else { prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); freeSrcClip = TRUE; } } else { prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; } } fastBox.x1 = srcx; fastBox.y1 = srcy; fastBox.x2 = srcx + width; fastBox.y2 = srcy + height; /* Don't create a source region if we are doing a fast clip */ if (fastClip) { fastExpose = 1; /* * clip the source; if regions extend beyond the source size, * make sure exposure events get sent */ if (fastBox.x1 < pSrcDrawable->x) { fastBox.x1 = pSrcDrawable->x; fastExpose = 0; } if (fastBox.y1 < pSrcDrawable->y) { fastBox.y1 = pSrcDrawable->y; fastExpose = 0; } if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; fastExpose = 0; } if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; fastExpose = 0; } } else { REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); } dstx += pDstDrawable->x; dsty += pDstDrawable->y; if (pDstDrawable->type == DRAWABLE_WINDOW) { if (!((WindowPtr)pDstDrawable)->realized) { if (!fastClip) REGION_UNINIT(pGC->pScreen, &rgnDst); if (freeSrcClip) REGION_DESTROY(pGC->pScreen, prgnSrcClip); return NULL; } } dx = srcx - dstx; dy = srcy - dsty; /* Translate and clip the dst to the destination composite clip */ if (fastClip) { RegionPtr cclip; /* Translate the region directly */ fastBox.x1 -= dx; fastBox.x2 -= dx; fastBox.y1 -= dy; fastBox.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 = pGC->pCompositeClip; if (REGION_NUM_RECTS(cclip) == 1) { BoxPtr pBox = REGION_RECTS(cclip); if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1; if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2; if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1; if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2; /* Check to see if the region is empty */ if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) { REGION_NULL(pGC->pScreen, &rgnDst); } else { REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); } } else { /* We must turn off fastClip now, since we must create a full blown region. It is intersected with the composite clip below. */ fastClip = 0; REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1); } } else { REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); } if (!fastClip) { REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, pGC->pCompositeClip); } /* Do bit blitting */ numRects = REGION_NUM_RECTS(&rgnDst); if (numRects && width && height) { if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects * sizeof(DDXPointRec)))) { REGION_UNINIT(pGC->pScreen, &rgnDst); if (freeSrcClip) REGION_DESTROY(pGC->pScreen, prgnSrcClip); return NULL; } pbox = REGION_RECTS(&rgnDst); ppt = pptSrc; for (i = numRects; --i >= 0; pbox++, ppt++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC, &rgnDst, pptSrc); DEALLOCATE_LOCAL(pptSrc); } prgnExposed = NULL; if (pGC->fExpose) { /* Pixmap sources generate a NoExposed (we return NULL to do this) */ if (!fastExpose) prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, origSource.x, origSource.y, (int)origSource.width, (int)origSource.height, origDest.x, origDest.y, bitPlane); } REGION_UNINIT(pGC->pScreen, &rgnDst); if (freeSrcClip) REGION_DESTROY(pGC->pScreen, prgnSrcClip); return prgnExposed; }
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; }
void fbWalkCompositeRegion (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height, Bool srcRepeat, Bool maskRepeat, CompositeFunc compositeRect) { RegionRec region; int n; BoxPtr pbox; int w, h, w_this, h_this; int x_msk, y_msk, x_src, y_src, x_dst, y_dst; xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; if (pSrc->pDrawable) { xSrc += pSrc->pDrawable->x; ySrc += pSrc->pDrawable->y; } if (pMask && pMask->pDrawable) { xMask += pMask->pDrawable->x; yMask += pMask->pDrawable->y; } if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) return; n = REGION_NUM_RECTS (®ion); pbox = REGION_RECTS (®ion); while (n--) { h = pbox->y2 - pbox->y1; y_src = pbox->y1 - yDst + ySrc; y_msk = pbox->y1 - yDst + yMask; y_dst = pbox->y1; while (h) { h_this = h; w = pbox->x2 - pbox->x1; x_src = pbox->x1 - xDst + xSrc; x_msk = pbox->x1 - xDst + xMask; x_dst = pbox->x1; if (maskRepeat) { y_msk = mod (y_msk - pMask->pDrawable->y, pMask->pDrawable->height); if (h_this > pMask->pDrawable->height - y_msk) h_this = pMask->pDrawable->height - y_msk; y_msk += pMask->pDrawable->y; } if (srcRepeat) { y_src = mod (y_src - pSrc->pDrawable->y, pSrc->pDrawable->height); if (h_this > pSrc->pDrawable->height - y_src) h_this = pSrc->pDrawable->height - y_src; y_src += pSrc->pDrawable->y; } while (w) { w_this = w; if (maskRepeat) { x_msk = mod (x_msk - pMask->pDrawable->x, pMask->pDrawable->width); if (w_this > pMask->pDrawable->width - x_msk) w_this = pMask->pDrawable->width - x_msk; x_msk += pMask->pDrawable->x; } if (srcRepeat) { x_src = mod (x_src - pSrc->pDrawable->x, pSrc->pDrawable->width); if (w_this > pSrc->pDrawable->width - x_src) w_this = pSrc->pDrawable->width - x_src; x_src += pSrc->pDrawable->x; } (*compositeRect) (op, pSrc, pMask, pDst, x_src, y_src, x_msk, y_msk, x_dst, y_dst, w_this, h_this); w -= w_this; x_src += w_this; x_msk += w_this; x_dst += w_this; } h -= h_this; y_src += h_this; y_msk += h_this; y_dst += h_this; } pbox++; } REGION_UNINIT (pDst->pDrawable->pScreen, ®ion); }
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; }
/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. * Based on fbFillRegionTiled(), fbTile(). */ Bool uxa_fill_region_tiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu) { uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); PixmapPtr pPixmap; int xoff, yoff; int tileWidth, tileHeight; int nbox = REGION_NUM_RECTS(pRegion); BoxPtr pBox = REGION_RECTS(pRegion); Bool ret = FALSE; tileWidth = pTile->drawable.width; tileHeight = pTile->drawable.height; /* If we're filling with a solid color, grab it out and go to * FillRegionsolid, saving numerous copies. */ if (tileWidth == 1 && tileHeight == 1) return uxa_fill_region_solid(pDrawable, pRegion, uxa_get_pixmap_first_pixel(pTile), planemask, alu); pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); if (!pPixmap || !uxa_pixmap_is_offscreen(pTile)) goto out; if (uxa_screen->info->check_copy && !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask)) return FALSE; REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, planemask)) { while (nbox--) { int height = pBox->y2 - pBox->y1; int dstY = pBox->y1; int tileY; modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); while (height > 0) { int width = pBox->x2 - pBox->x1; int dstX = pBox->x1; int tileX; int h = tileHeight - tileY; if (h > height) h = height; height -= h; modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth, tileX); while (width > 0) { int w = tileWidth - tileX; if (w > width) w = width; width -= w; (*uxa_screen->info->copy) (pPixmap, tileX, tileY, dstX, dstY, w, h); dstX += w; tileX = 0; } dstY += h; tileY = 0; } pBox++; } (*uxa_screen->info->done_copy) (pPixmap); ret = TRUE; } out: REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); return ret; }
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; int dirty_type; int post_process; int reset_surface; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; LLOGLN(10, ("rdpPolyFillRect:")); /* make a copy of rects */ fill_reg = RegionFromRects(nrectFill, prectInit, CT_NONE); /* do original call */ rdpPolyFillRectOrg(pDrawable, pGC, nrectFill, prectInit); dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); if (pDstPixmap->devPrivate.ptr == g_rdpScreen.pfbMemory) { /* treat like root window */ post_process = 1; if (g_do_dirty_ons) { LLOGLN(10, ("rdpPolyFillRect: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } else if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpPolyFillRect: gettig dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; dirty_type = RDI_FILL; } 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, ("rdpPolyFillRect: 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) { RegionDestroy(fill_reg); LLOGLN(10, ("rdpPolyFillRect: out, post_process not set")); return; } RegionTranslate(fill_reg, pDrawable->x, pDrawable->y); RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDrawable, pGC); LLOGLN(10, ("rdpPolyFillRect: cd %d", cd)); if (cd == 1) /* no clip */ { if (dirty_type != 0) { 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? */ { draw_item_add_fill_region(pDirtyPriv, fill_reg, pGC->fgPixel, pGC->alu); } else { draw_item_add_img_region(pDirtyPriv, fill_reg, GXcopy, RDI_IMGLL, 2); } } else if (got_id) { 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) { if (dirty_type != 0) { 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? */ { LLOGLN(10, ("rdpPolyFillRect: 3")); draw_item_add_fill_region(pDirtyPriv, &clip_reg, pGC->fgPixel, pGC->alu); } else { LLOGLN(10, ("rdpPolyFillRect: 4")); draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, RDI_IMGLL, 2); } } else if (got_id) { rdpup_begin_update(); LLOGLN(10, ("2 %x", pGC->fgPixel)); 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); if (reset_surface) { rdpup_switch_os_surface(-1); } }
static FBAreaPtr AllocateArea( FBManagerPtr offman, int w, int h, int granularity, MoveAreaCallbackProcPtr moveCB, RemoveAreaCallbackProcPtr removeCB, pointer privData ){ ScreenPtr pScreen = offman->pScreen; FBLinkPtr link = NULL; FBAreaPtr area = NULL; RegionRec NewReg; int i, x = 0, num; BoxPtr boxp; if(granularity <= 1) granularity = 0; boxp = REGION_RECTS(offman->FreeBoxes); num = REGION_NUM_RECTS(offman->FreeBoxes); /* look through the free boxes */ for(i = 0; i < num; i++, boxp++) { x = boxp->x1; if(granularity) { int tmp = x % granularity; if(tmp) x += (granularity - tmp); } if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) continue; link = xalloc(sizeof(FBLink)); if(!link) return NULL; area = &(link->area); link->next = offman->UsedAreas; offman->UsedAreas = link; offman->NumUsedAreas++; break; } /* try to boot a removeable one out if we are not expendable ourselves */ if(!area && !removeCB) { link = offman->UsedAreas; while(link) { if(!link->area.RemoveAreaCallback) { link = link->next; continue; } boxp = &(link->area.box); x = boxp->x1; if(granularity) { int tmp = x % granularity; if(tmp) x += (granularity - tmp); } if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) { link = link->next; continue; } /* bye, bye */ (*link->area.RemoveAreaCallback)(&link->area); REGION_INIT(pScreen, &NewReg, &(link->area.box), 1); REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg); REGION_UNINIT(pScreen, &NewReg); area = &(link->area); break; } } if(area) { area->pScreen = pScreen; area->granularity = granularity; area->box.x1 = x; area->box.x2 = x + w; area->box.y1 = boxp->y1; area->box.y2 = boxp->y1 + h; area->MoveAreaCallback = moveCB; area->RemoveAreaCallback = removeCB; area->devPrivate.ptr = privData; REGION_INIT(pScreen, &NewReg, &(area->box), 1); REGION_SUBTRACT(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg); REGION_UNINIT(pScreen, &NewReg); } return area; }
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); }
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; }
void XAAPolyRectangleThinSolid( DrawablePtr pDrawable, GCPtr pGC, int nRectsInit, xRectangle *pRectsInit ) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); int nClipRects; /* number of clip rectangles */ BoxPtr pClipRects; /* points to the list of clip rects */ int xOrigin; /* Drawables x origin */ int yOrigin; /* Drawables x origin */ xRectangle *pRect; /* list of rects */ int nRects; /* running count of number of rects */ int origX1, origY1; /* original rectangle's U/L corner */ int origX2, origY2; /* original rectangle's L/R corner */ int clippedX1; /* clipped rectangle's left x */ int clippedY1; /* clipped rectangle's top y */ int clippedX2; /* clipped rectangle's right x */ int clippedY2; /* clipped rectangle's bottom y */ int clipXMin; /* upper left corner of clip rect */ int clipYMin; /* upper left corner of clip rect */ int clipXMax; /* lower right corner of clip rect */ int clipYMax; /* lower right corner of clip rect */ int width, height; /* width and height of rect */ nClipRects = REGION_NUM_RECTS(pGC->pCompositeClip); pClipRects = REGION_RECTS(pGC->pCompositeClip); if(!nClipRects) return; xOrigin = pDrawable->x; yOrigin = pDrawable->y; (*infoRec->SetupForSolidLine)(infoRec->pScrn, pGC->fgPixel, pGC->alu, pGC->planemask); for ( ; nClipRects > 0; nClipRects--, pClipRects++ ) { clipYMin = pClipRects->y1; clipYMax = pClipRects->y2 - 1; clipXMin = pClipRects->x1; clipXMax = pClipRects->x2 - 1; for (pRect = pRectsInit, nRects = nRectsInit; nRects > 0; nRects--, pRect++ ) { /* translate rectangle data over to the drawable */ origX1 = pRect->x + xOrigin; origY1 = pRect->y + yOrigin; origX2 = origX1 + pRect->width; origY2 = origY1 + pRect->height; /* reject entire rectangle if completely outside clip rect */ if ((origX1 > clipXMax) || (origX2 < clipXMin) || (origY1 > clipYMax) || (origY2 < clipYMin)) continue; /* clip the rectangle */ clippedX1 = max (origX1, clipXMin); clippedX2 = min (origX2, clipXMax); clippedY1 = max (origY1, clipYMin); clippedY2 = min (origY2, clipYMax); width = clippedX2 - clippedX1 + 1; if (origY1 >= clipYMin) { (*infoRec->SubsequentSolidHorVertLine)(infoRec->pScrn, clippedX1, clippedY1, width, DEGREES_0); /* don't overwrite corner */ clippedY1++; } if ((origY2 <= clipYMax) && (origY1 != origY2)) { (*infoRec->SubsequentSolidHorVertLine)(infoRec->pScrn, clippedX1, clippedY2, width, DEGREES_0); /* don't overwrite corner */ clippedY2--; } if (clippedY2 < clippedY1) continue; height = clippedY2 - clippedY1 + 1; /* draw vertical edges using lines if not clipped out */ if (origX1 >= clipXMin) (*infoRec->SubsequentSolidHorVertLine)(infoRec->pScrn, clippedX1, clippedY1, height, DEGREES_270); if ((origX2 <= clipXMax) && (origX2 != origX1)) (*infoRec->SubsequentSolidHorVertLine)(infoRec->pScrn, clippedX2, clippedY1, height, DEGREES_270); } } SET_SYNC_FLAG(infoRec); }
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); }
static Bool uxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int format, char *bits, int src_stride) { uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); PixmapPtr pPix; RegionPtr pClip; BoxPtr pbox; int nbox; int xoff, yoff; int bpp = pDrawable->bitsPerPixel; /* Don't bother with under 8bpp, XYPixmaps. */ if (format != ZPixmap || bpp < 8) return FALSE; if (uxa_screen->force_fallback) return FALSE; if (!uxa_screen->info->put_image) return FALSE; /* Only accelerate copies: no rop or planemask. */ if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) return FALSE; pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); if (!pPix) return FALSE; x += pDrawable->x; y += pDrawable->y; pClip = fbGetCompositeClip(pGC); for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); nbox--; pbox++) { int x1 = x; int y1 = y; int x2 = x + w; int y2 = y + h; char *src; Bool ok; if (x1 < pbox->x1) x1 = pbox->x1; if (y1 < pbox->y1) y1 = pbox->y1; if (x2 > pbox->x2) x2 = pbox->x2; if (y2 > pbox->y2) y2 = pbox->y2; if (x1 >= x2 || y1 >= y2) continue; src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff, x2 - x1, y2 - y1, src, src_stride); /* If we fail to accelerate the upload, fall back to using * unaccelerated fb calls. */ if (!ok) { FbStip *dst; FbStride dst_stride; int dstBpp; int dstXoff, dstYoff; if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) return FALSE; fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, dstXoff, dstYoff); fbBltStip((FbStip *) bits + (y1 - y) * (src_stride / sizeof(FbStip)), src_stride / sizeof(FbStip), (x1 - x) * dstBpp, dst + (y1 + dstYoff) * dst_stride, dst_stride, (x1 + dstXoff) * dstBpp, (x2 - x1) * dstBpp, y2 - y1, GXcopy, FB_ALLONES, dstBpp); uxa_finish_access(pDrawable, UXA_ACCESS_RW); } } return TRUE; }
void rlPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { RegionPtr pClip = fbGetCompositeClip(pGC); register BoxPtr pbox; BoxPtr pextent; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1, fullY2; int partX1, partX2, partY1, partY2; int xorg, yorg; int n; xorg = pDrawable->x; yorg = pDrawable->y; pextent = REGION_EXTENTS(pGC->pScreen, 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 = REGION_NUM_RECTS (pClip); if (n == 1) { rlFill (pDrawable, pGC, fullX1, fullY1, fullX2-fullX1, fullY2-fullY1); } else { pbox = REGION_RECTS(pClip); /* * clip the rectangle to each box in the clip region * this is logically equivalent to calling Intersect() */ 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) rlFill (pDrawable, pGC, partX1, partY1, partX2 - partX1, partY2 - partY1); } } } }
static void uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { ScreenPtr screen = pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr dst_pixmap; BoxPtr pbox; int nbox; int x1, x2, y; int off_x, off_y; if (uxa_screen->info->flags & UXA_USE_GLAMOR) { int ok = 0; if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) { ok = glamor_fill_spans_nf(pDrawable, pGC, n, ppt, pwidth, fSorted); uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW); } if (!ok) goto fallback; return; } if (uxa_screen->force_fallback) goto fallback; if (pGC->fillStyle != FillSolid) goto fallback; dst_pixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y); if (!dst_pixmap) goto fallback; if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) goto fallback; if (!(*uxa_screen->info->prepare_solid) (dst_pixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) goto fallback; while (n--) { x1 = ppt->x; y = ppt->y; x2 = x1 + (int)*pwidth; ppt++; pwidth++; nbox = REGION_NUM_RECTS(pClip); pbox = REGION_RECTS(pClip); while (nbox--) { int X1 = x1, X2 = x2; if (X1 < pbox->x1) X1 = pbox->x1; if (X2 > pbox->x2) X2 = pbox->x2; if (X2 > X1 && pbox->y1 <= y && pbox->y2 > y) (*uxa_screen->info->solid) (dst_pixmap, X1 + off_x, y + off_y, X2 + off_x, y + 1 + off_y); pbox++; } } (*uxa_screen->info->done_solid) (dst_pixmap); return; fallback: uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); }
/* 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); } }
static void uxa_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle * prect) { uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap; RegionPtr pReg; BoxPtr pbox; int fullX1, fullX2, fullY1, fullY2; int xoff, yoff; int xorg, yorg; int n; if (uxa_screen->info->flags & UXA_USE_GLAMOR) { int ok = 0; if (uxa_prepare_access(pDrawable, UXA_GLAMOR_ACCESS_RW)) { ok = glamor_poly_fill_rect_nf(pDrawable, pGC, nrect, prect); uxa_finish_access(pDrawable, UXA_GLAMOR_ACCESS_RW); } if (!ok) uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect); return; } /* Compute intersection of rects and clip region */ pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); REGION_INTERSECT(pScreen, pReg, pClip, pReg); if (!REGION_NUM_RECTS(pReg)) goto out; if (uxa_screen->force_fallback) goto fallback; pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); if (!pPixmap) goto fallback; /* For ROPs where overlaps don't matter, convert rectangles to region * and call uxa_fill_region_{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) && uxa_fill_region_solid(pDrawable, pReg, pGC->fillStyle == FillSolid ? pGC->fgPixel : pGC->tile. pixel, pGC->planemask, pGC->alu)) || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && uxa_fill_region_tiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, pGC->planemask, pGC->alu))) { goto out; } } if (pGC->fillStyle != FillSolid && !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { goto fallback; } if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) { goto fallback; } if (!(*uxa_screen->info->prepare_solid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { fallback: uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect); goto out; } xorg = pDrawable->x; yorg = pDrawable->y; while (nrect--) { fullX1 = prect->x + xorg; fullY1 = prect->y + yorg; fullX2 = fullX1 + (int)prect->width; fullY2 = fullY1 + (int)prect->height; prect++; n = REGION_NUM_RECTS(pClip); pbox = REGION_RECTS(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--) { int x1 = fullX1; int x2 = fullX2; int y1 = fullY1; int y2 = fullY2; if (pbox->x1 > x1) x1 = pbox->x1; if (pbox->x2 < x2) x2 = pbox->x2; if (pbox->y1 > y1) y1 = pbox->y1; if (pbox->y2 < y2) y2 = pbox->y2; pbox++; if (x1 >= x2 || y1 >= y2) continue; (*uxa_screen->info->solid) (pPixmap, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } } (*uxa_screen->info->done_solid) (pPixmap); out: REGION_UNINIT(pScreen, pReg); REGION_DESTROY(pScreen, pReg); }
void rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs) { RegionRec clip_reg; int cd; int i; int j; int got_id; int dirty_type; int post_process; int reset_surface; xSegment *segs; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; LLOGLN(10, ("rdpPolySegment:")); LLOGLN(10, (" nseg %d", nseg)); segs = 0; if (nseg) /* get the rects */ { segs = (xSegment *)g_malloc(nseg * sizeof(xSegment), 0); for (i = 0; i < nseg; i++) { segs[i].x1 = pSegs[i].x1 + pDrawable->x; segs[i].y1 = pSegs[i].y1 + pDrawable->y; segs[i].x2 = pSegs[i].x2 + pDrawable->x; segs[i].y2 = pSegs[i].y2 + pDrawable->y; } } /* do original call */ rdpPolySegmentOrg(pDrawable, pGC, nseg, pSegs); 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, ("rdpPolySegment: 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, ("rdpPolySegment: 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(segs); return; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDrawable, pGC); LLOGLN(10, ("rdpPolySegment: cd %d", cd)); if (cd == 1) /* no clip */ { if (segs != 0) { if (dirty_type != 0) { RegionUninit(&clip_reg); RegionInit(&clip_reg, NullBox, 0); RegionAroundSegs(&clip_reg, segs, nseg); draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel, pGC->alu, pGC->lineWidth, segs, nseg, 1); } else if (got_id) { rdpup_begin_update(); rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_opcode(pGC->alu); rdpup_set_pen(0, pGC->lineWidth); for (i = 0; i < nseg; i++) { rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); } rdpup_set_opcode(GXcopy); rdpup_end_update(); } } } else if (cd == 2) /* clip */ { if (segs != 0) { if (dirty_type != 0) { draw_item_add_line_region(pDirtyPriv, &clip_reg, pGC->fgPixel, pGC->alu, pGC->lineWidth, segs, nseg, 1); } else if (got_id) { rdpup_begin_update(); rdpup_set_fgcolor(pGC->fgPixel); rdpup_set_opcode(pGC->alu); rdpup_set_pen(0, pGC->lineWidth); for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); for (i = 0; i < nseg; i++) { rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2); LLOGLN(10, (" %d %d %d %d", segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2)); } } rdpup_reset_clip(); rdpup_set_opcode(GXcopy); rdpup_end_update(); } } } g_free(segs); RegionUninit(&clip_reg); if (reset_surface) { rdpup_switch_os_surface(-1); } }
void rdpPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) { RegionRec clip_reg; int cd; int j; int reset_surface; int post_process; int got_id; int dirty_type; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; RegionRec reg1; RegionRec reg2; LLOGLN(10, ("rdpPutImage:")); LLOGLN(10, ("rdpPutImage: drawable id 0x%x", (int)(pDst->id))); LLOGLN(10, ("rdpPutImage: x %d y %d w %d h %d is_window %d", x, y, w, h, pDst->type == DRAWABLE_WINDOW)); /* do original call */ rdpPutImageOrg(pDst, pGC, depth, x, y, w, h, leftPad, format, pBits); 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, ("rdpPutImage: 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 (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(10, ("rdpPutImage: getting dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLY; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { return; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { if (dirty_type != 0) { box.x1 = pDst->x + x; box.y1 = pDst->y + y; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(®1, &box, 0); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, TAG_PUTIMAGE); RegionUninit(®1); } else if (got_id) { rdpup_begin_update(); rdpup_send_area(&id, pDst->x + x, pDst->y + y, w, h); rdpup_end_update(); } } else if (cd == 2) { if (dirty_type != 0) { box.x1 = pDst->x + x; box.y1 = pDst->y + y; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(®1, &box, 0); RegionInit(®2, NullBox, 0); RegionCopy(®2, &clip_reg); RegionIntersect(®1, ®1, ®2); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, TAG_PUTIMAGE); RegionUninit(®1); RegionUninit(®2); } else if (got_id) { rdpup_begin_update(); for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_set_clip(box.x1, box.y1, (box.x2 - box.x1), (box.y2 - box.y1)); rdpup_send_area(&id, pDst->x + x, pDst->y + y, w, h); } rdpup_reset_clip(); rdpup_end_update(); } } RegionUninit(&clip_reg); if (reset_surface) { rdpup_switch_os_surface(-1); } }
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; RegionRec reg1; RegionRec reg2; int cd; int num_clips; int j; int got_id; int dirty_type; int post_process; int reset_surface; BoxRec box; BoxPtr pbox; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; LLOGLN(10, ("rdpCopyPlane:")); /* do original call */ rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); 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, ("rdpCopyPlane: 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 (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(0, ("rdpCopyPlane: 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); 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(®1, &box, 0); RegionInit(®2, NullBox, 0); RegionCopy(®2, &clip_reg); RegionIntersect(®1, ®1, ®2); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type); RegionUninit(®1); RegionUninit(®2); } 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; }
/* * This function is largely ripped from miPaintWindow, but modified so * that the background is not painted to the root window, and so that * the backing store is not referenced. */ void PclPaintWindow( WindowPtr pWin, RegionPtr pRegion, int what) { int status; WindowPtr pRoot; #define FUNCTION 0 #define FOREGROUND 1 #define TILE 2 #define FILLSTYLE 3 #define ABSX 4 #define ABSY 5 #define CLIPMASK 6 #define SUBWINDOW 7 #define COUNT_BITS 8 pointer gcval[7]; pointer newValues [COUNT_BITS]; BITS32 gcmask, index, mask; RegionRec prgnWin; DDXPointRec oldCorner; BoxRec box; WindowPtr pBgWin; GCPtr pGC; register int i; register BoxPtr pbox; register ScreenPtr pScreen = pWin->drawable.pScreen; register xRectangle *prect; int numRects; gcmask = 0; /* * We don't want to paint a window that has no place to put the * PCL output. */ if( PclGetContextFromWindow( pWin ) == (XpContextPtr)NULL ) return; if (what == PW_BACKGROUND) { switch (pWin->backgroundState) { case None: return; case ParentRelative: (*pWin->parent->drawable.pScreen->PaintWindowBackground) (pWin->parent, pRegion, what); return; case BackgroundPixel: newValues[FOREGROUND] = (pointer)pWin->background.pixel; newValues[FILLSTYLE] = (pointer)FillSolid; gcmask |= GCForeground | GCFillStyle; break; case BackgroundPixmap: newValues[TILE] = (pointer)pWin->background.pixmap; newValues[FILLSTYLE] = (pointer)FillTiled; gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; break; } } else { if (pWin->borderIsPixel) { newValues[FOREGROUND] = (pointer)pWin->border.pixel; newValues[FILLSTYLE] = (pointer)FillSolid; gcmask |= GCForeground | GCFillStyle; } else { newValues[TILE] = (pointer)pWin->border.pixmap; newValues[FILLSTYLE] = (pointer)FillTiled; gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; } } prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(pRegion) * sizeof(xRectangle)); if (!prect) return; newValues[FUNCTION] = (pointer)GXcopy; gcmask |= GCFunction | GCClipMask; i = pScreen->myNum; pRoot = WindowTable[i]; pBgWin = pWin; if (what == PW_BORDER) { while (pBgWin->backgroundState == ParentRelative) pBgWin = pBgWin->parent; } pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); if (!pGC) { DEALLOCATE_LOCAL(prect); return; } /* * mash the clip list so we can paint the border by * mangling the window in place, pretending it * spans the entire screen */ if (what == PW_BORDER) { prgnWin = pWin->clipList; oldCorner.x = pWin->drawable.x; oldCorner.y = pWin->drawable.y; pWin->drawable.x = pWin->drawable.y = 0; box.x1 = 0; box.y1 = 0; box.x2 = pScreen->width; box.y2 = pScreen->height; REGION_INIT(pScreen, &pWin->clipList, &box, 1); pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; newValues[ABSX] = (pointer)(long)pBgWin->drawable.x; newValues[ABSY] = (pointer)(long)pBgWin->drawable.y; } else { newValues[ABSX] = (pointer)0; newValues[ABSY] = (pointer)0; } /* * XXX Backing store is turned off for the PCL driver if (pWin->backStorage) (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); */ mask = gcmask; gcmask = 0; i = 0; while (mask) { index = lowbit (mask); mask &= ~index; switch (index) { case GCFunction: if ((pointer)(long) pGC->alu != newValues[FUNCTION]) { gcmask |= index; gcval[i++] = newValues[FUNCTION]; } break; case GCTileStipXOrigin: if ((pointer)(long) pGC->patOrg.x != newValues[ABSX]) { gcmask |= index; gcval[i++] = newValues[ABSX]; } break; case GCTileStipYOrigin: if ((pointer)(long) pGC->patOrg.y != newValues[ABSY]) { gcmask |= index; gcval[i++] = newValues[ABSY]; } break; case GCClipMask: if ((pointer) pGC->clientClipType != (pointer)CT_NONE) { gcmask |= index; gcval[i++] = (pointer)CT_NONE; } break; case GCSubwindowMode: if ((pointer) pGC->subWindowMode != newValues[SUBWINDOW]) { gcmask |= index; gcval[i++] = newValues[SUBWINDOW]; } break; case GCTile: if (pGC->tileIsPixel || (pointer) pGC->tile.pixmap != newValues[TILE]) { gcmask |= index; gcval[i++] = newValues[TILE]; } break; case GCFillStyle: if ((pointer) pGC->fillStyle != newValues[FILLSTYLE]) { gcmask |= index; gcval[i++] = newValues[FILLSTYLE]; } break; case GCForeground: if ((pointer) pGC->fgPixel != newValues[FOREGROUND]) { gcmask |= index; gcval[i++] = newValues[FOREGROUND]; } break; } } if (gcmask) DoChangeGC(pGC, gcmask, (XID *)gcval, 1); if (pWin->drawable.serialNumber != pGC->serialNumber) ValidateGC((DrawablePtr)pWin, pGC); numRects = REGION_NUM_RECTS(pRegion); pbox = REGION_RECTS(pRegion); for (i= numRects; --i >= 0; pbox++, prect++) { prect->x = pbox->x1 - pWin->drawable.x; prect->y = pbox->y1 - pWin->drawable.y; prect->width = pbox->x2 - pbox->x1; prect->height = pbox->y2 - pbox->y1; } prect -= numRects; (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); DEALLOCATE_LOCAL(prect); /* * XXX Backing store is turned off for the PCL driver if (pWin->backStorage) (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); */ if (what == PW_BORDER) { REGION_UNINIT(pScreen, &pWin->clipList); pWin->clipList = prgnWin; pWin->drawable.x = oldCorner.x; pWin->drawable.y = oldCorner.y; pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; } FreeScratchGC(pGC); }
/* * Create and display a new frame. */ Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY, RegionPtr pShape) { WindowPtr pWin = pFrame->win; xp_window_changes wc; unsigned int mask = 0; xp_error err; wc.x = newX; wc.y = newY; wc.width = pFrame->width; wc.height = pFrame->height; wc.bit_gravity = XP_GRAVITY_NONE; mask |= XP_BOUNDS; if (pWin->drawable.depth == 8) { wc.depth = XP_DEPTH_INDEX8; #if 0 wc.colormap = xprColormapCallback; wc.colormap_data = pScreen; mask |= XP_COLORMAP; #endif } else if (pWin->drawable.depth == 15) wc.depth = XP_DEPTH_RGB555; else if (pWin->drawable.depth == 24) wc.depth = XP_DEPTH_ARGB8888; else wc.depth = XP_DEPTH_NIL; mask |= XP_DEPTH; if (pShape != NULL) { wc.shape_nrects = REGION_NUM_RECTS(pShape); wc.shape_rects = REGION_RECTS(pShape); wc.shape_tx = wc.shape_ty = 0; mask |= XP_SHAPE; } err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid); if (err != Success) { return FALSE; } if (window_hash == NULL) { window_hash = x_hash_table_new(NULL, NULL, NULL, NULL); pthread_mutex_init(&window_hash_mutex, NULL); } pthread_mutex_lock(&window_hash_mutex); x_hash_table_insert(window_hash, pFrame->wid, pFrame); pthread_mutex_unlock(&window_hash_mutex); xprSetNativeProperty(pFrame); return TRUE; }
/* 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); } }
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 rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion) { RegionRec reg; RegionRec clip; int dx; int dy; int i; int j; int num_clip_rects; int num_reg_rects; BoxRec box1; BoxRec box2; LLOGLN(10, ("in rdpCopyWindow")); RegionInit(®, NullBox, 0); RegionCopy(®, pOldRegion); g_pScreen->CopyWindow = g_rdpScreen.CopyWindow; g_pScreen->CopyWindow(pWin, ptOldOrg, pOldRegion); RegionInit(&clip, NullBox, 0); RegionCopy(&clip, &pWin->borderClip); dx = pWin->drawable.x - ptOldOrg.x; dy = pWin->drawable.y - ptOldOrg.y; if (g_do_dirty_ons) { LLOGLN(0, ("rdpCopyWindow: gettig dirty TODO")); //draw_item_add_srcblt_region } else { rdpup_begin_update(); num_clip_rects = REGION_NUM_RECTS(&clip); num_reg_rects = REGION_NUM_RECTS(®); /* should maybe sort the rects instead of checking dy < 0 */ /* If we can depend on the rects going from top to bottom, left to right we are ok */ if (dy < 0 || (dy == 0 && dx < 0)) { for (j = 0; j < num_clip_rects; j++) { box1 = REGION_RECTS(&clip)[j]; rdpup_set_clip(box1.x1, box1.y1, box1.x2 - box1.x1, box1.y2 - box1.y1); for (i = 0; i < num_reg_rects; i++) { box2 = REGION_RECTS(®)[i]; rdpup_screen_blt(box2.x1 + dx, box2.y1 + dy, box2.x2 - box2.x1, box2.y2 - box2.y1, box2.x1, box2.y1); } } } else { for (j = num_clip_rects - 1; j >= 0; j--) { box1 = REGION_RECTS(&clip)[j]; rdpup_set_clip(box1.x1, box1.y1, box1.x2 - box1.x1, box1.y2 - box1.y1); for (i = num_reg_rects - 1; i >= 0; i--) { box2 = REGION_RECTS(®)[i]; rdpup_screen_blt(box2.x1 + dx, box2.y1 + dy, box2.x2 - box2.x1, box2.y2 - box2.y1, box2.x1, box2.y1); } } } rdpup_reset_clip(); rdpup_end_update(); } RegionUninit(®); RegionUninit(&clip); g_pScreen->CopyWindow = rdpCopyWindow; }
Bool xglFillLine (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) { RegionPtr pClip = pGC->pCompositeClip; BoxPtr pExtent = REGION_EXTENTS (pGC->pScreen, pClip); Bool coincidentEndpoints = FALSE; Bool horizontalAndVertical = TRUE; DDXPointPtr pptTmp; int nptTmp; DDXPointRec pt; xglGeometryPtr pGeometry; XGL_SCREEN_PRIV (pGC->pScreen); if (npt < 2) return TRUE; pt = *ppt; nptTmp = npt - 1; pptTmp = ppt + 1; if (mode == CoordModePrevious) { while (nptTmp--) { if (pptTmp->x && pptTmp->y) horizontalAndVertical = FALSE; pt.x += pptTmp->x; pt.y += pptTmp->y; pptTmp++; } if (pt.x == ppt->x && pt.y == ppt->y) coincidentEndpoints = TRUE; } else { while (nptTmp--) { if (pptTmp->x != pt.x && pptTmp->y != pt.y) { horizontalAndVertical = FALSE; break; } pt = *pptTmp++; } if (ppt[npt - 1].x == ppt->x && ppt[npt - 1].y == ppt->y) coincidentEndpoints = TRUE; } if (horizontalAndVertical) { BoxPtr pClipBox; BoxRec part, full; BoxPtr heapBox = NULL; BoxRec stackBox[N_STACK_BOX]; int size = N_STACK_BOX; BoxPtr pBox = stackBox; int nClip, nBox = 0; int dx, dy; pt = *ppt; ppt++; npt--; while (npt--) { if (mode == CoordModePrevious) { dx = ppt->x; dy = ppt->y; } else { dx = ppt->x - pt.x; dy = ppt->y - pt.y; } if (dx) { if (dx > 0) { full.x1 = pt.x + pDrawable->x; if (npt || coincidentEndpoints) full.x2 = full.x1 + dx; else full.x2 = full.x1 + dx + 1; } else { full.x2 = pt.x + pDrawable->x + 1; if (npt || coincidentEndpoints) full.x1 = full.x2 + dx; else full.x1 = full.x2 + dx - 1; } full.y1 = pt.y + pDrawable->y; full.y2 = full.y1 + 1; } else { if (dy > 0) { full.y1 = pt.y + pDrawable->y; if (npt || coincidentEndpoints) full.y2 = full.y1 + dy; else full.y2 = full.y1 + dy + 1; } else { full.y2 = pt.y + pDrawable->y + 1; if (npt || coincidentEndpoints) full.y1 = full.y2 + dy; else full.y1 = full.y2 + dy - 1; } full.x1 = pt.x + pDrawable->x; full.x2 = full.x1 + 1; } pt.x += dx; pt.y += dy; ppt++; if (full.x1 < pExtent->x1) full.x1 = pExtent->x1; if (full.y1 < pExtent->y1) full.y1 = pExtent->y1; if (full.x2 > pExtent->x2) full.x2 = pExtent->x2; if (full.y2 > pExtent->y2) full.y2 = pExtent->y2; if (full.x1 >= full.x2 || full.y1 >= full.y2) continue; nClip = REGION_NUM_RECTS (pClip); if (nClip == 1) { ADD_BOX (pBox, nBox, stackBox, heapBox, size, full); } else { pClipBox = REGION_RECTS (pClip); while (nClip--) { part = *pClipBox++; if (part.x1 < full.x1) part.x1 = full.x1; if (part.y1 < full.y1) part.y1 = full.y1; if (part.x2 > full.x2) part.x2 = full.x2; if (part.y2 > full.y2) part.y2 = full.y2; if (part.x1 < part.x2 && part.y1 < part.y2) ADD_BOX (pBox, nBox, stackBox, heapBox, size, part); } } } xglFillBox (pDrawable, pGC, pExtent->x1, pExtent->y1, pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, (heapBox) ? heapBox : stackBox, nBox); if (heapBox) xfree (heapBox); return TRUE; } if (!pScreenPriv->lines) return FALSE; if (coincidentEndpoints) npt--; pGeometry = xglGetScratchVertexGeometry (pGC->pScreen, npt); GEOMETRY_ADD_LINE (pGC->pScreen, pGeometry, coincidentEndpoints, mode, npt, ppt); if (coincidentEndpoints) GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINE_LOOP); else GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINE_STRIP); /* Lines need a 0.5 translate */ GEOMETRY_TRANSLATE_FIXED (pGeometry, 1 << 15, 1 << 15); GEOMETRY_TRANSLATE (pGeometry, pDrawable->x, pDrawable->y); pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip); if (xglFill (pDrawable, pGC, pGeometry, pExtent->x1, pExtent->y1, pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1, REGION_RECTS (pGC->pCompositeClip), REGION_NUM_RECTS (pGC->pCompositeClip))) { xglAddCurrentBitDamage (pDrawable); return TRUE; } return FALSE; }
/* The hw attributes have been set by someone higher up in the call * chain. */ void CreatorDoBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask) { FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDst->pScreen); BoxPtr pboxTmp, pboxNext, pboxBase, pbox; DDXPointPtr pptTmp; unsigned char *psrcBase, *pdstBase; int nbox, widthSrc, widthDst, careful, use_prefetch; int psz_shift; cfbGetByteWidthAndPointer (pSrc, widthSrc, psrcBase) cfbGetByteWidthAndPointer (pDst, widthDst, pdstBase) careful = ((pSrc == pDst) || ((pSrc->type == DRAWABLE_WINDOW) && (pDst->type == DRAWABLE_WINDOW))); use_prefetch = (pFfb->use_blkread_prefetch && (psrcBase == (unsigned char *)pFfb->sfb32 || psrcBase == (unsigned char *)pFfb->sfb8r)); pbox = REGION_RECTS(prgnDst); nbox = REGION_NUM_RECTS(prgnDst); pptTmp = pptSrc; pboxTmp = pbox; FFBLOG(("GCOPY(%d): ", nbox)); if (pSrc->bitsPerPixel == 8) psz_shift = 0; else psz_shift = 2; if (careful && pptSrc->y < pbox->y1) { if (pptSrc->x < pbox->x1) { /* reverse order of bands and rects in each band */ pboxTmp=pbox+nbox; pptTmp=pptSrc+nbox; while (nbox--){ pboxTmp--; pptTmp--; FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); if (pptTmp->x < pbox->x2) { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EDRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageRL ((psrcBase + ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + ((pboxTmp->y2 - 1) * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), -widthSrc, -widthDst); } else { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + ((pboxTmp->y2 - 1) * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), -widthSrc, -widthDst); } } } else { /* keep ordering in each band, reverse order of bands */ pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox) { /* for each band */ /* find first box in band */ while (pboxNext >= pbox && pboxBase->y1 == pboxNext->y1) pboxNext--; pboxTmp = pboxNext+1; /* first box in band */ pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */ FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); while (pboxTmp <= pboxBase) { /* for each box in band */ if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + ((pptTmp->y + pboxTmp->y2 - pboxTmp->y1 - 1) * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + ((pboxTmp->y2 - 1) * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), -widthSrc, -widthDst); ++pboxTmp; ++pptTmp; } pboxBase = pboxNext; } } } else { if (careful && pptSrc->x < pbox->x1) { /* reverse order of rects in each band */ pboxBase = pboxNext = pbox; while (pboxBase < pbox+nbox) { /* for each band */ /* find last box in band */ while (pboxNext < pbox+nbox && pboxNext->y1 == pboxBase->y1) pboxNext++; pboxTmp = pboxNext; /* last box in band */ pptTmp = pptSrc + (pboxTmp - pbox); /* last point in band */ while (pboxTmp != pboxBase) { /* for each box in band */ --pboxTmp; --pptTmp; FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); if (pptTmp->x < pbox->x2) { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EDRA; pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; } VISmoveImageRL ((psrcBase + (pptTmp->y * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + (pboxTmp->y1 * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), widthSrc, widthDst); } else { if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + (pptTmp->y * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + (pboxTmp->y1 * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), widthSrc, widthDst); } } pboxBase = pboxNext; } } else { while (nbox--) { FFBLOG(("[%08x:%08x:%08x:%08x:%08x:%08x] ", pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, pboxTmp->x2, pboxTmp->y2)); if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_EIRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } VISmoveImageLR ((psrcBase + (pptTmp->y * widthSrc) + (pptTmp->x << psz_shift)), (pdstBase + (pboxTmp->y1 * widthDst) + (pboxTmp->x1 << psz_shift)), (pboxTmp->x2 - pboxTmp->x1) << psz_shift, (pboxTmp->y2 - pboxTmp->y1), widthSrc, widthDst); pboxTmp++; pptTmp++; } } } if (use_prefetch) { FFBFifo(pFfb, 1); pFfb->regs->mer = FFB_MER_DRA; pFfb->rp_active = 1; FFBWait(pFfb, pFfb->regs); } FFBLOG(("done\n")); }