diff options
Diffstat (limited to 'exa/exa_offscreen.c')
-rw-r--r-- | exa/exa_offscreen.c | 692 |
1 files changed, 337 insertions, 355 deletions
diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c index 5abe3b891..5e1d1398e 100644 --- a/exa/exa_offscreen.c +++ b/exa/exa_offscreen.c @@ -40,49 +40,48 @@ #if DEBUG_OFFSCREEN static void -ExaOffscreenValidate (ScreenPtr pScreen) +ExaOffscreenValidate(ScreenPtr pScreen) { - ExaScreenPriv (pScreen); + ExaScreenPriv(pScreen); ExaOffscreenArea *prev = 0, *area; - assert (pExaScr->info->offScreenAreas->base_offset == - pExaScr->info->offScreenBase); - for (area = pExaScr->info->offScreenAreas; area; area = area->next) - { - assert (area->offset >= area->base_offset && - area->offset < (area->base_offset + area->size)); - if (prev) - assert (prev->base_offset + prev->size == area->base_offset); - prev = area; + assert(pExaScr->info->offScreenAreas->base_offset == + pExaScr->info->offScreenBase); + for (area = pExaScr->info->offScreenAreas; area; area = area->next) { + assert(area->offset >= area->base_offset && + area->offset < (area->base_offset + area->size)); + if (prev) + assert(prev->base_offset + prev->size == area->base_offset); + prev = area; } - assert (prev->base_offset + prev->size == pExaScr->info->memorySize); + assert(prev->base_offset + prev->size == pExaScr->info->memorySize); } #else #define ExaOffscreenValidate(s) #endif static ExaOffscreenArea * -ExaOffscreenKickOut (ScreenPtr pScreen, ExaOffscreenArea *area) +ExaOffscreenKickOut(ScreenPtr pScreen, ExaOffscreenArea * area) { if (area->save) - (*area->save) (pScreen, area); - return exaOffscreenFree (pScreen, area); + (*area->save) (pScreen, area); + return exaOffscreenFree(pScreen, area); } static void -exaUpdateEvictionCost(ExaOffscreenArea *area, unsigned offScreenCounter) +exaUpdateEvictionCost(ExaOffscreenArea * area, unsigned offScreenCounter) { unsigned age; if (area->state == ExaOffscreenAvail) - return; + return; age = offScreenCounter - area->last_use; /* This is unlikely to happen, but could result in a division by zero... */ if (age > (UINT_MAX / 2)) { - age = UINT_MAX / 2; - area->last_use = offScreenCounter - age; + age = UINT_MAX / 2; + area->last_use = offScreenCounter - age; } area->eviction_cost = area->size / age; @@ -101,42 +100,40 @@ exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align) cost = 0; best = 0; - while (end != NULL) - { - restart: - while (begin != NULL && begin->state == ExaOffscreenLocked) - begin = end = begin->next; - - if (begin == NULL) - break; - - /* adjust size needed to account for alignment loss for this area */ - real_size = size + (begin->base_offset + begin->size - size) % align; - - while (avail < real_size && end != NULL) - { - if (end->state == ExaOffscreenLocked) { - /* Can't more room here, restart after this locked area */ - avail = 0; - cost = 0; - begin = end; - goto restart; - } - avail += end->size; - exaUpdateEvictionCost(end, pExaScr->offScreenCounter); - cost += end->eviction_cost; - end = end->next; - } - - /* Check the cost, update best */ - if (avail >= real_size && cost < best_cost) { - best = begin; - best_cost = cost; - } - - avail -= begin->size; - cost -= begin->eviction_cost; - begin = begin->next; + while (end != NULL) { + restart: + while (begin != NULL && begin->state == ExaOffscreenLocked) + begin = end = begin->next; + + if (begin == NULL) + break; + + /* adjust size needed to account for alignment loss for this area */ + real_size = size + (begin->base_offset + begin->size - size) % align; + + while (avail < real_size && end != NULL) { + if (end->state == ExaOffscreenLocked) { + /* Can't more room here, restart after this locked area */ + avail = 0; + cost = 0; + begin = end; + goto restart; + } + avail += end->size; + exaUpdateEvictionCost(end, pExaScr->offScreenCounter); + cost += end->eviction_cost; + end = end->next; + } + + /* Check the cost, update best */ + if (avail >= real_size && cost < best_cost) { + best = begin; + best_cost = cost; + } + + avail -= begin->size; + cost -= begin->eviction_cost; + begin = begin->next; } return best; @@ -162,120 +159,117 @@ exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align) * still called. */ ExaOffscreenArea * -exaOffscreenAlloc (ScreenPtr pScreen, int size, int align, - Bool locked, - ExaOffscreenSaveProc save, - pointer privData) +exaOffscreenAlloc(ScreenPtr pScreen, int size, int align, + Bool locked, ExaOffscreenSaveProc save, pointer privData) { ExaOffscreenArea *area; - ExaScreenPriv (pScreen); + + ExaScreenPriv(pScreen); int real_size = 0, largest_avail = 0; + #if DEBUG_OFFSCREEN static int number = 0; - ErrorF("================= ============ allocating a new pixmap %d\n", ++number); + + ErrorF("================= ============ allocating a new pixmap %d\n", + ++number); #endif - ExaOffscreenValidate (pScreen); + ExaOffscreenValidate(pScreen); if (!align) - align = 1; + align = 1; - if (!size) - { - DBG_OFFSCREEN (("Alloc 0x%x -> EMPTY\n", size)); - return NULL; + if (!size) { + DBG_OFFSCREEN(("Alloc 0x%x -> EMPTY\n", size)); + return NULL; } /* throw out requests that cannot fit */ - if (size > (pExaScr->info->memorySize - pExaScr->info->offScreenBase)) - { - DBG_OFFSCREEN (("Alloc 0x%x vs (0x%lx) -> TOBIG\n", size, - pExaScr->info->memorySize - - pExaScr->info->offScreenBase)); - return NULL; + if (size > (pExaScr->info->memorySize - pExaScr->info->offScreenBase)) { + DBG_OFFSCREEN(("Alloc 0x%x vs (0x%lx) -> TOBIG\n", size, + pExaScr->info->memorySize - + pExaScr->info->offScreenBase)); + return NULL; } /* Try to find a free space that'll fit. */ - for (area = pExaScr->info->offScreenAreas; area; area = area->next) - { - /* skip allocated areas */ - if (area->state != ExaOffscreenAvail) - continue; + for (area = pExaScr->info->offScreenAreas; area; area = area->next) { + /* skip allocated areas */ + if (area->state != ExaOffscreenAvail) + continue; - /* adjust size to match alignment requirement */ - real_size = size + (area->base_offset + area->size - size) % align; + /* adjust size to match alignment requirement */ + real_size = size + (area->base_offset + area->size - size) % align; - /* does it fit? */ - if (real_size <= area->size) - break; + /* does it fit? */ + if (real_size <= area->size) + break; - if (area->size > largest_avail) - largest_avail = area->size; + if (area->size > largest_avail) + largest_avail = area->size; } - if (!area) - { - area = exaFindAreaToEvict(pExaScr, size, align); - - if (!area) - { - DBG_OFFSCREEN (("Alloc 0x%x -> NOSPACE\n", size)); - /* Could not allocate memory */ - ExaOffscreenValidate (pScreen); - return NULL; - } - - /* adjust size needed to account for alignment loss for this area */ - real_size = size + (area->base_offset + area->size - size) % align; - - /* - * Kick out first area if in use - */ - if (area->state != ExaOffscreenAvail) - area = ExaOffscreenKickOut (pScreen, area); - /* - * Now get the system to merge the other needed areas together - */ - while (area->size < real_size) - { - assert (area->next && area->next->state == ExaOffscreenRemovable); - (void) ExaOffscreenKickOut (pScreen, area->next); - } + if (!area) { + area = exaFindAreaToEvict(pExaScr, size, align); + + if (!area) { + DBG_OFFSCREEN(("Alloc 0x%x -> NOSPACE\n", size)); + /* Could not allocate memory */ + ExaOffscreenValidate(pScreen); + return NULL; + } + + /* adjust size needed to account for alignment loss for this area */ + real_size = size + (area->base_offset + area->size - size) % align; + + /* + * Kick out first area if in use + */ + if (area->state != ExaOffscreenAvail) + area = ExaOffscreenKickOut(pScreen, area); + /* + * Now get the system to merge the other needed areas together + */ + while (area->size < real_size) { + assert(area->next && area->next->state == ExaOffscreenRemovable); + (void) ExaOffscreenKickOut(pScreen, area->next); + } } /* save extra space in new area */ - if (real_size < area->size) - { - ExaOffscreenArea *new_area = malloc(sizeof (ExaOffscreenArea)); - if (!new_area) - return NULL; - new_area->base_offset = area->base_offset; - - new_area->offset = new_area->base_offset; - new_area->align = 0; - new_area->size = area->size - real_size; - new_area->state = ExaOffscreenAvail; - new_area->save = NULL; - new_area->last_use = 0; - new_area->eviction_cost = 0; - new_area->next = area; - new_area->prev = area->prev; - if (area->prev->next) - area->prev->next = new_area; - else - pExaScr->info->offScreenAreas = new_area; - area->prev = new_area; - area->base_offset = new_area->base_offset + new_area->size; - area->size = real_size; - } else - pExaScr->numOffscreenAvailable--; + if (real_size < area->size) { + ExaOffscreenArea *new_area = malloc(sizeof(ExaOffscreenArea)); + + if (!new_area) + return NULL; + new_area->base_offset = area->base_offset; + + new_area->offset = new_area->base_offset; + new_area->align = 0; + new_area->size = area->size - real_size; + new_area->state = ExaOffscreenAvail; + new_area->save = NULL; + new_area->last_use = 0; + new_area->eviction_cost = 0; + new_area->next = area; + new_area->prev = area->prev; + if (area->prev->next) + area->prev->next = new_area; + else + pExaScr->info->offScreenAreas = new_area; + area->prev = new_area; + area->base_offset = new_area->base_offset + new_area->size; + area->size = real_size; + } + else + pExaScr->numOffscreenAvailable--; /* * Mark this area as in use */ if (locked) - area->state = ExaOffscreenLocked; + area->state = ExaOffscreenLocked; else - area->state = ExaOffscreenRemovable; + area->state = ExaOffscreenRemovable; area->privData = privData; area->save = save; area->last_use = pExaScr->offScreenCounter++; @@ -283,10 +277,10 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align, area->offset -= area->offset % align; area->align = align; - ExaOffscreenValidate (pScreen); + ExaOffscreenValidate(pScreen); - DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x (0x%x)\n", size, - area->base_offset, area->offset)); + DBG_OFFSCREEN(("Alloc 0x%x -> 0x%x (0x%x)\n", size, + area->base_offset, area->offset)); return area; } @@ -294,65 +288,60 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align, * Ejects all offscreen areas, and uninitializes the offscreen memory manager. */ void -ExaOffscreenSwapOut (ScreenPtr pScreen) +ExaOffscreenSwapOut(ScreenPtr pScreen) { - ExaScreenPriv (pScreen); + ExaScreenPriv(pScreen); - ExaOffscreenValidate (pScreen); + ExaOffscreenValidate(pScreen); /* loop until a single free area spans the space */ - for (;;) - { - ExaOffscreenArea *area = pExaScr->info->offScreenAreas; - - if (!area) - break; - if (area->state == ExaOffscreenAvail) - { - area = area->next; - if (!area) - break; - } - assert (area->state != ExaOffscreenAvail); - (void) ExaOffscreenKickOut (pScreen, area); - ExaOffscreenValidate (pScreen); + for (;;) { + ExaOffscreenArea *area = pExaScr->info->offScreenAreas; + + if (!area) + break; + if (area->state == ExaOffscreenAvail) { + area = area->next; + if (!area) + break; + } + assert(area->state != ExaOffscreenAvail); + (void) ExaOffscreenKickOut(pScreen, area); + ExaOffscreenValidate(pScreen); } - ExaOffscreenValidate (pScreen); - ExaOffscreenFini (pScreen); + ExaOffscreenValidate(pScreen); + ExaOffscreenFini(pScreen); } /** Ejects all pixmaps managed by EXA. */ static void -ExaOffscreenEjectPixmaps (ScreenPtr pScreen) +ExaOffscreenEjectPixmaps(ScreenPtr pScreen) { - ExaScreenPriv (pScreen); + ExaScreenPriv(pScreen); - ExaOffscreenValidate (pScreen); + ExaOffscreenValidate(pScreen); /* loop until a single free area spans the space */ - for (;;) - { - ExaOffscreenArea *area; - - for (area = pExaScr->info->offScreenAreas; area != NULL; - area = area->next) - { - if (area->state == ExaOffscreenRemovable && - area->save == exaPixmapSave) - { - (void) ExaOffscreenKickOut (pScreen, area); - ExaOffscreenValidate (pScreen); - break; - } - } - if (area == NULL) - break; + for (;;) { + ExaOffscreenArea *area; + + for (area = pExaScr->info->offScreenAreas; area != NULL; + area = area->next) { + if (area->state == ExaOffscreenRemovable && + area->save == exaPixmapSave) { + (void) ExaOffscreenKickOut(pScreen, area); + ExaOffscreenValidate(pScreen); + break; + } + } + if (area == NULL) + break; } - ExaOffscreenValidate (pScreen); + ExaOffscreenValidate(pScreen); } void -ExaOffscreenSwapIn (ScreenPtr pScreen) +ExaOffscreenSwapIn(ScreenPtr pScreen) { - exaOffscreenInit (pScreen); + exaOffscreenInit(pScreen); } /** @@ -371,43 +360,44 @@ ExaOffscreenSwapIn (ScreenPtr pScreen) * swapped out. */ void -exaEnableDisableFBAccess (int index, Bool enable) +exaEnableDisableFBAccess(int index, Bool enable) { ScreenPtr pScreen = screenInfo.screens[index]; - ExaScreenPriv (pScreen); + + ExaScreenPriv(pScreen); if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) - return; + return; if (!enable && pExaScr->disableFbCount++ == 0) { - if (pExaScr->info->exa_minor < 1) - ExaOffscreenSwapOut (pScreen); - else - ExaOffscreenEjectPixmaps (pScreen); - pExaScr->swappedOut = TRUE; + if (pExaScr->info->exa_minor < 1) + ExaOffscreenSwapOut(pScreen); + else + ExaOffscreenEjectPixmaps(pScreen); + pExaScr->swappedOut = TRUE; } - + if (enable && --pExaScr->disableFbCount == 0) { - if (pExaScr->info->exa_minor < 1) - ExaOffscreenSwapIn (pScreen); - pExaScr->swappedOut = FALSE; + if (pExaScr->info->exa_minor < 1) + ExaOffscreenSwapIn(pScreen); + pExaScr->swappedOut = FALSE; } } /* merge the next free area into this one */ static void -ExaOffscreenMerge (ExaScreenPrivPtr pExaScr, ExaOffscreenArea *area) +ExaOffscreenMerge(ExaScreenPrivPtr pExaScr, ExaOffscreenArea * area) { - ExaOffscreenArea *next = area->next; + ExaOffscreenArea *next = area->next; /* account for space */ area->size += next->size; /* frob pointer */ area->next = next->next; if (area->next) - area->next->prev = area; + area->next->prev = area; else - pExaScr->info->offScreenAreas->prev = area; + pExaScr->info->offScreenAreas->prev = area; free(next); pExaScr->numOffscreenAvailable--; @@ -427,15 +417,15 @@ ExaOffscreenMerge (ExaScreenPrivPtr pExaScr, ExaOffscreenArea *area) * on. */ ExaOffscreenArea * -exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area) +exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea * area) { ExaScreenPriv(pScreen); - ExaOffscreenArea *next = area->next; - ExaOffscreenArea *prev; + ExaOffscreenArea *next = area->next; + ExaOffscreenArea *prev; - DBG_OFFSCREEN (("Free 0x%x -> 0x%x (0x%x)\n", area->size, - area->base_offset, area->offset)); - ExaOffscreenValidate (pScreen); + DBG_OFFSCREEN(("Free 0x%x -> 0x%x (0x%x)\n", area->size, + area->base_offset, area->offset)); + ExaOffscreenValidate(pScreen); area->state = ExaOffscreenAvail; area->save = NULL; @@ -445,36 +435,35 @@ exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area) * Find previous area */ if (area == pExaScr->info->offScreenAreas) - prev = NULL; + prev = NULL; else - prev = area->prev; + prev = area->prev; pExaScr->numOffscreenAvailable++; /* link with next area if free */ if (next && next->state == ExaOffscreenAvail) - ExaOffscreenMerge (pExaScr, area); + ExaOffscreenMerge(pExaScr, area); /* link with prev area if free */ - if (prev && prev->state == ExaOffscreenAvail) - { - area = prev; - ExaOffscreenMerge (pExaScr, area); + if (prev && prev->state == ExaOffscreenAvail) { + area = prev; + ExaOffscreenMerge(pExaScr, area); } - ExaOffscreenValidate (pScreen); + ExaOffscreenValidate(pScreen); DBG_OFFSCREEN(("\tdone freeing\n")); return area; } void -ExaOffscreenMarkUsed (PixmapPtr pPixmap) +ExaOffscreenMarkUsed(PixmapPtr pPixmap) { - ExaPixmapPriv (pPixmap); - ExaScreenPriv (pPixmap->drawable.pScreen); + ExaPixmapPriv(pPixmap); + ExaScreenPriv(pPixmap->drawable.pScreen); if (!pExaPixmap || !pExaPixmap->area) - return; + return; pExaPixmap->area->last_use = pExaScr->offScreenCounter++; } @@ -484,10 +473,10 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap) * leaving the total amount of memory available as a single area at the * beginning (when there are no pinned allocations). */ -_X_HIDDEN ExaOffscreenArea* -ExaOffscreenDefragment (ScreenPtr pScreen) +_X_HIDDEN ExaOffscreenArea * +ExaOffscreenDefragment(ScreenPtr pScreen) { - ExaScreenPriv (pScreen); + ExaScreenPriv(pScreen); ExaOffscreenArea *area, *largest_available = NULL; int largest_size = 0; PixmapPtr pDstPix; @@ -496,135 +485,129 @@ ExaOffscreenDefragment (ScreenPtr pScreen) pDstPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, 0, 0); if (!pDstPix) - return NULL; + return NULL; - pExaDstPix = ExaGetPixmapPriv (pDstPix); + pExaDstPix = ExaGetPixmapPriv(pDstPix); pExaDstPix->use_gpu_copy = TRUE; for (area = pExaScr->info->offScreenAreas->prev; - area != pExaScr->info->offScreenAreas; - ) - { - ExaOffscreenArea *prev = area->prev; - PixmapPtr pSrcPix; - ExaPixmapPrivPtr pExaSrcPix; - Bool save_use_gpu_copy; - int save_pitch; - - if (area->state != ExaOffscreenAvail || - prev->state == ExaOffscreenLocked || - (prev->state == ExaOffscreenRemovable && - prev->save != exaPixmapSave)) { - area = prev; - continue; - } - - if (prev->state == ExaOffscreenAvail) { - if (area == largest_available) { - largest_available = prev; - largest_size += prev->size; - } - area = prev; - ExaOffscreenMerge (pExaScr, area); - continue; - } - - if (area->size > largest_size) { - largest_available = area; - largest_size = area->size; - } - - pSrcPix = prev->privData; - pExaSrcPix = ExaGetPixmapPriv (pSrcPix); - - pExaDstPix->fb_ptr = pExaScr->info->memoryBase + - area->base_offset + area->size - prev->size + prev->base_offset - - prev->offset; - pExaDstPix->fb_ptr -= (unsigned long)pExaDstPix->fb_ptr % prev->align; - - if (pExaDstPix->fb_ptr <= pExaSrcPix->fb_ptr) { - area = prev; - continue; - } - - if (!(pExaScr->info->flags & EXA_SUPPORTS_OFFSCREEN_OVERLAPS) && - (pExaSrcPix->fb_ptr + prev->size) > pExaDstPix->fb_ptr) { - area = prev; - continue; - } - - save_use_gpu_copy = pExaSrcPix->use_gpu_copy; - save_pitch = pSrcPix->devKind; - - pExaSrcPix->use_gpu_copy = TRUE; - pSrcPix->devKind = pExaSrcPix->fb_pitch; - - pDstPix->drawable.width = pSrcPix->drawable.width; - pDstPix->devKind = pSrcPix->devKind; - pDstPix->drawable.height = pSrcPix->drawable.height; - pDstPix->drawable.depth = pSrcPix->drawable.depth; - pDstPix->drawable.bitsPerPixel = pSrcPix->drawable.bitsPerPixel; - - if (!pExaScr->info->PrepareCopy (pSrcPix, pDstPix, -1, -1, GXcopy, ~0)) { - pExaSrcPix->use_gpu_copy = save_use_gpu_copy; - pSrcPix->devKind = save_pitch; - area = prev; - continue; - } - - pExaScr->info->Copy (pDstPix, 0, 0, 0, 0, pDstPix->drawable.width, - pDstPix->drawable.height); - pExaScr->info->DoneCopy (pDstPix); - exaMarkSync (pScreen); - - DBG_OFFSCREEN(("Before swap: prev=0x%08x-0x%08x-0x%08x area=0x%08x-0x%08x-0x%08x\n", - prev->base_offset, prev->offset, prev->base_offset + prev->size, - area->base_offset, area->offset, area->base_offset + area->size)); - - /* Calculate swapped area offsets and sizes */ - area->base_offset = prev->base_offset; - area->offset = area->base_offset; - prev->offset += pExaDstPix->fb_ptr - pExaSrcPix->fb_ptr; - assert(prev->offset >= pExaScr->info->offScreenBase && - prev->offset < pExaScr->info->memorySize); - prev->base_offset = prev->offset; - if (area->next) - prev->size = area->next->base_offset - prev->base_offset; - else - prev->size = pExaScr->info->memorySize - prev->base_offset; - area->size = prev->base_offset - area->base_offset; - - DBG_OFFSCREEN(("After swap: area=0x%08x-0x%08x-0x%08x prev=0x%08x-0x%08x-0x%08x\n", - area->base_offset, area->offset, area->base_offset + area->size, - prev->base_offset, prev->offset, prev->base_offset + prev->size)); - - /* Swap areas in list */ - if (area->next) - area->next->prev = prev; - else - pExaScr->info->offScreenAreas->prev = prev; - if (prev->prev->next) - prev->prev->next = area; - else - pExaScr->info->offScreenAreas = area; - prev->next = area->next; - area->next = prev; - area->prev = prev->prev; - prev->prev = area; - if (!area->prev->next) - pExaScr->info->offScreenAreas = area; + area != pExaScr->info->offScreenAreas;) { + ExaOffscreenArea *prev = area->prev; + PixmapPtr pSrcPix; + ExaPixmapPrivPtr pExaSrcPix; + Bool save_use_gpu_copy; + int save_pitch; + + if (area->state != ExaOffscreenAvail || + prev->state == ExaOffscreenLocked || + (prev->state == ExaOffscreenRemovable && + prev->save != exaPixmapSave)) { + area = prev; + continue; + } + + if (prev->state == ExaOffscreenAvail) { + if (area == largest_available) { + largest_available = prev; + largest_size += prev->size; + } + area = prev; + ExaOffscreenMerge(pExaScr, area); + continue; + } + + if (area->size > largest_size) { + largest_available = area; + largest_size = area->size; + } + + pSrcPix = prev->privData; + pExaSrcPix = ExaGetPixmapPriv(pSrcPix); + + pExaDstPix->fb_ptr = pExaScr->info->memoryBase + + area->base_offset + area->size - prev->size + prev->base_offset - + prev->offset; + pExaDstPix->fb_ptr -= (unsigned long) pExaDstPix->fb_ptr % prev->align; + + if (pExaDstPix->fb_ptr <= pExaSrcPix->fb_ptr) { + area = prev; + continue; + } + + if (!(pExaScr->info->flags & EXA_SUPPORTS_OFFSCREEN_OVERLAPS) && + (pExaSrcPix->fb_ptr + prev->size) > pExaDstPix->fb_ptr) { + area = prev; + continue; + } + + save_use_gpu_copy = pExaSrcPix->use_gpu_copy; + save_pitch = pSrcPix->devKind; + + pExaSrcPix->use_gpu_copy = TRUE; + pSrcPix->devKind = pExaSrcPix->fb_pitch; + + pDstPix->drawable.width = pSrcPix->drawable.width; + pDstPix->devKind = pSrcPix->devKind; + pDstPix->drawable.height = pSrcPix->drawable.height; + pDstPix->drawable.depth = pSrcPix->drawable.depth; + pDstPix->drawable.bitsPerPixel = pSrcPix->drawable.bitsPerPixel; + + if (!pExaScr->info->PrepareCopy(pSrcPix, pDstPix, -1, -1, GXcopy, ~0)) { + pExaSrcPix->use_gpu_copy = save_use_gpu_copy; + pSrcPix->devKind = save_pitch; + area = prev; + continue; + } + + pExaScr->info->Copy(pDstPix, 0, 0, 0, 0, pDstPix->drawable.width, + pDstPix->drawable.height); + pExaScr->info->DoneCopy(pDstPix); + exaMarkSync(pScreen); + + DBG_OFFSCREEN(("Before swap: prev=0x%08x-0x%08x-0x%08x area=0x%08x-0x%08x-0x%08x\n", prev->base_offset, prev->offset, prev->base_offset + prev->size, area->base_offset, area->offset, area->base_offset + area->size)); + + /* Calculate swapped area offsets and sizes */ + area->base_offset = prev->base_offset; + area->offset = area->base_offset; + prev->offset += pExaDstPix->fb_ptr - pExaSrcPix->fb_ptr; + assert(prev->offset >= pExaScr->info->offScreenBase && + prev->offset < pExaScr->info->memorySize); + prev->base_offset = prev->offset; + if (area->next) + prev->size = area->next->base_offset - prev->base_offset; + else + prev->size = pExaScr->info->memorySize - prev->base_offset; + area->size = prev->base_offset - area->base_offset; + + DBG_OFFSCREEN(("After swap: area=0x%08x-0x%08x-0x%08x prev=0x%08x-0x%08x-0x%08x\n", area->base_offset, area->offset, area->base_offset + area->size, prev->base_offset, prev->offset, prev->base_offset + prev->size)); + + /* Swap areas in list */ + if (area->next) + area->next->prev = prev; + else + pExaScr->info->offScreenAreas->prev = prev; + if (prev->prev->next) + prev->prev->next = area; + else + pExaScr->info->offScreenAreas = area; + prev->next = area->next; + area->next = prev; + area->prev = prev->prev; + prev->prev = area; + if (!area->prev->next) + pExaScr->info->offScreenAreas = area; #if DEBUG_OFFSCREEN - if (prev->prev == prev || prev->next == prev) - ErrorF("Whoops, prev points to itself!\n"); + if (prev->prev == prev || prev->next == prev) + ErrorF("Whoops, prev points to itself!\n"); - if (area->prev == area || area->next == area) - ErrorF("Whoops, area points to itself!\n"); + if (area->prev == area || area->next == area) + ErrorF("Whoops, area points to itself!\n"); #endif - pExaSrcPix->fb_ptr = pExaDstPix->fb_ptr; - pExaSrcPix->use_gpu_copy = save_use_gpu_copy; - pSrcPix->devKind = save_pitch; + pExaSrcPix->fb_ptr = pExaDstPix->fb_ptr; + pExaSrcPix->use_gpu_copy = save_use_gpu_copy; + pSrcPix->devKind = save_pitch; } pDstPix->drawable.width = 0; @@ -635,7 +618,7 @@ ExaOffscreenDefragment (ScreenPtr pScreen) (*pScreen->DestroyPixmap) (pDstPix); if (area->state == ExaOffscreenAvail && area->size > largest_size) - return area; + return area; return largest_available; } @@ -649,16 +632,16 @@ ExaOffscreenDefragment (ScreenPtr pScreen) * the screen, if any offscreen memory is available. */ Bool -exaOffscreenInit (ScreenPtr pScreen) +exaOffscreenInit(ScreenPtr pScreen) { - ExaScreenPriv (pScreen); + ExaScreenPriv(pScreen); ExaOffscreenArea *area; /* Allocate a big free area */ - area = malloc(sizeof (ExaOffscreenArea)); + area = malloc(sizeof(ExaOffscreenArea)); if (!area) - return FALSE; + return FALSE; area->state = ExaOffscreenAvail; area->base_offset = pExaScr->info->offScreenBase; @@ -676,21 +659,20 @@ exaOffscreenInit (ScreenPtr pScreen) pExaScr->offScreenCounter = 1; pExaScr->numOffscreenAvailable = 1; - ExaOffscreenValidate (pScreen); + ExaOffscreenValidate(pScreen); return TRUE; } void -ExaOffscreenFini (ScreenPtr pScreen) +ExaOffscreenFini(ScreenPtr pScreen) { - ExaScreenPriv (pScreen); + ExaScreenPriv(pScreen); ExaOffscreenArea *area; /* just free all of the area records */ - while ((area = pExaScr->info->offScreenAreas)) - { - pExaScr->info->offScreenAreas = area->next; - free(area); + while ((area = pExaScr->info->offScreenAreas)) { + pExaScr->info->offScreenAreas = area->next; + free(area); } } |