aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/xorg-xserver/xserver-kdrive/kdrive-vidmemarea.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/xorg-xserver/xserver-kdrive/kdrive-vidmemarea.patch')
-rw-r--r--recipes/xorg-xserver/xserver-kdrive/kdrive-vidmemarea.patch756
1 files changed, 756 insertions, 0 deletions
diff --git a/recipes/xorg-xserver/xserver-kdrive/kdrive-vidmemarea.patch b/recipes/xorg-xserver/xserver-kdrive/kdrive-vidmemarea.patch
new file mode 100644
index 0000000000..ed5b6f05cb
--- /dev/null
+++ b/recipes/xorg-xserver/xserver-kdrive/kdrive-vidmemarea.patch
@@ -0,0 +1,756 @@
+
+# Author : Manuel Teira <manuel.teira@telefonica.net> (sirfred in #oe)
+# Description: Support for multiple memory video zones in kdrive. Make offscreen
+# areas aware of the memory video zone it belongs to. Change the fbdev driver to
+# honour this new model.
+
+#
+# Patch managed by http://www.holgerschurig.de/patcher.html
+#
+
+--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.c~kdrive-vidmemarea
++++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.c
+@@ -908,9 +908,10 @@
+ ret = (*pScreen->CloseScreen) (index, pScreen);
+ else
+ ret = TRUE;
+-
+- if (screen->off_screen_base < screen->memory_size)
+- KdOffscreenFini (pScreen);
++
++ if (KdHasOffscreen(screen)) {
++ KdOffscreenFini(pScreen);
++ }
+
+ if (pScreenPriv->dpmsState != KD_DPMS_NORMAL)
+ (*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
+@@ -1219,8 +1220,9 @@
+ if (!(*card->cfuncs->initAccel) (pScreen))
+ screen->dumb = TRUE;
+
+- if (screen->off_screen_base < screen->memory_size)
+- KdOffscreenInit (pScreen);
++ if (KdHasOffscreen(screen)) {
++ KdOffscreenInit(pScreen);
++ }
+
+ #ifdef PSEUDO8
+ (void) p8Init (pScreen, PSEUDO8_USE_DEFAULT);
+--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.h~kdrive-vidmemarea
++++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.h
+@@ -63,6 +63,9 @@
+ #define KD_MAX_CARD_ADDRESS 8
+ #endif
+
++#define KD_VIDMEM_MINPRIO 0
++#define KD_VIDMEM_MAXPRIO 255
++
+ /*
+ * Configuration information per video card
+ */
+@@ -115,6 +118,13 @@
+
+ typedef void (*KdOffscreenSaveProc) (ScreenPtr pScreen, KdOffscreenArea *area);
+
++typedef struct _KdVideoMemArea {
++ CARD8 priority;
++ CARD8 *base;
++ CARD32 size;
++ CARD32 available_offset;
++} KdVideoMemArea;
++
+ typedef enum _KdOffscreenState {
+ KdOffscreenAvail,
+ KdOffscreenRemovable,
+@@ -127,7 +137,8 @@
+ int size;
+ int score;
+ pointer privData;
+-
++ KdVideoMemArea *vidmem;
++ int pool;
+ KdOffscreenSaveProc save;
+
+ KdOffscreenState state;
+@@ -138,6 +149,7 @@
+ #define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270)
+ #define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y)
+
++
+ typedef struct _KdScreenInfo {
+ struct _KdScreenInfo *next;
+ KdCardInfo *card;
+@@ -155,9 +167,8 @@
+ int mynum;
+ DDXPointRec origin;
+ KdFrameBuffer fb[KD_MAX_FB];
+- CARD8 *memory_base;
+- unsigned long memory_size;
+- unsigned long off_screen_base;
++ KdVideoMemArea **videomem_areas;
++ int num_videomem_areas;
+ } KdScreenInfo;
+
+ typedef struct _KdCardFuncs {
+@@ -187,7 +198,6 @@
+
+ void (*getColors) (ScreenPtr, int, int, xColorItem *);
+ void (*putColors) (ScreenPtr, int, int, xColorItem *);
+-
+ } KdCardFuncs;
+
+ #define KD_MAX_PSEUDO_DEPTH 8
+@@ -203,7 +213,8 @@
+
+ int dpmsState;
+
+- KdOffscreenArea *off_screen_areas;
++ KdOffscreenArea **offscreen_pools;
++ int num_offscreen_pools;
+
+ ColormapPtr pInstalledmap[KD_MAX_FB]; /* current colormap */
+ xColorItem systemPalette[KD_MAX_PSEUDO_SIZE];/* saved windows colors */
+@@ -881,6 +892,15 @@
+ KdOffscreenInit (ScreenPtr pScreen);
+
+ KdOffscreenArea *
++KdOffscreenAllocPrio (ScreenPtr pScreen, int size, int align,
++ Bool locked,
++ KdOffscreenSaveProc save,
++ pointer privData,
++ int minPriority,
++ int maxPriority,
++ Bool allowEviction);
++
++KdOffscreenArea *
+ KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
+ Bool locked,
+ KdOffscreenSaveProc save,
+--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kaa.c~kdrive-vidmemarea
++++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kaa.c
+@@ -160,7 +160,7 @@
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ pPixmap->devKind = pitch;
+- pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pScreenPriv->screen->memory_base + pKaaPixmap->area->offset);
++ pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pKaaPixmap->area->vidmem->base + pKaaPixmap->area->offset);
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ return TRUE;
+ }
+@@ -198,7 +198,7 @@
+
+ dst = pPixmap->devPrivate.ptr;
+ dst_pitch = pPixmap->devKind;
+-
++
+ bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+
+ kaaWaitSync (pPixmap->drawable.pScreen);
+@@ -336,10 +336,16 @@
+ {
+ ScreenPtr pScreen = p->drawable.pScreen;
+ KdScreenPriv(pScreen);
++ int index;
+
+- return ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
+- (CARD8 *) pScreenPriv->screen->memory_base) <
+- pScreenPriv->screen->memory_size);
++ for (index = 0; index < pScreenPriv->screen->num_videomem_areas; index++) {
++ KdVideoMemArea *vidmem = pScreenPriv->screen->videomem_areas[index];
++ if ((((CARD8 *)p->devPrivate.ptr) >= vidmem->base) &&
++ (((CARD8 *)p->devPrivate.ptr) <= (vidmem->base + vidmem->size))) {
++ return TRUE;
++ }
++ }
++ return FALSE;
+ }
+
+ PixmapPtr
+@@ -1060,6 +1066,7 @@
+ KdCheckPaintWindow (pWin, pRegion, what);
+ }
+
++
+ Bool
+ kaaDrawInit (ScreenPtr pScreen,
+ KaaScreenInfoPtr pScreenInfo)
+@@ -1109,7 +1116,7 @@
+ * Hookup offscreen pixmaps
+ */
+ if ((pKaaScr->info->flags & KAA_OFFSCREEN_PIXMAPS) &&
+- screen->off_screen_base < screen->memory_size)
++ KdHasOffscreen(screen))
+ {
+ if (!AllocatePixmapPrivate(pScreen, kaaPixmapPrivateIndex,
+ sizeof (KaaPixmapPrivRec)))
+--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/koffscreen.c~kdrive-vidmemarea
++++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/koffscreen.c
+@@ -41,16 +41,20 @@
+ {
+ KdScreenPriv (pScreen);
+ KdOffscreenArea *prev = 0, *area;
+-
+- assert (pScreenPriv->screen->off_screen_areas->area.offset == 0);
+- for (area = pScreenPriv->off_screen_areas; area; area = area->next)
+- {
+- if (prev)
+- assert (prev->offset + prev->size == area->offset);
++ int index;
++
++ for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
++ area = pScreenPriv->offscreen_pools[index];
++ assert (area->vidmem->available_offset - area.offset == 0);
++ while(area) {
++ if (prev)
++ assert (prev->offset + prev->size == area->offset);
+
+- prev = area;
++ prev = area;
++ area = area->next;
++ }
++ assert (prev->offset + prev->size == prev->vidmem->size);
+ }
+- assert (prev->offset + prev->size == pScreenPriv->screen->memory_size);
+ }
+ #else
+ #define KdOffscreenValidate(s)
+@@ -65,101 +69,133 @@
+ }
+
+ KdOffscreenArea *
+-KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
+- Bool locked,
+- KdOffscreenSaveProc save,
+- pointer privData)
++KdOffscreenAllocPrio (ScreenPtr pScreen, int size, int align,
++ Bool locked,
++ KdOffscreenSaveProc save,
++ pointer privData,
++ int minPriority,
++ int maxPriority,
++ Bool allowEviction)
+ {
+ KdOffscreenArea *area, *begin, *best;
+ KdScreenPriv (pScreen);
+ int tmp, real_size = 0, best_score;
++ int index;
++ Bool canFit = FALSE;
+
+- KdOffscreenValidate (pScreen);
+ if (!align)
+ align = 1;
+
+ if (!size)
+ {
+- DBG_OFFSCREEN (("Alloc 0x%x -> EMPTY\n", size));
++ DBG_OFFSCREEN(("Alloc 0x%x -> EMPTY\n", size));
+ return NULL;
+ }
+
+ /* throw out requests that cannot fit */
+- if (size > (pScreenPriv->screen->memory_size - pScreenPriv->screen->off_screen_base))
+- {
+- DBG_OFFSCREEN (("Alloc 0x%x -> TOBIG\n", size));
+- return NULL;
++ for (index = 0; index < pScreenPriv->screen->num_videomem_areas; index++) {
++ KdVideoMemArea *vidmem = pScreenPriv->screen->videomem_areas[index];
++ if ((vidmem->priority <= maxPriority) &&
++ (vidmem->priority >= minPriority)) {
++ if (size <= (vidmem->size - vidmem->available_offset)) {
++ canFit = TRUE;
++ break;
++ }
++ }
+ }
+-
+- /* Try to find a free space that'll fit. */
+- for (area = pScreenPriv->off_screen_areas; area; area = area->next)
++ if (!canFit)
+ {
+- /* skip allocated areas */
+- if (area->state != KdOffscreenAvail)
+- continue;
++ DBG_OFFSCREEN(("Alloc 0x%x -> TOOBIG\n", size));
++ return NULL;
++ }
+
+- /* adjust size to match alignment requirement */
+- real_size = size;
+- tmp = area->offset % align;
+- if (tmp)
+- real_size += (align - tmp);
+-
+- /* does it fit? */
+- if (real_size <= area->size)
+- break;
++ for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
++ /* Look just in the head, as all the areas of the pool have
++ the same vidmem */
++ area = pScreenPriv->offscreen_pools[index];
++ if ((area->vidmem->priority > maxPriority) ||
++ (area->vidmem->priority < minPriority))
++ continue;
++
++ /* Try to find a free space that'll fit. */
++ for (area = pScreenPriv->offscreen_pools[index]; area;
++ area = area->next) {
++ /* skip allocated areas */
++ if (area->state != KdOffscreenAvail)
++ continue;
++
++ /* adjust size to match alignment requirement */
++ real_size = size;
++ tmp = area->offset % align;
++ if (tmp)
++ real_size += (align - tmp);
++
++ /* does it fit? */
++ if (real_size <= area->size)
++ break;
++ }
++ if (area)
++ break;
+ }
+-
+- if (!area)
+- {
++
++ if (!area && allowEviction) {
+ /*
+ * Kick out existing users to make space.
+ *
+ * First, locate a region which can hold the desired object.
+ */
++ for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
++ if ((area->vidmem->priority > maxPriority) ||
++ (area->vidmem->priority < minPriority))
++ continue;
+
+- /* prev points at the first object to boot */
+- best = NULL;
+- best_score = MAXINT;
+- for (begin = pScreenPriv->off_screen_areas; begin != NULL;
+- begin = begin->next)
+- {
+- int avail, score;
+- KdOffscreenArea *scan;
++ /* prev points at the first object to boot */
++ best = NULL;
++ best_score = MAXINT;
+
+- if (begin->state == KdOffscreenLocked)
+- continue;
++ for (begin = pScreenPriv->offscreen_pools[index]; begin != NULL;
++ begin = begin->next) {
++ int avail, score;
++ KdOffscreenArea *scan;
+
+- /* adjust size to match alignment requirement */
+- real_size = size;
+- tmp = begin->offset % align;
+- if (tmp)
+- real_size += (align - tmp);
++ if (begin->state == KdOffscreenLocked)
++ continue;
++
++ /* adjust size to match alignment requirement */
++ real_size = size;
++ tmp = begin->offset % align;
++ if (tmp)
++ real_size += (align - tmp);
+
+- avail = 0;
+- score = 0;
+- /* now see if we can make room here, and how "costly" it'll be. */
+- for (scan = begin; scan != NULL; scan = scan->next)
+- {
+- if (scan->state == KdOffscreenLocked) {
+- /* Can't make room here, start after this locked area. */
+- begin = scan->next;
+- break;
+- }
+- /* Score should only be non-zero for KdOffscreenRemovable */
+- score += scan->score;
+- avail += scan->size;
+- if (avail >= real_size)
+- break;
+- }
+- /* Is it the best option we've found so far? */
+- if (avail >= real_size && score < best_score) {
+- best = begin;
+- best_score = score;
+- }
+- }
+- area = best;
+- if (!area)
+- {
++ avail = 0;
++ score = 0;
++ /* now see if we can make room here,
++ and how "costly" it'll be. */
++ for (scan = begin; scan != NULL; scan = scan->next) {
++ if (scan->state == KdOffscreenLocked) {
++ /* Can't make room here,
++ start after this locked area. */
++ begin = scan->next;
++ break;
++ }
++ /* Score should only be non-zero for KdOffscreenRemovable */
++ score += scan->score;
++ avail += scan->size;
++ if (avail >= real_size)
++ break;
++ }
++ /* Is it the best option we've found so far? */
++ if (avail >= real_size && score < best_score) {
++ best = begin;
++ best_score = score;
++ }
++ }
++ area = best;
++ if (area)
++ break;
++ }
++
++ if (!area) {
+ DBG_OFFSCREEN (("Alloc 0x%x -> NOSPACE\n", size));
+ /* Could not allocate memory */
+ KdOffscreenValidate (pScreen);
+@@ -180,16 +216,14 @@
+ /*
+ * Now get the system to merge the other needed areas together
+ */
+- while (area->size < real_size)
+- {
+- assert (area->next && area->next->state == KdOffscreenRemovable);
++ while (area->size < real_size) {
++ assert (area->next && area->next->state == KdOffscreenRemovable);
+ (void) KdOffscreenKickOut (pScreen, area->next);
+ }
+ }
+-
++
+ /* save extra space in new area */
+- if (real_size < area->size)
+- {
++ if (real_size < area->size) {
+ KdOffscreenArea *new_area = xalloc (sizeof (KdOffscreenArea));
+ if (!new_area)
+ return NULL;
+@@ -198,9 +232,14 @@
+ new_area->state = KdOffscreenAvail;
+ new_area->save = 0;
+ new_area->score = 0;
++ new_area->vidmem = area->vidmem;
++ new_area->pool = area->pool;
+ new_area->next = area->next;
+ area->next = new_area;
+ area->size = real_size;
++ DBG_OFFSCREEN (("New OffscreenArea at %p (offset:0x%08x, size:0x%08x, pool:%d\n", area, area->offset, area->size, area->pool));
++
++
+ }
+ /*
+ * Mark this area as in use
+@@ -212,42 +251,80 @@
+ area->privData = privData;
+ area->save = save;
+ area->score = 0;
+-
++
+ area->save_offset = area->offset;
+ {
+ int tmp = area->offset % align;
+ if (tmp)
+ area->offset += (align - tmp);
+ }
+-
++
+ KdOffscreenValidate (pScreen);
+
+ DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x\n", size, area->offset));
+ return area;
+ }
+
++Bool
++KdHasOffscreen(KdScreenInfo *screen)
++{
++ int index;
++ DBG_OFFSCREEN (("KdHasOffscreen\n"));
++
++ for (index = 0; index < screen->num_videomem_areas; index++) {
++ KdVideoMemArea *vidmem = screen->videomem_areas[index];
++ if (vidmem->available_offset < vidmem->size) {
++ return TRUE;
++ }
++ }
++ return FALSE;
++}
++
++KdOffscreenArea *
++KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
++ Bool locked,
++ KdOffscreenSaveProc save,
++ pointer privData)
++{
++ DBG_OFFSCREEN (("KdOffscreenAlloc(size:%d, align:%d, locked:%d)\n",
++ size, align, locked));
++ return KdOffscreenAllocPrio(pScreen, size, align,
++ locked,
++ save,
++ privData,
++ KD_VIDMEM_MINPRIO,
++ KD_VIDMEM_MAXPRIO,
++ TRUE);
++}
++
+ void
+ KdOffscreenSwapOut (ScreenPtr pScreen)
+ {
+ KdScreenPriv (pScreen);
++ int index;
++
++ DBG_OFFSCREEN (("KdOffscreenSwapOut\n"));
+
+ KdOffscreenValidate (pScreen);
+- /* loop until a single free area spans the space */
+- for (;;)
+- {
+- KdOffscreenArea *area = pScreenPriv->off_screen_areas;
++
++ for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
++ /* loop until a single free area spans the space */
++ for (;;)
++ {
++ KdOffscreenArea *area = pScreenPriv->offscreen_pools[index];
+
+- if (!area)
+- break;
+- if (area->state == KdOffscreenAvail)
+- {
+- area = area->next;
+- if (!area)
+- break;
+- }
+- assert (area->state != KdOffscreenAvail);
+- (void) KdOffscreenKickOut (pScreen, area);
+- KdOffscreenValidate (pScreen);
++ if (!area)
++ break;
++ if (area->state == KdOffscreenAvail)
++ {
++ area = area->next;
++ if (!area)
++ break;
++ }
++ assert (area->state != KdOffscreenAvail);
++ (void) KdOffscreenKickOut (pScreen, area);
++ KdOffscreenValidate (pScreen);
++ }
+ }
+ KdOffscreenValidate (pScreen);
+ KdOffscreenFini (pScreen);
+@@ -256,6 +333,8 @@
+ void
+ KdOffscreenSwapIn (ScreenPtr pScreen)
+ {
++ KdScreenPriv (pScreen);
++ DBG_OFFSCREEN (("KdOffscreenSwapIn\n"));
+ KdOffscreenInit (pScreen);
+ }
+
+@@ -264,7 +343,7 @@
+ KdOffscreenMerge (KdOffscreenArea *area)
+ {
+ KdOffscreenArea *next = area->next;
+-
++ //DBG_OFFSCREEN (("KdOffscreenMerge %p\n", area));
+ /* account for space */
+ area->size += next->size;
+ /* frob pointer */
+@@ -278,8 +357,9 @@
+ KdScreenPriv(pScreen);
+ KdOffscreenArea *next = area->next;
+ KdOffscreenArea *prev;
+-
+- DBG_OFFSCREEN (("Free 0x%x -> 0x%x\n", area->size, area->offset));
++
++ DBG_OFFSCREEN (("KdOffscreenFree 0x%x -> 0x%x\n",
++ area->size, area->offset));
+ KdOffscreenValidate (pScreen);
+
+ area->state = KdOffscreenAvail;
+@@ -290,10 +370,11 @@
+ /*
+ * Find previous area
+ */
+- if (area == pScreenPriv->off_screen_areas)
++ if (area == pScreenPriv->offscreen_pools[area->pool])
+ prev = 0;
+ else
+- for (prev = pScreenPriv->off_screen_areas; prev; prev = prev->next)
++ for (prev = pScreenPriv->offscreen_pools[area->pool];
++ prev; prev = prev->next)
+ if (prev->next == area)
+ break;
+
+@@ -317,21 +398,30 @@
+ {
+ KaaPixmapPriv (pPixmap);
+ KdScreenPriv (pPixmap->drawable.pScreen);
++ int index;
+ static int iter = 0;
+
++
+ if (!pKaaPixmap->area)
+ return;
+
++ /*
++ DBG_OFFSCREEN(("KdOffscreenMarkUsed(offset:0x%08x, pool:%d)\n",
++ pKaaPixmap->area->offset,
++ pKaaPixmap->area->pool));
++ */
+ /* The numbers here are arbitrary. We may want to tune these. */
+ pKaaPixmap->area->score += 100;
+ if (++iter == 10) {
+ KdOffscreenArea *area;
+- for (area = pScreenPriv->off_screen_areas; area != NULL;
+- area = area->next)
+- {
+- if (area->state == KdOffscreenRemovable)
+- area->score = (area->score * 7) / 8;
+- }
++ for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
++ for (area = pScreenPriv->offscreen_pools[index]; area != NULL;
++ area = area->next)
++ {
++ if (area->state == KdOffscreenRemovable)
++ area->score = (area->score * 7) / 8;
++ }
++ }
+ }
+ }
+
+@@ -340,23 +430,41 @@
+ {
+ KdScreenPriv (pScreen);
+ KdOffscreenArea *area;
++ KdVideoMemArea *vidmem;
++ int index, num_offscreen;
+
+- /* Allocate a big free area */
+- area = xalloc (sizeof (KdOffscreenArea));
++ DBG_OFFSCREEN (("KdOffscreenInit\n"));
++ num_offscreen = 0;
++ pScreenPriv->num_offscreen_pools = 0;
++ pScreenPriv->offscreen_pools = NULL;
+
+- if (!area)
+- return FALSE;
++ for (index = 0; index < pScreenPriv->screen->num_videomem_areas; index++) {
++ vidmem = pScreenPriv->screen->videomem_areas[index];
++ DBG_OFFSCREEN (("Searching vidmemarea base:0x%p, size:0x%08x, available_offset:0x%08x\n", vidmem->base, vidmem->size, vidmem->available_offset));
++ if (vidmem->available_offset < vidmem->size) {
++ pScreenPriv->offscreen_pools = xrealloc(pScreenPriv->offscreen_pools,
++ sizeof(KdOffscreenArea*) * (pScreenPriv->num_offscreen_pools + 1));
++ if (!pScreenPriv->offscreen_pools) {
++ return FALSE;
++ }
++ pScreenPriv->offscreen_pools[pScreenPriv->num_offscreen_pools] =
++ area = xcalloc(sizeof(KdOffscreenArea), 1);
++ if (!area)
++ return FALSE;
++
++ area->state = KdOffscreenAvail;
++ area->vidmem = vidmem;
++ area->offset = vidmem->available_offset;
++ area->size = vidmem->size - vidmem->available_offset;
++ area->save = 0;
++ area->pool = pScreenPriv->num_offscreen_pools;
++ area->next = NULL;
++ area->score = 0;
++ pScreenPriv->num_offscreen_pools++;
++ DBG_OFFSCREEN (("New OffscreenArea at %p (offset:0x%08x, size:0x%08x, pool:%d)\n", area, area->offset, area->size, area->pool));
++ }
++ }
+
+- area->state = KdOffscreenAvail;
+- area->offset = pScreenPriv->screen->off_screen_base;
+- area->size = pScreenPriv->screen->memory_size - area->offset;
+- area->save = 0;
+- area->next = NULL;
+- area->score = 0;
+-
+- /* Add it to the free areas */
+- pScreenPriv->off_screen_areas = area;
+-
+ KdOffscreenValidate (pScreen);
+
+ return TRUE;
+@@ -367,11 +475,17 @@
+ {
+ KdScreenPriv (pScreen);
+ KdOffscreenArea *area;
+-
+- /* just free all of the area records */
+- while ((area = pScreenPriv->off_screen_areas))
+- {
+- pScreenPriv->off_screen_areas = area->next;
+- xfree (area);
++ int index;
++
++ DBG_OFFSCREEN (("KdOffscreenFini\n"));
++ for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
++ /* just free all of the area records */
++ while ((area = pScreenPriv->offscreen_pools[index])) {
++ pScreenPriv->offscreen_pools[index] = area->next;
++ xfree (area);
++ }
+ }
++ xfree(pScreenPriv->offscreen_pools);
++ pScreenPriv->offscreen_pools = NULL;
++ pScreenPriv->num_offscreen_pools = 0;
+ }
+--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/fbdev/fbdev.c~kdrive-vidmemarea
++++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/fbdev/fbdev.c
+@@ -330,6 +330,7 @@
+ FbdevScrPriv *scrpriv = screen->driver;
+ KdMouseMatrix m;
+ FbdevPriv *priv = screen->card->driver;
++ KdVideoMemArea *vidmem;
+
+ if (scrpriv->randr != RR_Rotate_0)
+ scrpriv->shadow = TRUE;
+@@ -342,15 +343,20 @@
+
+ screen->width = priv->var.xres;
+ screen->height = priv->var.yres;
+- screen->memory_base = (CARD8 *) (priv->fb);
+- screen->memory_size = priv->fix.smem_len;
++ screen->videomem_areas = xcalloc(sizeof(KdVideoMemArea*), 1);
++ screen->videomem_areas[0] = vidmem = xcalloc(sizeof(KdVideoMemArea), 1);
++ screen->num_videomem_areas = 1;
++
++ vidmem->priority = KD_VIDMEM_MINPRIO;
++ vidmem->base = (CARD8 *) (priv->fb);
++ vidmem->size = priv->fix.smem_len;
+
+ if (scrpriv->shadow)
+ {
+ if (!KdShadowFbAlloc (screen, 0,
+ scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)))
+ return FALSE;
+- screen->off_screen_base = screen->memory_size;
++ vidmem->available_offset = vidmem->size;
+ }
+ else
+ {
+@@ -358,7 +364,7 @@
+ screen->fb[0].pixelStride = (priv->fix.line_length * 8 /
+ priv->var.bits_per_pixel);
+ screen->fb[0].frameBuffer = (CARD8 *) (priv->fb);
+- screen->off_screen_base = screen->fb[0].byteStride * screen->height;
++ vidmem->available_offset = screen->fb[0].byteStride * screen->height;
+ }
+
+ return TRUE;