Пример #1
0
static int
ProcDamageSubtract (ClientPtr client)
{
    REQUEST(xDamageSubtractReq);
    DamageExtPtr    pDamageExt;
    RegionPtr	    pRepair;
    RegionPtr	    pParts;

    REQUEST_SIZE_MATCH(xDamageSubtractReq);
    VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
    VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess);
    VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess);

    if (pDamageExt->level != DamageReportRawRegion)
    {
	DamagePtr   pDamage = pDamageExt->pDamage;
	if (pRepair)
	{
	    if (pParts)
		RegionIntersect(pParts, DamageRegion (pDamage), pRepair);
	    if (DamageSubtract (pDamage, pRepair))
		DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt);
	}
	else
	{
	    if (pParts)
		RegionCopy(pParts, DamageRegion (pDamage));
	    DamageEmpty (pDamage);
	}
    }
    return Success;
}
Пример #2
0
static int
ProcDamageSubtract (ClientPtr client)
{
    REQUEST(xDamageSubtractReq);
    DamageExtPtr    pDamageExt;
    RegionPtr	    pRepair;
    RegionPtr	    pParts;

    REQUEST_SIZE_MATCH(xDamageSubtractReq);
    VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess);
    VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, SecurityWriteAccess);
    VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, SecurityWriteAccess);

    if (pDamageExt->level != DamageReportRawRegion)
    {
        DamagePtr   pDamage = pDamageExt->pDamage;
        if (pRepair)
        {
            if (pParts)
                REGION_INTERSECT (prScreen, pParts, DamageRegion (pDamage), pRepair);
            if (DamageSubtract (pDamage, pRepair))
                DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt);
        }
        else
        {
            if (pParts)
                REGION_COPY (prScreen, pParts, DamageRegion (pDamage));
            DamageEmpty (pDamage);
        }
    }
    return (client->noClientException);
}
Пример #3
0
/**
 * exaPixmapDirty() marks a pixmap as dirty, allowing for
 * optimizations in pixmap migration when no changes have occurred.
 */
void
exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
{
    ExaPixmapPriv(pPix);
    BoxRec box;
    RegionPtr pDamageReg;
    RegionRec region;

    if (!pExaPixmap)
	return;
	
    box.x1 = max(x1, 0);
    box.y1 = max(y1, 0);
    box.x2 = min(x2, pPix->drawable.width);
    box.y2 = min(y2, pPix->drawable.height);

    if (box.x1 >= box.x2 || box.y1 >= box.y2)
	return;

    pDamageReg = DamageRegion(pExaPixmap->pDamage);

    REGION_INIT(pScreen, &region, &box, 1);
    REGION_UNION(pScreen, pDamageReg, pDamageReg, &region);
    REGION_UNINIT(pScreen, &region);
}
Пример #4
0
void
xglAddCurrentSurfaceDamage (DrawablePtr pDrawable)
{
    XGL_DRAWABLE_PIXMAP_PRIV (pDrawable);

    if (BOX_NOTEMPTY (&pPixmapPriv->damageBox))
    {
	RegionRec region;

	REGION_INIT (pDrawable->pScreen, &region, &pPixmapPriv->damageBox, 1);

	if (pPixmapPriv->pDamage)
	{
	    RegionPtr pDamageRegion;

	    pDamageRegion = DamageRegion (pPixmapPriv->pDamage);

	    REGION_UNION (pDrawable->pScreen,
			  pDamageRegion, pDamageRegion,
			  &region);
	}

	REGION_UNION (pDrawable->pScreen,
		      &pPixmapPriv->bitRegion, &pPixmapPriv->bitRegion,
		      &region);

	REGION_UNINIT (pDrawable->pScreen, &region);

	pPixmapPriv->damageBox = miEmptyBox;
    }
}
Пример #5
0
static void
ephyrInternalDamageRedisplay(ScreenPtr pScreen)
{
    KdScreenPriv(pScreen);
    KdScreenInfo *screen = pScreenPriv->screen;
    EphyrScrPriv *scrpriv = screen->driver;
    RegionPtr pRegion;

    if (!scrpriv || !scrpriv->pDamage)
        return;

    pRegion = DamageRegion(scrpriv->pDamage);

    if (RegionNotEmpty(pRegion)) {
        int nbox;
        BoxPtr pbox;

        if (ephyr_glamor) {
            ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion);
        } else {
            nbox = RegionNumRects(pRegion);
            pbox = RegionRects(pRegion);

            while (nbox--) {
                hostx_paint_rect(screen,
                                 pbox->x1, pbox->y1,
                                 pbox->x1, pbox->y1,
                                 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
                pbox++;
            }
        }
        DamageEmpty(scrpriv->pDamage);
    }
}
Пример #6
0
void
xglAddSurfaceDamage (DrawablePtr pDrawable,
		     RegionPtr   pRegion)
{
    glitz_surface_t *surface;
    int		    xOff, yOff;

    XGL_DRAWABLE_PIXMAP_PRIV (pDrawable);

    pPixmapPriv->damageBox = miEmptyBox;

    XGL_GET_DRAWABLE (pDrawable, surface, xOff, yOff);

    if (xOff || yOff)
	REGION_TRANSLATE (pDrawable->pScreen, pRegion, xOff, yOff);

    if (pPixmapPriv->pDamage)
    {
	RegionPtr pDamageRegion;

	pDamageRegion = DamageRegion (pPixmapPriv->pDamage);

	REGION_UNION (pDrawable->pScreen,
		      pDamageRegion, pDamageRegion,
		      pRegion);
    }

    REGION_UNION (pDrawable->pScreen,
		  &pPixmapPriv->bitRegion, &pPixmapPriv->bitRegion,
		  pRegion);

    if (xOff || yOff)
	REGION_TRANSLATE (pDrawable->pScreen, pRegion, -xOff, -yOff);
}
Пример #7
0
/**
 * Copies out important pixmap data and removes references to framebuffer area.
 * Called when the memory manager decides it's time to kick the pixmap out of
 * framebuffer entirely.
 */
