Example #1
0
/**
 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
 *
 * It deals with waiting for synchronization with the card, determining if
 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
 */
void
exaPrepareAccess(DrawablePtr pDrawable, int index)
{
    ScreenPtr	    pScreen = pDrawable->pScreen;
    ExaScreenPriv  (pScreen);
    PixmapPtr	    pPixmap;

    pPixmap = exaGetDrawablePixmap (pDrawable);

    if (exaPixmapIsOffscreen (pPixmap))
	exaWaitSync (pDrawable->pScreen);
    else
	return;

    /* Unhide pixmap pointer */
    if (pPixmap->devPrivate.ptr == NULL) {
	ExaPixmapPriv (pPixmap);

	pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
    }

    if (pExaScr->info->PrepareAccess == NULL)
	return;

    if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
	ExaPixmapPriv (pPixmap);
	if (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED)
	    FatalError("Driver failed PrepareAccess on a pinned pixmap\n");
	exaMoveOutPixmap (pPixmap);
    }
}
Example #2
0
Bool
exaDestroyPixmap_classic(PixmapPtr pPixmap)
{
    ScreenPtr pScreen = pPixmap->drawable.pScreen;

    ExaScreenPriv(pScreen);
    Bool ret;

    if (pPixmap->refcnt == 1) {
        ExaPixmapPriv(pPixmap);

        exaDestroyPixmap(pPixmap);

        if (pExaPixmap->area) {
            DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
                        (void *) pPixmap->drawable.id,
                        ExaGetPixmapPriv(pPixmap)->area->offset,
                        pPixmap->drawable.width, pPixmap->drawable.height));
            /* Free the offscreen area */
            exaOffscreenFree(pPixmap->drawable.pScreen, pExaPixmap->area);
            pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
            pPixmap->devKind = pExaPixmap->sys_pitch;
        }
        RegionUninit(&pExaPixmap->validSys);
        RegionUninit(&pExaPixmap->validFB);
    }

    swap(pExaScr, pScreen, DestroyPixmap);
    ret = pScreen->DestroyPixmap(pPixmap);
    swap(pExaScr, pScreen, DestroyPixmap);

    return ret;
}
Example #3
0
/**
 * For the "greedy" migration scheme, pushes the pixmap toward being located in
 * system memory.
 */
static void
exaMigrateTowardSys (PixmapPtr pPixmap)
{
    ExaPixmapPriv (pPixmap);

    if (pExaPixmap == NULL) {
	DBG_MIGRATE(("UseMem: ignoring exa-uncontrolled pixmap %p (%s)\n",
		     (pointer)pPixmap,
		     exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
	return;
    }

    DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score));

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
	return;

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
	pExaPixmap->score = 0;

    if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
	pExaPixmap->score--;

    if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
	exaMoveOutPixmap (pPixmap);
}
/**
 * Switches the current active location of the pixmap to system memory, copying
 * updated data out if necessary.
 */
static void
exaDoMoveOutPixmap(ExaMigrationPtr migrate)
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaPixmapPriv(pPixmap);

    if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
        return;

    exaCopyDirtyToSys(migrate);

    if (exaPixmapHasGpuCopy(pPixmap)) {

        DBG_MIGRATE(("<- %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'));

        pExaPixmap->use_gpu_copy = FALSE;

        pPixmap->devKind = pExaPixmap->sys_pitch;
        pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    }
}
Example #5
0
/**
 * Returns TRUE if the pixmap is not movable.  This is the case where it's a
 * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch
 * pixmap created by some other X Server internals (the score says it's
 * pinned).
 */
static Bool
exaPixmapIsPinned (PixmapPtr pPix)
{
    ExaPixmapPriv (pPix);

    return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
}
Example #6
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);
}
/**
 * For the "greedy" migration scheme, pushes the pixmap toward being located in
 * system memory.
 */
