Ejemplo n.º 1
0
/**
 * 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);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
/**
 * 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);
}
Ejemplo n.º 4
0
/**
 * 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 (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", __func__, 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) &&
	    !exaPixmapIsOffscreen (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))
			exaMoveOutPixmap (pixmaps[i].pPix);
		}
		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].pPix);
		if (!exaPixmapIsDirty (pixmaps[i].pPix))
		    exaMoveOutPixmap (pixmaps[i].pPix);
	    }
	    return;
	}

	/* Finally, the acceleration path.  Move them all in. */
	for (i = 0; i < npixmaps; i++) {
	    exaMigrateTowardFb(pixmaps[i].pPix);
	    exaMoveInPixmap(pixmaps[i].pPix);
	}
    } 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].pPix);
	    return;
	}

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

	/* Nobody's in FB, so move all away from FB. */
	for (i = 0; i < npixmaps; i++)
	    exaMigrateTowardSys(pixmaps[i].pPix);
    } 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++)
		exaMoveOutPixmap(pixmaps[i].pPix);
	    return;
	}

	/* Now, try to move them all into FB */
	for (i = 0; i < npixmaps; i++) {
	    exaMoveInPixmap(pixmaps[i].pPix);
	    ExaOffscreenMarkUsed (pixmaps[i].pPix);
	}

	/* If we couldn't fit everything in, then kick back out */
	for (i = 0; i < npixmaps; i++) {
	    if (!exaPixmapIsOffscreen(pixmaps[i].pPix)) {
		EXA_FALLBACK(("Pixmap %p (%dx%d) not in fb\n", pixmaps[i].pPix,
			      pixmaps[i].pPix->drawable.width,
			      pixmaps[i].pPix->drawable.height));
		for (j = 0; j < npixmaps; j++)
		    exaMoveOutPixmap(pixmaps[j].pPix);
		break;
	    }
	}
    }
}