# Author : Manuel Teira (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;