103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 1998 Keith Packard
303b705cfSriastradh * Copyright © 2012 Intel Corporation
403b705cfSriastradh *
503b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its
603b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that
703b705cfSriastradh * the above copyright notice appear in all copies and that both that
803b705cfSriastradh * copyright notice and this permission notice appear in supporting
903b705cfSriastradh * documentation, and that the name of Keith Packard not be used in
1003b705cfSriastradh * advertising or publicity pertaining to distribution of the software without
1103b705cfSriastradh * specific, written prior permission.  Keith Packard makes no
1203b705cfSriastradh * representations about the suitability of this software for any purpose.  It
1303b705cfSriastradh * is provided "as is" without express or implied warranty.
1403b705cfSriastradh *
1503b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1603b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1703b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1803b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1903b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2003b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2103b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE.
2203b705cfSriastradh */
2303b705cfSriastradh
2403b705cfSriastradh#include "fb.h"
2503b705cfSriastradh#include "fbclip.h"
2603b705cfSriastradh
2703b705cfSriastradhstatic void
2803b705cfSriastradhfbSolid(FbBits * dst,
2903b705cfSriastradh        FbStride dstStride,
3003b705cfSriastradh        int dstX, int bpp, int width, int height, FbBits and, FbBits xor)
3103b705cfSriastradh{
3203b705cfSriastradh	FbBits startmask, endmask;
3303b705cfSriastradh	int n, nmiddle;
3403b705cfSriastradh	int startbyte, endbyte;
3503b705cfSriastradh
3603b705cfSriastradh	dst += dstX >> FB_SHIFT;
3703b705cfSriastradh	dstX &= FB_MASK;
3803b705cfSriastradh	FbMaskBitsBytes(dstX, width, and == 0, startmask, startbyte,
3903b705cfSriastradh			nmiddle, endmask, endbyte);
4003b705cfSriastradh	if (startmask)
4103b705cfSriastradh		dstStride--;
4203b705cfSriastradh	dstStride -= nmiddle;
4303b705cfSriastradh	while (height--) {
4403b705cfSriastradh		if (startmask) {
4503b705cfSriastradh			FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor);
4603b705cfSriastradh			dst++;
4703b705cfSriastradh		}
4803b705cfSriastradh		n = nmiddle;
4903b705cfSriastradh		if (!and)
5003b705cfSriastradh			while (n--)
5103b705cfSriastradh				WRITE(dst++, xor);
5203b705cfSriastradh		else
5303b705cfSriastradh			while (n--) {
5403b705cfSriastradh				WRITE(dst, FbDoRRop(READ(dst), and, xor));
5503b705cfSriastradh				dst++;
5603b705cfSriastradh			}
5703b705cfSriastradh		if (endmask)
5803b705cfSriastradh			FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
5903b705cfSriastradh		dst += dstStride;
6003b705cfSriastradh	}
6103b705cfSriastradh}
6203b705cfSriastradh
6303b705cfSriastradhvoid
6403b705cfSriastradhfbFill(DrawablePtr drawable, GCPtr gc, int x, int y, int width, int height)
6503b705cfSriastradh{
6603b705cfSriastradh	FbBits *dst;
6703b705cfSriastradh	FbStride dstStride;
6803b705cfSriastradh	int dstBpp;
6903b705cfSriastradh	int dstXoff, dstYoff;
7003b705cfSriastradh	FbGCPrivPtr pgc = fb_gc(gc);
7103b705cfSriastradh
7203b705cfSriastradh	DBG(("%s (%d, %d)x(%d, %d), style=%d\n",
7303b705cfSriastradh	     __FUNCTION__, x, y, width, height, gc->fillStyle));
7403b705cfSriastradh
7503b705cfSriastradh	fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
7603b705cfSriastradh
7703b705cfSriastradh	switch (gc->fillStyle) {
7803b705cfSriastradh	case FillSolid:
7903b705cfSriastradh		if (pgc->and ||
8003b705cfSriastradh		    !pixman_fill((uint32_t *) dst, dstStride, dstBpp,
8103b705cfSriastradh				 x + dstXoff, y + dstYoff,
8203b705cfSriastradh				 width, height, pgc->xor))
8303b705cfSriastradh			fbSolid(dst + (y + dstYoff) * dstStride,
8403b705cfSriastradh				dstStride,
8503b705cfSriastradh				(x + dstXoff) * dstBpp,
8603b705cfSriastradh				dstBpp, width * dstBpp, height, pgc->and, pgc->xor);
8703b705cfSriastradh		break;
8803b705cfSriastradh
8903b705cfSriastradh	case FillStippled:
9003b705cfSriastradh	case FillOpaqueStippled:
9103b705cfSriastradh		{
9203b705cfSriastradh			PixmapPtr pStip = gc->stipple;
9303b705cfSriastradh			int stipWidth = pStip->drawable.width;
9403b705cfSriastradh			int stipHeight = pStip->drawable.height;
9503b705cfSriastradh
9603b705cfSriastradh			if (dstBpp == 1) {
9703b705cfSriastradh				int alu;
9803b705cfSriastradh				FbBits *stip;
9903b705cfSriastradh				FbStride stipStride;
10003b705cfSriastradh				int stipBpp;
10103b705cfSriastradh				_X_UNUSED int stipXoff, stipYoff;
10203b705cfSriastradh
10303b705cfSriastradh				if (gc->fillStyle == FillStippled)
10403b705cfSriastradh					alu = FbStipple1Rop(gc->alu, gc->fgPixel);
10503b705cfSriastradh				else
10603b705cfSriastradh					alu = FbOpaqueStipple1Rop(gc->alu, gc->fgPixel, gc->bgPixel);
10703b705cfSriastradh				fbGetDrawable(&pStip->drawable, stip, stipStride, stipBpp, stipXoff,
10803b705cfSriastradh					      stipYoff);
10903b705cfSriastradh				fbTile(dst + (y + dstYoff) * dstStride, dstStride, x + dstXoff,
11003b705cfSriastradh				       width, height, stip, stipStride, stipWidth, stipHeight, alu,
11103b705cfSriastradh				       pgc->pm, dstBpp, (gc->patOrg.x + drawable->x + dstXoff),
11203b705cfSriastradh				       gc->patOrg.y + drawable->y - y);
11303b705cfSriastradh			} else {
11403b705cfSriastradh				FbStip *stip;
11503b705cfSriastradh				FbStride stipStride;
11603b705cfSriastradh				int stipBpp;
11703b705cfSriastradh				_X_UNUSED int stipXoff, stipYoff;
11803b705cfSriastradh				FbBits fgand, fgxor, bgand, bgxor;
11903b705cfSriastradh
12003b705cfSriastradh				fgand = pgc->and;
12103b705cfSriastradh				fgxor = pgc->xor;
12203b705cfSriastradh				if (gc->fillStyle == FillStippled) {
12303b705cfSriastradh					bgand = fbAnd(GXnoop, (FbBits) 0, FB_ALLONES);
12403b705cfSriastradh					bgxor = fbXor(GXnoop, (FbBits) 0, FB_ALLONES);
12503b705cfSriastradh				} else {
12603b705cfSriastradh					bgand = pgc->bgand;
12703b705cfSriastradh					bgxor = pgc->bgxor;
12803b705cfSriastradh				}
12903b705cfSriastradh
13003b705cfSriastradh				fbGetStipDrawable(&pStip->drawable, stip, stipStride, stipBpp,
13103b705cfSriastradh						  stipXoff, stipYoff);
13203b705cfSriastradh				fbStipple(dst + (y + dstYoff) * dstStride, dstStride,
13303b705cfSriastradh					  (x + dstXoff) * dstBpp, dstBpp, width * dstBpp, height,
13403b705cfSriastradh					  stip, stipStride, stipWidth, stipHeight,
13503b705cfSriastradh					  pgc->evenStipple, fgand, fgxor, bgand, bgxor,
13603b705cfSriastradh					  gc->patOrg.x + drawable->x + dstXoff,
13703b705cfSriastradh					  gc->patOrg.y + drawable->y - y);
13803b705cfSriastradh			}
13903b705cfSriastradh			break;
14003b705cfSriastradh		}
14103b705cfSriastradh
14203b705cfSriastradh	case FillTiled:
14303b705cfSriastradh		{
14403b705cfSriastradh			PixmapPtr tile = gc->tile.pixmap;
14503b705cfSriastradh
14603b705cfSriastradh			fbTile(dst + (y + dstYoff) * dstStride, dstStride,
14703b705cfSriastradh			       (x + dstXoff) * dstBpp, width * dstBpp, height,
14803b705cfSriastradh			       tile->devPrivate.ptr, tile->devKind / sizeof(FbBits),
14903b705cfSriastradh			       tile->drawable.width * tile->drawable.bitsPerPixel,
15003b705cfSriastradh			       tile->drawable.height,
15103b705cfSriastradh			       gc->alu, pgc->pm, dstBpp,
15203b705cfSriastradh			       (gc->patOrg.x + drawable->x + dstXoff) * dstBpp,
15303b705cfSriastradh			       gc->patOrg.y + drawable->y - y);
15403b705cfSriastradh			break;
15503b705cfSriastradh		}
15603b705cfSriastradh	}
15703b705cfSriastradh}
15803b705cfSriastradh
15903b705cfSriastradhstatic void
16003b705cfSriastradh_fbSolidBox(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
16103b705cfSriastradh{
16203b705cfSriastradh	FbBits *dst;
16303b705cfSriastradh	FbStride stride;
16403b705cfSriastradh	int dx, dy, bpp;
16503b705cfSriastradh	FbBits and = fbAnd(GXcopy, fb_gc(gc)->bg, fb_gc(gc)->pm);
16603b705cfSriastradh	FbBits xor = fbXor(GXcopy, fb_gc(gc)->bg, fb_gc(gc)->pm);
16703b705cfSriastradh
16803b705cfSriastradh	fbGetDrawable(drawable, dst, stride, bpp, dx, dy);
16903b705cfSriastradh
17003b705cfSriastradh	if (and ||
17103b705cfSriastradh	    !pixman_fill((uint32_t *) dst, stride, bpp,
17203b705cfSriastradh			 b->x1 + dx, b->y1 + dy,
17303b705cfSriastradh			 (b->x2 - b->x1), (b->y2 - b->y1), xor))
17403b705cfSriastradh		fbSolid(dst + (b->y1 + dy) * stride, stride,
17503b705cfSriastradh			(b->x1 + dx) * bpp, bpp,
17603b705cfSriastradh			(b->x2 - b->x1) * bpp, (b->y2 - b->y1),
17703b705cfSriastradh			and, xor);
17803b705cfSriastradh}
17903b705cfSriastradh
18003b705cfSriastradhvoid
18103b705cfSriastradhfbSolidBoxClipped(DrawablePtr drawable, GCPtr gc,
18203b705cfSriastradh                  int x1, int y1, int x2, int y2)
18303b705cfSriastradh{
18403b705cfSriastradh	BoxRec box;
18503b705cfSriastradh
18603b705cfSriastradh	box.x1 = x1;
18703b705cfSriastradh	box.y1 = y1;
18803b705cfSriastradh	box.x2 = x2;
18903b705cfSriastradh	box.y2 = y2;
19003b705cfSriastradh
19103b705cfSriastradh	fbDrawableRun(drawable, gc, &box, _fbSolidBox, NULL);
19203b705cfSriastradh}
19303b705cfSriastradh
19403b705cfSriastradhinline static void
19503b705cfSriastradhfbFillBox(DrawablePtr drawable, GCPtr gc, const BoxRec *box, void *data)
19603b705cfSriastradh{
19703b705cfSriastradh	DBG(("%s box=(%d, %d), (%d, %d)\n", __FUNCTION__,
19803b705cfSriastradh	     box->x1, box->y1, box->x2, box->y2));
19903b705cfSriastradh	fbFill(drawable, gc,
20003b705cfSriastradh	       box->x1, box->y1,
20103b705cfSriastradh	       box->x2 - box->x1, box->y2 - box->y1);
20203b705cfSriastradh}
20303b705cfSriastradh
20403b705cfSriastradhvoid
20503b705cfSriastradhfbPolyFillRect(DrawablePtr drawable, GCPtr gc, int n, xRectangle *r)
20603b705cfSriastradh{
20703b705cfSriastradh	DBG(("%s x %d\n", __FUNCTION__, n));
20803b705cfSriastradh	while (n--) {
20903b705cfSriastradh		BoxRec b;
21003b705cfSriastradh
21103b705cfSriastradh		b.x1 = r->x + drawable->x;
21203b705cfSriastradh		b.y1 = r->y + drawable->y;
21303b705cfSriastradh		b.x2 = fbBound(b.x1, r->width);
21403b705cfSriastradh		b.y2 = fbBound(b.y1, r->height);
21503b705cfSriastradh		r++;
21603b705cfSriastradh
21703b705cfSriastradh		DBG(("%s: rectangle (%d, %d), (%d, %d)\n",
21803b705cfSriastradh		     __FUNCTION__, b.x1, b.y1, b.x2, b.y2));
21903b705cfSriastradh		fbDrawableRun(drawable, gc, &b, fbFillBox, NULL);
22003b705cfSriastradh	}
22103b705cfSriastradh}
222