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 <gcstruct.h>
2603b705cfSriastradh#include <scrnintstr.h>
2703b705cfSriastradh
2803b705cfSriastradh/*
2903b705cfSriastradh * Pad pixmap to FB_UNIT bits wide
3003b705cfSriastradh */
3103b705cfSriastradhvoid
3203b705cfSriastradhfbPadPixmap(PixmapPtr pPixmap)
3303b705cfSriastradh{
3403b705cfSriastradh	int width;
3503b705cfSriastradh	FbBits *bits;
3603b705cfSriastradh	FbBits b;
3703b705cfSriastradh	FbBits mask;
3803b705cfSriastradh	int height;
3903b705cfSriastradh	int w;
4003b705cfSriastradh	int stride;
4103b705cfSriastradh	int bpp;
4203b705cfSriastradh	_X_UNUSED int xOff, yOff;
4303b705cfSriastradh
4403b705cfSriastradh	fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
4503b705cfSriastradh
4603b705cfSriastradh	width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
4703b705cfSriastradh	height = pPixmap->drawable.height;
4803b705cfSriastradh	mask = FbBitsMask(0, width);
4903b705cfSriastradh	while (height--) {
5003b705cfSriastradh		b = READ(bits) & mask;
5103b705cfSriastradh		w = width;
5203b705cfSriastradh		while (w < FB_UNIT) {
5303b705cfSriastradh			b = b | FbScrRight(b, w);
5403b705cfSriastradh			w <<= 1;
5503b705cfSriastradh		}
5603b705cfSriastradh		WRITE(bits, b);
5703b705cfSriastradh		bits += stride;
5803b705cfSriastradh	}
5903b705cfSriastradh}
6003b705cfSriastradh
6103b705cfSriastradh/*
6203b705cfSriastradh * Verify that 'bits' repeats every 'len' bits
6303b705cfSriastradh */
6403b705cfSriastradhstatic Bool
6503b705cfSriastradhfbBitsRepeat(FbBits bits, int len, int width)
6603b705cfSriastradh{
6703b705cfSriastradh	FbBits mask = FbBitsMask(0, len);
6803b705cfSriastradh	FbBits orig = bits & mask;
6903b705cfSriastradh	int i;
7003b705cfSriastradh
7103b705cfSriastradh	if (width > FB_UNIT)
7203b705cfSriastradh		width = FB_UNIT;
7303b705cfSriastradh	for (i = 0; i < width / len; i++) {
7403b705cfSriastradh		if ((bits & mask) != orig)
7503b705cfSriastradh			return FALSE;
7603b705cfSriastradh		bits = FbScrLeft(bits, len);
7703b705cfSriastradh	}
7803b705cfSriastradh	return TRUE;
7903b705cfSriastradh}
8003b705cfSriastradh
8103b705cfSriastradh/*
8203b705cfSriastradh * Check whether an entire bitmap line is a repetition of
8303b705cfSriastradh * the first 'len' bits
8403b705cfSriastradh */
8503b705cfSriastradhstatic Bool
8603b705cfSriastradhfbLineRepeat(FbBits * bits, int len, int width)
8703b705cfSriastradh{
8803b705cfSriastradh	FbBits first = bits[0];
8903b705cfSriastradh
9003b705cfSriastradh	if (!fbBitsRepeat(first, len, width))
9103b705cfSriastradh		return FALSE;
9203b705cfSriastradh	width = (width + FB_UNIT - 1) >> FB_SHIFT;
9303b705cfSriastradh	bits++;
9403b705cfSriastradh	while (--width)
9503b705cfSriastradh		if (READ(bits) != first)
9603b705cfSriastradh			return FALSE;
9703b705cfSriastradh	return TRUE;
9803b705cfSriastradh}
9903b705cfSriastradh
10003b705cfSriastradh/*
10103b705cfSriastradh * The even stipple code wants the first FB_UNIT/bpp bits on
10203b705cfSriastradh * each scanline to represent the entire stipple
10303b705cfSriastradh */
10403b705cfSriastradhstatic Bool
10503b705cfSriastradhfbCanEvenStipple(PixmapPtr pStipple, int bpp)
10603b705cfSriastradh{
10703b705cfSriastradh	int len = FB_UNIT / bpp;
10803b705cfSriastradh	FbBits *bits;
10903b705cfSriastradh	int stride;
11003b705cfSriastradh	int stip_bpp;
11103b705cfSriastradh	_X_UNUSED int stipXoff, stipYoff;
11203b705cfSriastradh	int h;
11303b705cfSriastradh
11403b705cfSriastradh	/* make sure the stipple width is a multiple of the even stipple width */
11503b705cfSriastradh	if (pStipple->drawable.width % len != 0)
11603b705cfSriastradh		return FALSE;
11703b705cfSriastradh
11803b705cfSriastradh	fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff,
11903b705cfSriastradh		      stipYoff);
12003b705cfSriastradh	h = pStipple->drawable.height;
12103b705cfSriastradh	/* check to see that the stipple repeats horizontally */
12203b705cfSriastradh	while (h--) {
12303b705cfSriastradh		if (!fbLineRepeat(bits, len, pStipple->drawable.width))
12403b705cfSriastradh			return FALSE;
12503b705cfSriastradh
12603b705cfSriastradh		bits += stride;
12703b705cfSriastradh	}
12803b705cfSriastradh	return TRUE;
12903b705cfSriastradh}
13003b705cfSriastradh
13103b705cfSriastradhvoid
13203b705cfSriastradhfbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable)
13303b705cfSriastradh{
13403b705cfSriastradh	FbGCPrivPtr pgc = fb_gc(gc);
13503b705cfSriastradh	FbBits mask;
13603b705cfSriastradh
13703b705cfSriastradh	DBG(("%s changes=%lx\n", __FUNCTION__, changes));
13803b705cfSriastradh
13903b705cfSriastradh	if (changes & GCStipple) {
14003b705cfSriastradh		pgc->evenStipple = FALSE;
14103b705cfSriastradh
14203b705cfSriastradh		if (gc->stipple) {
14303b705cfSriastradh			/* can we do an even stipple ?? */
14403b705cfSriastradh			if (FbEvenStip(gc->stipple->drawable.width,
14503b705cfSriastradh				       drawable->bitsPerPixel) &&
14603b705cfSriastradh			    (fbCanEvenStipple(gc->stipple, drawable->bitsPerPixel)))
14703b705cfSriastradh				pgc->evenStipple = TRUE;
14803b705cfSriastradh		}
14903b705cfSriastradh	}
15003b705cfSriastradh
15103b705cfSriastradh	/*
15203b705cfSriastradh	 * Recompute reduced rop values
15303b705cfSriastradh	 */
15403b705cfSriastradh	if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
15503b705cfSriastradh		int s;
15603b705cfSriastradh		FbBits depthMask;
15703b705cfSriastradh
15803b705cfSriastradh		mask = FbFullMask(drawable->bitsPerPixel);
15903b705cfSriastradh		depthMask = FbFullMask(drawable->depth);
16003b705cfSriastradh
16103b705cfSriastradh		DBG(("%s: computing rrop mask=%08x, depthMask=%08x, fg=%08x, bg=%08x, planemask=%08x\n",
16203b705cfSriastradh		     __FUNCTION__, mask, depthMask, (int)gc->fgPixel, (int)gc->bgPixel, (int)gc->planemask));
16303b705cfSriastradh
16403b705cfSriastradh		pgc->fg = gc->fgPixel & mask;
16503b705cfSriastradh		pgc->bg = gc->bgPixel & mask;
16603b705cfSriastradh
16703b705cfSriastradh		if ((gc->planemask & depthMask) == depthMask)
16803b705cfSriastradh			pgc->pm = mask;
16903b705cfSriastradh		else
17003b705cfSriastradh			pgc->pm = gc->planemask & mask;
17103b705cfSriastradh
17203b705cfSriastradh		s = drawable->bitsPerPixel;
17303b705cfSriastradh		while (s < FB_UNIT) {
17403b705cfSriastradh			pgc->fg |= pgc->fg << s;
17503b705cfSriastradh			pgc->bg |= pgc->bg << s;
17603b705cfSriastradh			pgc->pm |= pgc->pm << s;
17703b705cfSriastradh			s <<= 1;
17803b705cfSriastradh		}
17903b705cfSriastradh		pgc->and = fbAnd(gc->alu, pgc->fg, pgc->pm);
18003b705cfSriastradh		pgc->xor = fbXor(gc->alu, pgc->fg, pgc->pm);
18103b705cfSriastradh		pgc->bgand = fbAnd(gc->alu, pgc->bg, pgc->pm);
18203b705cfSriastradh		pgc->bgxor = fbXor(gc->alu, pgc->bg, pgc->pm);
18303b705cfSriastradh
18403b705cfSriastradh		DBG(("%s: rrop fg=%08x, bg=%08x, pm=%08x, and=%08x, xor=%08x, bgand=%08x, bgxor=%08x\n",
18503b705cfSriastradh		     __FUNCTION__, pgc->fg, pgc->bg, pgc->pm, pgc->and, pgc->xor, pgc->bgand, pgc->bgxor));
18603b705cfSriastradh	}
18703b705cfSriastradh
18803b705cfSriastradh	if (changes & GCDashList) {
18903b705cfSriastradh		unsigned short n = gc->numInDashList;
19003b705cfSriastradh		unsigned char *dash = gc->dash;
19103b705cfSriastradh		unsigned int dashLength = 0;
19203b705cfSriastradh
19303b705cfSriastradh		while (n--)
19403b705cfSriastradh			dashLength += (unsigned int) *dash++;
19503b705cfSriastradh		pgc->dashLength = dashLength;
19603b705cfSriastradh	}
19703b705cfSriastradh}
198