summaryrefslogtreecommitdiff
path: root/exa/exa.c
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2009-05-18 17:48:57 +0200
committerMichel Dänzer <daenzer@vmware.com>2009-05-18 17:48:57 +0200
commit510cbd43cd4e34bd459e8f74ab2855714b4ca95d (patch)
treeaab6ba5505b9d6ff97e5b32993fc5b5a43720ce4 /exa/exa.c
parent8331bde0adeccefb275c4d707e7b2cb1d95b1581 (diff)
EXA: Defragment offscreen memory.
At most once per second, under the following circumstances: * We can't satisfy an offscreen memory allocation, but there seems to be enough offscreen memory available in total. or * The server has been idle for at least 100ms, and there is more than one available offscreen area. Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Diffstat (limited to 'exa/exa.c')
-rw-r--r--exa/exa.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/exa/exa.c b/exa/exa.c
index 2de348a8d..089350b24 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -1048,6 +1048,50 @@ exaCreateScreenResources(ScreenPtr pScreen)
return TRUE;
}
+static void
+ExaBlockHandler(int screenNum, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[screenNum];
+ ExaScreenPriv(pScreen);
+
+ unwrap(pExaScr, pScreen, BlockHandler);
+ (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
+ wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
+
+ /* Try and keep the offscreen memory area tidy every now and then (at most
+ * once per second) when the server has been idle for at least 100ms.
+ */
+ if (pExaScr->numOffscreenAvailable > 1) {
+ CARD32 now = GetTimeInMillis();
+
+ pExaScr->nextDefragment = now +
+ max(100, (INT32)(pExaScr->lastDefragment + 1000 - now));
+ AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now);
+ }
+}
+
+static void
+ExaWakeupHandler(int screenNum, pointer wakeupData, unsigned long result,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[screenNum];
+ ExaScreenPriv(pScreen);
+
+ unwrap(pExaScr, pScreen, WakeupHandler);
+ (*pScreen->WakeupHandler) (screenNum, wakeupData, result, pReadmask);
+ wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
+
+ if (result == 0 && pExaScr->numOffscreenAvailable > 1) {
+ CARD32 now = GetTimeInMillis();
+
+ if ((int)(now - pExaScr->nextDefragment) > 0) {
+ ExaOffscreenDefragment(pScreen);
+ pExaScr->lastDefragment = now;
+ }
+ }
+}
+
/**
* exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
* screen private, before calling down to the next CloseSccreen.
@@ -1063,6 +1107,10 @@ exaCloseScreen(int i, ScreenPtr pScreen)
if (ps->Glyphs == exaGlyphs)
exaGlyphsFini(pScreen);
+ if (pScreen->BlockHandler == ExaBlockHandler)
+ unwrap(pExaScr, pScreen, BlockHandler);
+ if (pScreen->WakeupHandler == ExaWakeupHandler)
+ unwrap(pExaScr, pScreen, WakeupHandler);
unwrap(pExaScr, pScreen, CreateGC);
unwrap(pExaScr, pScreen, CloseScreen);
unwrap(pExaScr, pScreen, GetImage);
@@ -1223,6 +1271,11 @@ exaDriverInit (ScreenPtr pScreen,
/*
* Replace various fb screen functions
*/
+ if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
+ !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
+ wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
+ wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
+ }
wrap(pExaScr, pScreen, CreateGC, exaCreateGC);
wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen);
wrap(pExaScr, pScreen, GetImage, exaGetImage);