diff --git a/ChangeLog b/ChangeLog index 89c7720ca..5a54f678f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-03-14 Eric Anholt + + * exa/exa.c: (exaDriverInit): + * exa/exa_migration.c: (exaDoMigration): + * exa/exa_priv.h: + * hw/xfree86/exa/examodule.c: (exaXorgCloseScreen), + (exaDDXDriverInit): + Add a new migration scheme, "always", which will move pixmaps to their + desired location always (unless they don't fit in FB, in which case they + all get moved out for software rendering). The default remains as + before, but can be controlled by the MigrationHeuristic xorg.conf option + (which is intentionally not documented, as it may be short-lived). This + is part of the exa-damagetrack work, which appears stable in testing + with fakexa, unlike the work as a whole. + 2006-03-14 Eric Anholt * exa/exa.c: diff --git a/exa/exa.c b/exa/exa.c index db76b8038..548f76ad9 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -456,6 +456,8 @@ exaDriverInit (ScreenPtr pScreen, pScreen->devPrivates[exaScreenPrivateIndex].ptr = (pointer) pExaScr; + pExaScr->migration = ExaMigrationGreedy; + exaDDXDriverInit(pScreen); /* diff --git a/exa/exa_migration.c b/exa/exa_migration.c index d48abf066..ce4ce7455 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -247,6 +247,10 @@ exaMoveOutPixmap (PixmapPtr pPixmap) } } +/** + * For the "greedy" migration scheme, pushes the pixmap toward being located in + * framebuffer memory. + */ static void exaMigrateTowardFb (PixmapPtr pPixmap) { @@ -285,6 +289,10 @@ exaMigrateTowardFb (PixmapPtr pPixmap) ExaOffscreenMarkUsed (pPixmap); } +/** + * For the "greedy" migration scheme, pushes the pixmap toward being located in + * system memory. + */ static void exaMigrateTowardSys (PixmapPtr pPixmap) { @@ -314,13 +322,14 @@ exaMigrateTowardSys (PixmapPtr pPixmap) /** * Performs migration of the pixmaps according to the operation information - * provided in pixmaps and can_accel. In the future, other migration schemes - * may be added, which is facilitated by having this logic all in one place. + * 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 anything is pinned in system memory, we won't be able to @@ -338,33 +347,63 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) } } - /* 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); + 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; } - } - /* Nobody's in FB, so move all away from FB. */ - for (i = 0; i < npixmaps; i++) - exaMigrateTowardSys(pixmaps[i].pPix); + 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; + } + } + } } diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 036433266..f199cab88 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -77,6 +77,15 @@ do { \ #define EXA_MAX_FB FB_OVERLAY_MAX #endif +/** + * This is the list of migration heuristics supported by EXA. See + * exaDoMigration() for what their implementations do. + */ +enum ExaMigrationHeuristic { + ExaMigrationGreedy, + ExaMigrationAlways +}; + typedef void (*EnableDisableFBAccessProcPtr)(int, Bool); typedef struct { ExaDriverPtr info; @@ -94,6 +103,7 @@ typedef struct { GlyphsProcPtr SavedGlyphs; #endif Bool swappedOut; + enum ExaMigrationHeuristic migration; } ExaScreenPrivRec, *ExaScreenPrivPtr; /* diff --git a/hw/xfree86/exa/examodule.c b/hw/xfree86/exa/examodule.c index 8b48444f1..627bfd567 100644 --- a/hw/xfree86/exa/examodule.c +++ b/hw/xfree86/exa/examodule.c @@ -29,6 +29,8 @@ #include #endif +#include + #include "exa_priv.h" #include "xf86str.h" @@ -37,11 +39,21 @@ typedef struct _ExaXorgScreenPrivRec { CloseScreenProcPtr SavedCloseScreen; EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess; + OptionInfoPtr options; } ExaXorgScreenPrivRec, *ExaXorgScreenPrivPtr; static int exaXorgServerGeneration; static int exaXorgScreenPrivateIndex; +typedef enum { + EXAOPT_MIGRATION_HEURISTIC, +} EXAOpts; + +static const OptionInfoRec EXAOptions[] = { + { EXAOPT_MIGRATION_HEURISTIC, "MigrationHeuristic", OPTV_ANYSTR, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + static Bool exaXorgCloseScreen (int i, ScreenPtr pScreen) { @@ -53,6 +65,7 @@ exaXorgCloseScreen (int i, ScreenPtr pScreen) pScrn->EnableDisableFBAccess = pScreenPriv->SavedEnableDisableFBAccess; + xfree (pScreenPriv->options); xfree (pScreenPriv); return pScreen->CloseScreen (i, pScreen); @@ -82,6 +95,7 @@ exaXorgEnableDisableFBAccess (int index, Bool enable) void exaDDXDriverInit(ScreenPtr pScreen) { + ExaScreenPriv(pScreen); /* Do NOT use XF86SCRNINFO macro here!! */ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; ExaXorgScreenPrivPtr pScreenPriv; @@ -95,6 +109,30 @@ exaDDXDriverInit(ScreenPtr pScreen) if (pScreenPriv == NULL) return; + pScreenPriv->options = xnfalloc (sizeof(EXAOptions)); + memcpy(pScreenPriv->options, EXAOptions, sizeof(EXAOptions)); + xf86ProcessOptions (pScrn->scrnIndex, pScrn->options, pScreenPriv->options); + + if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && + pExaScr->info->offScreenBase < pExaScr->info->memorySize) + { + char *heuristicName; + + heuristicName = xf86GetOptValString (pScreenPriv->options, + EXAOPT_MIGRATION_HEURISTIC); + if (heuristicName != NULL) { + if (strcmp(heuristicName, "greedy") == 0) + pExaScr->migration = ExaMigrationGreedy; + else if (strcmp(heuristicName, "always") == 0) + pExaScr->migration = ExaMigrationAlways; + else { + xf86DrvMsg (pScreen->myNum, X_WARNING, + "EXA: unknown migration heuristic %s\n", + heuristicName); + } + } + } + pScreen->devPrivates[exaXorgScreenPrivateIndex].ptr = pScreenPriv; pScreenPriv->SavedEnableDisableFBAccess = pScrn->EnableDisableFBAccess; @@ -107,11 +145,6 @@ exaDDXDriverInit(ScreenPtr pScreen) static MODULESETUPPROTO(exaSetup); -static const OptionInfoRec EXAOptions[] = { - { -1, NULL, - OPTV_NONE, {0}, FALSE } -}; - /*ARGSUSED*/ static const OptionInfoRec * EXAAvailableOptions(void *unused)