/* changed area is *dest* rect */ static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long plane) { RegionPtr result; BoxRec box; GCOP_UNWRAP(pGC); RL_DEBUG_MSG("copy plane start "); if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) { RootlessStartDrawing((WindowPtr) pSrc); } RootlessStartDrawing((WindowPtr) dst); result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty, plane); box.x1 = dstx + dst->x; box.x2 = box.x1 + w; box.y1 = dsty + dst->y; box.y2 = box.y1 + h; TRIM_BOX(box, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); GCOP_WRAP(pGC); RL_DEBUG_MSG("copy plane end\n"); return result; }
static void RootlessPutImage(DrawablePtr dst, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) { BoxRec box; GCOP_UNWRAP(pGC); RL_DEBUG_MSG("put image start "); RootlessStartDrawing((WindowPtr) dst); pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); box.x1 = x + dst->x; box.x2 = box.x1 + w; box.y1 = y + dst->y; box.y2 = box.y1 + h; TRIM_BOX(box, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); GCOP_WRAP(pGC); RL_DEBUG_MSG("put image end\n"); }
static void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, DDXPointPtr pptInit, int *pwidthInit, int sorted) { GC_SAVE(pGC); GCOP_UNWRAP(pGC); RL_DEBUG_MSG("fill spans start "); if (nInit <= 0) { pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); } else { DDXPointPtr ppt = pptInit; int *pwidth = pwidthInit; int i = nInit; BoxRec box; box.x1 = ppt->x; box.x2 = box.x1 + *pwidth; box.y2 = box.y1 = ppt->y; while (--i) { ppt++; pwidth++; if (box.x1 > ppt->x) box.x1 = ppt->x; if (box.x2 < (ppt->x + *pwidth)) box.x2 = ppt->x + *pwidth; if (box.y1 > ppt->y) box.y1 = ppt->y; else if (box.y2 < ppt->y) box.y2 = ppt->y; } box.y2++; RootlessStartDrawing((WindowPtr) dst); if (canAccelFill(dst, pGC)) { GC_UNSET_PM(pGC, dst); } pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); TRIM_AND_TRANSLATE_BOX(box, dst, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); } GC_RESTORE(pGC, dst); GCOP_WRAP(pGC); RL_DEBUG_MSG("fill spans end\n"); }
/* changed area is *dest* rect */ static RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { RegionPtr result; BoxRec box; GC_SAVE(pGC); GCOP_UNWRAP(pGC); RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst); if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) { /* If both source and dest are windows, and we're doing a simple copy operation, we can remove the alpha-protecting planemask (since source has opaque alpha as well) */ if (canAccelBlit(pSrc, pGC)) { GC_UNSET_PM(pGC, dst); } RootlessStartDrawing((WindowPtr) pSrc); } RootlessStartDrawing((WindowPtr) dst); result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); box.x1 = dstx + dst->x; box.x2 = box.x1 + w; box.y1 = dsty + dst->y; box.y2 = box.y1 + h; TRIM_BOX(box, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); GC_RESTORE(pGC, dst); GCOP_WRAP(pGC); RL_DEBUG_MSG("copy area end\n"); return result; }
static void RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, unsigned int format, unsigned long planeMask, char *pdstLine) { ScreenPtr pScreen = pDrawable->pScreen; SCREEN_UNWRAP(pScreen, GetImage); if (pDrawable->type == DRAWABLE_WINDOW) { int x0, y0, x1, y1; RootlessWindowRec *winRec; // Many apps use GetImage to sync with the visible frame buffer // FIXME: entire screen or just window or all screens? RootlessRedisplayScreen(pScreen); // RedisplayScreen stops drawing, so we need to start it again RootlessStartDrawing((WindowPtr)pDrawable); /* Check that we have some place to read from. */ winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); if (winRec == NULL) goto out; /* Clip to top-level window bounds. */ /* FIXME: fbGetImage uses the width parameter to calculate the stride of the destination pixmap. If w is clipped, the data returned will be garbage, although we will not crash. */ x0 = pDrawable->x + sx; y0 = pDrawable->y + sy; x1 = x0 + w; y1 = y0 + h; x0 = max (x0, winRec->x); y0 = max (y0, winRec->y); x1 = min (x1, winRec->x + winRec->width); y1 = min (y1, winRec->y + winRec->height); sx = x0 - pDrawable->x; sy = y0 - pDrawable->y; w = x1 - x0; h = y1 - y0; if (w <= 0 || h <= 0) goto out; } pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); out: SCREEN_WRAP(pScreen, GetImage); }
static void RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); WindowPtr srcWin, dstWin, maskWin = NULL; if (pMask) { // pMask can be NULL maskWin = (pMask->pDrawable && pMask->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pMask->pDrawable : NULL; } srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pSrc->pDrawable : NULL; dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pDst->pDrawable : NULL; // SCREEN_UNWRAP(ps, Composite); ps->Composite = SCREENREC(pScreen)->Composite; if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); if (maskWin && IsFramedWindow(maskWin)) RootlessStartDrawing(maskWin); if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); if (dstWin && IsFramedWindow(dstWin)) { RootlessDamageRect(dstWin, xDst, yDst, width, height); } ps->Composite = RootlessComposite; // SCREEN_WRAP(ps, Composite); }
/* * RootlessSourceValidate * CopyArea and CopyPlane use a GC tied to the destination drawable. * StartDrawing/StopDrawing wrappers won't be called if source is * a visible window but the destination isn't. So, we call StartDrawing * here and leave StopDrawing for the block handler. */ static void RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int subWindowMode) { SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); if (pDrawable->type == DRAWABLE_WINDOW) { WindowPtr pWin = (WindowPtr)pDrawable; RootlessStartDrawing(pWin); } if (pDrawable->pScreen->SourceValidate) { pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode); } SCREEN_WRAP(pDrawable->pScreen, SourceValidate); }
static void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, DDXPointPtr pptInit, int *pwidthInit, int nspans, int sorted) { GCOP_UNWRAP(pGC); RL_DEBUG_MSG("set spans start "); if (nspans <= 0) { pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); } else { DDXPointPtr ppt = pptInit; int *pwidth = pwidthInit; int i = nspans; BoxRec box; box.x1 = ppt->x; box.x2 = box.x1 + *pwidth; box.y2 = box.y1 = ppt->y; while (--i) { ppt++; pwidth++; if (box.x1 > ppt->x) box.x1 = ppt->x; if (box.x2 < (ppt->x + *pwidth)) box.x2 = ppt->x + *pwidth; if (box.y1 > ppt->y) box.y1 = ppt->y; else if (box.y2 < ppt->y) box.y2 = ppt->y; } box.y2++; RootlessStartDrawing((WindowPtr) dst); pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); TRIM_AND_TRANSLATE_BOX(box, dst, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); } GCOP_WRAP(pGC); RL_DEBUG_MSG("set spans end\n"); }
static void RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); int x, y; int n; GlyphPtr glyph; WindowPtr srcWin, dstWin; srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pSrc->pDrawable : NULL; dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? (WindowPtr)pDst->pDrawable : NULL; if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); //SCREEN_UNWRAP(ps, Glyphs); ps->Glyphs = SCREENREC(pScreen)->Glyphs; ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); ps->Glyphs = RootlessGlyphs; //SCREEN_WRAP(ps, Glyphs); if (dstWin && IsFramedWindow(dstWin)) { x = xSrc; y = ySrc; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; /* Calling DamageRect for the bounding box of each glyph is inefficient. So compute the union of all glyphs in a list and damage that. */ if (n > 0) { BoxRec box; glyph = *glyphs++; box.x1 = x - glyph->info.x; box.y1 = y - glyph->info.y; box.x2 = box.x1 + glyph->info.width; box.y2 = box.y1 + glyph->info.height; x += glyph->info.xOff; y += glyph->info.yOff; while (--n > 0) { short x1, y1, x2, y2; glyph = *glyphs++; x1 = x - glyph->info.x; y1 = y - glyph->info.y; x2 = x1 + glyph->info.width; y2 = y1 + glyph->info.height; box.x1 = max (box.x1, x1); box.y1 = max (box.y1, y1); box.x2 = max (box.x2, x2); box.y2 = max (box.y2, y2); x += glyph->info.xOff; y += glyph->info.yOff; } RootlessDamageBox(dstWin, &box); } list++; } } }
/* changed area is box around each line */ static void RootlessPolylines(DrawablePtr dst, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { GCOP_UNWRAP(pGC); RL_DEBUG_MSG("poly lines start "); RootlessStartDrawing((WindowPtr) dst); pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); if (npt > 0) { BoxRec box; int extra = pGC->lineWidth >> 1; box.x2 = box.x1 = pptInit->x; box.y2 = box.y1 = pptInit->y; if (npt > 1) { if (pGC->joinStyle == JoinMiter) extra = 6 * pGC->lineWidth; else if (pGC->capStyle == CapProjecting) extra = pGC->lineWidth; } if (mode == CoordModePrevious) { int x = box.x1; int y = box.y1; while (--npt) { pptInit++; x += pptInit->x; y += pptInit->y; if (box.x1 > x) box.x1 = x; else if (box.x2 < x) box.x2 = x; if (box.y1 > y) box.y1 = y; else if (box.y2 < y) box.y2 = y; } } else { while (--npt) { pptInit++; if (box.x1 > pptInit->x) box.x1 = pptInit->x; else if (box.x2 < pptInit->x) box.x2 = pptInit->x; if (box.y1 > pptInit->y) box.y1 = pptInit->y; else if (box.y2 < pptInit->y) box.y2 = pptInit->y; } } box.x2++; box.y2++; if (extra) { box.x1 -= extra; box.x2 += extra; box.y1 -= extra; box.y2 += extra; } TRIM_AND_TRANSLATE_BOX(box, dst, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); }
/* changed area is box around all points */ static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { GCOP_UNWRAP(pGC); RL_DEBUG_MSG("polypoint start "); RootlessStartDrawing((WindowPtr) dst); pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); if (npt > 0) { #if ROOTLESS_CHANGED_AREA==0 // box per point BoxRec box; while (npt) { box.x1 = pptInit->x; box.y1 = pptInit->y; box.x2 = box.x1 + 1; box.y2 = box.y1 + 1; TRIM_AND_TRANSLATE_BOX(box, dst, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); npt--; pptInit++; } #elif ROOTLESS_CHANGED_AREA==1 // one big box BoxRec box; box.x2 = box.x1 = pptInit->x; box.y2 = box.y1 = pptInit->y; while (--npt) { pptInit++; if (box.x1 > pptInit->x) box.x1 = pptInit->x; else if (box.x2 < pptInit->x) box.x2 = pptInit->x; if (box.y1 > pptInit->y) box.y1 = pptInit->y; else if (box.y2 < pptInit->y) box.y2 = pptInit->y; } box.x2++; box.y2++; TRIM_AND_TRANSLATE_BOX(box, dst, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); #elif ROOTLESS_CHANGED_AREA==2 // clever(?) method: accumulate point in 20-pixel radius BoxRec box; int firstx, firsty; box.x2 = box.x1 = firstx = pptInit->x; box.y2 = box.y1 = firsty = pptInit->y; while (--npt) { pptInit++; if (abs(pptInit->x - firstx) > 20 || abs(pptInit->y - firsty) > 20) { box.x2++; box.y2++; TRIM_AND_TRANSLATE_BOX(box, dst, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); box.x2 = box.x1 = firstx = pptInit->x; box.y2 = box.y1 = firsty = pptInit->y; } else { if (box.x1 > pptInit->x) box.x1 = pptInit->x; else if (box.x2 < pptInit->x) box.x2 = pptInit->x; if (box.y1 > pptInit->y) box.y1 = pptInit->y; else if (box.y2 < pptInit->y) box.y2 = pptInit->y; } } box.x2++; box.y2++; TRIM_AND_TRANSLATE_BOX(box, dst, pGC); if (BOX_NOT_EMPTY(box)) RootlessDamageBox((WindowPtr) dst, &box); #endif /* ROOTLESS_CHANGED_AREA */ } GCOP_WRAP(pGC); RL_DEBUG_MSG("polypoint end\n"); }
void miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what) { ScreenPtr pScreen = pWin->drawable.pScreen; ChangeGCVal gcval[6]; BITS32 gcmask; GCPtr pGC; int i; BoxPtr pbox; xRectangle *prect; int numRects; /* * Distance from screen to destination drawable, use this * to adjust rendering coordinates which come in in screen space */ int draw_x_off, draw_y_off; /* * Tile offset for drawing; these need to align the tile * to the appropriate window origin */ int tile_x_off, tile_y_off; PixUnion fill; Bool solid = TRUE; DrawablePtr drawable = &pWin->drawable; #ifdef ROOTLESS if (!drawable || drawable->type == UNDRAWABLE_WINDOW) return; if (IsFramedWindow(pWin)) { RootlessStartDrawing(pWin); RootlessDamageRegion(pWin, prgn); if (pWin->backgroundState == ParentRelative) { if ((what == PW_BACKGROUND) || (what == PW_BORDER && !pWin->borderIsPixel)) RootlessSetPixmapOfAncestors(pWin); } } #endif if (what == PW_BACKGROUND) { while (pWin->backgroundState == ParentRelative) pWin = pWin->parent; draw_x_off = drawable->x; draw_y_off = drawable->y; tile_x_off = pWin->drawable.x - draw_x_off; tile_y_off = pWin->drawable.y - draw_y_off; fill = pWin->background; #ifdef COMPOSITE if (pWin->inhibitBGPaint) return; #endif switch (pWin->backgroundState) { case None: return; case BackgroundPixmap: solid = FALSE; break; } } else { PixmapPtr pixmap; tile_x_off = drawable->x; tile_y_off = drawable->y; /* servers without pixmaps draw their own borders */ if (!pScreen->GetWindowPixmap) return; pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable); drawable = &pixmap->drawable; #ifdef COMPOSITE draw_x_off = pixmap->screen_x; draw_y_off = pixmap->screen_y; tile_x_off -= draw_x_off; tile_y_off -= draw_y_off; #else draw_x_off = 0; draw_y_off = 0; #endif fill = pWin->border; solid = pWin->borderIsPixel; } gcval[0].val = GXcopy; gcmask = GCFunction; #ifdef ROOTLESS_SAFEALPHA /* Bit mask for alpha channel with a particular number of bits per * pixel. Note that we only care for 32bpp data. Mac OS X uses planar * alpha for 16bpp. */ #define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0) #endif if (solid) { #ifdef ROOTLESS_SAFEALPHA gcval[1].val = fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel); #else gcval[1].val = fill.pixel; #endif gcval[2].val = FillSolid; gcmask |= GCForeground | GCFillStyle; } else { int c = 1; #ifdef ROOTLESS_SAFEALPHA gcval[c++].val = ((CARD32) -1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel); gcmask |= GCPlaneMask; #endif gcval[c++].val = FillTiled; gcval[c++].ptr = (void *) fill.pixmap; gcval[c++].val = tile_x_off; gcval[c++].val = tile_y_off; gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin; } prect = malloc(RegionNumRects(prgn) * sizeof(xRectangle)); if (!prect) return; pGC = GetScratchGC(drawable->depth, drawable->pScreen); if (!pGC) { free(prect); return; } ChangeGC(NullClient, pGC, gcmask, gcval); ValidateGC(drawable, pGC); numRects = RegionNumRects(prgn); pbox = RegionRects(prgn); for (i = numRects; --i >= 0; pbox++, prect++) { prect->x = pbox->x1 - draw_x_off; prect->y = pbox->y1 - draw_y_off; prect->width = pbox->x2 - pbox->x1; prect->height = pbox->y2 - pbox->y1; } prect -= numRects; (*pGC->ops->PolyFillRect) (drawable, pGC, numRects, prect); free(prect); FreeScratchGC(pGC); }