Пример #1
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);
}
/**
 * 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);
}
/**
 * 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;
    }
}
Пример #4
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;
    }
}
/**
 * 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);
}
Пример #6
0
/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
 * use the DownloadFromScreen hook to retrieve contents to a copy in system
 * memory, perform software rendering on that and move back the results with the
 * UploadToScreen hook (see exaDamageReport_mixed).
 */
void
exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
{
    ExaPixmapPriv(pPixmap);
    Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
    Bool success;

    success = ExaDoPrepareAccess(pPixmap, index);

    if (success && has_gpu_copy && pExaPixmap->pDamage) {
        /* You cannot do accelerated operations while a buffer is mapped. */
        exaFinishAccess(&pPixmap->drawable, index);
        /* Update the gpu view of both deferred destination pixmaps and of
         * source pixmaps that were migrated with a bounding region.
         */
        exaMoveInPixmap_mixed(pPixmap);
        success = ExaDoPrepareAccess(pPixmap, index);

        if (success) {
            /* We have a gpu pixmap that can be accessed, we don't need the cpu
             * copy anymore. Drivers that prefer DFS, should fail prepare
             * access.
             */
            DamageDestroy(pExaPixmap->pDamage);
            pExaPixmap->pDamage = NULL;

            free(pExaPixmap->sys_ptr);
            pExaPixmap->sys_ptr = NULL;

            return;
        }
    }

    if (!success) {
        ExaMigrationRec pixmaps[1];

        /* Do we need to allocate our system buffer? */
        if (!pExaPixmap->sys_ptr) {
            pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
                                         pPixmap->drawable.height);
            if (!pExaPixmap->sys_ptr)
                FatalError("EXA: malloc failed for size %d bytes\n",
                           pExaPixmap->sys_pitch * pPixmap->drawable.height);
        }

        if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
            pixmaps[0].as_dst = TRUE;
            pixmaps[0].as_src = FALSE;
        }
        else {
            pixmaps[0].as_dst = FALSE;
            pixmaps[0].as_src = TRUE;
        }
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = pReg;

        if (!pExaPixmap->pDamage &&
            (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
            Bool as_dst = pixmaps[0].as_dst;

            /* Set up damage tracking */
            pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
                                               DamageReportNonEmpty, TRUE,
                                               pPixmap->drawable.pScreen,
                                               pPixmap);

            if (pExaPixmap->pDamage) {
                DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
                /* This ensures that pending damage reflects the current
                 * operation. This is used by exa to optimize migration.
                 */
                DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
            }

            if (has_gpu_copy) {
                exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
                               pPixmap->drawable.height);

                /* We don't know which region of the destination will be damaged,
                 * have to assume all of it
                 */
                if (as_dst) {
                    pixmaps[0].as_dst = FALSE;
                    pixmaps[0].as_src = TRUE;
                    pixmaps[0].pReg = NULL;
                }
                exaCopyDirtyToSys(pixmaps);
            }

            if (as_dst)
                exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
                               pPixmap->drawable.height);
        }
        else if (has_gpu_copy)
            exaCopyDirtyToSys(pixmaps);

        pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
        pPixmap->devKind = pExaPixmap->sys_pitch;
        pExaPixmap->use_gpu_copy = FALSE;
    }
}