summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2006-04-18 19:14:07 +0000
committerEric Anholt <anholt@freebsd.org>2006-04-18 19:14:07 +0000
commitb17a4de83e7ab18bef29ae898195889638f1cc6a (patch)
tree6ae3d6465edfbe4c950ebfff9a8641894607ea7a /exa
parent771b366abe0bc060592b548612ec413291e14bf0 (diff)
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.
Diffstat (limited to 'exa')
-rw-r--r--exa/exa.c2
-rw-r--r--exa/exa_migration.c61
-rw-r--r--exa/exa_priv.h3
3 files changed, 63 insertions, 3 deletions
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
@@ -58,6 +58,36 @@ exaPixmapIsPinned (PixmapPtr pPix)
}
/**
+ * 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
* allocated.
@@ -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);