void
exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
{
    PixmapPtr pPixmap = area->privData;
    ExaPixmapPriv(pPixmap);
    RegionPtr pDamageReg = DamageRegion(pExaPixmap->pDamage);

    DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap,
		  (void*)(ExaGetPixmapPriv(pPixmap)->area ?
                          ExaGetPixmapPriv(pPixmap)->area->offset : 0),
		  pPixmap->drawable.width,
		  pPixmap->drawable.height,
		  exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));

    if (exaPixmapIsOffscreen(pPixmap)) {
	exaCopyDirtyToSys (pPixmap);
	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
	pPixmap->devKind = pExaPixmap->sys_pitch;
	pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    }

    pExaPixmap->fb_ptr = NULL;
    pExaPixmap->area = NULL;

    /* Mark all valid bits as damaged, so they'll get copied to FB next time */
    REGION_UNION(pPixmap->drawable.pScreen, pDamageReg, pDamageReg,
		 &pExaPixmap->validReg);
}
Пример #8
0
static void
NestedShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf) {
    RegionPtr pRegion = DamageRegion(pBuf->pDamage);
    NestedClientUpdateScreen(PCLIENTDATA(xf86Screens[pScreen->myNum]),
                             pRegion->extents.x1, pRegion->extents.y1,
                             pRegion->extents.x2, pRegion->extents.y2);
}
Пример #9
0
static int
dispatch_dirty_region(ScrnInfoPtr scrn,
                      PixmapPtr pixmap, DamagePtr damage, int fb_id)
{
    modesettingPtr ms = modesettingPTR(scrn);
    RegionPtr dirty = DamageRegion(damage);
    unsigned num_cliprects = REGION_NUM_RECTS(dirty);
    int ret = 0;

    if (num_cliprects) {
        drmModeClip *clip = malloc(num_cliprects * sizeof(drmModeClip));
        BoxPtr rect = REGION_RECTS(dirty);
        int i;

        if (!clip)
            return -ENOMEM;

        /* XXX no need for copy? */
        for (i = 0; i < num_cliprects; i++, rect++) {
            clip[i].x1 = rect->x1;
            clip[i].y1 = rect->y1;
            clip[i].x2 = rect->x2;
            clip[i].y2 = rect->y2;
        }

        /* TODO query connector property to see if this is needed */
        ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects);
        free(clip);
        DamageEmpty(damage);
    }
    return ret;
}
Пример #10
0
static CARD32
damage_timer(OsTimerPtr timer, CARD32 time, pointer arg)
{
    struct omap_screen_info *omaps = arg;
    int needUpdate = 0;
    RegionPtr region = NULL;
#ifdef XSP
    xspScrPrivPtr xsp_priv = NULL;
#endif

#ifdef XSP
    if (xspScrPrivateIndex > 0) {
        xsp_priv = xspGetScrPriv(omaps->screen->pScreen);
        if (xsp_priv && xsp_priv->dsp_enabled)
            needUpdate = 1;
    }
#endif

    if (!omaps->damage) {
        omaps->timer_active = 0;
        omaps->empty_updates = 0;
        return 0;
    }

#ifdef PROFILE_ME_HARDER
    omaps->updates++;
    if (omaps->updates > (5000 / OMAP_UPDATE_TIME))
        video_stats(omaps, time);
#endif

    region = DamageRegion(omaps->damage);
    if (REGION_NOTEMPTY(omaps->screen->pScreen, region)) {
        accumulate_damage(omaps, region);
        DamageEmpty(omaps->damage);
    }

    if (!region_is_null(omaps))
        needUpdate = 1;

    if (needUpdate) {
        omaps->empty_updates = 0;
        update_screen(omaps);
    }
    else {
        omaps->empty_updates++;
    }

#if !defined(PROFILE_ME_HARDER) && !defined(DEBUG)
    /* Kill the timer if we've gone more than 500ms without an update. */
    if (omaps->empty_updates >= 500 / OMAP_UPDATE_TIME) {
        omaps->timer_active = 0;
        omaps->empty_updates = 0;
        return 0;
    }
    else
#endif
    {
        return OMAP_UPDATE_TIME;
    }
}
Пример #11
0
void
shadowUpdateIplan2p4(ScreenPtr pScreen, shadowBufPtr pBuf)
{
    RegionPtr damage = DamageRegion(pBuf->pDamage);
    PixmapPtr pShadow = pBuf->pPixmap;
    int nbox = RegionNumRects(damage);
    BoxPtr pbox = RegionRects(damage);
    FbBits *shaBase;
    CARD16 *shaLine, *sha;
    FbStride shaStride;
    int scrLine;
    _X_UNUSED int shaBpp, shaXoff, shaYoff;
    int x, y, w, h;
    int i, n;
    CARD16 *win;
    _X_UNUSED CARD32 winSize;
    union {
        CARD8 bytes[8];
        CARD32 words[2];
    } d;

    fbGetDrawable(&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff,
                  shaYoff);
    shaStride *= sizeof(FbBits) / sizeof(CARD16);

    while (nbox--) {
        x = pbox->x1;
        y = pbox->y1;
        w = pbox->x2 - pbox->x1;
        h = pbox->y2 - pbox->y1;

        scrLine = (x & -16) / 2;
        shaLine = (CARD16 *)shaBase + y * shaStride + scrLine / sizeof(CARD16);

        n = ((x & 15) + w + 15) / 16;   /* number of c2p units in scanline */

        while (h--) {
            sha = shaLine;
            win = (CARD16 *) (*pBuf->window) (pScreen,
                                              y,
                                              scrLine,
                                              SHADOW_WINDOW_WRITE,
                                              &winSize,
                                              pBuf->closure);
            if (!win)
                return;
            for (i = 0; i < n; i++) {
                memcpy(d.bytes, sha, sizeof(d.bytes));
                c2p_16x4(d.words);
                store_iplan2p4(win, d.words);
                sha += sizeof(d.bytes) / sizeof(*sha);
                win += sizeof(d.bytes) / sizeof(*win);
            }
            shaLine += shaStride;
            y++;
        }
        pbox++;
    }
}
Пример #12
0
/**
 * If the pixmap is currently dirty, this copies at least the dirty area from
 * the system memory copy to the framebuffer memory copy.  Both areas must be
 * allocated.
 */