static void
exaMigrateTowardSys(ExaMigrationPtr migrate)
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaPixmapPriv(pPixmap);

    DBG_MIGRATE(("UseMem: %p score %d\n", (pointer) pPixmap,
                 pExaPixmap->score));

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
        return;

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
        pExaPixmap->score = 0;

    if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
        pExaPixmap->score--;

    if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
        exaDoMoveOutPixmap(migrate);

    if (exaPixmapHasGpuCopy(pPixmap)) {
        exaCopyDirtyToFb(migrate);
        ExaOffscreenMarkUsed(pPixmap);
    }
    else
        exaCopyDirtyToSys(migrate);
}
Example #8
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);
}
Example #9
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);
}
Example #10
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));
}
/**
 * Allocates a framebuffer copy of the pixmap if necessary, and then copies
 * any necessary pixmap data into the framebuffer copy and points the pixmap at
 * it.
 *
 * Note that when first allocated, a pixmap will have FALSE dirty flag.
 * This is intentional because pixmap data starts out undefined.  So if we move
 * it in due to the first operation against it being accelerated, it will have
 * undefined framebuffer contents that we didn't have to upload.  If we do
 * moveouts (and moveins) after the first movein, then we will only have to copy
 * back and forth if the pixmap was written to after the last synchronization of
 * the two copies.  Then, at exaPixmapSave (when the framebuffer copy goes away)
 * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
 * all the data, since it's almost surely all valid now.
 */
static void
exaDoMoveInPixmap(ExaMigrationPtr migrate)
{
    PixmapPtr pPixmap = migrate->pPix;
    ScreenPtr pScreen = pPixmap->drawable.pScreen;

    ExaScreenPriv(pScreen);
    ExaPixmapPriv(pPixmap);

    /* If we're VT-switched away, no touching card memory allowed. */
    if (pExaScr->swappedOut)
        return;

    /* If we're not allowed to move, then fail. */
    if (exaPixmapIsPinned(pPixmap))
        return;

    /* Don't migrate in pixmaps which are less than 8bpp.  This avoids a lot of
     * fragility in EXA, and <8bpp is probably not used enough any more to care
     * (at least, not in acceleratd paths).
     */
    if (pPixmap->drawable.bitsPerPixel < 8)
        return;

    if (pExaPixmap->accel_blocked)
        return;

    if (pExaPixmap->area == NULL) {
        pExaPixmap->area =
            exaOffscreenAlloc(pScreen, pExaPixmap->fb_size,
                              pExaScr->info->pixmapOffsetAlign, FALSE,
                              exaPixmapSave, (pointer) pPixmap);
        if (pExaPixmap->area == NULL)
            return;

        pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
                             pExaPixmap->area->offset;
    }

    exaCopyDirtyToFb(migrate);

    if (exaPixmapHasGpuCopy(pPixmap))
        return;

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

    pExaPixmap->use_gpu_copy = TRUE;

    pPixmap->devKind = pExaPixmap->fb_pitch;
    pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
Example #12
0
static _X_INLINE void *
ExaGetPixmapAddress(PixmapPtr p)
{
    ExaPixmapPriv(p);

    if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr)
        return pExaPixmap->fb_ptr;
    else
        return pExaPixmap->sys_ptr;
}
Example #13
0
/**
 * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
 * to be considered "should be in framebuffer".  That's just anything that has
 * had more acceleration than fallbacks, or has no score yet.
 *
 * Only valid if using a migration scheme that tracks score.
 */
static Bool
exaPixmapShouldBeInFB (PixmapPtr pPix)
{
    ExaPixmapPriv (pPix);

    if (exaPixmapIsPinned (pPix))
	return TRUE;

    return pExaPixmap->score >= 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.
 */
void
exaCopyDirtyToFb(ExaMigrationPtr migrate)
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaScreenPriv(pPixmap->drawable.pScreen);
    ExaPixmapPriv(pPixmap);

    exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
                 pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
}
/**
 * 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.
 */
void
exaCopyDirtyToSys(ExaMigrationPtr migrate)
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaScreenPriv(pPixmap->drawable.pScreen);
    ExaPixmapPriv(pPixmap);

    exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
                 pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
                 exaWaitSync);
}
Example #16
0
/**
 * If the pixmap has both a framebuffer and system memory copy, this function
 * asserts that both of them are the same.
 */
