diff options
author | Dave Airlie <airlied@redhat.com> | 2011-11-22 16:04:42 +0000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-01-11 09:42:52 +0000 |
commit | 8178d23142d039674e5d6dc59b21e107b1ac1340 (patch) | |
tree | 4f2ea8b868ea7b82e8451da0563bc289c6bb3195 /drv | |
parent | 92aaa6d28aa056b16a3bf8a2c000e075504aecf3 (diff) |
add drvcopy
Diffstat (limited to 'drv')
-rw-r--r-- | drv/Makefile.am | 3 | ||||
-rw-r--r-- | drv/drv_screenint.h | 30 | ||||
-rw-r--r-- | drv/drvcopy.c | 268 | ||||
-rw-r--r-- | drv/fb/drvfb.h | 12 | ||||
-rw-r--r-- | drv/fb/fbcopy.c | 21 | ||||
-rw-r--r-- | drv/fb/fbgc.c | 2 |
6 files changed, 334 insertions, 2 deletions
diff --git a/drv/Makefile.am b/drv/Makefile.am index 3e8d0c67a..7c4475ef5 100644 --- a/drv/Makefile.am +++ b/drv/Makefile.am @@ -38,4 +38,5 @@ libdrv_la_SOURCES = \ impedgc.c \ impedpict.c \ impedplug.c \ - impedrandr.c + impedrandr.c\ + drvcopy.c diff --git a/drv/drv_screenint.h b/drv/drv_screenint.h index 99e0ffa77..a257ce21b 100644 --- a/drv/drv_screenint.h +++ b/drv/drv_screenint.h @@ -2,6 +2,7 @@ #define DRV_SCREENINT_H #include "drv_types.h" +#include "pixmap.h" DrvScreenPtr DrvScreenAllocate(void); extern _X_EXPORT Bool @@ -9,4 +10,33 @@ drvScreenInit(DrvScreenPtr pDrvScreen); void drvSetScreenPixmap(DrvScreenPtr pDrvScreen, DrvPixmapPtr drvPixmap); + +extern _X_EXPORT void +DrvPixmapSetGPUPixmap(PixmapPtr parent, DrvPixmapPtr new); + + +extern _X_EXPORT void +drvCopyRegion (DrvPixmapPtr pSrcPixmap, + DrvPixmapPtr pDstPixmap, + DrvGCPtr pGC, + RegionPtr pDstRegion, + int dx, + int dy, + drvCopyProc copyProc, + Pixel bitPlane, + void *closure); + +extern _X_EXPORT RegionPtr +drvDoCopy (DrvPixmapPtr pSrcPixmap, + DrvPixmapPtr pDstPixmap, + DrvGCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut, + drvCopyProc copyProc, + Pixel bitPlane, + void *closure); #endif diff --git a/drv/drvcopy.c b/drv/drvcopy.c new file mode 100644 index 000000000..8460ea36f --- /dev/null +++ b/drv/drvcopy.c @@ -0,0 +1,268 @@ + +/* + * Copyright © 1998 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "drv_screenint.h" +#include "drv_pixmapstr.h" +#include "drv_gcstruct.h" + +void +drvCopyRegion (DrvPixmapPtr pSrcPixmap, + DrvPixmapPtr pDstPixmap, + DrvGCPtr pGC, + RegionPtr pDstRegion, + int dx, + int dy, + drvCopyProc copyProc, + Pixel bitPlane, + void *closure) +{ + int careful; + Bool reverse; + Bool upsidedown; + BoxPtr pbox; + int nbox; + BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp; + + pbox = RegionRects(pDstRegion); + nbox = RegionNumRects(pDstRegion); + + careful = (pSrcPixmap == pDstPixmap); + + pboxNew1 = NULL; + pboxNew2 = NULL; + if (careful && dy < 0) + { + upsidedown = TRUE; + + if (nbox > 1) + { + /* keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); + if(!pboxNew1) + return; + pboxBase = pboxNext = pbox+nbox-1; + while (pboxBase >= pbox) + { + while ((pboxNext >= pbox) && + (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext+1; + while (pboxTmp <= pboxBase) + { + *pboxNew1++ = *pboxTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + } + } + else + { + /* walk source top to bottom */ + upsidedown = FALSE; + } + + if (careful && dx < 0) + { + /* walk source right to left */ + if (dy <= 0) + reverse = TRUE; + else + reverse = FALSE; + + if (nbox > 1) + { + /* reverse order of rects in each band */ + pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); + if(!pboxNew2) + { + free(pboxNew1); + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox+nbox) + { + while ((pboxNext < pbox+nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + while (pboxTmp != pboxBase) + { + *pboxNew2++ = *--pboxTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + } + } + else + { + /* walk source left to right */ + reverse = FALSE; + } + + (*copyProc) (pSrcPixmap, + pDstPixmap, + pGC, + pbox, + nbox, + dx, dy, + reverse, upsidedown, bitPlane, closure); + + free(pboxNew1); + free(pboxNew2); +} + + +RegionPtr +drvDoCopy (DrvPixmapPtr pSrcPixmap, + DrvPixmapPtr pDstPixmap, + DrvGCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut, + drvCopyProc copyProc, + Pixel bitPlane, + void *closure) +{ + RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ + Bool freeSrcClip = FALSE; + RegionPtr prgnExposed = NULL; + RegionRec rgnDst; + int dx; + int dy; + int numRects; + int box_x1; + int box_y1; + int box_x2; + int box_y2; + Bool fastSrc = FALSE; /* for fast clipping with pixmap source */ + Bool fastDst = FALSE; /* for fast clipping with one rect dest */ + Bool fastExpose = FALSE; /* for fast exposures with pixmap source */ + + if ((pSrcPixmap == pDstPixmap) && (pGC->clientClipType == CT_NONE)) + prgnSrcClip = pGC->pCompositeClip;//GetCompositeClip(pGC); + else + fastSrc = TRUE; + + box_x1 = xIn; + box_y1 = yIn; + box_x2 = xIn + widthSrc; + box_y2 = yIn + heightSrc; + + dx = xIn - xOut; + dy = yIn - yOut; + + /* Don't create a source region if we are doing a fast clip */ + if (fastSrc) + { + RegionPtr cclip; + + fastExpose = TRUE; + /* + * clip the source; if regions extend beyond the source size, + * make sure exposure events get sent + */ + if (box_x2 > (int) pSrcPixmap->width) + { + box_x2 = (int) pSrcPixmap->width; + fastExpose = FALSE; + } + if (box_y2 > (int) pSrcPixmap->height) + { + box_y2 = (int) pSrcPixmap->height; + fastExpose = FALSE; + } + + /* Translate and clip the dst to the destination composite clip */ + box_x1 -= dx; + box_x2 -= dx; + box_y1 -= dy; + box_y2 -= dy; + + /* If the destination composite clip is one rectangle we can + do the clip directly. Otherwise we have to create a full + blown region and call intersect */ + + cclip = pGC->pCompositeClip;//miGetCompositeClip(pGC); + if (RegionNumRects(cclip) == 1) + { + BoxPtr pBox = RegionRects(cclip); + + if (box_x1 < pBox->x1) box_x1 = pBox->x1; + if (box_x2 > pBox->x2) box_x2 = pBox->x2; + if (box_y1 < pBox->y1) box_y1 = pBox->y1; + if (box_y2 > pBox->y2) box_y2 = pBox->y2; + fastDst = TRUE; + } + } + + /* Check to see if the region is empty */ + if (box_x1 >= box_x2 || box_y1 >= box_y2) + { + RegionNull(&rgnDst); + } + else + { + BoxRec box; + box.x1 = box_x1; + box.y1 = box_y1; + box.x2 = box_x2; + box.y2 = box_y2; + RegionInit(&rgnDst, &box, 1); + } + + /* Clip against complex source if needed */ + if (!fastSrc) + { + RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip); + RegionTranslate(&rgnDst, -dx, -dy); + } + + /* Clip against complex dest if needed */ + if (!fastDst) + { + RegionIntersect(&rgnDst, &rgnDst, + pGC->pCompositeClip);// miGetCompositeClip(pGC)); + } + + /* Do bit blitting */ + numRects = RegionNumRects(&rgnDst); + if (numRects && widthSrc && heightSrc) + drvCopyRegion (pSrcPixmap, pDstPixmap, pGC, + &rgnDst, dx, dy, copyProc, bitPlane, closure); + + RegionUninit(&rgnDst); + if (freeSrcClip) + RegionDestroy(prgnSrcClip); + return prgnExposed; +} diff --git a/drv/fb/drvfb.h b/drv/fb/drvfb.h index 1c4e0718d..05347f858 100644 --- a/drv/fb/drvfb.h +++ b/drv/fb/drvfb.h @@ -1271,6 +1271,18 @@ drvCopyProc fbGetCopyPlaneFunction(DrvPixmapPtr pSrc, DrvPixmapPtr pDst, int bitplane); + +RegionPtr +drvfbCopyArea(DrvPixmapPtr pSrc, + DrvPixmapPtr pDst, + DrvGCPtr pGC, + int srcx, + int srcy, + int w, + int h, + int dstx, + int dsty); + /* * fbfill.c */ diff --git a/drv/fb/fbcopy.c b/drv/fb/fbcopy.c index d4484d989..10b72f435 100644 --- a/drv/fb/fbcopy.c +++ b/drv/fb/fbcopy.c @@ -310,3 +310,24 @@ fbGetCopyPlaneFunction(DrvPixmapPtr pSrc, else return NULL; } + +RegionPtr +drvfbCopyArea(DrvPixmapPtr pSrc, + DrvPixmapPtr pDst, + DrvGCPtr pGC, + int srcx, + int srcy, + int w, + int h, + int dstx, + int dsty) +{ + drvCopyProc copy; + + if (pSrc->bitsPerPixel != pDst->bitsPerPixel) + copy = drvfb24_32CopyMtoN; + else + copy = drvfbCopyNtoN; + return drvDoCopy (pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, copy, 0, 0); +} diff --git a/drv/fb/fbgc.c b/drv/fb/fbgc.c index 4b88bb4bd..5c352d691 100644 --- a/drv/fb/fbgc.c +++ b/drv/fb/fbgc.c @@ -34,7 +34,7 @@ const DrvGCOps drvfbGCOps = { drvfbFillSpans, drvfbSetSpans, drvfbPutImage, - NULL, + drvfbCopyArea, NULL, drvfbPolyPoint, drvfbPolyLine, |