static void
exaCopyDirtyToFb (PixmapPtr pPixmap)
{
    ExaScreenPriv (pPixmap->drawable.pScreen);
    ExaPixmapPriv (pPixmap);
    RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage);
    CARD8 *save_ptr;
    int save_pitch;
    BoxPtr pBox = REGION_RECTS(pRegion);
    int nbox = REGION_NUM_RECTS(pRegion);
    Bool do_sync = FALSE;

    save_ptr = pPixmap->devPrivate.ptr;
    save_pitch = pPixmap->devKind;
    pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
    pPixmap->devKind = pExaPixmap->fb_pitch;

    while (nbox--) {
	pBox->x1 = max(pBox->x1, 0);
	pBox->y1 = max(pBox->y1, 0);
	pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
	pBox->y2 = min(pBox->y2, pPixmap->drawable.height);

	if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
	    continue;

	if (pExaScr->info->UploadToScreen == NULL ||
	    !pExaScr->info->UploadToScreen (pPixmap,
					    pBox->x1, pBox->y1,
					    pBox->x2 - pBox->x1,
					    pBox->y2 - pBox->y1,
					    pExaPixmap->sys_ptr
					    + pBox->y1 * pExaPixmap->sys_pitch
					    + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
					    pExaPixmap->sys_pitch))
	{
	    exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
	    exaMemcpyBox (pPixmap, pBox,
			  pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
			  pExaPixmap->fb_ptr, pExaPixmap->fb_pitch);
	    exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
	}
	else
	    do_sync = TRUE;

	pBox++;
    }

    if (do_sync)
	exaMarkSync (pPixmap->drawable.pScreen);

    pPixmap->devPrivate.ptr = save_ptr;
    pPixmap->devKind = save_pitch;

    /* The previously damaged bits are now no longer damaged but valid */
    REGION_UNION(pPixmap->drawable.pScreen,
		 &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion);
    DamageEmpty (pExaPixmap->pDamage);
}
Пример #13
0
/**
 * Returns TRUE if the pixmap is dirty (has been modified in its current
 * location compared to the other), or lacks a private for tracking
 * dirtiness.
 */
