123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- /*
- *
- * 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 <stdlib.h>
- #include "fb.h"
- void
- fbCopyNtoN(DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
- {
- CARD8 alu = pGC ? pGC->alu : GXcopy;
- FbBits pm = pGC ? fbGetGCPrivate(pGC)->pm : FB_ALLONES;
- FbBits *src;
- FbStride srcStride;
- int srcBpp;
- int srcXoff, srcYoff;
- FbBits *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
- fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- while (nbox--) {
- fbBlt(src + (pbox->y1 + dy + srcYoff) * srcStride,
- srcStride,
- (pbox->x1 + dx + srcXoff) * srcBpp,
- dst + (pbox->y1 + dstYoff) * dstStride,
- dstStride,
- (pbox->x1 + dstXoff) * dstBpp,
- (pbox->x2 - pbox->x1) * dstBpp,
- (pbox->y2 - pbox->y1), alu, pm, dstBpp, reverse, upsidedown);
- pbox++;
- }
- }
- void
- fbCopy1toN(DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
- {
- FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
- FbBits *src;
- FbStride srcStride;
- int srcBpp;
- int srcXoff, srcYoff;
- FbBits *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
- fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- while (nbox--) {
- if (dstBpp == 1) {
- fbBlt(src + (pbox->y1 + dy + srcYoff) * srcStride,
- srcStride,
- (pbox->x1 + dx + srcXoff) * srcBpp,
- dst + (pbox->y1 + dstYoff) * dstStride,
- dstStride,
- (pbox->x1 + dstXoff) * dstBpp,
- (pbox->x2 - pbox->x1) * dstBpp,
- (pbox->y2 - pbox->y1),
- FbOpaqueStipple1Rop(pGC->alu,
- pGC->fgPixel, pGC->bgPixel),
- pPriv->pm, dstBpp, reverse, upsidedown);
- }
- else {
- fbBltOne((FbStip *) (src + (pbox->y1 + dy + srcYoff) * srcStride),
- srcStride * (FB_UNIT / FB_STIP_UNIT),
- (pbox->x1 + dx + srcXoff),
- dst + (pbox->y1 + dstYoff) * dstStride,
- dstStride,
- (pbox->x1 + dstXoff) * dstBpp,
- dstBpp,
- (pbox->x2 - pbox->x1) * dstBpp,
- (pbox->y2 - pbox->y1),
- pPriv->and, pPriv->xor, pPriv->bgand, pPriv->bgxor);
- }
- pbox++;
- }
- }
- void
- fbCopyNto1(DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
- {
- FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
- while (nbox--) {
- if (pDstDrawable->bitsPerPixel == 1) {
- FbBits *src;
- FbStride srcStride;
- int srcBpp;
- int srcXoff, srcYoff;
- FbStip *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff,
- srcYoff);
- fbGetStipDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff,
- dstYoff);
- fbBltPlane(src + (pbox->y1 + dy + srcYoff) * srcStride, srcStride,
- (pbox->x1 + dx + srcXoff) * srcBpp, srcBpp,
- dst + (pbox->y1 + dstYoff) * dstStride, dstStride,
- (pbox->x1 + dstXoff) * dstBpp,
- (pbox->x2 - pbox->x1) * srcBpp, (pbox->y2 - pbox->y1),
- (FbStip) pPriv->and, (FbStip) pPriv->xor,
- (FbStip) pPriv->bgand, (FbStip) pPriv->bgxor, bitplane);
- }
- else {
- FbBits *src;
- FbStride srcStride;
- int srcBpp;
- int srcXoff, srcYoff;
- FbBits *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- FbStip *tmp;
- FbStride tmpStride;
- int width, height;
- width = pbox->x2 - pbox->x1;
- height = pbox->y2 - pbox->y1;
- tmpStride = ((width + FB_STIP_MASK) >> FB_STIP_SHIFT);
- tmp = malloc(tmpStride * height * sizeof(FbStip));
- if (!tmp)
- return;
- fbGetDrawable(pSrcDrawable, src, srcStride, srcBpp, srcXoff,
- srcYoff);
- fbGetDrawable(pDstDrawable, dst, dstStride, dstBpp, dstXoff,
- dstYoff);
- fbBltPlane(src + (pbox->y1 + dy + srcYoff) * srcStride,
- srcStride,
- (pbox->x1 + dx + srcXoff) * srcBpp,
- srcBpp,
- tmp,
- tmpStride,
- 0,
- width * srcBpp,
- height,
- fbAndStip(GXcopy, FB_ALLONES, FB_ALLONES),
- fbXorStip(GXcopy, FB_ALLONES, FB_ALLONES),
- fbAndStip(GXcopy, 0, FB_ALLONES),
- fbXorStip(GXcopy, 0, FB_ALLONES), bitplane);
- fbBltOne(tmp,
- tmpStride,
- 0,
- dst + (pbox->y1 + dstYoff) * dstStride,
- dstStride,
- (pbox->x1 + dstXoff) * dstBpp,
- dstBpp,
- width * dstBpp,
- height,
- pPriv->and, pPriv->xor, pPriv->bgand, pPriv->bgxor);
- free(tmp);
- }
- pbox++;
- }
- }
- void
- fbCopyRegion(DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- RegionPtr pDstRegion,
- int dx, int dy, fbCopyProc copyProc, Pixel bitPlane, void *closure)
- {
- int careful;
- Bool reverse;
- Bool upsidedown;
- BoxPtr pbox;
- int nbox;
- BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp;
- pbox = REGION_RECTS(pDstRegion);
- nbox = REGION_NUM_RECTS(pDstRegion);
- /* XXX we have to err on the side of safety when both are windows,
- * because we don't know if IncludeInferiors is being used.
- */
- careful = ((pSrcDrawable == pDstDrawable) ||
- ((pSrcDrawable->type == DRAWABLE_WINDOW) &&
- (pDstDrawable->type == DRAWABLE_WINDOW)));
- pboxNew1 = NULL;
- pboxNew2 = NULL;
- if (careful && dy < 0) {
- upsidedown = TRUE;
- if (nbox > 1) {
- /* keep ordering in each band, reverse order of bands */
- pboxNew1 = (BoxPtr) ALLOCATE_LOCAL(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) ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
- if (!pboxNew2) {
- if (pboxNew1)
- DEALLOCATE_LOCAL(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) (pSrcDrawable,
- pDstDrawable,
- pGC,
- pbox, nbox, dx, dy, reverse, upsidedown, bitPlane, closure);
- if (pboxNew1)
- DEALLOCATE_LOCAL(pboxNew1);
- if (pboxNew2)
- DEALLOCATE_LOCAL(pboxNew2);
- }
- RegionPtr
- fbDoCopy(DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- int xIn,
- int yIn,
- int widthSrc,
- int heightSrc,
- int xOut, int yOut, fbCopyProc 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 */
- /* Short cut for unmapped windows */
- if (pDstDrawable->type == DRAWABLE_WINDOW &&
- !((WindowPtr) pDstDrawable)->realized) {
- return NULL;
- }
- if ((pSrcDrawable != pDstDrawable) && pSrcDrawable->pScreen->SourceValidate) {
- (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn,
- widthSrc, heightSrc);
- }
- /* Compute source clip region */
- if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
- if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
- prgnSrcClip = fbGetCompositeClip(pGC);
- else
- fastSrc = TRUE;
- }
- else {
- if (pGC->subWindowMode == IncludeInferiors) {
- /*
- * XFree86 DDX empties the border clip when the
- * VT is inactive, make sure the region isn't empty
- */
- if (!((WindowPtr) pSrcDrawable)->parent &&
- REGION_NOTEMPTY(
- &((WindowPtr) pSrcDrawable)->borderClip)) {
- /*
- * special case bitblt from root window in
- * IncludeInferiors mode; just like from a pixmap
- */
- fastSrc = TRUE;
- }
- else if ((pSrcDrawable == pDstDrawable) &&
- (pGC->clientClipType == CT_NONE)) {
- prgnSrcClip = fbGetCompositeClip(pGC);
- }
- else {
- prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable);
- freeSrcClip = TRUE;
- }
- }
- else {
- prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList;
- }
- }
- xIn += pSrcDrawable->x;
- yIn += pSrcDrawable->y;
- xOut += pDstDrawable->x;
- yOut += pDstDrawable->y;
- 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_x1 < pSrcDrawable->x) {
- box_x1 = pSrcDrawable->x;
- fastExpose = FALSE;
- }
- if (box_y1 < pSrcDrawable->y) {
- box_y1 = pSrcDrawable->y;
- fastExpose = FALSE;
- }
- if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) {
- box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
- fastExpose = FALSE;
- }
- if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) {
- box_y2 = pSrcDrawable->y + (int) pSrcDrawable->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 = fbGetCompositeClip(pGC);
- if (REGION_NUM_RECTS(cclip) == 1) {
- BoxPtr pBox = REGION_RECTS(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) {
- REGION_NULL(&rgnDst);
- }
- else {
- BoxRec box;
- box.x1 = box_x1;
- box.y1 = box_y1;
- box.x2 = box_x2;
- box.y2 = box_y2;
- REGION_INIT(&rgnDst, &box, 1);
- }
- /* Clip against complex source if needed */
- if (!fastSrc) {
- REGION_INTERSECT(&rgnDst, &rgnDst, prgnSrcClip);
- REGION_TRANSLATE(&rgnDst, -dx, -dy);
- }
- /* Clip against complex dest if needed */
- if (!fastDst) {
- REGION_INTERSECT(&rgnDst, &rgnDst,
- fbGetCompositeClip(pGC));
- }
- /* Do bit blitting */
- numRects = REGION_NUM_RECTS(&rgnDst);
- if (numRects && widthSrc && heightSrc)
- fbCopyRegion(pSrcDrawable, pDstDrawable, pGC,
- &rgnDst, dx, dy, copyProc, bitPlane, closure);
- /* Pixmap sources generate a NoExposed (we return NULL to do this) */
- if (!fastExpose && pGC->fExpose)
- prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
- xIn - pSrcDrawable->x,
- yIn - pSrcDrawable->y,
- widthSrc, heightSrc,
- xOut - pDstDrawable->x,
- yOut - pDstDrawable->y,
- (unsigned long) bitPlane);
- REGION_UNINIT(&rgnDst);
- if (freeSrcClip)
- REGION_DESTROY(prgnSrcClip);
- fbValidateDrawable(pDstDrawable);
- return prgnExposed;
- }
- RegionPtr
- fbCopyArea(DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut)
- {
- fbCopyProc copy;
- if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
- copy = fb24_32CopyMtoN;
- else
- copy = fbCopyNtoN;
- return fbDoCopy(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
- widthSrc, heightSrc, xOut, yOut, copy, 0, 0);
- }
- RegionPtr
- fbCopyPlane(DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- int xIn,
- int yIn,
- int widthSrc,
- int heightSrc, int xOut, int yOut, unsigned long bitplane)
- {
- if (pSrcDrawable->bitsPerPixel > 1)
- return fbDoCopy(pSrcDrawable, pDstDrawable, pGC,
- xIn, yIn, widthSrc, heightSrc,
- xOut, yOut, fbCopyNto1, (Pixel) bitplane, 0);
- else if (bitplane & 1)
- return fbDoCopy(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
- widthSrc, heightSrc, xOut, yOut, fbCopy1toN,
- (Pixel) bitplane, 0);
- else
- return miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
- xIn, yIn,
- widthSrc, heightSrc, xOut, yOut, bitplane);
- }
|