diff --git a/ChangeLog b/ChangeLog index fbdd69c88..36147cbeb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2006-04-18 Eric Anholt + + * exa/exa.c: (exaDriverInit): + * exa/exa_migration.c: (exaPixmapIsDirty), (exaPixmapShouldBeInFB), + (exaDoMigration): + * exa/exa_priv.h: + * hw/kdrive/ephyr/ephyr_draw.c: (exaDDXDriverInit): + * hw/xfree86/exa/examodule.c: (exaDDXDriverInit): + Add a new migration scheme, called "Smart" for lack of a better name. + This one behaves somewhat between Greedy and Always. It moves in if we + can accelerate, unless the destination is clean and shouldn't be kept in + framebuffer according to the score, in which case we migrate out (and + force-migrate anything where migration is free). This should help fix + lack of acceleration for drivers without UTS since removing + exaAsyncPixmapGCOps, and has removed one performance trap with Radeon + I'd noticed. It is the new default. + 2006-04-18 Eric Anholt * exa/exa_unaccel.c: (ExaCheckPolyGlyphBlt), diff --git a/exa/exa.c b/exa/exa.c index aa191a863..75d5c0d69 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -557,7 +557,7 @@ exaDriverInit (ScreenPtr pScreen, pScreen->devPrivates[exaScreenPrivateIndex].ptr = (pointer) pExaScr; - pExaScr->migration = ExaMigrationGreedy; + pExaScr->migration = ExaMigrationSmart; exaDDXDriverInit(pScreen); diff --git a/exa/exa_migration.c b/exa/exa_migration.c index 50700ed46..ef7cfd86e 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -57,6 +57,36 @@ exaPixmapIsPinned (PixmapPtr pPix) return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED; } +/** + * 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 || pExaPixmap->dirty == TRUE; +} + +/** + * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score + * to be considered "should be in framebuffer". + * + * 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 >= EXA_PIXMAP_SCORE_INIT; +} + /** * 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 @@ -403,7 +433,36 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) } } - if (pExaScr->migration == ExaMigrationGreedy) { + 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)) + { + can_accel = FALSE; + } + } + + /* 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. diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 18550eec0..89f8b0c9d 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -83,7 +83,8 @@ do { \ */ enum ExaMigrationHeuristic { ExaMigrationGreedy, - ExaMigrationAlways + ExaMigrationAlways, + ExaMigrationSmart }; typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);