static Bool
exaPixmapIsDirty (PixmapPtr pPix)
{
    ExaPixmapPriv (pPix);

    return pExaPixmap == NULL ||
	REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage));
}
Пример #14
0
static void
shadowRedisplay(ScreenPtr pScreen)
{
    shadowBuf(pScreen);
    RegionPtr pRegion;

    if (!pBuf || !pBuf->pDamage || !pBuf->update)
        return;
    pRegion = DamageRegion(pBuf->pDamage);
    if (RegionNotEmpty(pRegion)) {
        (*pBuf->update) (pScreen, pBuf);
        DamageEmpty(pBuf->pDamage);
    }
}
Пример #15
0
static Bool
xf86RotateRedisplay(ScreenPtr pScreen)
{
    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    DamagePtr		damage = xf86_config->rotation_damage;
    RegionPtr		region;

    if (!damage)
	return FALSE;
    xf86RotatePrepare (pScreen);
    region = DamageRegion(damage);
    if (REGION_NOTEMPTY(pScreen, region)) 
    {
	int			c;
	SourceValidateProcPtr	SourceValidate;

	/*
	 * SourceValidate is used by the software cursor code
	 * to pull the cursor off of the screen when reading
	 * bits from the frame buffer. Bypassing this function
	 * leaves the software cursor in place
	 */
	SourceValidate = pScreen->SourceValidate;
	pScreen->SourceValidate = NULL;

	for (c = 0; c < xf86_config->num_crtc; c++)
	{
	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];

	    if (crtc->rotation != RR_Rotate_0 && crtc->enabled)
	    {
		RegionRec   crtc_damage;

		/* compute portion of damage that overlaps crtc */
		REGION_INIT(pScreen, &crtc_damage, &crtc->bounds, 1);
		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
		
		/* update damaged region */
		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
    		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
		
		REGION_UNINIT (pScreen, &crtc_damage);
	    }
	}
	pScreen->SourceValidate = SourceValidate;
	DamageEmpty(damage);
    }
    return TRUE;
}
Пример #16
0
/**
 * Returns TRUE if the pixmap is dirty (has been modified in its current
 * location compared to the other), or lacks a private for tracking
 * dirtiness.
 */