static Bool
exaAssertNotDirty (PixmapPtr pPixmap)
{
    ExaPixmapPriv (pPixmap);
    CARD8 *dst, *src;
    RegionPtr pValidReg = &pExaPixmap->validReg;
    int dst_pitch, src_pitch, cpp, y, nbox = REGION_NUM_RECTS(pValidReg);
    BoxPtr pBox = REGION_RECTS(pValidReg);
    Bool ret = TRUE;

    if (pExaPixmap == NULL || pExaPixmap->fb_ptr == NULL)
	return ret;

    dst = pExaPixmap->sys_ptr;
    dst_pitch = pExaPixmap->sys_pitch;
    src = pExaPixmap->fb_ptr;
    src_pitch = pExaPixmap->fb_pitch;
    cpp = pPixmap->drawable.bitsPerPixel / 8;

    exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
    while (nbox--) {
	    int rowbytes;

	    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;

	    rowbytes = (pBox->x2 - pBox->x1) * cpp;
	    src += pBox->y1 * src_pitch + pBox->x1 * cpp;
	    dst += pBox->y1 * dst_pitch + pBox->x1 * cpp;

	    for (y = pBox->y2 - pBox->y1; y; y--) {
		if (memcmp(dst + pBox->y1 * dst_pitch + pBox->x1 * cpp,
			   src + pBox->y1 * src_pitch + pBox->x1 * cpp,
			   (pBox->x2 - pBox->x1) * cpp) != 0) {
		    ret = FALSE;
		    break;
		}
		src += src_pitch;
		dst += dst_pitch;
	    }
	    src -= pBox->y1 * src_pitch + pBox->x1 * cpp;
	    dst -= pBox->y1 * dst_pitch + pBox->x1 * cpp;
    }
    exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);

    return ret;
}
Example #17
0
void
exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
{
    int i;

    /* If anything is pinned in system memory, we won't be able to
     * accelerate.
     */
    for (i = 0; i < npixmaps; i++) {
        if (exaPixmapIsPinned(pixmaps[i].pPix) &&
            !exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
            can_accel = FALSE;
            break;
        }
    }

    /* We can do nothing. */
    if (!can_accel)
        return;

    for (i = 0; i < npixmaps; i++) {
        PixmapPtr pPixmap = pixmaps[i].pPix;

        ExaPixmapPriv(pPixmap);

        if (!pExaPixmap->driverPriv)
            exaCreateDriverPixmap_mixed(pPixmap);

        if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) {
            ExaScreenPriv(pPixmap->drawable.pScreen);

            /* This pitch is needed for proper acceleration. For some reason
             * there are pixmaps without pDamage and a bad fb_pitch value.
             * So setting devKind when only exaPixmapHasGpuCopy() is true
             * causes corruption. Pixmaps without pDamage are not migrated
             * and should have a valid devKind at all times, so that's why this
             * isn't causing problems. Pixmaps have their gpu pitch set the
             * first time in the MPH call from exaCreateDriverPixmap_mixed().
             */
            pPixmap->devKind = pExaPixmap->fb_pitch;
            exaCopyDirtyToFb(pixmaps + i);

            if (pExaScr->deferred_mixed_pixmap == pPixmap &&
                !pixmaps[i].as_dst && !pixmaps[i].pReg)
                pExaScr->deferred_mixed_pixmap = NULL;
        }

        pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
    }
}
/**
 * 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);
}
Example #19
0
/**
 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
 * the beginning of the given pixmap.
 *
 * Note that drivers are free to, and often do, munge this offset as necessary
 * for handing to the hardware -- for example, translating it into a different
 * aperture.  This function may need to be extended in the future if we grow
 * support for having multiple card-accessible offscreen, such as an AGP memory
 * pool alongside the framebuffer pool.
 */
