fbimage.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg * Copyright © 1998 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that 705b261ecSmrg * copyright notice and this permission notice appear in supporting 805b261ecSmrg * documentation, and that the name of Keith Packard not be used in 905b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1005b261ecSmrg * specific, written prior permission. Keith Packard makes no 1105b261ecSmrg * representations about the suitability of this software for any purpose. It 1205b261ecSmrg * is provided "as is" without express or implied warranty. 1305b261ecSmrg * 1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2105b261ecSmrg */ 2205b261ecSmrg 2305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2405b261ecSmrg#include <dix-config.h> 2505b261ecSmrg#endif 2605b261ecSmrg 2705b261ecSmrg#include <string.h> 2805b261ecSmrg 2905b261ecSmrg#include "fb.h" 3005b261ecSmrg 3105b261ecSmrgvoid 3205b261ecSmrgfbPutImage (DrawablePtr pDrawable, 3305b261ecSmrg GCPtr pGC, 3405b261ecSmrg int depth, 3505b261ecSmrg int x, 3605b261ecSmrg int y, 3705b261ecSmrg int w, 3805b261ecSmrg int h, 3905b261ecSmrg int leftPad, 4005b261ecSmrg int format, 4105b261ecSmrg char *pImage) 4205b261ecSmrg{ 4305b261ecSmrg FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 4405b261ecSmrg unsigned long i; 4505b261ecSmrg FbStride srcStride; 4605b261ecSmrg FbStip *src = (FbStip *) pImage; 4705b261ecSmrg 4805b261ecSmrg x += pDrawable->x; 4905b261ecSmrg y += pDrawable->y; 5005b261ecSmrg 5105b261ecSmrg switch (format) 5205b261ecSmrg { 5305b261ecSmrg case XYBitmap: 5405b261ecSmrg srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip); 5505b261ecSmrg fbPutXYImage (pDrawable, 5605b261ecSmrg fbGetCompositeClip(pGC), 5705b261ecSmrg pPriv->fg, 5805b261ecSmrg pPriv->bg, 5905b261ecSmrg pPriv->pm, 6005b261ecSmrg pGC->alu, 6105b261ecSmrg TRUE, 6205b261ecSmrg x, y, w, h, 6305b261ecSmrg src, 6405b261ecSmrg srcStride, 6505b261ecSmrg leftPad); 6605b261ecSmrg break; 6705b261ecSmrg case XYPixmap: 6805b261ecSmrg srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip); 6905b261ecSmrg for (i = (unsigned long)1 << (pDrawable->depth - 1); i; i >>= 1) 7005b261ecSmrg { 7105b261ecSmrg if (i & pGC->planemask) 7205b261ecSmrg { 7305b261ecSmrg fbPutXYImage (pDrawable, 7405b261ecSmrg fbGetCompositeClip(pGC), 7505b261ecSmrg FB_ALLONES, 7605b261ecSmrg 0, 7705b261ecSmrg fbReplicatePixel (i, pDrawable->bitsPerPixel), 7805b261ecSmrg pGC->alu, 7905b261ecSmrg TRUE, 8005b261ecSmrg x, y, w, h, 8105b261ecSmrg src, 8205b261ecSmrg srcStride, 8305b261ecSmrg leftPad); 8405b261ecSmrg src += srcStride * h; 8505b261ecSmrg } 8605b261ecSmrg } 8705b261ecSmrg break; 8805b261ecSmrg case ZPixmap: 8905b261ecSmrg#ifdef FB_24_32BIT 9005b261ecSmrg if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) 9105b261ecSmrg { 9205b261ecSmrg srcStride = PixmapBytePad(w, pDrawable->depth); 9305b261ecSmrg fb24_32PutZImage (pDrawable, 9405b261ecSmrg fbGetCompositeClip(pGC), 9505b261ecSmrg pGC->alu, 9605b261ecSmrg (FbBits) pGC->planemask, 9705b261ecSmrg x, y, w, h, 9805b261ecSmrg (CARD8 *) pImage, 9905b261ecSmrg srcStride); 10005b261ecSmrg } 10105b261ecSmrg else 10205b261ecSmrg#endif 10305b261ecSmrg { 10405b261ecSmrg srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof (FbStip); 10505b261ecSmrg fbPutZImage (pDrawable, 10605b261ecSmrg fbGetCompositeClip(pGC), 10705b261ecSmrg pGC->alu, 10805b261ecSmrg pPriv->pm, 10905b261ecSmrg x, y, w, h, 11005b261ecSmrg src, srcStride); 11105b261ecSmrg } 11205b261ecSmrg } 11305b261ecSmrg} 11405b261ecSmrg 11505b261ecSmrgvoid 11605b261ecSmrgfbPutZImage (DrawablePtr pDrawable, 11705b261ecSmrg RegionPtr pClip, 11805b261ecSmrg int alu, 11905b261ecSmrg FbBits pm, 12005b261ecSmrg int x, 12105b261ecSmrg int y, 12205b261ecSmrg int width, 12305b261ecSmrg int height, 12405b261ecSmrg FbStip *src, 12505b261ecSmrg FbStride srcStride) 12605b261ecSmrg{ 12705b261ecSmrg FbStip *dst; 12805b261ecSmrg FbStride dstStride; 12905b261ecSmrg int dstBpp; 13005b261ecSmrg int dstXoff, dstYoff; 13105b261ecSmrg int nbox; 13205b261ecSmrg BoxPtr pbox; 13305b261ecSmrg int x1, y1, x2, y2; 13405b261ecSmrg 13505b261ecSmrg fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 13605b261ecSmrg 13705b261ecSmrg for (nbox = REGION_NUM_RECTS (pClip), 13805b261ecSmrg pbox = REGION_RECTS(pClip); 13905b261ecSmrg nbox--; 14005b261ecSmrg pbox++) 14105b261ecSmrg { 14205b261ecSmrg x1 = x; 14305b261ecSmrg y1 = y; 14405b261ecSmrg x2 = x + width; 14505b261ecSmrg y2 = y + height; 14605b261ecSmrg if (x1 < pbox->x1) 14705b261ecSmrg x1 = pbox->x1; 14805b261ecSmrg if (y1 < pbox->y1) 14905b261ecSmrg y1 = pbox->y1; 15005b261ecSmrg if (x2 > pbox->x2) 15105b261ecSmrg x2 = pbox->x2; 15205b261ecSmrg if (y2 > pbox->y2) 15305b261ecSmrg y2 = pbox->y2; 15405b261ecSmrg if (x1 >= x2 || y1 >= y2) 15505b261ecSmrg continue; 15605b261ecSmrg fbBltStip (src + (y1 - y) * srcStride, 15705b261ecSmrg srcStride, 15805b261ecSmrg (x1 - x) * dstBpp, 15905b261ecSmrg 16005b261ecSmrg dst + (y1 + dstYoff) * dstStride, 16105b261ecSmrg dstStride, 16205b261ecSmrg (x1 + dstXoff) * dstBpp, 16305b261ecSmrg 16405b261ecSmrg (x2 - x1) * dstBpp, 16505b261ecSmrg (y2 - y1), 16605b261ecSmrg 16705b261ecSmrg alu, 16805b261ecSmrg pm, 16905b261ecSmrg dstBpp); 17005b261ecSmrg } 17105b261ecSmrg 17205b261ecSmrg fbFinishAccess (pDrawable); 17305b261ecSmrg} 17405b261ecSmrg 17505b261ecSmrgvoid 17605b261ecSmrgfbPutXYImage (DrawablePtr pDrawable, 17705b261ecSmrg RegionPtr pClip, 17805b261ecSmrg FbBits fg, 17905b261ecSmrg FbBits bg, 18005b261ecSmrg FbBits pm, 18105b261ecSmrg int alu, 18205b261ecSmrg Bool opaque, 18305b261ecSmrg 18405b261ecSmrg int x, 18505b261ecSmrg int y, 18605b261ecSmrg int width, 18705b261ecSmrg int height, 18805b261ecSmrg 18905b261ecSmrg FbStip *src, 19005b261ecSmrg FbStride srcStride, 19105b261ecSmrg int srcX) 19205b261ecSmrg{ 19305b261ecSmrg FbBits *dst; 19405b261ecSmrg FbStride dstStride; 19505b261ecSmrg int dstBpp; 19605b261ecSmrg int dstXoff, dstYoff; 19705b261ecSmrg int nbox; 19805b261ecSmrg BoxPtr pbox; 19905b261ecSmrg int x1, y1, x2, y2; 20005b261ecSmrg FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0; 20105b261ecSmrg 20205b261ecSmrg fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 20305b261ecSmrg 20405b261ecSmrg if (dstBpp == 1) 20505b261ecSmrg { 20605b261ecSmrg if (opaque) 20705b261ecSmrg alu = FbOpaqueStipple1Rop(alu,fg,bg); 20805b261ecSmrg else 20905b261ecSmrg alu = FbStipple1Rop(alu,fg); 21005b261ecSmrg } 21105b261ecSmrg else 21205b261ecSmrg { 21305b261ecSmrg fgand = fbAnd(alu,fg,pm); 21405b261ecSmrg fgxor = fbXor(alu,fg,pm); 21505b261ecSmrg if (opaque) 21605b261ecSmrg { 21705b261ecSmrg bgand = fbAnd(alu,bg,pm); 21805b261ecSmrg bgxor = fbXor(alu,bg,pm); 21905b261ecSmrg } 22005b261ecSmrg else 22105b261ecSmrg { 22205b261ecSmrg bgand = fbAnd(GXnoop,(FbBits)0,FB_ALLONES); 22305b261ecSmrg bgxor = fbXor(GXnoop,(FbBits)0,FB_ALLONES); 22405b261ecSmrg } 22505b261ecSmrg } 22605b261ecSmrg 22705b261ecSmrg for (nbox = REGION_NUM_RECTS (pClip), 22805b261ecSmrg pbox = REGION_RECTS(pClip); 22905b261ecSmrg nbox--; 23005b261ecSmrg pbox++) 23105b261ecSmrg { 23205b261ecSmrg x1 = x; 23305b261ecSmrg y1 = y; 23405b261ecSmrg x2 = x + width; 23505b261ecSmrg y2 = y + height; 23605b261ecSmrg if (x1 < pbox->x1) 23705b261ecSmrg x1 = pbox->x1; 23805b261ecSmrg if (y1 < pbox->y1) 23905b261ecSmrg y1 = pbox->y1; 24005b261ecSmrg if (x2 > pbox->x2) 24105b261ecSmrg x2 = pbox->x2; 24205b261ecSmrg if (y2 > pbox->y2) 24305b261ecSmrg y2 = pbox->y2; 24405b261ecSmrg if (x1 >= x2 || y1 >= y2) 24505b261ecSmrg continue; 24605b261ecSmrg if (dstBpp == 1) 24705b261ecSmrg { 24805b261ecSmrg fbBltStip (src + (y1 - y) * srcStride, 24905b261ecSmrg srcStride, 25005b261ecSmrg (x1 - x) + srcX, 25105b261ecSmrg 25205b261ecSmrg (FbStip *) (dst + (y1 + dstYoff) * dstStride), 25305b261ecSmrg FbBitsStrideToStipStride(dstStride), 25405b261ecSmrg (x1 + dstXoff) * dstBpp, 25505b261ecSmrg 25605b261ecSmrg (x2 - x1) * dstBpp, 25705b261ecSmrg (y2 - y1), 25805b261ecSmrg 25905b261ecSmrg alu, 26005b261ecSmrg pm, 26105b261ecSmrg dstBpp); 26205b261ecSmrg } 26305b261ecSmrg else 26405b261ecSmrg { 26505b261ecSmrg fbBltOne (src + (y1 - y) * srcStride, 26605b261ecSmrg srcStride, 26705b261ecSmrg (x1 - x) + srcX, 26805b261ecSmrg 26905b261ecSmrg dst + (y1 + dstYoff) * dstStride, 27005b261ecSmrg dstStride, 27105b261ecSmrg (x1 + dstXoff) * dstBpp, 27205b261ecSmrg dstBpp, 27305b261ecSmrg 27405b261ecSmrg (x2 - x1) * dstBpp, 27505b261ecSmrg (y2 - y1), 27605b261ecSmrg 27705b261ecSmrg fgand, fgxor, bgand, bgxor); 27805b261ecSmrg } 27905b261ecSmrg } 28005b261ecSmrg 28105b261ecSmrg fbFinishAccess (pDrawable); 28205b261ecSmrg} 28305b261ecSmrg 28405b261ecSmrgvoid 28505b261ecSmrgfbGetImage (DrawablePtr pDrawable, 28605b261ecSmrg int x, 28705b261ecSmrg int y, 28805b261ecSmrg int w, 28905b261ecSmrg int h, 29005b261ecSmrg unsigned int format, 29105b261ecSmrg unsigned long planeMask, 29205b261ecSmrg char *d) 29305b261ecSmrg{ 29405b261ecSmrg FbBits *src; 29505b261ecSmrg FbStride srcStride; 29605b261ecSmrg int srcBpp; 29705b261ecSmrg int srcXoff, srcYoff; 29805b261ecSmrg FbStip *dst; 29905b261ecSmrg FbStride dstStride; 30005b261ecSmrg 30105b261ecSmrg /* 30205b261ecSmrg * XFree86 DDX empties the root borderClip when the VT is 30305b261ecSmrg * switched away; this checks for that case 30405b261ecSmrg */ 30505b261ecSmrg if (!fbDrawableEnabled(pDrawable)) 30605b261ecSmrg return; 30705b261ecSmrg 30805b261ecSmrg#ifdef FB_24_32BIT 30905b261ecSmrg if (format == ZPixmap && 31005b261ecSmrg pDrawable->bitsPerPixel != BitsPerPixel (pDrawable->depth)) 31105b261ecSmrg { 31205b261ecSmrg fb24_32GetImage (pDrawable, x, y, w, h, format, planeMask, d); 31305b261ecSmrg return; 31405b261ecSmrg } 31505b261ecSmrg#endif 31605b261ecSmrg 31705b261ecSmrg fbGetDrawable (pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); 31805b261ecSmrg 31905b261ecSmrg x += pDrawable->x; 32005b261ecSmrg y += pDrawable->y; 32105b261ecSmrg 32205b261ecSmrg dst = (FbStip *) d; 32305b261ecSmrg if (format == ZPixmap || srcBpp == 1) 32405b261ecSmrg { 32505b261ecSmrg FbBits pm; 32605b261ecSmrg 32705b261ecSmrg pm = fbReplicatePixel (planeMask, srcBpp); 32805b261ecSmrg dstStride = PixmapBytePad(w, pDrawable->depth); 32905b261ecSmrg if (pm != FB_ALLONES) 33005b261ecSmrg memset (d, 0, dstStride * h); 33105b261ecSmrg dstStride /= sizeof (FbStip); 33205b261ecSmrg fbBltStip ((FbStip *) (src + (y + srcYoff) * srcStride), 33305b261ecSmrg FbBitsStrideToStipStride(srcStride), 33405b261ecSmrg (x + srcXoff) * srcBpp, 33505b261ecSmrg 33605b261ecSmrg dst, 33705b261ecSmrg dstStride, 33805b261ecSmrg 0, 33905b261ecSmrg 34005b261ecSmrg w * srcBpp, h, 34105b261ecSmrg 34205b261ecSmrg GXcopy, 34305b261ecSmrg pm, 34405b261ecSmrg srcBpp); 34505b261ecSmrg } 34605b261ecSmrg else 34705b261ecSmrg { 34805b261ecSmrg dstStride = BitmapBytePad(w) / sizeof (FbStip); 34905b261ecSmrg fbBltPlane (src + (y + srcYoff) * srcStride, 35005b261ecSmrg srcStride, 35105b261ecSmrg (x + srcXoff) * srcBpp, 35205b261ecSmrg srcBpp, 35305b261ecSmrg 35405b261ecSmrg dst, 35505b261ecSmrg dstStride, 35605b261ecSmrg 0, 35705b261ecSmrg 35805b261ecSmrg w * srcBpp, h, 35905b261ecSmrg 36005b261ecSmrg fbAndStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES), 36105b261ecSmrg fbXorStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES), 36205b261ecSmrg fbAndStip(GXcopy,0,FB_STIP_ALLONES), 36305b261ecSmrg fbXorStip(GXcopy,0,FB_STIP_ALLONES), 36405b261ecSmrg planeMask); 36505b261ecSmrg } 36605b261ecSmrg 36705b261ecSmrg fbFinishAccess (pDrawable); 36805b261ecSmrg} 369