static Bool
exaPixmapIsDirty(PixmapPtr pPix)
{
    ExaPixmapPriv(pPix);

    if (pExaPixmap == NULL)
        EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);

    if (!pExaPixmap->pDamage)
        return FALSE;

    return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
           !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
}
Пример #17
0
static void
shadowRedisplay(ScreenPtr pScreen)
{
    shadowBuf(pScreen);
    RegionPtr pRegion;

    if (!pBuf || !pBuf->pDamage || !pBuf->update)
	return;
    /* allow deferral of updates, to minimize overdraw, etc. */
    if (!pBuf->ready_to_update(pScreen, pBuf))
	return;
    pRegion = DamageRegion(pBuf->pDamage);
    if (REGION_NOTEMPTY(pScreen, pRegion)) {
	(*pBuf->update)(pScreen, pBuf);
	DamageEmpty(pBuf->pDamage);
    }
}
Пример #18
0
static void
xf86RotateRedisplay(ScreenPtr pScreen)
{
    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    DamagePtr		damage = xf86_config->rotation_damage;
    RegionPtr		region;

    if (!damage)
	return;
    xf86RotatePrepare (pScreen);
    region = DamageRegion(damage);
    if (REGION_NOTEMPTY(pScreen, region)) 
    {
	int		    c;
	
	for (c = 0; c < xf86_config->num_crtc; c++)
	{
	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];

	    if (crtc->rotation != RR_Rotate_0)
	    {
		BoxRec	    box;
		RegionRec   crtc_damage;

		/* compute portion of damage that overlaps crtc */
		box.x1 = crtc->x;
		box.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
		box.y1 = crtc->y;
		box.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
		REGION_INIT(pScreen, &crtc_damage, &box, 1);
		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
		
		/* update damaged region */
		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
    		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
		
		REGION_UNINIT (pScreen, &crtc_damage);
	    }
	}
	DamageEmpty(damage);
    }
}
static inline RegionPtr
saa_pix_damage_region(struct saa_pixmap *spix)
{
    return (spix->damage ? DamageRegion(spix->damage) : NULL);
}
Пример #20
0
Bool
xglSyncSurface (DrawablePtr pDrawable)
{
    RegionPtr pRegion;

    XGL_DRAWABLE_PIXMAP (pDrawable);
    XGL_PIXMAP_PRIV (pPixmap);

    if (!pPixmapPriv->surface)
    {
	if (!xglCreatePixmapSurface (pPixmap))
	    return FALSE;
    }

    pRegion = DamageRegion (pPixmapPriv->pDamage);

    if (REGION_NOTEMPTY (pDrawable->pScreen, pRegion))
    {
	glitz_pixel_format_t format;
	BoxPtr		     pBox;
	BoxPtr		     pExt;
	int		     nBox;

	xglUnmapPixmapBits (pPixmap);

	nBox = REGION_NUM_RECTS (pRegion);
	pBox = REGION_RECTS (pRegion);
	pExt = REGION_EXTENTS (pDrawable->pScreen, pRegion);

	format.fourcc  = pPixmapPriv->pVisual->format.surface->color.fourcc;
	format.masks   = pPixmapPriv->pVisual->pPixel->masks;
	format.xoffset = pExt->x1;

	if (pPixmapPriv->stride < 0)
	{
	    format.skip_lines	  = pPixmap->drawable.height - pExt->y2;
	    format.bytes_per_line = -pPixmapPriv->stride;
	    format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP;
	}
	else
	{
	    format.skip_lines	  = pExt->y1;
	    format.bytes_per_line = pPixmapPriv->stride;
	    format.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
	}

	glitz_surface_set_clip_region (pPixmapPriv->surface,
				       0, 0, (glitz_box_t *) pBox, nBox);

	glitz_set_pixels (pPixmapPriv->surface,
			  pExt->x1,
			  pExt->y1,
			  pExt->x2 - pExt->x1,
			  pExt->y2 - pExt->y1,
			  &format,
			  pPixmapPriv->buffer);

	glitz_surface_set_clip_region (pPixmapPriv->surface, 0, 0, NULL, 0);

	REGION_EMPTY (pDrawable->pScreen, pRegion);
    }

    return TRUE;
}
Пример #21
0
/**
 * If the pixmap is currently dirty, this copies at least the dirty area from
 * the framebuffer  memory copy to the system memory copy.  Both areas must be
 * allocated.
 */
