1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 1998 Keith Packard
3428d7b3dSmrg * Copyright © 2012 Intel Corporation
4428d7b3dSmrg *
5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that
7428d7b3dSmrg * the above copyright notice appear in all copies and that both that
8428d7b3dSmrg * copyright notice and this permission notice appear in supporting
9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in
10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without
11428d7b3dSmrg * specific, written prior permission.  Keith Packard makes no
12428d7b3dSmrg * representations about the suitability of this software for any purpose.  It
13428d7b3dSmrg * is provided "as is" without express or implied warranty.
14428d7b3dSmrg *
15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE.
22428d7b3dSmrg */
23428d7b3dSmrg
24428d7b3dSmrg#include "fb.h"
25428d7b3dSmrg#include <gcstruct.h>
26428d7b3dSmrg#include <scrnintstr.h>
27428d7b3dSmrg
28428d7b3dSmrg/*
29428d7b3dSmrg * Pad pixmap to FB_UNIT bits wide
30428d7b3dSmrg */
31428d7b3dSmrgvoid
32428d7b3dSmrgfbPadPixmap(PixmapPtr pPixmap)
33428d7b3dSmrg{
34428d7b3dSmrg	int width;
35428d7b3dSmrg	FbBits *bits;
36428d7b3dSmrg	FbBits b;
37428d7b3dSmrg	FbBits mask;
38428d7b3dSmrg	int height;
39428d7b3dSmrg	int w;
40428d7b3dSmrg	int stride;
41428d7b3dSmrg	int bpp;
42428d7b3dSmrg	_X_UNUSED int xOff, yOff;
43428d7b3dSmrg
44428d7b3dSmrg	fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
45428d7b3dSmrg
46428d7b3dSmrg	width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
47428d7b3dSmrg	height = pPixmap->drawable.height;
48428d7b3dSmrg	mask = FbBitsMask(0, width);
49428d7b3dSmrg	while (height--) {
50428d7b3dSmrg		b = READ(bits) & mask;
51428d7b3dSmrg		w = width;
52428d7b3dSmrg		while (w < FB_UNIT) {
53428d7b3dSmrg			b = b | FbScrRight(b, w);
54428d7b3dSmrg			w <<= 1;
55428d7b3dSmrg		}
56428d7b3dSmrg		WRITE(bits, b);
57428d7b3dSmrg		bits += stride;
58428d7b3dSmrg	}
59428d7b3dSmrg}
60428d7b3dSmrg
61428d7b3dSmrg/*
62428d7b3dSmrg * Verify that 'bits' repeats every 'len' bits
63428d7b3dSmrg */
64428d7b3dSmrgstatic Bool
65428d7b3dSmrgfbBitsRepeat(FbBits bits, int len, int width)
66428d7b3dSmrg{
67428d7b3dSmrg	FbBits mask = FbBitsMask(0, len);
68428d7b3dSmrg	FbBits orig = bits & mask;
69428d7b3dSmrg	int i;
70428d7b3dSmrg
71428d7b3dSmrg	if (width > FB_UNIT)
72428d7b3dSmrg		width = FB_UNIT;
73428d7b3dSmrg	for (i = 0; i < width / len; i++) {
74428d7b3dSmrg		if ((bits & mask) != orig)
75428d7b3dSmrg			return FALSE;
76428d7b3dSmrg		bits = FbScrLeft(bits, len);
77428d7b3dSmrg	}
78428d7b3dSmrg	return TRUE;
79428d7b3dSmrg}
80428d7b3dSmrg
81428d7b3dSmrg/*
82428d7b3dSmrg * Check whether an entire bitmap line is a repetition of
83428d7b3dSmrg * the first 'len' bits
84428d7b3dSmrg */
85428d7b3dSmrgstatic Bool
86428d7b3dSmrgfbLineRepeat(FbBits * bits, int len, int width)
87428d7b3dSmrg{
88428d7b3dSmrg	FbBits first = bits[0];
89428d7b3dSmrg
90428d7b3dSmrg	if (!fbBitsRepeat(first, len, width))
91428d7b3dSmrg		return FALSE;
92428d7b3dSmrg	width = (width + FB_UNIT - 1) >> FB_SHIFT;
93428d7b3dSmrg	bits++;
94428d7b3dSmrg	while (--width)
95428d7b3dSmrg		if (READ(bits) != first)
96428d7b3dSmrg			return FALSE;
97428d7b3dSmrg	return TRUE;
98428d7b3dSmrg}
99428d7b3dSmrg
100428d7b3dSmrg/*
101428d7b3dSmrg * The even stipple code wants the first FB_UNIT/bpp bits on
102428d7b3dSmrg * each scanline to represent the entire stipple
103428d7b3dSmrg */
104428d7b3dSmrgstatic Bool
105428d7b3dSmrgfbCanEvenStipple(PixmapPtr pStipple, int bpp)
106428d7b3dSmrg{
107428d7b3dSmrg	int len = FB_UNIT / bpp;
108428d7b3dSmrg	FbBits *bits;
109428d7b3dSmrg	int stride;
110428d7b3dSmrg	int stip_bpp;
111428d7b3dSmrg	_X_UNUSED int stipXoff, stipYoff;
112428d7b3dSmrg	int h;
113428d7b3dSmrg
114428d7b3dSmrg	/* make sure the stipple width is a multiple of the even stipple width */
115428d7b3dSmrg	if (pStipple->drawable.width % len != 0)
116428d7b3dSmrg		return FALSE;
117428d7b3dSmrg
118428d7b3dSmrg	fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff,
119428d7b3dSmrg		      stipYoff);
120428d7b3dSmrg	h = pStipple->drawable.height;
121428d7b3dSmrg	/* check to see that the stipple repeats horizontally */
122428d7b3dSmrg	while (h--) {
123428d7b3dSmrg		if (!fbLineRepeat(bits, len, pStipple->drawable.width))
124428d7b3dSmrg			return FALSE;
125428d7b3dSmrg
126428d7b3dSmrg		bits += stride;
127428d7b3dSmrg	}
128428d7b3dSmrg	return TRUE;
129428d7b3dSmrg}
130428d7b3dSmrg
131428d7b3dSmrgvoid
132428d7b3dSmrgfbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable)
133428d7b3dSmrg{
134428d7b3dSmrg	FbGCPrivPtr pgc = fb_gc(gc);
135428d7b3dSmrg	FbBits mask;
136428d7b3dSmrg
137428d7b3dSmrg	DBG(("%s changes=%lx\n", __FUNCTION__, changes));
138428d7b3dSmrg
139428d7b3dSmrg	if (changes & GCStipple) {
140428d7b3dSmrg		pgc->evenStipple = FALSE;
141428d7b3dSmrg
142428d7b3dSmrg		if (gc->stipple) {
143428d7b3dSmrg			/* can we do an even stipple ?? */
144428d7b3dSmrg			if (FbEvenStip(gc->stipple->drawable.width,
145428d7b3dSmrg				       drawable->bitsPerPixel) &&
146428d7b3dSmrg			    (fbCanEvenStipple(gc->stipple, drawable->bitsPerPixel)))
147428d7b3dSmrg				pgc->evenStipple = TRUE;
148428d7b3dSmrg		}
149428d7b3dSmrg	}
150428d7b3dSmrg
151428d7b3dSmrg	/*
152428d7b3dSmrg	 * Recompute reduced rop values
153428d7b3dSmrg	 */
154428d7b3dSmrg	if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
155428d7b3dSmrg		int s;
156428d7b3dSmrg		FbBits depthMask;
157428d7b3dSmrg
158428d7b3dSmrg		mask = FbFullMask(drawable->bitsPerPixel);
159428d7b3dSmrg		depthMask = FbFullMask(drawable->depth);
160428d7b3dSmrg
161428d7b3dSmrg		DBG(("%s: computing rrop mask=%08x, depthMask=%08x, fg=%08x, bg=%08x, planemask=%08x\n",
162428d7b3dSmrg		     __FUNCTION__, mask, depthMask, (int)gc->fgPixel, (int)gc->bgPixel, (int)gc->planemask));
163428d7b3dSmrg
164428d7b3dSmrg		pgc->fg = gc->fgPixel & mask;
165428d7b3dSmrg		pgc->bg = gc->bgPixel & mask;
166428d7b3dSmrg
167428d7b3dSmrg		if ((gc->planemask & depthMask) == depthMask)
168428d7b3dSmrg			pgc->pm = mask;
169428d7b3dSmrg		else
170428d7b3dSmrg			pgc->pm = gc->planemask & mask;
171428d7b3dSmrg
172428d7b3dSmrg		s = drawable->bitsPerPixel;
173428d7b3dSmrg		while (s < FB_UNIT) {
174428d7b3dSmrg			pgc->fg |= pgc->fg << s;
175428d7b3dSmrg			pgc->bg |= pgc->bg << s;
176428d7b3dSmrg			pgc->pm |= pgc->pm << s;
177428d7b3dSmrg			s <<= 1;
178428d7b3dSmrg		}
179428d7b3dSmrg		pgc->and = fbAnd(gc->alu, pgc->fg, pgc->pm);
180428d7b3dSmrg		pgc->xor = fbXor(gc->alu, pgc->fg, pgc->pm);
181428d7b3dSmrg		pgc->bgand = fbAnd(gc->alu, pgc->bg, pgc->pm);
182428d7b3dSmrg		pgc->bgxor = fbXor(gc->alu, pgc->bg, pgc->pm);
183428d7b3dSmrg
184428d7b3dSmrg		DBG(("%s: rrop fg=%08x, bg=%08x, pm=%08x, and=%08x, xor=%08x, bgand=%08x, bgxor=%08x\n",
185428d7b3dSmrg		     __FUNCTION__, pgc->fg, pgc->bg, pgc->pm, pgc->and, pgc->xor, pgc->bgand, pgc->bgxor));
186428d7b3dSmrg	}
187428d7b3dSmrg
188428d7b3dSmrg	if (changes & GCDashList) {
189428d7b3dSmrg		unsigned short n = gc->numInDashList;
190428d7b3dSmrg		unsigned char *dash = gc->dash;
191428d7b3dSmrg		unsigned int dashLength = 0;
192428d7b3dSmrg
193428d7b3dSmrg		while (n--)
194428d7b3dSmrg			dashLength += (unsigned int) *dash++;
195428d7b3dSmrg		pgc->dashLength = dashLength;
196428d7b3dSmrg	}
197428d7b3dSmrg}
198