/**
 * 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);
}
void
exaMoveOutPixmap_classic(PixmapPtr pPixmap)
{
    static ExaMigrationRec migrate = { FALSE, TRUE,
                                       NULL, NULL
                                     };

    migrate.pPix = pPixmap;
    exaDoMoveOutPixmap(&migrate);
}
示例#3
0
void
exaMoveOutPixmap_classic(PixmapPtr pPixmap)
{
    static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
                                      .pReg = NULL
                                     };

    migrate.pPix = pPixmap;
    exaDoMoveOutPixmap(&migrate);
}
/**
 * Performs migration of the pixmaps according to the operation information
 * provided in pixmaps and can_accel and the migration scheme chosen in the
 * config file.
 */
void
exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
{
    ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;

    ExaScreenPriv(pScreen);
    int i, j;

    /* If this debugging flag is set, check each pixmap for whether it is marked
     * as clean, and if so, actually check if that's the case.  This should help
     * catch issues with failing to mark a drawable as dirty.  While it will
     * catch them late (after the operation happened), it at least explains what
     * went wrong, and instrumenting the code to find what operation happened
     * to the pixmap last shouldn't be hard.
     */
    if (pExaScr->checkDirtyCorrectness) {
        for (i = 0; i < npixmaps; i++) {
            if (!exaPixmapIsDirty(pixmaps[i].pPix) &&
                    !exaAssertNotDirty(pixmaps[i].pPix))
                ErrorF("%s: Pixmap %d dirty but not marked as such!\n",
                       __FUNCTION__, 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)) {
            EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
                          pixmaps[i].pPix->drawable.width,
                          pixmaps[i].pPix->drawable.height));
            can_accel = FALSE;
            break;
        }
    }

    if (pExaScr->migration == ExaMigrationSmart) {
        /* If we've got something as a destination that we shouldn't cause to
         * become newly dirtied, take the unaccelerated route.
         */
        for (i = 0; i < npixmaps; i++) {
            if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB(pixmaps[i].pPix) &&
                    !exaPixmapIsDirty(pixmaps[i].pPix)) {
                for (i = 0; i < npixmaps; i++) {
                    if (!exaPixmapIsDirty(pixmaps[i].pPix))
                        exaDoMoveOutPixmap(pixmaps + i);
                }
                return;
            }
        }

        /* If we aren't going to accelerate, then we migrate everybody toward
         * system memory, and kick out if it's free.
         */
        if (!can_accel) {
            for (i = 0; i < npixmaps; i++) {
                exaMigrateTowardSys(pixmaps + i);
                if (!exaPixmapIsDirty(pixmaps[i].pPix))
                    exaDoMoveOutPixmap(pixmaps + i);
            }
            return;
        }

        /* Finally, the acceleration path.  Move them all in. */
        for (i = 0; i < npixmaps; i++) {
            exaMigrateTowardFb(pixmaps + i);
            exaDoMoveInPixmap(pixmaps + i);
        }
    }
    else if (pExaScr->migration == ExaMigrationGreedy) {
        /* If we can't accelerate, either because the driver can't or because one of
         * the pixmaps is pinned in system memory, then we migrate everybody toward
         * system memory.
         *
         * We also migrate toward system if all pixmaps involved are currently in
         * system memory -- this can mitigate thrashing when there are significantly
         * more pixmaps active than would fit in memory.
         *
         * If not, then we migrate toward FB so that hopefully acceleration can
         * happen.
         */
        if (!can_accel) {
            for (i = 0; i < npixmaps; i++)
                exaMigrateTowardSys(pixmaps + i);
            return;
        }

        for (i = 0; i < npixmaps; i++) {
            if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
                /* Found one in FB, so move all to FB. */
                for (j = 0; j < npixmaps; j++)
                    exaMigrateTowardFb(pixmaps + i);
                return;
            }
        }

        /* Nobody's in FB, so move all away from FB. */
        for (i = 0; i < npixmaps; i++)
            exaMigrateTowardSys(pixmaps + i);
    }
    else if (pExaScr->migration == ExaMigrationAlways) {
        /* Always move the pixmaps out if we can't accelerate.  If we can
         * accelerate, try to move them all in.  If that fails, then move them
         * back out.
         */
        if (!can_accel) {
            for (i = 0; i < npixmaps; i++)
                exaDoMoveOutPixmap(pixmaps + i);
            return;
        }

        /* Now, try to move them all into FB */
        for (i = 0; i < npixmaps; i++) {
            exaDoMoveInPixmap(pixmaps + i);
        }

        /* If we couldn't fit everything in, abort */
        for (i = 0; i < npixmaps; i++) {
            if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
                return;
            }
        }

        /* Yay, everything has a gpu copy, mark memory as used */
        for (i = 0; i < npixmaps; i++) {
            ExaOffscreenMarkUsed(pixmaps[i].pPix);
        }
    }
}