static void
exaCopyDirtyToSys (PixmapPtr pPixmap)
{
    ExaScreenPriv (pPixmap->drawable.pScreen);
    ExaPixmapPriv (pPixmap);
    RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage);
    CARD8 *save_ptr;
    int save_pitch;
    BoxPtr pBox = REGION_RECTS(pRegion);
    int nbox = REGION_NUM_RECTS(pRegion);
    Bool do_sync = FALSE;

    save_ptr = pPixmap->devPrivate.ptr;
    save_pitch = pPixmap->devKind;
    pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
    pPixmap->devKind = pExaPixmap->fb_pitch;

    while (nbox--) {
	pBox->x1 = max(pBox->x1, 0);
	pBox->y1 = max(pBox->y1, 0);
	pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
	pBox->y2 = min(pBox->y2, pPixmap->drawable.height);

	if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
	    continue;

	if (pExaScr->info->DownloadFromScreen == NULL ||
	    !pExaScr->info->DownloadFromScreen (pPixmap,
						pBox->x1, pBox->y1,
						pBox->x2 - pBox->x1,
						pBox->y2 - pBox->y1,
						pExaPixmap->sys_ptr
						+ pBox->y1 * pExaPixmap->sys_pitch
						+ pBox->x1 * pPixmap->drawable.bitsPerPixel / 8,
						pExaPixmap->sys_pitch))
	{
	    exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
	    exaMemcpyBox (pPixmap, pBox,
			  pExaPixmap->fb_ptr, pExaPixmap->fb_pitch,
			  pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
	    exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
	}
	else
	    do_sync = TRUE;

	pBox++;
    }

    /* Make sure the bits have actually landed, since we don't necessarily sync
     * when accessing pixmaps in system memory.
     */
    if (do_sync)
	exaWaitSync (pPixmap->drawable.pScreen);

    pPixmap->devPrivate.ptr = save_ptr;
    pPixmap->devKind = save_pitch;

    /* The previously damaged bits are now no longer damaged but valid */
    REGION_UNION(pPixmap->drawable.pScreen,
		 &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion);
    DamageEmpty (pExaPixmap->pDamage);
}
Пример #22
0
/**
 * If the pixmap is currently dirty, this copies at least the dirty area from
 * FB to system or vice versa.  Both areas must be allocated.
 */
