Use same assumptions as layergc about what layer kind is approprate for

unwrapping pixmap operations. This makes sure the accelerated code gets
    invoked for pixmaps
Add pixmap migration support to kaa. Can't quite automatically migrate
    pixmaps off-screen, but soon we will. Can kick objects out of video
    memory. Move per-screen linked list pointers to pixmap private. Wrap
    Composite in preparation for migrating pixmaps. Have kasync ignore
    drawable type so that pixmaps trigger sync Add KdOffscreenFini to
    cleanup on server reset. Switch off screen area to have only a 'save'
    function; moving objects to off screen memory is done by saving then
    freeing the area.
This commit is contained in:
Keith Packard 2003-10-14 21:10:53 +00:00
parent 109b949516
commit cb46169759
5 changed files with 447 additions and 239 deletions

View File

@ -31,43 +31,50 @@
#include "fontstruct.h"
#include "dixfontstr.h"
#define DEBUG_MIGRATE 0
#if DEBUG_MIGRATE
#define DBG_MIGRATE(a) ErrorF a
#else
#define DBG_MIGRATE(a)
#endif
int kaaGeneration;
int kaaScreenPrivateIndex;
int kaaPixmapPrivateIndex;
typedef struct _PixmapLink {
PixmapPtr pPixmap;
struct _PixmapLink *next;
} PixmapLink;
typedef struct {
KaaScreenInfoPtr info;
int offscreenSize;
int offscreenBase;
PixmapLink *offscreenPixmaps;
CreatePixmapProcPtr CreatePixmap;
DestroyPixmapProcPtr DestroyPixmap;
int pixelOffset; /* offset from pPixmap to pixels */
} KaaScreenPrivRec, *KaaScreenPrivPtr;
typedef struct {
KdOffscreenArea *offscreenArea;
KdOffscreenArea *area;
int score;
int devKind;
DevUnion devPrivate;
} KaaPixmapPrivRec, *KaaPixmapPrivPtr;
#define KAA_PIXMAP_SCORE_MOVE_IN 10
#define KAA_PIXMAP_SCORE_MAX 20
#define KAA_PIXMAP_SCORE_MOVE_OUT -10
#define KAA_PIXMAP_SCORE_MIN -20
#define KaaGetScreenPriv(s) ((KaaScreenPrivPtr)(s)->devPrivates[kaaScreenPrivateIndex].ptr)
#define KaaScreenPriv(s) KaaScreenPrivPtr pKaaScr = KaaGetScreenPriv(s)
#define KaaGetPixmapPriv(p) ((KaaPixmapPrivPtr)(p)->devPrivates[kaaPixmapPrivateIndex].ptr)
#define KaaPixmapPriv(p) KaaPixmapPrivPtr pKaaPixmap = KaaGetPixmapPriv (p)
#define KaaSetPixmapPriv(p,a) ((p)->devPrivates[kaaPixmapPrivateIndex].ptr = (pointer) (a))
#define KaaPixmapPriv(p) KaaPixmapPrivPtr pKaaPixmap = KaaGetPixmapPriv(p)
#define KaaPixmapPitch(w) (((w) + (pKaaScr->info->offscreenPitch - 1)) & ~(pKaaScr->info->offscreenPitch - 1))
#define KaaDrawableIsOffscreenPixmap(d) (d->type == DRAWABLE_PIXMAP && \
KaaGetPixmapPriv ((PixmapPtr)(d)) != NULL && \
KaaGetPixmapPriv ((PixmapPtr)(d))->offscreenArea != NULL && \
!KaaGetPixmapPriv ((PixmapPtr)(d))->offscreenArea->swappedOut)
KaaGetPixmapPriv((PixmapPtr)(d)) && \
KaaGetPixmapPriv((PixmapPtr)(d))->area)
#define KaaDrawableIsScreen(d) (((d)->type == DRAWABLE_WINDOW) || \
KaaDrawableIsOffscreenPixmap(d))
#define KAA_SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
((KaaScreenPrivPtr) (pScreen)->devPrivates[kaaScreenPrivateIndex].ptr)->field)
@ -75,62 +82,162 @@ typedef struct {
#define KAA_SCREEN_EPILOGUE(pScreen, field, wrapper)\
((pScreen)->field = wrapper)
#define MIN_OFFPIX_SIZE (320*200)
#define MIN_OFFPIX_SIZE (4096)
static void
kaaMoveOutPixmap (KdOffscreenArea *area)
kaaPixmapSave (KdOffscreenArea *area)
{
PixmapPtr pPixmap = area->privData;
int dst_pitch, src_pitch;
KaaPixmapPriv(pPixmap);
int dst_pitch, src_pitch, bytes;
unsigned char *dst, *src;
int i;
DBG_MIGRATE (("Save 0x%08x (0x%x) (%dx%d)\n",
pPixmap->drawable.id,
KaaGetPixmapPriv(pPixmap)->area ?
KaaGetPixmapPriv(pPixmap)->area->offset : -1,
pPixmap->drawable.width,
pPixmap->drawable.height));
KdCheckSync (pPixmap->drawable.pScreen);
src_pitch = pPixmap->devKind;
dst_pitch = BitmapBytePad (pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel);
dst_pitch = pKaaPixmap->devKind;
src = pPixmap->devPrivate.ptr;
dst = xalloc (dst_pitch * pPixmap->drawable.height);
if (!dst)
FatalError("Out of memory\n");
dst = pKaaPixmap->devPrivate.ptr;
pPixmap->devKind = dst_pitch;
pPixmap->devPrivate.ptr = dst;
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
pKaaPixmap->area = NULL;
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
i = pPixmap->drawable.height;
while (i--) {
memcpy (dst, src, dst_pitch);
memcpy (dst, src, bytes);
dst += dst_pitch;
src += src_pitch;
}
}
static Bool
kaaPixmapAllocArea (PixmapPtr pPixmap)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
KaaScreenPriv (pScreen);
KaaPixmapPriv (pPixmap);
int bpp = pPixmap->drawable.bitsPerPixel;
CARD16 h = pPixmap->drawable.height;
CARD16 w = pPixmap->drawable.width;
int pitch = KaaPixmapPitch (w);
PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen);
pKaaPixmap->devKind = pPixmap->devKind;
pKaaPixmap->devPrivate = pPixmap->devPrivate;
pKaaPixmap->area = KdOffscreenAlloc (pScreen, pitch * h * (bpp >> 3),
pKaaScr->info->offscreenByteAlign,
FALSE,
kaaPixmapSave, (pointer) pPixmap);
if (!pKaaPixmap->area)
return FALSE;
DBG_MIGRATE(("++ 0x%08x (0x%x) (%dx%d)\n",
pPixmap->drawable.id,
KaaGetPixmapPriv(pPixmap)->area ?
KaaGetPixmapPriv(pPixmap)->area->offset : -1,
pPixmap->drawable.width,
pPixmap->drawable.height));
pPixmap->devKind = pitch * (bpp >> 3);
pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pScreenPixmap->devPrivate.ptr + pKaaPixmap->area->offset);
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
return TRUE;
}
static void
kaaMoveInPixmap (PixmapPtr pPixmap)
{
int dst_pitch, src_pitch, bytes;
unsigned char *dst, *src;
int i;
return;
KdCheckSync (pPixmap->drawable.pScreen);
DBG_MIGRATE (("-> 0x%08x (0x%x) (%dx%d)\n",
pPixmap->drawable.id,
KaaGetPixmapPriv(pPixmap)->area ?
KaaGetPixmapPriv(pPixmap)->area->offset : -1,
pPixmap->drawable.width,
pPixmap->drawable.height));
src = pPixmap->devPrivate.ptr;
src_pitch = pPixmap->devKind;
if (!kaaPixmapAllocArea (pPixmap))
return;
dst = pPixmap->devPrivate.ptr;
dst_pitch = pPixmap->devKind;
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
i = pPixmap->drawable.height;
while (i--) {
memcpy (dst, src, bytes);
dst += dst_pitch;
src += src_pitch;
}
}
static void
kaaMoveInPixmap (KdOffscreenArea *area)
kaaMoveOutPixmap (PixmapPtr pPixmap)
{
PixmapPtr pPixmap = area->privData;
ScreenPtr pScreen = pPixmap->drawable.pScreen;
KaaScreenPriv (pScreen);
PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
int dst_pitch, src_pitch;
unsigned char *dst, *src;
int i;
src_pitch = pPixmap->devKind;
dst_pitch = BitmapBytePad (KaaPixmapPitch (pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel));
KaaPixmapPriv (pPixmap);
KdOffscreenArea *area = pKaaPixmap->area;
src = pPixmap->devPrivate.ptr;
dst = pScreenPixmap->devPrivate.ptr + area->offset;
DBG_MIGRATE (("<- 0x%08x (0x%x) (%dx%d)\n",
pPixmap->drawable.id,
KaaGetPixmapPriv(pPixmap)->area ?
KaaGetPixmapPriv(pPixmap)->area->offset : -1,
pPixmap->drawable.width,
pPixmap->drawable.height));
if (area)
{
kaaPixmapSave (area);
KdOffscreenFree (area);
}
}
pPixmap->devKind = dst_pitch;
pPixmap->devPrivate.ptr = dst;
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
i = pPixmap->drawable.height;
while (i--) {
memcpy (dst, src, dst_pitch);
dst += dst_pitch;
src += src_pitch;
static void
kaaPixmapUseScreen (PixmapPtr pPixmap)
{
KaaPixmapPriv (pPixmap);
if (pKaaPixmap->score < KAA_PIXMAP_SCORE_MAX)
{
pKaaPixmap->score++;
DBG_MIGRATE (("UseScreen 0x%x (%d)\n", pPixmap->drawable.id, pKaaPixmap->score));
if (!pKaaPixmap->area &&
pKaaPixmap->score >= KAA_PIXMAP_SCORE_MOVE_IN)
kaaMoveInPixmap (pPixmap);
}
}
static void
kaaPixmapUseMemory (PixmapPtr pPixmap)
{
KaaPixmapPriv (pPixmap);
if (pKaaPixmap->score > KAA_PIXMAP_SCORE_MIN)
{
pKaaPixmap->score--;
DBG_MIGRATE (("UseMemory 0x%x (%d)\n", pPixmap->drawable.id, pKaaPixmap->score));
if (pKaaPixmap->area &&
pKaaPixmap->score <= KAA_PIXMAP_SCORE_MOVE_OUT)
kaaMoveOutPixmap (pPixmap);
}
}
@ -138,39 +245,23 @@ static Bool
kaaDestroyPixmap (PixmapPtr pPixmap)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
KaaPixmapPriv (pPixmap);
KaaScreenPriv (pScreen);
Bool ret;
if (pPixmap->refcnt == 1)
{
if (pKaaPixmap->offscreenArea)
KaaPixmapPriv (pPixmap);
if (pKaaPixmap->area)
{
PixmapLink *link, *prev;
DBG_MIGRATE(("-- 0x%08x (0x%x) (%dx%d)\n",
pPixmap->drawable.id,
KaaGetPixmapPriv(pPixmap)->area->offset,
pPixmap->drawable.width,
pPixmap->drawable.height));
/* Free the offscreen area */
KdOffscreenFree (pKaaPixmap->offscreenArea);
if (pKaaPixmap->offscreenArea->swappedOut)
{
xfree (pPixmap->devPrivate.ptr);
pPixmap->devPrivate.ptr = NULL;
}
link = pKaaScr->offscreenPixmaps;
prev = NULL;
while (link->pPixmap != pPixmap)
{
prev = link;
link = link->next;
}
if (prev)
prev->next = link->next;
else
pKaaScr->offscreenPixmaps = link->next;
xfree (link);
KdCheckSync (pScreen);
KdOffscreenFree (pKaaPixmap->area);
pPixmap->devPrivate = pKaaPixmap->devPrivate;
pPixmap->devKind = pKaaPixmap->devKind;
}
}
@ -184,72 +275,21 @@ kaaDestroyPixmap (PixmapPtr pPixmap)
static PixmapPtr
kaaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
{
KaaScreenPriv (pScreen);
int size = w * h;
int pitch;
int bpp;
PixmapPtr pPixmap = NULL;
KaaPixmapPrivPtr pKaaPixmap;
KaaPixmapPrivPtr pKaaPixmap;
if (kdEnabled &&
size > MIN_OFFPIX_SIZE)
{
KdOffscreenArea *area;
PixmapLink *link;
PixmapPtr pScreenPixmap;
bpp = BitsPerPixel (depth);
pitch = KaaPixmapPitch (w);
area = KdOffscreenAlloc (pScreen, pitch * h * (bpp >> 3), pKaaScr->info->offscreenByteAlign,
FALSE, kaaMoveInPixmap, kaaMoveOutPixmap, NULL);
if (!area)
goto oom;
link = xalloc (sizeof (PixmapLink));
if (!link)
{
KdOffscreenFree (area);
goto oom;
}
KAA_SCREEN_PROLOGUE (pScreen, CreatePixmap);
pPixmap = (* pScreen->CreatePixmap) (pScreen, 0, 0, depth);
KAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, kaaCreatePixmap);
pKaaPixmap = (KaaPixmapPrivPtr)pPixmap->devPrivates[kaaPixmapPrivateIndex].ptr;
pKaaPixmap->offscreenArea = area;
pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen);
pPixmap->drawable.width = w;
pPixmap->drawable.height = h;
pPixmap->drawable.bitsPerPixel = bpp;
pPixmap->devKind = pitch * (bpp >> 3);
pPixmap->devPrivate.ptr = pScreenPixmap->devPrivate.ptr + area->offset;
link->pPixmap = pPixmap;
link->next = pKaaScr->offscreenPixmaps;
area->privData = pPixmap;
pKaaScr->offscreenPixmaps = link;
return pPixmap;
}
oom:
KAA_SCREEN_PROLOGUE (pScreen, CreatePixmap);
pPixmap = (* pScreen->CreatePixmap) (pScreen, w, h, depth);
KAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, kaaCreatePixmap);
if (pPixmap)
{
pKaaPixmap = (KaaPixmapPrivPtr)pPixmap->devPrivates[kaaPixmapPrivateIndex].ptr;
pKaaPixmap->offscreenArea = NULL;
}
if (!pPixmap)
return NULL;
pKaaPixmap = KaaGetPixmapPriv(pPixmap);
pKaaPixmap->score = 0;
pKaaPixmap->area = NULL;
/* if ((pPixmap->devKind * h >= MIN_OFFPIX_SIZE) */
if (w * h > 100 * 100)
kaaPixmapAllocArea (pPixmap);
return pPixmap;
}
@ -374,6 +414,14 @@ kaaCopyNtoN (DrawablePtr pSrcDrawable,
KaaScreenPriv (pDstDrawable->pScreen);
PixmapPtr pSrcPixmap, pDstPixmap;
/* Migrate pixmaps to same place as destination */
if (pScreenPriv->enabled && pSrcDrawable->type == DRAWABLE_PIXMAP) {
if (KaaDrawableIsScreen (pDstDrawable))
kaaPixmapUseScreen ((PixmapPtr) pSrcDrawable);
else
kaaPixmapUseMemory ((PixmapPtr) pSrcDrawable);
}
if (pScreenPriv->enabled &&
(pSrcPixmap = kaaGetDrawingPixmap (pSrcDrawable, NULL, NULL)) &&
(pDstPixmap = kaaGetDrawingPixmap (pDstDrawable, NULL, NULL)) &&
@ -731,8 +779,7 @@ kaaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
{
fbValidateGC (pGC, changes, pDrawable);
if (pDrawable->type == DRAWABLE_WINDOW ||
KaaDrawableIsOffscreenPixmap (pDrawable))
if (KaaDrawableIsScreen (pDrawable))
pGC->ops = (GCOps *) &kaaOps;
else
pGC->ops = (GCOps *) &kdAsyncPixmapGCOps;
@ -850,12 +897,44 @@ kaaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
KdCheckPaintWindow (pWin, pRegion, what);
}
#ifdef RENDER
static void
kaaComposite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
#if 0
if (pSrc->pDrawable->type == DRAWABLE_PIXMAP)
kaaPixmapUseMemory ((PixmapPtr) pSrc->pDrawable);
if (pMask && pMask->pDrawable->type == DRAWABLE_PIXMAP)
kaaPixmapUseMemory ((PixmapPtr) pMask->pDrawable);
if (pDst->pDrawable->type == DRAWABLE_PIXMAP)
kaaPixmapUseMemory ((PixmapPtr) pDst->pDrawable);
#endif
KdCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc,
xMask, yMask, xDst, yDst, width, height);
}
#endif
Bool
kaaDrawInit (ScreenPtr pScreen,
KaaScreenInfoPtr pScreenInfo)
{
KaaScreenPrivPtr pKaaScr;
KdScreenInfo *screen = KdGetScreenPriv (pScreen)->screen;
#ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
#endif
if (kaaGeneration != serverGeneration)
{
@ -870,7 +949,6 @@ kaaDrawInit (ScreenPtr pScreen,
return FALSE;
pKaaScr->info = pScreenInfo;
pKaaScr->offscreenPixmaps = NULL;
pScreen->devPrivates[kaaScreenPrivateIndex].ptr = (pointer) pKaaScr;
@ -885,6 +963,10 @@ kaaDrawInit (ScreenPtr pScreen,
pScreen->CopyWindow = kaaCopyWindow;
pScreen->PaintWindowBackground = kaaPaintWindow;
pScreen->PaintWindowBorder = kaaPaintWindow;
#ifdef RENDER
if (ps)
ps->Composite = kaaComposite;
#endif
/*
* Hookup offscreen pixmaps
@ -892,13 +974,13 @@ kaaDrawInit (ScreenPtr pScreen,
if ((pKaaScr->info->flags & KAA_OFFSCREEN_PIXMAPS) &&
screen->off_screen_size > 0)
{
if (!AllocatePixmapPrivate(pScreen, kaaPixmapPrivateIndex, sizeof(KaaPixmapPrivRec)))
return FALSE;
pKaaScr->CreatePixmap = pScreen->CreatePixmap;
pScreen->CreatePixmap = kaaCreatePixmap;
pKaaScr->DestroyPixmap = pScreen->DestroyPixmap;
pScreen->DestroyPixmap = kaaDestroyPixmap;
if (!AllocatePixmapPrivate(pScreen, kaaPixmapPrivateIndex,
sizeof (KaaPixmapPrivRec)))
return FALSE;
}
else
{

View File

@ -63,8 +63,7 @@ RegionPtr
KdCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty)
{
if (pSrc->type == DRAWABLE_WINDOW || pDst->type == DRAWABLE_WINDOW)
KdCheckSync (pSrc->pScreen);
KdCheckSync (pSrc->pScreen);
return fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
}
@ -73,8 +72,7 @@ KdCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty,
unsigned long bitPlane)
{
if (pSrc->type == DRAWABLE_WINDOW || pDst->type == DRAWABLE_WINDOW)
KdCheckSync (pSrc->pScreen);
KdCheckSync (pSrc->pScreen);
return fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
bitPlane);
}
@ -199,8 +197,7 @@ KdCheckGetSpans (DrawablePtr pDrawable,
int nspans,
char *pdstStart)
{
if (pDrawable->type != DRAWABLE_PIXMAP)
KdCheckSync(pDrawable->pScreen);
KdCheckSync(pDrawable->pScreen);
fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
}
@ -308,3 +305,11 @@ const GCOps kdAsyncPixmapGCOps = {
,NULL
#endif
};
void
KdAssertSync (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdCardInfo *card = pScreenPriv->card;
assert (!card->needSync);
}

View File

@ -844,6 +844,9 @@ KdCloseScreen (int index, ScreenPtr pScreen)
pScreen->CloseScreen = pScreenPriv->CloseScreen;
ret = (*pScreen->CloseScreen) (index, pScreen);
if (screen->off_screen_size > 0)
KdOffscreenFini (pScreen);
if (pScreenPriv->dpmsState != KD_DPMS_NORMAL)
(*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);

View File

@ -267,7 +267,6 @@ typedef struct _KdOffscreenArea {
int offset;
int size;
pointer privData;
Bool swappedOut;
} KdOffscreenArea;
extern const KdMonitorTiming kdMonitorTimings[];
@ -753,6 +752,22 @@ KdRandRGetTiming (ScreenPtr pScreen,
void
KdPictureInitAsync (ScreenPtr pScreen);
#ifdef RENDER
void
KdCheckComposite (CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
#endif
/* kshadow.c */
Bool
KdShadowScreenInit (KdScreenInfo *screen);
@ -771,7 +786,7 @@ int
KdFrameBufferSize (CARD8 *base, int max);
/* koffscreen.c */
typedef void (*KdOffscreenMoveDataProc) (KdOffscreenArea *area);
typedef void (*KdOffscreenSaveProc) (KdOffscreenArea *area);
Bool
KdOffscreenInit (ScreenPtr pScreen);
@ -779,8 +794,7 @@ KdOffscreenInit (ScreenPtr pScreen);
KdOffscreenArea *
KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
Bool locked,
KdOffscreenMoveDataProc moveIn,
KdOffscreenMoveDataProc moveOut,
KdOffscreenSaveProc save,
pointer privData);
void
@ -792,6 +806,9 @@ KdOffscreenSwapOut (ScreenPtr pScreen);
void
KdOffscreenSwapIn (ScreenPtr pScreen);
void
KdOffscreenFini (ScreenPtr pScreen);
/* function prototypes to be implemented by the drivers */
void
InitCard (char *name);

View File

@ -28,91 +28,171 @@
#endif
#include "kdrive.h"
#define DEBUG_OFFSCREEN 0
#if DEBUG_OFFSCREEN
#define DBG_OFFSCREEN(a) ErrorF a
#else
#define DBG_OFFSCREEN(a)
#endif
typedef struct _RealOffscreenArea {
KdOffscreenArea area;
KdOffscreenMoveDataProc moveIn;
KdOffscreenMoveDataProc moveOut;
KdOffscreenSaveProc save;
Bool locked;
struct _RealOffscreenArea *next;
struct _RealOffscreenArea *prev;
struct _RealOffscreenArea *next;
} RealOffscreenArea;
#if DEBUG_OFFSCREEN
static void
KdOffscreenValidate (ScreenPtr pScreen)
{
KdScreenPriv (pScreen);
RealOffscreenArea *prev = 0, *area;
assert (pScreenPriv->screen->off_screen_areas->area.offset == 0);
for (area = pScreenPriv->screen->off_screen_areas; area; area = area->next)
{
if (prev)
assert (prev->area.offset + prev->area.size == area->area.offset);
prev = area;
}
assert (prev->area.offset + prev->area.size == pScreenPriv->screen->off_screen_size);
}
#else
#define KdOffscreenValidate(s)
#endif
static void
KdOffscreenKickOut (KdOffscreenArea *area)
{
RealOffscreenArea *real_area = (RealOffscreenArea *) area;
KdCheckSync (area->screen);
if (real_area->save)
(*real_area->save) (area);
KdOffscreenFree (area);
}
KdOffscreenArea *
KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
Bool locked,
KdOffscreenMoveDataProc moveIn,
KdOffscreenMoveDataProc moveOut,
KdOffscreenSaveProc save,
pointer privData)
{
RealOffscreenArea *area;
RealOffscreenArea *area, **prev;
KdScreenPriv (pScreen);
int tmp, real_size;
KdOffscreenValidate (pScreen);
if (!align)
align = 1;
/* Go through the areas */
area = pScreenPriv->screen->off_screen_areas;
while (area != NULL)
if (!size)
{
if (area->area.screen != NULL)
{
area = area->next;
DBG_OFFSCREEN (("Alloc 0x%x -> EMPTY\n", size));
return NULL;
}
/* throw out requests that cannot fit */
if (size > pScreenPriv->screen->off_screen_size)
{
DBG_OFFSCREEN (("Alloc 0x%x -> TOBIG\n", size));
return NULL;
}
retry:
/* Go through the areas */
for (area = pScreenPriv->screen->off_screen_areas; area; area = area->next)
{
/* skip allocated areas */
if (area->area.screen)
continue;
}
/* adjust size to match alignment requirement */
real_size = size;
tmp = (area->area.offset + area->area.size - size) % align;
tmp = area->area.offset % align;
if (tmp)
real_size += (align - tmp);
/* does it fit? */
if (real_size <= area->area.size)
{
RealOffscreenArea *new_area;
if (real_size == area->area.size)
/* save extra space in new area */
if (real_size < area->area.size)
{
area->area.screen = pScreen;
area->area.privData = privData;
area->area.swappedOut = FALSE;
area->locked = locked;
area->moveIn = moveIn;
area->moveOut = moveOut;
return (KdOffscreenArea *)area;
new_area = xalloc (sizeof (RealOffscreenArea));
if (!new_area)
return NULL;
new_area->area.offset = area->area.offset + real_size;
new_area->area.size = area->area.size - real_size;
new_area->area.screen = 0;
new_area->locked = FALSE;
new_area->save = 0;
if ((new_area->next = area->next))
new_area->next->prev = new_area;
new_area->prev = area;
area->next = new_area;
area->area.size = real_size;
}
area->area.screen = pScreen;
area->area.privData = privData;
area->locked = locked;
area->save = save;
KdOffscreenValidate (pScreen);
/* Create a new area */
new_area = xalloc (sizeof (RealOffscreenArea));
new_area->area.offset = area->area.offset + area->area.size - real_size;
new_area->area.size = real_size;
new_area->area.screen = pScreen;
new_area->area.swappedOut = FALSE;
new_area->locked = locked;
new_area->moveIn = moveIn;
new_area->moveOut = moveOut;
area->area.size -= real_size;
new_area->prev = area;
new_area->next = area->next;
if (area->next)
area->next->prev = new_area;
area->next = new_area;
return (KdOffscreenArea *)new_area;
DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x\n", size, area->area.offset));
return &area->area;
}
area = area->next;
}
/*
* Kick out existing users. This is pretty simplistic; it just
* keeps deleting areas until the first area is free and has enough room
*/
prev = (RealOffscreenArea **) &pScreenPriv->screen->off_screen_areas;
while ((area = *prev))
{
if (area->area.screen && !area->locked)
{
KdOffscreenKickOut (&area->area);
continue;
}
/* adjust size to match alignment requirement */
real_size = size;
tmp = area->area.offset % align;
if (tmp)
real_size += (align - tmp);
/* does it fit? */
if (real_size <= area->area.size)
goto retry;
/* kick out the next area */
area = area->next;
if (!area)
break;
/* skip over locked areas */
if (area->locked)
{
prev = &area->next;
continue;
}
assert (area->area.screen);
KdOffscreenKickOut (&area->area);
}
DBG_OFFSCREEN (("Alloc 0x%x -> NOSPACE\n", size));
/* Could not allocate memory */
KdOffscreenValidate (pScreen);
return NULL;
}
@ -120,68 +200,73 @@ void
KdOffscreenSwapOut (ScreenPtr pScreen)
{
KdScreenPriv (pScreen);
RealOffscreenArea *area = pScreenPriv->screen->off_screen_areas;
while (area)
KdOffscreenValidate (pScreen);
/* loop until a single free area spans the space */
for (;;)
{
if (area->area.screen && area->moveOut)
(*area->moveOut) ((KdOffscreenArea *)area);
area->area.swappedOut = TRUE;
RealOffscreenArea *area = pScreenPriv->screen->off_screen_areas;
if (!area)
break;
if (area->area.screen)
{
KdOffscreenKickOut (&area->area);
continue;
}
area = area->next;
if (!area)
break;
assert (area->area.screen);
KdOffscreenKickOut (&area->area);
KdOffscreenValidate (pScreen);
}
KdOffscreenValidate (pScreen);
}
void
KdOffscreenSwapIn (ScreenPtr pScreen)
{
KdScreenPriv (pScreen);
RealOffscreenArea *area = pScreenPriv->screen->off_screen_areas;
/* nothing to do here; page in on usage */
}
while (area)
{
if (area->area.screen && area->moveIn)
(*area->moveIn) ((KdOffscreenArea *)area);
/* merge the next free area into this one */
static void
KdOffscreenMerge (KdOffscreenArea *area)
{
RealOffscreenArea *real_area = (RealOffscreenArea *) area;
RealOffscreenArea *next = real_area->next;
area->area.swappedOut = FALSE;
area = area->next;
}
/* account for space */
real_area->area.size += next->area.size;
/* frob pointers */
if ((real_area->next = next->next))
real_area->next->prev = real_area;
xfree (next);
}
void
KdOffscreenFree (KdOffscreenArea *area)
{
RealOffscreenArea *real_area = (RealOffscreenArea *)area;
ScreenPtr pScreen = area->screen;
RealOffscreenArea *real_area = (RealOffscreenArea *) area;
RealOffscreenArea *next = real_area->next;
RealOffscreenArea *prev = real_area->prev;
real_area->area.screen = NULL;
DBG_OFFSCREEN (("Free 0x%x -> 0x%x\n", area->size, area->offset));
KdOffscreenValidate (pScreen);
if (real_area && real_area->next && !real_area->next->area.screen)
{
RealOffscreenArea *tmp;
real_area->next->prev = real_area->prev;
if (real_area->prev)
real_area->prev->next = real_area->next;
area->screen = NULL;
real_area->next->area.size += real_area->area.size;
real_area->next->area.offset = real_area->area.offset;
tmp = real_area->next;
xfree (real_area);
real_area = tmp;
}
/* link with next area if free */
if (next && !next->area.screen)
KdOffscreenMerge (&real_area->area);
if (real_area->prev && !real_area->prev->area.screen)
{
real_area->prev->next = real_area->next;
if (real_area->next)
real_area->next->prev = real_area->prev;
real_area->prev->area.size += real_area->area.size;
xfree (real_area);
}
/* link with prev area if free */
if (prev && !prev->area.screen)
KdOffscreenMerge (&prev->area);
KdOffscreenValidate (pScreen);
}
Bool
@ -199,13 +284,29 @@ KdOffscreenInit (ScreenPtr pScreen)
area->area.screen = NULL;
area->area.offset = pScreenPriv->screen->off_screen_base;
area->area.size = pScreenPriv->screen->off_screen_size;
area->area.swappedOut = FALSE;
area->save = 0;
area->locked = FALSE;
area->next = NULL;
area->prev = NULL;
/* Add it to the free areas */
pScreenPriv->screen->off_screen_areas = area;
KdOffscreenValidate (pScreen);
return TRUE;
}
void
KdOffscreenFini (ScreenPtr pScreen)
{
KdScreenPriv (pScreen);
RealOffscreenArea *area;
/* just free all of the area records */
while ((area = pScreenPriv->screen->off_screen_areas))
{
pScreenPriv->screen->off_screen_areas = area->next;
xfree (area);
}
}