unsigned long
exaGetPixmapOffset(PixmapPtr pPix)
{
    ExaScreenPriv (pPix->drawable.pScreen);
    ExaPixmapPriv (pPix);
    void *ptr;

    /* Return the offscreen pointer if we've hidden the data. */
    if (pPix->devPrivate.ptr == NULL)
	ptr = pExaPixmap->fb_ptr;
    else
	ptr = pPix->devPrivate.ptr;

    return ((unsigned long)ptr - (unsigned long)pExaScr->info->memoryBase);
}
/**
 * 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);

    exaMoveOutPixmap(pPixmap);

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

    /* Mark all FB bits as invalid, so all valid system bits get copied to FB
     * next time */
    RegionEmpty(&pExaPixmap->validFB);
}
Example #21
0
/**
 * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
 *
 * This is probably the only case we actually care about.  The rest fall through
 * to migration and fbGetImage, which hopefully will result in migration pushing
 * the pixmap out of framebuffer.
 */
void
exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
            unsigned int format, unsigned long planeMask, char *d)
{
    ExaScreenPriv(pDrawable->pScreen);
    PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);

    ExaPixmapPriv(pPix);
    int xoff, yoff;
    Bool ok;

    if (pExaScr->fallback_counter || pExaScr->swappedOut)
        goto fallback;

    /* If there's a system copy, we want to save the result there */
    if (pExaPixmap->pDamage)
        goto fallback;

    pPix = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff);

    if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL)
        goto fallback;

    /* Only cover the ZPixmap, solid copy case. */
    if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
        goto fallback;

    /* Only try to handle the 8bpp and up cases, since we don't want to think
     * about <8bpp.
     */
    if (pDrawable->bitsPerPixel < 8)
        goto fallback;

    ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
                                           pDrawable->y + y + yoff, w, h, d,
                                           PixmapBytePad(w, pDrawable->depth));
    if (ok) {
        exaWaitSync(pDrawable->pScreen);
        return;
    }

 fallback:
    ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
}
Example #22
0
void
exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
{
    ScreenPtr pScreen = pPixmap->drawable.pScreen;

    ExaScreenPriv(pScreen);
    ExaPixmapPriv(pPixmap);
    int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
    int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
    int usage_hint = pPixmap->usage_hint;
    int paddedWidth = pExaPixmap->sys_pitch;

    /* Already done. */
    if (pExaPixmap->driverPriv)
        return;

    if (exaPixmapIsPinned(pPixmap))
        return;

    /* Can't accel 1/4 bpp. */
    if (pExaPixmap->accel_blocked || bpp < 8)
        return;

    if (pExaScr->info->CreatePixmap2) {
        int new_pitch = 0;

        pExaPixmap->driverPriv =
            pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp,
                                         &new_pitch);
        paddedWidth = pExaPixmap->fb_pitch = new_pitch;
    }
    else {
        if (paddedWidth < pExaPixmap->fb_pitch)
            paddedWidth = pExaPixmap->fb_pitch;
        pExaPixmap->driverPriv =
            pExaScr->info->CreatePixmap(pScreen, paddedWidth * h, 0);
    }

    if (!pExaPixmap->driverPriv)
        return;

    (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
}
Example #23
0
Bool
exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
{
    ScreenPtr pScreen = pPixmap->drawable.pScreen;

    ExaScreenPriv(pScreen);
    ExaPixmapPriv(pPixmap);
    Bool ret;

    if (pExaScr->info->PixmapIsOffscreen) {
        void *old_ptr = pPixmap->devPrivate.ptr;

        pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
        ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
        pPixmap->devPrivate.ptr = old_ptr;
    }
    else
        ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);

    return ret;
}
Example #24
0
void
ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
		 int x, int y, int w, int h, int leftPad, int format,
		 char *bits)
{
    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
    ExaPixmapPriv(pPixmap);

    EXA_PRE_FALLBACK_GC(pGC);
    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
    if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
	exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
			      pGC->alu, pGC->clientClipType))
	exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
    else
	pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
				    DamagePendingRegion(pExaPixmap->pDamage));
    pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
    EXA_POST_FALLBACK_GC(pGC);
}
Example #25
0
void
exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
    PixmapPtr pPixmap = closure;

    ExaPixmapPriv(pPixmap);

    /* Move back results of software rendering on system memory copy of mixed driver
     * pixmap (see exaPrepareAccessReg_mixed).
     *
     * Defer moving the destination back into the driver pixmap, to try and save
     * overhead on multiple subsequent software fallbacks.
     */
    if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) {
        ExaScreenPriv(pPixmap->drawable.pScreen);

        if (pExaScr->deferred_mixed_pixmap &&
            pExaScr->deferred_mixed_pixmap != pPixmap)
            exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
        pExaScr->deferred_mixed_pixmap = pPixmap;
    }
}
Example #26
0
static Bool
exaDestroyPixmap (PixmapPtr pPixmap)
{
    if (pPixmap->refcnt == 1)
    {
	ExaPixmapPriv (pPixmap);
	if (pExaPixmap->area)
	{
	    DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
                        (void*)pPixmap->drawable.id,
			 ExaGetPixmapPriv(pPixmap)->area->offset,
			 pPixmap->drawable.width,
			 pPixmap->drawable.height));
	    /* Free the offscreen area */
	    exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
	    pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
	    pPixmap->devKind = pExaPixmap->sys_pitch;
	}
	REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg);
    }
    return fbDestroyPixmap (pPixmap);
}
Example #27
0
void
ExaOffscreenMarkUsed (PixmapPtr pPixmap)
{
    ExaPixmapPriv (pPixmap);
    ExaScreenPriv (pPixmap->drawable.pScreen);
    static int iter = 0;

    if (!pExaPixmap->area)
	return;

    /* The numbers here are arbitrary.  We may want to tune these. */
    pExaPixmap->area->score += 100;
    if (++iter == 10) {
	ExaOffscreenArea *area;
	for (area = pExaScr->info->offScreenAreas; area != NULL;
	     area = area->next)
	{
	    if (area->state == ExaOffscreenRemovable)
		area->score = (area->score * 7) / 8;
	}
	iter = 0;
    }
}
Example #28
0
/**
 * For the "greedy" migration scheme, pushes the pixmap toward being located in
 * framebuffer memory.
 */