static void
exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
             Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
                               char *sys, int sys_pitch), int fallback_index,
             void (*sync) (ScreenPtr pScreen))
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaPixmapPriv(pPixmap);
    RegionPtr damage = DamageRegion(pExaPixmap->pDamage);
    RegionRec CopyReg;
    Bool save_use_gpu_copy;
    int save_pitch;
    BoxPtr pBox;
    int nbox;
    Bool access_prepared = FALSE;
    Bool need_sync = FALSE;

    /* Damaged bits are valid in current copy but invalid in other one */
    if (pExaPixmap->use_gpu_copy) {
        RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
        RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
    }
    else {
        RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
        RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
    }

    RegionEmpty(damage);

    /* Copy bits valid in source but not in destination */
    RegionNull(&CopyReg);
    RegionSubtract(&CopyReg, pValidSrc, pValidDst);

    if (migrate->as_dst) {
        ExaScreenPriv(pPixmap->drawable.pScreen);

        /* XXX: The pending damage region will be marked as damaged after the
         * operation, so it should serve as an upper bound for the region that
         * needs to be synchronized for the operation. Unfortunately, this
         * causes corruption in some cases, e.g. when starting compiz. See
         * https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
         */
        if (pExaScr->optimize_migration) {
            RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);

#if DEBUG_MIGRATE
            if (RegionNil(pending_damage)) {
                static Bool firsttime = TRUE;

                if (firsttime) {
                    ErrorF("%s: Pending damage region empty!\n", __func__);
                    firsttime = FALSE;
                }
            }
#endif

            /* Try to prevent destination valid region from growing too many
             * rects by filling it up to the extents of the union of the
             * destination valid region and the pending damage region.
             */
            if (RegionNumRects(pValidDst) > 10) {
                BoxRec box;
                BoxPtr pValidExt, pDamageExt;
                RegionRec closure;

                pValidExt = RegionExtents(pValidDst);
                pDamageExt = RegionExtents(pending_damage);

                box.x1 = min(pValidExt->x1, pDamageExt->x1);
                box.y1 = min(pValidExt->y1, pDamageExt->y1);
                box.x2 = max(pValidExt->x2, pDamageExt->x2);
                box.y2 = max(pValidExt->y2, pDamageExt->y2);

                RegionInit(&closure, &box, 0);
                RegionIntersect(&CopyReg, &CopyReg, &closure);
            }
            else
                RegionIntersect(&CopyReg, &CopyReg, pending_damage);
        }

        /* The caller may provide a region to be subtracted from the calculated
         * dirty region. This is to avoid migration of bits that don't
         * contribute to the result of the operation.
         */
        if (migrate->pReg)
            RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
    }
    else {
        /* The caller may restrict the region to be migrated for source pixmaps
         * to what's relevant for the operation.
         */
        if (migrate->pReg)
            RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
    }

    pBox = RegionRects(&CopyReg);
    nbox = RegionNumRects(&CopyReg);

    save_use_gpu_copy = pExaPixmap->use_gpu_copy;
    save_pitch = pPixmap->devKind;
    pExaPixmap->use_gpu_copy = TRUE;
    pPixmap->devKind = pExaPixmap->fb_pitch;

    while (nbox--) {
        pBox->x1 = max(pBox->x1, 0);
        pBox->y1 = max(pBox->y1, 0);
        pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
        pBox->y2 = min(pBox->y2, pPixmap->drawable.height);

        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
            continue;

        if (!transfer || !transfer(pPixmap,
                                   pBox->x1, pBox->y1,
                                   pBox->x2 - pBox->x1,
                                   pBox->y2 - pBox->y1,
                                   (char *) (pExaPixmap->sys_ptr
                                             + pBox->y1 * pExaPixmap->sys_pitch
                                             +
                                             pBox->x1 *
                                             pPixmap->drawable.bitsPerPixel /
                                             8), pExaPixmap->sys_pitch)) {
            if (!access_prepared) {
                ExaDoPrepareAccess(pPixmap, fallback_index);
                access_prepared = TRUE;
            }
            if (fallback_index == EXA_PREPARE_DEST) {
                exaMemcpyBox(pPixmap, pBox,
                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
                             pPixmap->devPrivate.ptr, pPixmap->devKind);
            }
            else {
                exaMemcpyBox(pPixmap, pBox,
                             pPixmap->devPrivate.ptr, pPixmap->devKind,
                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
            }
        }
        else
            need_sync = TRUE;

        pBox++;
    }

    pExaPixmap->use_gpu_copy = save_use_gpu_copy;
    pPixmap->devKind = save_pitch;

    /* Try to prevent source valid region from growing too many rects by
     * removing parts of it which are also in the destination valid region.
     * Removing anything beyond that would lead to data loss.
     */
    if (RegionNumRects(pValidSrc) > 20)
        RegionSubtract(pValidSrc, pValidSrc, pValidDst);

    /* The copied bits are now valid in destination */
    RegionUnion(pValidDst, pValidDst, &CopyReg);

    RegionUninit(&CopyReg);

    if (access_prepared)
        exaFinishAccess(&pPixmap->drawable, fallback_index);
    else if (need_sync && sync)
        sync(pPixmap->drawable.pScreen);
}