static RegionPtr rdpCopyAreaWndToWnd(WindowPtr pSrcWnd, WindowPtr pDstWnd, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { int cd; int lsrcx; int lsrcy; int ldstx; int ldsty; int num_clips; int dx; int dy; int j; BoxRec box; RegionPtr rv; RegionRec clip_reg; LLOGLN(10, ("rdpCopyAreaWndToWnd:")); RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, &(pDstWnd->drawable), pGC); lsrcx = pSrcWnd->drawable.x + srcx; lsrcy = pSrcWnd->drawable.y + srcy; ldstx = pDstWnd->drawable.x + dstx; ldsty = pDstWnd->drawable.y + dsty; if (cd == 1) { rdpup_begin_update(); rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); rdpup_end_update(); } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { rdpup_begin_update(); dx = ldstx - lsrcx; dy = ldsty - lsrcy; if ((dy < 0) || ((dy == 0) && (dx < 0))) { for (j = 0; j < num_clips; j++) { box = REGION_RECTS(&clip_reg)[j]; LLOGLN(10, (" index %d x1 %d y1 %d x2 %d y2 %d", j, box.x1, box.y1, box.x2, box.y2)); rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); } } else { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; LLOGLN(10, (" index %d x1 %d y1 %d x2 %d y2 %d", j, box.x1, box.y1, box.x2, box.y2)); rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_screen_blt(ldstx, ldsty, w, h, lsrcx, lsrcy); } } rdpup_reset_clip(); rdpup_end_update(); } } RegionUninit(&clip_reg); rv = rdpCopyAreaOrg(&(pSrcWnd->drawable), &(pDstWnd->drawable), pGC, srcx, srcy, w, h, dstx, dsty); return rv; }
/* This routine is a modified form of XAADoBitBlt with the calls to * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source * instead of destination. My origin is upside down so the ydir cases * are reversed. * * KW: can you believe that this is called even when a 2d window moves? */ static void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index) { ScreenPtr pScreen = pParent->drawable.pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); BoxPtr pboxTmp, pboxNext, pboxBase; DDXPointPtr pptTmp, pptNew2 = NULL; int xdir, ydir; int screenwidth = pScrn->virtualX; int screenheight = pScrn->virtualY; BoxPtr pbox = REGION_RECTS(prgnSrc); int nbox = REGION_NUM_RECTS(prgnSrc); BoxPtr pboxNew1 = NULL; BoxPtr pboxNew2 = NULL; DDXPointPtr pptNew1 = NULL; DDXPointPtr pptSrc = &ptOldOrg; int dx = pParent->drawable.x - ptOldOrg.x; int dy = pParent->drawable.y - ptOldOrg.y; /* If the copy will overlap in Y, reverse the order */ if (dy > 0) { ydir = -1; if (nbox > 1) { /* Keep ordering in each band, reverse order of bands */ pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); if (!pboxNew1) return; pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); if (!pptNew1) { free(pboxNew1); return; } pboxBase = pboxNext = pbox + nbox - 1; while (pboxBase >= pbox) { while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) pboxNext--; pboxTmp = pboxNext + 1; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp <= pboxBase) { *pboxNew1++ = *pboxTmp++; *pptNew1++ = *pptTmp++; } pboxBase = pboxNext; } pboxNew1 -= nbox; pbox = pboxNew1; pptNew1 -= nbox; pptSrc = pptNew1; } } else { /* No changes required */ ydir = 1; } /* If the regions will overlap in X, reverse the order */ if (dx > 0) { xdir = -1; if (nbox > 1) { /*reverse orderof rects in each band */ pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); if (!pboxNew2 || !pptNew2) { if (pptNew2) free(pptNew2); if (pboxNew2) free(pboxNew2); if (pboxNew1) { free(pptNew1); free(pboxNew1); } return; } 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) { *pboxNew2++ = *--pboxTmp; *pptNew2++ = *--pptTmp; } pboxBase = pboxNext; } pboxNew2 -= nbox; pbox = pboxNew2; pptNew2 -= nbox; pptSrc = pptNew2; } } else { /* No changes are needed */ xdir = 1; } /* SelectBuffer isn't really a good concept for the i810. */ I810EmitFlush(pScrn); I810SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1); for (; nbox--; pbox++) { int x1 = pbox->x1; int y1 = pbox->y1; int destx = x1 + dx; int desty = y1 + dy; int w = pbox->x2 - x1 + 1; int h = pbox->y2 - y1 + 1; if (destx < 0) x1 -= destx, w += destx, destx = 0; if (desty < 0) y1 -= desty, h += desty, desty = 0; if (destx + w > screenwidth) w = screenwidth - destx; if (desty + h > screenheight) h = screenheight - desty; if (w <= 0) continue; if (h <= 0) continue; if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n", x1, y1, w, h, dx, dy); I810SelectBuffer(pScrn, I810_SELECT_BACK); I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); I810SelectBuffer(pScrn, I810_SELECT_DEPTH); I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); } I810SelectBuffer(pScrn, I810_SELECT_FRONT); I810EmitFlush(pScrn); if (pboxNew2) { free(pptNew2); free(pboxNew2); } if (pboxNew1) { free(pptNew1); free(pboxNew1); } I810DRISetNeedSync(pScrn); }
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; }
void rdpImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars) { RegionRec reg; RegionRec reg1; int num_clips; int cd; int j; int got_id; int dirty_type; int post_process; int reset_surface; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; LLOGLN(10, ("rdpImageText8:")); if (count != 0) { GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box); } /* do original call */ rdpImageText8Org(pDrawable, pGC, x, y, count, chars); 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, ("rdpImageText8: 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, ("rdpImageText8: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { return; } RegionInit(®, NullBox, 0); if (count == 0) { cd = 0; } else { cd = rdp_get_clip(®, pDrawable, pGC); } if (cd == 1) { if (dirty_type != 0) { RegionInit(®1, &box, 0); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, 9); RegionUninit(®1); } else if (got_id) { rdpup_begin_update(); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_end_update(); } } else if (cd == 2) { RegionInit(®1, &box, 0); RegionIntersect(®, ®, ®1); num_clips = REGION_NUM_RECTS(®); if (num_clips > 0) { if (dirty_type != 0) { draw_item_add_img_region(pDirtyPriv, ®, GXcopy, dirty_type, 9); } else if (got_id) { rdpup_begin_update(); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(®)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } } RegionUninit(®1); } RegionUninit(®); if (reset_surface) { rdpup_switch_os_surface(-1); } return; }
void XAAPaintWindow( WindowPtr pWin, RegionPtr prgn, int what ) { ScreenPtr pScreen = pWin->drawable.pScreen; XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); int nBox = REGION_NUM_RECTS(prgn); BoxPtr pBox = REGION_RECTS(prgn); int fg = -1; PixmapPtr pPix = NULL; if(!infoRec->pScrn->vtSema) goto BAILOUT; switch (what) { case PW_BACKGROUND: switch(pWin->backgroundState) { case None: return; case ParentRelative: do { pWin = pWin->parent; } while(pWin->backgroundState == ParentRelative); (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, what); return; case BackgroundPixel: fg = pWin->background.pixel; break; case BackgroundPixmap: pPix = pWin->background.pixmap; break; } break; case PW_BORDER: if (pWin->borderIsPixel) fg = pWin->border.pixel; else /* pixmap */ pPix = pWin->border.pixmap; break; default: return; } if(!pPix) { if(infoRec->FillSolidRects && (!(infoRec->FillSolidRectsFlags & RGB_EQUAL) || (CHECK_RGB_EQUAL(fg))) ) { (*infoRec->FillSolidRects)(infoRec->pScrn, fg, GXcopy, ~0, nBox, pBox); return; } } else { /* pixmap */ XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); WindowPtr pBgWin = pWin; Bool NoCache = FALSE; int xorg, yorg; /* Hack so we can use this with the dual framebuffer layers which only support the pixmap cache in the primary bpp */ if(pPix->drawable.bitsPerPixel != infoRec->pScrn->bitsPerPixel) NoCache = TRUE; if (what == PW_BORDER) { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); } xorg = pBgWin->drawable.x; yorg = pBgWin->drawable.y; if(IS_OFFSCREEN_PIXMAP(pPix) && infoRec->FillCacheBltRects) { XAACacheInfoPtr pCache = &(infoRec->ScratchCacheInfoRec); pCache->x = pPriv->offscreenArea->box.x1; pCache->y = pPriv->offscreenArea->box.y1; pCache->w = pCache->orig_w = pPriv->offscreenArea->box.x2 - pCache->x; pCache->h = pCache->orig_h = pPriv->offscreenArea->box.y2 - pCache->y; pCache->trans_color = -1; (*infoRec->FillCacheBltRects)(infoRec->pScrn, GXcopy, ~0, nBox, pBox, xorg, yorg, pCache); return; } if(pPriv->flags & DIRTY) { pPriv->flags &= ~(DIRTY | REDUCIBILITY_MASK); pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; } if(!(pPriv->flags & REDUCIBILITY_CHECKED) && (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { XAACheckTileReducibility(pPix, infoRec->CanDoMono8x8); } if(pPriv->flags & REDUCIBLE_TO_8x8) { if((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 && infoRec->FillMono8x8PatternRects && !(infoRec->FillMono8x8PatternRectsFlags & TRANSPARENCY_ONLY) && (!(infoRec->FillMono8x8PatternRectsFlags & RGB_EQUAL) || (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg)))) { (*infoRec->FillMono8x8PatternRects)(infoRec->pScrn, pPriv->fg, pPriv->bg, GXcopy, ~0, nBox, pBox, pPriv->pattern0, pPriv->pattern1, xorg, yorg); return; } if(infoRec->CanDoColor8x8 && !NoCache && infoRec->FillColor8x8PatternRects) { XAACacheInfoPtr pCache = (*infoRec->CacheColor8x8Pattern)( infoRec->pScrn, pPix, -1, -1); (*infoRec->FillColor8x8PatternRects) ( infoRec->pScrn, GXcopy, ~0, nBox, pBox, xorg, yorg, pCache); return; } } /* The window size check is to reduce pixmap cache thrashing when there are lots of little windows with pixmap backgrounds like are sometimes used for buttons, etc... */ if(infoRec->UsingPixmapCache && infoRec->FillCacheBltRects && !NoCache && ((what == PW_BORDER) || (pPix->drawable.height != pWin->drawable.height) || (pPix->drawable.width != pWin->drawable.width)) && (pPix->drawable.height <= infoRec->MaxCacheableTileHeight) && (pPix->drawable.width <= infoRec->MaxCacheableTileWidth)) { XAACacheInfoPtr pCache = (*infoRec->CacheTile)(infoRec->pScrn, pPix); (*infoRec->FillCacheBltRects)(infoRec->pScrn, GXcopy, ~0, nBox, pBox, xorg, yorg, pCache); return; } if(infoRec->FillImageWriteRects && !(infoRec->FillImageWriteRectsFlags & NO_GXCOPY)) { (*infoRec->FillImageWriteRects) (infoRec->pScrn, GXcopy, ~0, nBox, pBox, xorg, yorg, pPix); return; } } if(infoRec->NeedToSync) { (*infoRec->Sync)(infoRec->pScrn); infoRec->NeedToSync = FALSE; } BAILOUT: if(what == PW_BACKGROUND) { XAA_SCREEN_PROLOGUE (pScreen, PaintWindowBackground); (*pScreen->PaintWindowBackground) (pWin, prgn, what); XAA_SCREEN_EPILOGUE(pScreen, PaintWindowBackground, XAAPaintWindow); } else { XAA_SCREEN_PROLOGUE (pScreen, PaintWindowBorder); (*pScreen->PaintWindowBorder) (pWin, prgn, what); XAA_SCREEN_EPILOGUE(pScreen, PaintWindowBorder, XAAPaintWindow); } }
void PclPolyRectangle( DrawablePtr pDrawable, GCPtr pGC, int nRects, xRectangle *pRects) { char t[80]; FILE *outFile; int nbox, i; BoxPtr pbox; xRectangle *drawRects, *r; RegionPtr drawRegion, region; short fudge; int xoffset, yoffset; XpContextPtr pCon; PclContextPrivPtr pConPriv; if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) return; pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); pConPriv = (PclContextPrivPtr) pCon->devPrivates[PclContextPrivateIndex].ptr; /* * Allocate the storage required to deal with the clipping * regions. */ region = REGION_CREATE( pGC->pScreen, NULL, 0 ); drawRects = (xRectangle *)xalloc( nRects * sizeof( xRectangle ) ); fudge = 3 * pGC->lineWidth + 1; /* * Generate the PCL code to draw the rectangles, by defining them * as a macro which uses the HP-GL/2 rectangle drawing function. */ MACRO_START( outFile, pConPriv ); SAVE_PCL( outFile, pConPriv, "\033%0B" ); xoffset = pDrawable->x; yoffset = pDrawable->y; for( i = 0, r = drawRects; i < nRects; i++, r++ ) { xRectangle rect = pRects[i]; /* Draw the rectangle */ sprintf( t, "PU%d,%d;ER%d,%d;", rect.x + xoffset, rect.y + yoffset, rect.width, rect.height ); SAVE_PCL( outFile, pConPriv, t ); /* Build the bounding box */ r->x = MIN( rect.x, rect.x + rect.width ) + xoffset - fudge; r->y = MIN( rect.y, rect.y + rect.height ) + yoffset - fudge; r->width = rect.width + 2 * fudge; r->height = rect.height + 2 * fudge; } SAVE_PCL( outFile, pConPriv, ";\033%0A" ); /* End the macro */ MACRO_END( outFile ); /* * Convert the collection of rectangles to a proper region, then * intersect it with the clip region. */ drawRegion = RECTS_TO_REGION( pGC->pScreen, nRects, drawRects, CT_UNSORTED ); REGION_INTERSECT( pGC->pScreen, region, drawRegion, pGC->pCompositeClip ); /* * For each rectangle in the clip region, set the HP-GL/2 "input * window" and render the set of rectangles to it. */ pbox = REGION_RECTS( region ); nbox = REGION_NUM_RECTS( region ); PclSendData(outFile, pConPriv, pbox, nbox, 1.0); /* * Clean up the temporary regions */ REGION_DESTROY( pGC->pScreen, drawRegion ); REGION_DESTROY( pGC->pScreen, region ); xfree( drawRects ); }
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: gettig 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: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { return; } RegionInit(&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); } }
void EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) { RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_accel_state *accel_state = info->accel_state; PixmapPtr pPixmap = pPriv->pPixmap; BoxPtr pBox = REGION_RECTS(&pPriv->clip); int nBox = REGION_NUM_RECTS(&pPriv->clip); int dstxoff, dstyoff; struct r600_accel_object src_obj, dst_obj; cb_config_t cb_conf; tex_resource_t tex_res; tex_sampler_t tex_samp; shader_config_t vs_conf, ps_conf; /* * 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' * * DP3 might look like the straightforward solution * but we'd need to move the texture yuv values in * the same reg for this to work. Therefore use MADs. * Brightness just adds to the off constant. * Contrast is multiplication of luminance. * Saturation and hue change the u and v coeffs. * Default values (before adjustments - depend on colorspace): * yco = 1.1643 * uco = 0, -0.39173, 2.017 * vco = 1.5958, -0.8129, 0 * off = -0.0625 * yco + -0.5 * uco[r] + -0.5 * vco[r], * -0.0625 * yco + -0.5 * uco[g] + -0.5 * vco[g], * -0.0625 * yco + -0.5 * uco[b] + -0.5 * vco[b], * * temp = MAD(yco, yuv.yyyy, off) * temp = MAD(uco, yuv.uuuu, temp) * result = MAD(vco, yuv.vvvv, temp) */ /* TODO: calc consts in the shader */ const float Loff = -0.0627; const float Coff = -0.502; float uvcosf, uvsinf; float yco; float uco[3], vco[3], off[3]; float bright, cont, gamma; int ref = pPriv->transform_index; Bool needgamma = FALSE; float *ps_alu_consts; const_config_t ps_const_conf; float *vs_alu_consts; const_config_t vs_const_conf; cont = RTFContrast(pPriv->contrast); bright = RTFBrightness(pPriv->brightness); gamma = (float)pPriv->gamma / 1000.0; uvcosf = RTFSaturation(pPriv->saturation) * cos(RTFHue(pPriv->hue)); uvsinf = RTFSaturation(pPriv->saturation) * sin(RTFHue(pPriv->hue)); /* overlay video also does pre-gamma contrast/sat adjust, should we? */ yco = trans[ref].RefLuma * cont; uco[0] = -trans[ref].RefRCr * uvsinf; uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf; uco[2] = trans[ref].RefBCb * uvcosf; vco[0] = trans[ref].RefRCr * uvcosf; vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf; vco[2] = trans[ref].RefBCb * uvsinf; off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright; off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright; off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright; // XXX gamma = 1.0; if (gamma != 1.0) { needgamma = TRUE; /* note: gamma correction is out = in ^ gamma; gpu can only do LG2/EX2 therefore we transform into in ^ gamma = 2 ^ (log2(in) * gamma). Lots of scalar ops, unfortunately (better solution?) - without gamma that's 3 inst, with gamma it's 10... could use different gamma factors per channel, if that's of any use. */ } CLEAR (cb_conf); CLEAR (tex_res); CLEAR (tex_samp); CLEAR (vs_conf); CLEAR (ps_conf); CLEAR (vs_const_conf); CLEAR (ps_const_conf); dst_obj.offset = 0; src_obj.offset = 0; dst_obj.bo = radeon_get_pixmap_bo(pPixmap); dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap); dst_obj.surface = radeon_get_pixmap_surface(pPixmap); dst_obj.pitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel / 8); src_obj.pitch = pPriv->src_pitch; src_obj.width = pPriv->w; src_obj.height = pPriv->h; src_obj.bpp = 16; src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT; src_obj.bo = pPriv->src_bo[pPriv->currentBuffer]; src_obj.tiling_flags = 0; src_obj.surface = NULL; dst_obj.width = pPixmap->drawable.width; dst_obj.height = pPixmap->drawable.height; dst_obj.bpp = pPixmap->drawable.bitsPerPixel; dst_obj.domain = RADEON_GEM_DOMAIN_VRAM; if (!R600SetAccelState(pScrn, &src_obj, NULL, &dst_obj, accel_state->xv_vs_offset, accel_state->xv_ps_offset, 3, 0xffffffff)) return; #ifdef COMPOSITE dstxoff = -pPixmap->screen_x + pPixmap->drawable.x; dstyoff = -pPixmap->screen_y + pPixmap->drawable.y; #else dstxoff = 0; dstyoff = 0; #endif radeon_vbo_check(pScrn, &accel_state->vbo, 16); radeon_vbo_check(pScrn, &accel_state->cbuf, 512); radeon_cp_start(pScrn); evergreen_set_default_state(pScrn); evergreen_set_generic_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height); evergreen_set_screen_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height); evergreen_set_window_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height); /* PS bool constant */ switch(pPriv->id) { case FOURCC_YV12: case FOURCC_I420: evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (1 << 0)); break; case FOURCC_UYVY: case FOURCC_YUY2: default: evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (0 << 0)); break; } /* Shader */ vs_conf.shader_addr = accel_state->vs_mc_addr; vs_conf.shader_size = accel_state->vs_size; vs_conf.num_gprs = 2; vs_conf.stack_size = 0; vs_conf.bo = accel_state->shaders_bo; evergreen_vs_setup(pScrn, &vs_conf, RADEON_GEM_DOMAIN_VRAM); ps_conf.shader_addr = accel_state->ps_mc_addr; ps_conf.shader_size = accel_state->ps_size; ps_conf.num_gprs = 3; ps_conf.stack_size = 1; ps_conf.clamp_consts = 0; ps_conf.export_mode = 2; ps_conf.bo = accel_state->shaders_bo; evergreen_ps_setup(pScrn, &ps_conf, RADEON_GEM_DOMAIN_VRAM); /* Texture */ switch(pPriv->id) { case FOURCC_YV12: case FOURCC_I420: accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h; /* Y texture */ tex_res.id = 0; tex_res.w = accel_state->src_obj[0].width; tex_res.h = accel_state->src_obj[0].height; tex_res.pitch = accel_state->src_obj[0].pitch; tex_res.depth = 0; tex_res.dim = SQ_TEX_DIM_2D; tex_res.base = accel_state->src_obj[0].offset; tex_res.mip_base = accel_state->src_obj[0].offset; tex_res.size = accel_state->src_size[0]; tex_res.bo = accel_state->src_obj[0].bo; tex_res.mip_bo = accel_state->src_obj[0].bo; tex_res.surface = NULL; tex_res.format = FMT_8; tex_res.dst_sel_x = SQ_SEL_X; /* Y */ tex_res.dst_sel_y = SQ_SEL_1; tex_res.dst_sel_z = SQ_SEL_1; tex_res.dst_sel_w = SQ_SEL_1; tex_res.base_level = 0; tex_res.last_level = 0; tex_res.perf_modulation = 0; tex_res.interlaced = 0; if (accel_state->src_obj[0].tiling_flags == 0) tex_res.array_mode = 1; evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); /* Y sampler */ tex_samp.id = 0; tex_samp.clamp_x = SQ_TEX_CLAMP_LAST_TEXEL; tex_samp.clamp_y = SQ_TEX_CLAMP_LAST_TEXEL; tex_samp.clamp_z = SQ_TEX_WRAP; /* xxx: switch to bicubic */ tex_samp.xy_mag_filter = SQ_TEX_XY_FILTER_BILINEAR; tex_samp.xy_min_filter = SQ_TEX_XY_FILTER_BILINEAR; tex_samp.z_filter = SQ_TEX_Z_FILTER_NONE; tex_samp.mip_filter = 0; /* no mipmap */ evergreen_set_tex_sampler(pScrn, &tex_samp); /* U or V texture */ tex_res.id = 1; tex_res.format = FMT_8; tex_res.w = accel_state->src_obj[0].width >> 1; tex_res.h = accel_state->src_obj[0].height >> 1; tex_res.pitch = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, pPriv->hw_align); tex_res.dst_sel_x = SQ_SEL_X; /* V or U */ tex_res.dst_sel_y = SQ_SEL_1; tex_res.dst_sel_z = SQ_SEL_1; tex_res.dst_sel_w = SQ_SEL_1; tex_res.interlaced = 0; tex_res.base = accel_state->src_obj[0].offset + pPriv->planev_offset; tex_res.mip_base = accel_state->src_obj[0].offset + pPriv->planev_offset; tex_res.size = tex_res.pitch * (pPriv->h >> 1); if (accel_state->src_obj[0].tiling_flags == 0) tex_res.array_mode = 1; evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); /* U or V sampler */ tex_samp.id = 1; evergreen_set_tex_sampler(pScrn, &tex_samp); /* U or V texture */ tex_res.id = 2; tex_res.format = FMT_8; tex_res.w = accel_state->src_obj[0].width >> 1; tex_res.h = accel_state->src_obj[0].height >> 1; tex_res.pitch = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, pPriv->hw_align); tex_res.dst_sel_x = SQ_SEL_X; /* V or U */ tex_res.dst_sel_y = SQ_SEL_1; tex_res.dst_sel_z = SQ_SEL_1; tex_res.dst_sel_w = SQ_SEL_1; tex_res.interlaced = 0; tex_res.base = accel_state->src_obj[0].offset + pPriv->planeu_offset; tex_res.mip_base = accel_state->src_obj[0].offset + pPriv->planeu_offset; tex_res.size = tex_res.pitch * (pPriv->h >> 1); if (accel_state->src_obj[0].tiling_flags == 0) tex_res.array_mode = 1; evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); /* UV sampler */ tex_samp.id = 2; evergreen_set_tex_sampler(pScrn, &tex_samp); break; case FOURCC_UYVY: case FOURCC_YUY2: default: accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h; /* Y texture */ tex_res.id = 0; tex_res.w = accel_state->src_obj[0].width; tex_res.h = accel_state->src_obj[0].height; tex_res.pitch = accel_state->src_obj[0].pitch >> 1; tex_res.depth = 0; tex_res.dim = SQ_TEX_DIM_2D; tex_res.base = accel_state->src_obj[0].offset; tex_res.mip_base = accel_state->src_obj[0].offset; tex_res.size = accel_state->src_size[0]; tex_res.bo = accel_state->src_obj[0].bo; tex_res.mip_bo = accel_state->src_obj[0].bo; tex_res.surface = NULL; tex_res.format = FMT_8_8; if (pPriv->id == FOURCC_UYVY) tex_res.dst_sel_x = SQ_SEL_Y; /* Y */ else tex_res.dst_sel_x = SQ_SEL_X; /* Y */ tex_res.dst_sel_y = SQ_SEL_1; tex_res.dst_sel_z = SQ_SEL_1; tex_res.dst_sel_w = SQ_SEL_1; tex_res.base_level = 0; tex_res.last_level = 0; tex_res.perf_modulation = 0; tex_res.interlaced = 0; if (accel_state->src_obj[0].tiling_flags == 0) tex_res.array_mode = 1; evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); /* Y sampler */ tex_samp.id = 0; tex_samp.clamp_x = SQ_TEX_CLAMP_LAST_TEXEL; tex_samp.clamp_y = SQ_TEX_CLAMP_LAST_TEXEL; tex_samp.clamp_z = SQ_TEX_WRAP; tex_samp.xy_mag_filter = SQ_TEX_XY_FILTER_BILINEAR; tex_samp.xy_min_filter = SQ_TEX_XY_FILTER_BILINEAR; tex_samp.z_filter = SQ_TEX_Z_FILTER_NONE; tex_samp.mip_filter = 0; /* no mipmap */ evergreen_set_tex_sampler(pScrn, &tex_samp); /* UV texture */ tex_res.id = 1; tex_res.format = FMT_8_8_8_8; tex_res.w = accel_state->src_obj[0].width >> 1; tex_res.h = accel_state->src_obj[0].height; tex_res.pitch = accel_state->src_obj[0].pitch >> 2; if (pPriv->id == FOURCC_UYVY) { tex_res.dst_sel_x = SQ_SEL_X; /* V */ tex_res.dst_sel_y = SQ_SEL_Z; /* U */ } else { tex_res.dst_sel_x = SQ_SEL_Y; /* V */ tex_res.dst_sel_y = SQ_SEL_W; /* U */ } tex_res.dst_sel_z = SQ_SEL_1; tex_res.dst_sel_w = SQ_SEL_1; tex_res.interlaced = 0; tex_res.base = accel_state->src_obj[0].offset; tex_res.mip_base = accel_state->src_obj[0].offset; tex_res.size = accel_state->src_size[0]; if (accel_state->src_obj[0].tiling_flags == 0) tex_res.array_mode = 1; evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain); /* UV sampler */ tex_samp.id = 1; evergreen_set_tex_sampler(pScrn, &tex_samp); break; } cb_conf.id = 0; cb_conf.w = accel_state->dst_obj.pitch; cb_conf.h = accel_state->dst_obj.height; cb_conf.base = accel_state->dst_obj.offset; cb_conf.bo = accel_state->dst_obj.bo; cb_conf.surface = accel_state->dst_obj.surface; switch (accel_state->dst_obj.bpp) { case 16: if (pPixmap->drawable.depth == 15) { cb_conf.format = COLOR_1_5_5_5; cb_conf.comp_swap = 1; /* ARGB */ } else { cb_conf.format = COLOR_5_6_5; cb_conf.comp_swap = 2; /* RGB */ } #if X_BYTE_ORDER == X_BIG_ENDIAN cb_conf.endian = ENDIAN_8IN16; #endif break; case 32: cb_conf.format = COLOR_8_8_8_8; cb_conf.comp_swap = 1; /* ARGB */ #if X_BYTE_ORDER == X_BIG_ENDIAN cb_conf.endian = ENDIAN_8IN32; #endif break; default: return; } cb_conf.source_format = EXPORT_4C_16BPC; cb_conf.blend_clamp = 1; cb_conf.pmask = 0xf; cb_conf.rop = 3; if (accel_state->dst_obj.tiling_flags == 0) { cb_conf.array_mode = 1; cb_conf.non_disp_tiling = 1; } evergreen_set_render_target(pScrn, &cb_conf, accel_state->dst_obj.domain); evergreen_set_spi(pScrn, (1 - 1), 1); /* PS alu constants */ ps_const_conf.size_bytes = 256; ps_const_conf.type = SHADER_TYPE_PS; ps_alu_consts = radeon_vbo_space(pScrn, &accel_state->cbuf, 256); ps_const_conf.bo = accel_state->cbuf.vb_bo; ps_const_conf.const_addr = accel_state->cbuf.vb_mc_addr + accel_state->cbuf.vb_offset; ps_const_conf.cpu_ptr = (uint32_t *)(char *)ps_alu_consts; ps_alu_consts[0] = off[0]; ps_alu_consts[1] = off[1]; ps_alu_consts[2] = off[2]; ps_alu_consts[3] = yco; ps_alu_consts[4] = uco[0]; ps_alu_consts[5] = uco[1]; ps_alu_consts[6] = uco[2]; ps_alu_consts[7] = gamma; ps_alu_consts[8] = vco[0]; ps_alu_consts[9] = vco[1]; ps_alu_consts[10] = vco[2]; ps_alu_consts[11] = 0.0; radeon_vbo_commit(pScrn, &accel_state->cbuf); evergreen_set_alu_consts(pScrn, &ps_const_conf, RADEON_GEM_DOMAIN_GTT); /* VS alu constants */ vs_const_conf.size_bytes = 256; vs_const_conf.type = SHADER_TYPE_VS; vs_alu_consts = radeon_vbo_space(pScrn, &accel_state->cbuf, 256); vs_const_conf.bo = accel_state->cbuf.vb_bo; vs_const_conf.const_addr = accel_state->cbuf.vb_mc_addr + accel_state->cbuf.vb_offset; vs_const_conf.cpu_ptr = (uint32_t *)(char *)vs_alu_consts; vs_alu_consts[0] = 1.0 / pPriv->w; vs_alu_consts[1] = 1.0 / pPriv->h; vs_alu_consts[2] = 0.0; vs_alu_consts[3] = 0.0; radeon_vbo_commit(pScrn, &accel_state->cbuf); evergreen_set_alu_consts(pScrn, &vs_const_conf, RADEON_GEM_DOMAIN_GTT); if (pPriv->vsync) { xf86CrtcPtr crtc; if (pPriv->desired_crtc) crtc = pPriv->desired_crtc; else crtc = radeon_pick_best_crtc(pScrn, pPriv->drw_x, pPriv->drw_x + pPriv->dst_w, pPriv->drw_y, pPriv->drw_y + pPriv->dst_h); if (crtc) evergreen_cp_wait_vline_sync(pScrn, pPixmap, crtc, pPriv->drw_y - crtc->y, (pPriv->drw_y - crtc->y) + pPriv->dst_h); } while (nBox--) { int srcX, srcY, srcw, srch; int dstX, dstY, dstw, dsth; float *vb; dstX = pBox->x1 + dstxoff; dstY = pBox->y1 + dstyoff; dstw = pBox->x2 - pBox->x1; dsth = pBox->y2 - pBox->y1; srcX = pPriv->src_x; srcX += ((pBox->x1 - pPriv->drw_x) * pPriv->src_w) / pPriv->dst_w; srcY = pPriv->src_y; srcY += ((pBox->y1 - pPriv->drw_y) * pPriv->src_h) / pPriv->dst_h; srcw = (pPriv->src_w * dstw) / pPriv->dst_w; srch = (pPriv->src_h * dsth) / pPriv->dst_h; vb = radeon_vbo_space(pScrn, &accel_state->vbo, 16); vb[0] = (float)dstX; vb[1] = (float)dstY; vb[2] = (float)srcX; vb[3] = (float)srcY; vb[4] = (float)dstX; vb[5] = (float)(dstY + dsth); vb[6] = (float)srcX; vb[7] = (float)(srcY + srch); vb[8] = (float)(dstX + dstw); vb[9] = (float)(dstY + dsth); vb[10] = (float)(srcX + srcw); vb[11] = (float)(srcY + srch); radeon_vbo_commit(pScrn, &accel_state->vbo); pBox++; } evergreen_finish_op(pScrn, 16); DamageDamageRegion(pPriv->pDraw, &pPriv->clip); }
void rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr* ppci, pointer pglyphBase) { RegionRec reg; RegionRec reg1; int num_clips; int cd; int j; int got_id; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec* pDstPriv; LLOGLN(10, ("rdpPolyGlyphBlt:")); if (nglyph != 0) { GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box); } /* do original call */ rdpPolyGlyphBltOrg(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 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) { return; } RegionInit(®, NullBox, 0); if (nglyph == 0) { cd = 0; } else { cd = rdp_get_clip(®, pDrawable, pGC); } if (cd == 1) { rdpup_begin_update(); rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); rdpup_end_update(); } else if (cd == 2) { RegionInit(®1, &box, 0); RegionIntersect(®, ®, ®1); num_clips = REGION_NUM_RECTS(®); if (num_clips > 0) { rdpup_begin_update(); for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(®)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } rdpup_end_update(); } RegionUninit(®1); } RegionUninit(®); rdpup_switch_os_surface(-1); return; }
void fbPutXYImage (DrawablePtr pDrawable, RegionPtr pClip, FbBits fg, FbBits bg, FbBits pm, int alu, Bool opaque, int x, int y, int width, int height, FbStip *src, FbStride srcStride, int srcX) { FbBits *dst; FbStride dstStride; int dstBpp; int dstXoff, dstYoff; int nbox; BoxPtr pbox; int x1, y1, x2, y2; FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0; fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); if (dstBpp == 1) { if (opaque) alu = FbOpaqueStipple1Rop(alu,fg,bg); else alu = FbStipple1Rop(alu,fg); } else { fgand = fbAnd(alu,fg,pm); fgxor = fbXor(alu,fg,pm); if (opaque) { bgand = fbAnd(alu,bg,pm); bgxor = fbXor(alu,bg,pm); } else { bgand = fbAnd(GXnoop,(FbBits)0,FB_ALLONES); bgxor = fbXor(GXnoop,(FbBits)0,FB_ALLONES); } } for (nbox = REGION_NUM_RECTS (pClip), pbox = REGION_RECTS(pClip); nbox--; pbox++) { x1 = x; y1 = y; x2 = x + width; y2 = y + height; 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; if (dstBpp == 1) { fbBltStip (src + (y1 - y) * srcStride, srcStride, (x1 - x) + srcX, (FbStip *) (dst + (y1 + dstYoff) * dstStride), FbBitsStrideToStipStride(dstStride), (x1 + dstXoff) * dstBpp, (x2 - x1) * dstBpp, (y2 - y1), alu, pm, dstBpp); } else { fbBltOne (src + (y1 - y) * srcStride, srcStride, (x1 - x) + srcX, dst + (y1 + dstYoff) * dstStride, dstStride, (x1 + dstXoff) * dstBpp, dstBpp, (x2 - x1) * dstBpp, (y2 - y1), fgand, fgxor, bgand, bgxor); } } }
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 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); }
void rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSegs) { RegionRec clip_reg; int cd; int i; int j; int post_process; xSegment *segs; BoxRec box; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; 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); post_process = 0; if (pDrawable->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr) pDrawable; pDstPriv = GETPIXPRIV(pDstPixmap); } else { if (pDrawable->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr) pDrawable; if (pDstWnd->viewable) { post_process = 1; } } } if (!post_process) { 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) { XRDP_MSG_LINE_TO msg; rdpup_begin_update(); msg.bRop2 = rdpup_convert_opcode(pGC->alu); msg.penColor = rdpup_convert_color(pGC->fgPixel); msg.penWidth = pGC->lineWidth; msg.penStyle = 0; for (i = 0; i < nseg; i++) { msg.nXStart = segs[i].x1; msg.nYStart = segs[i].y1; msg.nXEnd = segs[i].x2; msg.nYEnd = segs[i].y2; rdpup_draw_line(&msg); } rdpup_end_update(); } } else if (cd == 2) /* clip */ { if (segs != 0) { XRDP_MSG_LINE_TO msg; rdpup_begin_update(); msg.bRop2 = rdpup_convert_opcode(pGC->alu); msg.penColor = rdpup_convert_color(pGC->fgPixel); msg.penWidth = pGC->lineWidth; msg.penStyle = 0; 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++) { msg.nXStart = segs[i].x1; msg.nYStart = segs[i].y1; msg.nXEnd = segs[i].x2; msg.nYEnd = segs[i].y2; rdpup_draw_line(&msg); } } rdpup_reset_clip(); rdpup_end_update(); } } free(segs); RegionUninit(&clip_reg); }
void region_pack(RegionPtr pregion, int threshold) { int i, num_rects; int height, overhead, area1, area2, area3; int joins = 0, sum_overhead = 0; BoxRec prev_rect, this_rect, tmp_rect; RegionRec tmp_region, add_region; num_rects = REGION_NUM_RECTS(pregion); if (num_rects < 2) { return; /* nothing to optimize */ } REGION_INIT(&add_region, NullBox, 16); prev_rect = REGION_RECTS(pregion)[0]; for (i = 1; i < num_rects; i++) { this_rect = REGION_RECTS(pregion)[i]; if (this_rect.y1 == prev_rect.y1 && this_rect.y2 == prev_rect.y2) { /* Try to join two rectangles of the same "band" */ if (prev_rect.x2 > this_rect.x1) { report_bad_rect_order(); REGION_UNINIT(&add_region); return; } height = this_rect.y2 - this_rect.y1; overhead = (this_rect.x1 - prev_rect.x2) * height; if (overhead < threshold) { tmp_rect.y1 = prev_rect.y1; tmp_rect.y2 = prev_rect.y2; tmp_rect.x1 = prev_rect.x2; tmp_rect.x2 = this_rect.x1; REGION_INIT(&tmp_region, &tmp_rect, 1); REGION_UNION(&add_region, &add_region, &tmp_region); REGION_UNINIT(&tmp_region); joins++; sum_overhead += overhead; } } else { /* Try to join two rectangles of neighboring "bands" */ area1 = (prev_rect.x2 - prev_rect.x1) * (prev_rect.y2 - prev_rect.y1); area2 = (this_rect.x2 - this_rect.x1) * (this_rect.y2 - this_rect.y1); tmp_rect.x1 = min(prev_rect.x1, this_rect.x1); tmp_rect.x2 = max(prev_rect.x2, this_rect.x2); tmp_rect.y1 = min(prev_rect.y1, this_rect.y1); tmp_rect.y2 = max(prev_rect.y2, this_rect.y2); area3 = (tmp_rect.x2 - tmp_rect.x1) * (tmp_rect.y2 - tmp_rect.y1); overhead = area3 - area2 - area1; if (overhead < threshold || overhead < (area1 + area2) / 100) { REGION_INIT(&tmp_region, &tmp_rect, 1); REGION_UNION(&add_region, &add_region, &tmp_region); REGION_UNINIT(&tmp_region); joins++; sum_overhead += overhead; this_rect = tmp_rect; /* copy the joined one to prev_rect */ } } prev_rect = this_rect; } if (sum_overhead) { REGION_UNION(pregion, pregion, &add_region); log_write(LL_DEBUG, "Joined rectangles: %d -> %d, overhead %d", num_rects, (int)(REGION_NUM_RECTS(pregion)), sum_overhead); } REGION_UNINIT(&add_region); }
void PsPaintWindow( 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 * PS output. */ if( PsGetContextFromWindow(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 PS 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 PS 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); }
void PsFillSpans( DrawablePtr pDrawable, GCPtr pGC, int nSpans, DDXPointPtr pPoints, int *pWidths, int fSorted) { char t[80]; PsOutPtr psOut; int xoffset, yoffset; xRectangle *rects, *r; RegionPtr fillRegion, region; int i; int nbox; BoxPtr pbox; ColormapPtr cMap; if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return; /* * Build a region out of the spans */ rects = (xRectangle *)xalloc(nSpans*sizeof(xRectangle)); xoffset = pDrawable->x; yoffset = pDrawable->y; for( i = 0, r = rects; i < nSpans; i++, r++ ) { r->x = pPoints[i].x + xoffset; r->y = pPoints[i].y + yoffset; r->width = pWidths[i]; r->height = 1; } fillRegion = miRectsToRegion(nSpans, rects, (fSorted)?CT_YSORTED:CT_UNSORTED); /* * Intersect this region with the clip region. Whatever's left, * should be filled. */ /*miIntersect(region, fillRegion, pGC->clientClip);*/ pbox = REGION_RECTS(region); nbox = REGION_NUM_RECTS(region); /* Enter HP-GL/2 */ /*###SEND_PCL( outFile, "\27%0B" );*/ while( nbox ) { /*### sprintf( t, "PU%d,%d;RR%d,%d;", pbox->x1, pbox->y1, pbox->x2, pbox->y2); SEND_PCL( outFile, t ); */ nbox--; pbox++; } /* Go back to PCL */ /*###SEND_PCL( outFile, "\27%0A" );*/ /* * Clean up the temporary regions */ miRegionDestroy(fillRegion); miRegionDestroy(region); xfree(rects); }
void PclFillPolygon( DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int nPoints, DDXPointPtr pPoints) { char t[80]; FILE *outFile; int nbox, i; BoxPtr pbox; BoxRec box; RegionPtr drawRegion, region; int xoffset, yoffset; int xtop, xbottom, yleft, yright; int fillRule; XpContextPtr pCon; PclContextPrivPtr pConPriv; char *command; if( PclUpdateDrawableGC( pGC, pDrawable, &outFile ) == FALSE ) return; pCon = PclGetContextFromWindow( (WindowPtr) pDrawable ); pConPriv = (PclContextPrivPtr) pCon->devPrivates[PclContextPrivateIndex].ptr; /* * Generate the PCL code to draw the filled polygon, by defining * it as a macro which uses the HP-GL/2 polygon drawing function. */ MACRO_START( outFile, pConPriv ); SAVE_PCL( outFile, pConPriv, "\033%0B" ); if( mode == CoordModeOrigin ) { xoffset = pDrawable->x; yoffset = pDrawable->y; command = "PA"; } else { xoffset = yoffset = 0; command = "PR"; } /* Begin the polygon */ sprintf( t, "PU%d,%d;PM0;%s", pPoints[0].x + xoffset, pPoints[0].y + yoffset, command ); SAVE_PCL( outFile, pConPriv, t ); /* Seed the bounding box */ xtop = xbottom = pPoints[0].x + xoffset; yleft = yright = pPoints[0].y + yoffset; /* Add the rest of the points to the polygon */ for( i = 1; i < nPoints; i++ ) { if( i != 1 ) SAVE_PCL( outFile, pConPriv, "," ); sprintf( t, "%d,%d", pPoints[i].x + xoffset, pPoints[i].y + yoffset ); SAVE_PCL( outFile, pConPriv, t ); /* Update the bounding box */ xtop = MIN( xtop, pPoints[i].x + xoffset ); xbottom = MAX( xbottom, pPoints[i].x + xoffset ); yleft = MIN( yleft, pPoints[i].y + yoffset ); yright = MAX( yright, pPoints[i].y + yoffset ); } /* Close the polygon and the macro */ if( pGC->fillRule == EvenOddRule ) fillRule = 0; else fillRule = 1; sprintf( t, ";PM2;FP%d;\033%%0A", fillRule ); SAVE_PCL( outFile, pConPriv, t ); MACRO_END ( outFile ); /* * Build the bounding region from the bounding box of the polygon */ box.x1 = xtop; box.y1 = yleft; box.x2 = xbottom; box.y2 = yright; drawRegion = REGION_CREATE( pGC->pScreen, &box, 0 ); if( mode == CoordModePrevious ) REGION_TRANSLATE( pGC->pScreen, drawRegion, pPoints[0].x, pPoints[0].y ); region = REGION_CREATE( pGC->pScreen, NULL, 0 ); REGION_INTERSECT( pGC->pScreen, region, drawRegion, pGC->pCompositeClip ); /* * For each rectangle in the clip region, set the HP-GL/2 "input * window" and render the polygon to it. */ pbox = REGION_RECTS( region ); nbox = REGION_NUM_RECTS( region ); PclSendData(outFile, pConPriv, pbox, nbox, 1.0); /* * Clean up the temporary regions */ REGION_DESTROY( pGC->pScreen, drawRegion ); REGION_DESTROY( pGC->pScreen, region ); }
void fbFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { RegionPtr pClip = fbGetCompositeClip(pGC); BoxPtr pextent, pbox; int nbox; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1; int partX1, partX2; pextent = REGION_EXTENTS(pGC->pScreen, pClip); extentX1 = pextent->x1; extentY1 = pextent->y1; extentX2 = pextent->x2; extentY2 = pextent->y2; while (n--) { fullX1 = ppt->x; fullY1 = ppt->y; fullX2 = fullX1 + (int) *pwidth; ppt++; pwidth++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; nbox = REGION_NUM_RECTS (pClip); if (nbox == 1) { fbFill (pDrawable, pGC, fullX1, fullY1, fullX2-fullX1, 1); } else { pbox = REGION_RECTS(pClip); while(nbox--) { if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) { partX1 = pbox->x1; if (partX1 < fullX1) partX1 = fullX1; partX2 = pbox->x2; if (partX2 > fullX2) partX2 = fullX2; if (partX2 > partX1) { fbFill (pDrawable, pGC, partX1, fullY1, partX2 - partX1, 1); } } pbox++; } } } }
/* XaceCensorImage * * Called after pScreen->GetImage to prevent pieces or trusted windows from * being returned in image data from an untrusted window. * * Arguments: * client is the client doing the GetImage. * pVisibleRegion is the visible region of the window. * widthBytesLine is the width in bytes of one horizontal line in pBuf. * pDraw is the source window. * x, y, w, h is the rectangle of image data from pDraw in pBuf. * format is the format of the image data in pBuf: ZPixmap or XYPixmap. * pBuf is the image data. * * Returns: nothing. * * Side Effects: * Any part of the rectangle (x, y, w, h) that is outside the visible * region of the window will be destroyed (overwritten) in pBuf. */ void XaceCensorImage( ClientPtr client, RegionPtr pVisibleRegion, long widthBytesLine, DrawablePtr pDraw, int x, int y, int w, int h, unsigned int format, char *pBuf) { ScreenPtr pScreen; RegionRec imageRegion; /* region representing x,y,w,h */ RegionRec censorRegion; /* region to obliterate */ BoxRec imageBox; int nRects; pScreen = pDraw->pScreen; imageBox.x1 = x; imageBox.y1 = y; imageBox.x2 = x + w; imageBox.y2 = y + h; REGION_INIT(pScreen, &imageRegion, &imageBox, 1); REGION_NULL(pScreen, &censorRegion); /* censorRegion = imageRegion - visibleRegion */ REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion); nRects = REGION_NUM_RECTS(&censorRegion); if (nRects > 0) { /* we have something to censor */ GCPtr pScratchGC = NULL; PixmapPtr pPix = NULL; xRectangle *pRects = NULL; Bool failed = FALSE; int depth = 1; int bitsPerPixel = 1; int i; BoxPtr pBox; /* convert region to list-of-rectangles for PolyFillRect */ pRects = xalloc(nRects * sizeof(xRectangle)); if (!pRects) { failed = TRUE; goto failSafe; } for (pBox = REGION_RECTS(&censorRegion), i = 0; i < nRects; i++, pBox++) { pRects[i].x = pBox->x1; pRects[i].y = pBox->y1 - imageBox.y1; pRects[i].width = pBox->x2 - pBox->x1; pRects[i].height = pBox->y2 - pBox->y1; } /* use pBuf as a fake pixmap */ if (format == ZPixmap) { depth = pDraw->depth; bitsPerPixel = pDraw->bitsPerPixel; } pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, depth, bitsPerPixel, widthBytesLine, (pointer)pBuf); if (!pPix) { failed = TRUE; goto failSafe; } pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); if (!pScratchGC) { failed = TRUE; goto failSafe; } ValidateGC(&pPix->drawable, pScratchGC); (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, pScratchGC, nRects, pRects); failSafe: if (failed) { /* Censoring was not completed above. To be safe, wipe out * all the image data so that nothing trusted gets out. */ bzero(pBuf, (int)(widthBytesLine * h)); } if (pRects) xfree(pRects); if (pScratchGC) FreeScratchGC(pScratchGC); if (pPix) FreeScratchPixmapHeader(pPix); } REGION_UNINIT(pScreen, &imageRegion); REGION_UNINIT(pScreen, &censorRegion); } /* XaceCensorImage */
void rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs) { RegionRec clip_reg; int cd; int i; int j; int got_id; xSegment* segs; BoxRec box; struct image_data id; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec* pDstPriv; LLOGLN(10, ("rdpPolySegment:")); 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); 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(segs); return; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDrawable, pGC); if (cd == 1) /* no clip */ { if (segs != 0) { 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) { 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); } } rdpup_reset_clip(); rdpup_set_opcode(GXcopy); rdpup_end_update(); } } g_free(segs); RegionUninit(&clip_reg); rdpup_switch_os_surface(-1); }
/* 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); } }
void rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, int w, int h, int x, int y) { RegionRec clip_reg; RegionRec box_reg; int num_clips; int cd; int j; int post_process; BoxRec box; WindowPtr pDstWnd; PixmapPtr pDstPixmap; rdpPixmapRec *pDstPriv; LLOGLN(10, ("rdpPushPixels:")); /* do original call */ rdpPushPixelsOrg(pGC, pBitMap, pDst, w, h, x, y); 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; memset(&box, 0, sizeof(box)); RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { rdp_send_area_update(pDst->x + x, pDst->y + y, w, h); } else if (cd == 2) { box.x1 = pDst->x + x; box.y1 = pDst->y + y; 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 > 0) { 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); } } RegionUninit(&box_reg); } RegionUninit(&clip_reg); }
void cfb8_16CopyWindow( WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc ){ ScreenPtr pScreen = pWin->drawable.pScreen; cfb8_16ScreenPtr pScreenPriv = CFB8_16_GET_SCREEN_PRIVATE(pWin->drawable.pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; DDXPointPtr ppt, pptSrc; RegionRec rgnDst; BoxPtr pbox; int i, nbox, dx, dy; WindowPtr pRoot = WindowTable[pScreen->myNum]; REGION_INIT(pScreen, &rgnDst, NullBox, 0); 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); 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; } cfbDoBitbltCopy((DrawablePtr)pRoot, (DrawablePtr)pRoot, GXcopy, &rgnDst, pptSrc, ~0L); if(pWin->drawable.bitsPerPixel == 16) cfb16DoBitbltCopy((DrawablePtr)pScreenPriv->pix16, (DrawablePtr)pScreenPriv->pix16, GXcopy, &rgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } REGION_UNINIT(pScreen, &rgnDst); if(pWin->drawable.depth == 8) { REGION_INIT(pScreen, &rgnDst, NullBox, 0); miSegregateChildren(pWin, &rgnDst, pScrn->depth); if(REGION_NOTEMPTY(pScreen, &rgnDst)) { REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrc); 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; } cfb16DoBitbltCopy((DrawablePtr)pScreenPriv->pix16, (DrawablePtr)pScreenPriv->pix16, GXcopy, &rgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); } } REGION_UNINIT(pScreen, &rgnDst); } }
static void kaaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { ScreenPtr pScreen = pDrawable->pScreen; KdScreenPriv (pScreen); KaaScreenPriv (pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap; BoxPtr pextent, pbox; int nbox; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1; int partX1, partX2; int off_x, off_y; if (!pScreenPriv->enabled || pGC->fillStyle != FillSolid || !(pPixmap = kaaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) || !(*pKaaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; } pextent = REGION_EXTENTS(pGC->pScreen, pClip); extentX1 = pextent->x1; extentY1 = pextent->y1; extentX2 = pextent->x2; extentY2 = pextent->y2; while (n--) { fullX1 = ppt->x; fullY1 = ppt->y; fullX2 = fullX1 + (int) *pwidth; ppt++; pwidth++; if (fullY1 < extentY1 || extentY2 <= fullY1) continue; if (fullX1 < extentX1) fullX1 = extentX1; if (fullX2 > extentX2) fullX2 = extentX2; if (fullX1 >= fullX2) continue; nbox = REGION_NUM_RECTS (pClip); if (nbox == 1) { (*pKaaScr->info->Solid) (fullX1 + off_x, fullY1 + off_y, fullX2 + off_x, fullY1 + 1 + off_y); } else { pbox = REGION_RECTS(pClip); while(nbox--) { if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) { partX1 = pbox->x1; if (partX1 < fullX1) partX1 = fullX1; partX2 = pbox->x2; if (partX2 > fullX2) partX2 = fullX2; if (partX2 > partX1) (*pKaaScr->info->Solid) (partX1 + off_x, fullY1 + off_y, partX2 + off_x, fullY1 + 1 + off_y); } pbox++; } } } (*pKaaScr->info->DoneSolid) (); kaaDrawableDirty (pDrawable); kaaMarkSync (pDrawable->pScreen); }
static void winShadowUpdateDD (ScreenPtr pScreen, shadowBufPtr pBuf) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; RegionPtr damage = shadowDamage(pBuf); 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); /* Unlock the shadow surface, so we can blit */ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL); if (FAILED (ddrval)) { ErrorF ("winShadowUpdateDD - Unlock failed\n"); return; } /* * 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 rectange */ 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 = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, &rcDest, pScreenPriv->pddsShadow, &rcSrc, DDBLT_WAIT, NULL); /* 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; /* 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 = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, &rcDest, pScreenPriv->pddsShadow, &rcSrc, DDBLT_WAIT, NULL); /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } /* Relock the shadow surface */ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow, NULL, pScreenPriv->pddsdShadow, DDLOCK_WAIT, NULL); if (FAILED (ddrval)) { ErrorF ("winShadowUpdateDD - Lock failed\n"); return; } /* Has our memory pointer changed? */ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface) { ErrorF ("winShadowUpdateDD - Memory location of the shadow " "surface has changed, trying to update the root window " "pixmap header to point to the new address. If you get " "this message and "PROJECT_NAME" freezes or crashes " "after this message then send a problem report and your " "%s file to " BUILDERADDR, g_pszLogFile); /* Location of shadow framebuffer has changed */ pScreenInfo->pfb = pScreenPriv->pddsdShadow->lpSurface; /* Update the screen pixmap */ if (!(*pScreen->ModifyPixmapHeader)(pScreen->devPrivate, pScreen->width, pScreen->height, pScreen->rootDepth, BitsPerPixel (pScreen->rootDepth), PixmapBytePad (pScreenInfo->dwStride, pScreenInfo->dwBPP), pScreenInfo->pfb)) { ErrorF ("winShadowUpdateDD - Bits changed, could not " "notify fb.\n"); return; } } }
static void kaaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { KdScreenPriv (pDrawable->pScreen); KaaScreenPriv (pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); PixmapPtr pPixmap; register BoxPtr pbox; BoxPtr pextent; int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1, fullY2; int partX1, partX2, partY1, partY2; int xoff, yoff; int xorg, yorg; int n; if (!pScreenPriv->enabled || pGC->fillStyle != FillSolid || !(pPixmap = kaaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pKaaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { KdCheckPolyFillRect (pDrawable, pGC, nrect, prect); return; } 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) { (*pKaaScr->info->Solid) (fullX1 + xoff, fullY1 + yoff, fullX2 + xoff, fullY2 + yoff); } 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) (*pKaaScr->info->Solid) (partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); } } } (*pKaaScr->info->DoneSolid) (); kaaDrawableDirty (pDrawable); kaaMarkSync (pDrawable->pScreen); }
static void glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc, int x, int y, int w, int h, int left_pad, int image_format, char *bits) { ScreenPtr screen = drawable->pScreen; PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); float fg[4], bg[4]; GLuint tex; unsigned int stride = PixmapBytePad(1, w + left_pad); RegionPtr clip; BoxPtr box; int nbox; float dest_coords[8]; const float bitmap_coords[8] = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, }; GLfloat xscale, yscale; glamor_pixmap_private *pixmap_priv; pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale); glamor_set_normalize_vcoords(xscale, yscale, x, y, x + w, y + h, glamor_priv->yInverted, dest_coords); glamor_fallback("glamor_put_image_xybitmap: disabled\n"); goto fail; if (glamor_priv->put_image_xybitmap_prog == 0) { ErrorF("no program for xybitmap putimage\n"); goto fail; } glamor_set_alu(gc->alu); if (!glamor_set_planemask(pixmap, gc->planemask)) goto fail; dispatch->glUseProgram(glamor_priv->put_image_xybitmap_prog); glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg); dispatch->glUniform4fv (glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg); glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg); dispatch->glUniform4fv (glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg); dispatch->glGenTextures(1, &tex); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad); dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits); dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); /* Now that we've set up our bitmap texture and the shader, shove * the destination rectangle through the cliprects and run the * shader on the resulting fragments. */ dispatch->glVertexPointer(2, GL_FLOAT, 0, dest_coords); dispatch->glEnableClientState(GL_VERTEX_ARRAY); dispatch->glClientActiveTexture(GL_TEXTURE0); dispatch->glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords); dispatch->glEnableClientState(GL_TEXTURE_COORD_ARRAY); dispatch->glEnable(GL_SCISSOR_TEST); clip = fbGetCompositeClip(gc); for (nbox = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nbox--; box++) { int x1 = x; int y1 = y; int x2 = x + w; int y2 = y + h; if (x1 < box->x1) x1 = box->x1; if (y1 < box->y1) y1 = box->y1; if (x2 > box->x2) x2 = box->x2; if (y2 > box->y2) y2 = box->y2; if (x1 >= x2 || y1 >= y2) continue; dispatch->glScissor(box->x1, y_flip(pixmap, box->y1), box->x2 - box->x1, box->y2 - box->y1); dispatch->glDrawArrays(GL_QUADS, 0, 4); } dispatch->glDisable(GL_SCISSOR_TEST); glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); dispatch->glDeleteTextures(1, &tex); dispatch->glDisableClientState(GL_VERTEX_ARRAY); dispatch->glDisableClientState(GL_TEXTURE_COORD_ARRAY); return; glamor_set_alu(GXcopy); glamor_set_planemask(pixmap, ~0); glamor_fallback(": to %p (%c)\n", drawable, glamor_get_drawable_location(drawable)); fail: if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && glamor_prepare_access_gc(gc)) { fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits); } glamor_finish_access_gc(gc); glamor_finish_access(drawable); }
static void kaaSolidBoxClipped (DrawablePtr pDrawable, RegionPtr pClip, FbBits pm, FbBits fg, int x1, int y1, int x2, int y2) { KdScreenPriv (pDrawable->pScreen); KaaScreenPriv (pDrawable->pScreen); PixmapPtr pPixmap; BoxPtr pbox; int nbox; int xoff, yoff; int partX1, partX2, partY1, partY2; if (!pScreenPriv->enabled || !(pPixmap = kaaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || !(*pKaaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) { kaaWaitSync (pDrawable->pScreen); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); kaaDrawableDirty (pDrawable); return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); nbox--; pbox++) { partX1 = pbox->x1; if (partX1 < x1) partX1 = x1; partX2 = pbox->x2; if (partX2 > x2) partX2 = x2; if (partX2 <= partX1) continue; partY1 = pbox->y1; if (partY1 < y1) partY1 = y1; partY2 = pbox->y2; if (partY2 > y2) partY2 = y2; if (partY2 <= partY1) continue; (*pKaaScr->info->Solid) (partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); } (*pKaaScr->info->DoneSolid) (); kaaDrawableDirty (pDrawable); kaaMarkSync (pDrawable->pScreen); }
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; }
RegionPtr rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { RegionPtr rv; RegionRec clip_reg; RegionRec box_reg; RegionRec reg1; int num_clips; int cd; int j; int can_do_screen_blt; int got_id; int dirty_type; int post_process; int reset_surface; struct image_data id; BoxRec box; BoxPtr pbox; PixmapPtr pSrcPixmap; PixmapPtr pDstPixmap; rdpPixmapRec *pSrcPriv; rdpPixmapRec *pDstPriv; rdpPixmapRec *pDirtyPriv; WindowPtr pDstWnd; WindowPtr pSrcWnd; LLOGLN(10, ("rdpCopyArea: x %d y %d w %d h %d", dstx, dsty, w, h)); if (pSrc->type == DRAWABLE_WINDOW) { pSrcWnd = (WindowPtr)pSrc; if (pSrcWnd->viewable) { rdpup_check_dirty_screen(&g_screenPriv); if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { can_do_screen_blt = pGC->alu == GXcopy; if (can_do_screen_blt) { return rdpCopyAreaWndToWnd(pSrcWnd, pDstWnd, pGC, srcx, srcy, w, h, dstx, dsty); } } } else if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { can_do_screen_blt = pGC->alu == GXcopy; if (can_do_screen_blt) { rdpup_check_dirty(pDstPixmap, pDstPriv); return rdpCopyAreaWndToPixmap(pSrcWnd, pDstPixmap, pDstPriv, pGC, srcx, srcy, w, h, dstx, dsty); } } else { LLOGLN(10, ("rdpCopyArea: 1")); } } } } if (pSrc->type == DRAWABLE_PIXMAP) { pSrcPixmap = (PixmapPtr)pSrc; pSrcPriv = GETPIXPRIV(pSrcPixmap); if (xrdp_is_os(pSrcPixmap, pSrcPriv)) { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { rdpup_check_dirty_screen(&g_screenPriv); rdpup_check_dirty(pSrcPixmap, pSrcPriv); return rdpCopyAreaPixmapToWnd(pSrcPixmap, pSrcPriv, pDstWnd, pGC, srcx, srcy, w, h, dstx, dsty); } } else if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { if (g_can_do_pix_to_pix) { rdpup_check_dirty(pSrcPixmap, pSrcPriv); rdpup_check_dirty(pDstPixmap, pDstPriv); return rdpCopyAreaPixmapToPixmap(pSrcPixmap, pSrcPriv, pDstPixmap, pDstPriv, pGC, srcx, srcy, w, h, dstx, dsty); } } else { LLOGLN(10, ("rdpCopyArea: 4")); } } } else { LLOGLN(10, ("rdpCopyArea: 2")); } } /* do original call */ rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); dirty_type = 0; pDirtyPriv = 0; post_process = 0; reset_surface = 0; got_id = 0; if (pDst->type == DRAWABLE_PIXMAP) { pDstPixmap = (PixmapPtr)pDst; pDstPriv = GETPIXPRIV(pDstPixmap); if (xrdp_is_os(pDstPixmap, pDstPriv)) { post_process = 1; if (g_do_dirty_os) { LLOGLN(10, ("rdpCopyArea: gettig dirty")); pDstPriv->is_dirty = 1; pDirtyPriv = pDstPriv; dirty_type = RDI_IMGLL; } else { rdpup_switch_os_surface(pDstPriv->rdpindex); reset_surface = 1; rdpup_get_pixmap_image_rect(pDstPixmap, &id); got_id = 1; } } else { LLOGLN(10, ("rdpCopyArea: 3")); } } else { if (pDst->type == DRAWABLE_WINDOW) { pDstWnd = (WindowPtr)pDst; if (pDstWnd->viewable) { post_process = 1; if (g_do_dirty_ons) { LLOGLN(10, ("rdpCopyArea: gettig dirty")); g_screenPriv.is_dirty = 1; pDirtyPriv = &g_screenPriv; dirty_type = RDI_IMGLL; } else { rdpup_get_screen_image_rect(&id); got_id = 1; } } } } if (!post_process) { return rv; } RegionInit(&clip_reg, NullBox, 0); cd = rdp_get_clip(&clip_reg, pDst, pGC); if (cd == 1) { if (dirty_type != 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(®1, &box, 0); draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, 1); RegionUninit(®1); } else if (got_id) { rdpup_begin_update(); rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h); rdpup_end_update(); } } else if (cd == 2) { num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips > 0) { if (dirty_type != 0) { box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 1); RegionUninit(&box_reg); } else if (got_id) { rdpup_begin_update(); box.x1 = pDst->x + dstx; box.y1 = pDst->y + dsty; box.x2 = box.x1 + w; box.y2 = box.y1 + h; RegionInit(&box_reg, &box, 0); RegionIntersect(&clip_reg, &clip_reg, &box_reg); num_clips = REGION_NUM_RECTS(&clip_reg); if (num_clips < 10) { for (j = num_clips - 1; j >= 0; j--) { box = REGION_RECTS(&clip_reg)[j]; rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); } } else { pbox = RegionExtents(&clip_reg); rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); } RegionUninit(&box_reg); rdpup_end_update(); } } } RegionUninit(&clip_reg); if (reset_surface) { rdpup_switch_os_surface(-1); } return rv; }