static void
exaMigrateTowardFb (PixmapPtr pPixmap)
{
    ExaPixmapPriv (pPixmap);

    if (pExaPixmap == NULL) {
	DBG_MIGRATE(("UseScreen: ignoring exa-uncontrolled pixmap %p (%s)\n",
		     (pointer)pPixmap,
		     exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
	return;
    }

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
	DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
		     (pointer)pPixmap));
	return;
    }

    DBG_MIGRATE(("UseScreen %p score %d\n",
		 (pointer)pPixmap, pExaPixmap->score));

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
	exaMoveInPixmap(pPixmap);
	pExaPixmap->score = 0;
    }

    if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
	pExaPixmap->score++;

    if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
	!exaPixmapIsOffscreen(pPixmap))
    {
	exaMoveInPixmap (pPixmap);
    }

    ExaOffscreenMarkUsed (pPixmap);
}
/**
 * For the "greedy" migration scheme, pushes the pixmap toward being located in
 * framebuffer memory.
 */
static void
exaMigrateTowardFb(ExaMigrationPtr migrate)
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaPixmapPriv(pPixmap);

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
        DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
                     (pointer) pPixmap));
        return;
    }

    DBG_MIGRATE(("UseScreen %p score %d\n",
                 (pointer) pPixmap, pExaPixmap->score));

    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
        exaDoMoveInPixmap(migrate);
        pExaPixmap->score = 0;
    }

    if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
        pExaPixmap->score++;

    if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
            !exaPixmapHasGpuCopy(pPixmap)) {
        exaDoMoveInPixmap(migrate);
    }

    if (exaPixmapHasGpuCopy(pPixmap)) {
        exaCopyDirtyToFb(migrate);
        ExaOffscreenMarkUsed(pPixmap);
    }
    else
        exaCopyDirtyToSys(migrate);
}
Example #30
0
/**
 * Switches the current active location of the pixmap to system memory, copying
 * updated data out if necessary.
 */
void
exaMoveOutPixmap (PixmapPtr pPixmap)
{
    ExaPixmapPriv (pPixmap);

    if (exaPixmapIsPinned(pPixmap))
	return;

    if (exaPixmapIsOffscreen(pPixmap)) {

	DBG_MIGRATE (("<- %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'));

	exaCopyDirtyToSys (pPixmap);

	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
	pPixmap->devKind = pExaPixmap->sys_pitch;
	pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    }
}