From 47a9fab5e286c5224047690482a2cb36a3c17b88 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 13 Oct 2003 01:19:37 +0000 Subject: [PATCH] Add support for offscreen pixmaps. --- hw/kdrive/mga/mgadraw.c | 3 +- hw/kdrive/src/kaa.c | 188 ++++++++++++++++++++++++++++++++++++- hw/kdrive/src/kdrive.h | 2 + hw/kdrive/src/koffscreen.c | 2 - 4 files changed, 188 insertions(+), 7 deletions(-) diff --git a/hw/kdrive/mga/mgadraw.c b/hw/kdrive/mga/mgadraw.c index d080d0fa9..cb77334d7 100644 --- a/hw/kdrive/mga/mgadraw.c +++ b/hw/kdrive/mga/mgadraw.c @@ -239,7 +239,8 @@ KaaScreenInfoRec mgaKaa = { mgaDoneCopy, 192, /* Offscreen byte alignment */ - 64, /* Offset pitch */ + 64, /* Offset pitch */ + KAA_OFFSCREEN_PIXMAPS, /* Flags */ }; Bool diff --git a/hw/kdrive/src/kaa.c b/hw/kdrive/src/kaa.c index 49a2885bd..7de52589d 100644 --- a/hw/kdrive/src/kaa.c +++ b/hw/kdrive/src/kaa.c @@ -54,13 +54,17 @@ typedef struct { typedef struct { KdOffscreenArea *offscreenArea; - Bool swappedOut; } KaaPixmapPrivRec, *KaaPixmapPrivPtr; #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 KaaPixmapPitch(w) (((w) + (pKaaScr->info->offscreenPitch - 1)) & ~(pKaaScr->info->offscreenPitch - 1)) + #define KAA_SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ ((KaaScreenPrivPtr) (pScreen)->devPrivates[kaaScreenPrivateIndex].ptr)->field) @@ -69,6 +73,182 @@ typedef struct { #define MIN_OFFPIX_SIZE (320*200) +static void +kaaMoveOutPixmap (KdOffscreenArea *area) +{ + PixmapPtr pPixmap = area->privData; + int dst_pitch, src_pitch; + unsigned char *dst, *src; + int i; + + src_pitch = pPixmap->devKind; + dst_pitch = BitmapBytePad (pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel); + + src = pPixmap->devPrivate.ptr; + dst = xalloc (dst_pitch * pPixmap->drawable.height); + if (!dst) + FatalError("Out of memory\n"); + + 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 +kaaMoveInPixmap (KdOffscreenArea *area) +{ + 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)); + + src = pPixmap->devPrivate.ptr; + dst = pScreenPixmap->devPrivate.ptr + area->offset; + + 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 Bool +kaaDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + KaaPixmapPriv (pPixmap); + KaaScreenPriv (pScreen); + Bool ret; + + if (pPixmap->refcnt == 1) + { + if (pKaaPixmap->offscreenArea) + { + PixmapLink *link, *prev; + + /* 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); + } + } + + KAA_SCREEN_PROLOGUE (pScreen, DestroyPixmap); + ret = (*pScreen->DestroyPixmap) (pPixmap); + KAA_SCREEN_EPILOGUE (pScreen, DestroyPixmap, kaaDestroyPixmap); + + return ret; +} + +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; + + 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; + } + + return pPixmap; +} + void kaaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, @@ -689,18 +869,18 @@ kaaDrawInit (ScreenPtr pScreen, pScreen->PaintWindowBackground = kaaPaintWindow; pScreen->PaintWindowBorder = kaaPaintWindow; -#if 0 /* * Hookup offscreen pixmaps */ - if (screen->off_screen_size > 0) + if ((pKaaScr->info->flags & KAA_OFFSCREEN_PIXMAPS) && + screen->off_screen_size > 0) { pKaaScr->CreatePixmap = pScreen->CreatePixmap; pScreen->CreatePixmap = kaaCreatePixmap; pKaaScr->DestroyPixmap = pScreen->DestroyPixmap; pScreen->DestroyPixmap = kaaDestroyPixmap; } -#endif + return TRUE; } diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h index 30e852476..db0851ae5 100644 --- a/hw/kdrive/src/kdrive.h +++ b/hw/kdrive/src/kdrive.h @@ -301,8 +301,10 @@ typedef struct _KaaScreenInfo { int offscreenByteAlign; int offscreenPitch; + int flags; } KaaScreenInfoRec, *KaaScreenInfoPtr; +#define KAA_OFFSCREEN_PIXMAPS (1 << 0) /* * This is the only completely portable way to diff --git a/hw/kdrive/src/koffscreen.c b/hw/kdrive/src/koffscreen.c index 60023f6b9..a407fc4ee 100644 --- a/hw/kdrive/src/koffscreen.c +++ b/hw/kdrive/src/koffscreen.c @@ -121,8 +121,6 @@ KdOffscreenSwapOut (ScreenPtr pScreen) while (area) { - fprintf (stderr, "area is: %p\n", area); - if (area->area.screen && area->moveOut) (*area->moveOut) ((KdOffscreenArea *)area);