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