fbgc.c revision 03b705cf
1/*
2 * Copyright © 1998 Keith Packard
3 * Copyright © 2012 Intel Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Keith Packard makes no
12 * representations about the suitability of this software for any purpose.  It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include "fb.h"
25#include <gcstruct.h>
26#include <migc.h>
27#include <scrnintstr.h>
28
29/*
30 * Pad pixmap to FB_UNIT bits wide
31 */
32void
33fbPadPixmap(PixmapPtr pPixmap)
34{
35	int width;
36	FbBits *bits;
37	FbBits b;
38	FbBits mask;
39	int height;
40	int w;
41	int stride;
42	int bpp;
43	_X_UNUSED int xOff, yOff;
44
45	fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff);
46
47	width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
48	height = pPixmap->drawable.height;
49	mask = FbBitsMask(0, width);
50	while (height--) {
51		b = READ(bits) & mask;
52		w = width;
53		while (w < FB_UNIT) {
54			b = b | FbScrRight(b, w);
55			w <<= 1;
56		}
57		WRITE(bits, b);
58		bits += stride;
59	}
60}
61
62/*
63 * Verify that 'bits' repeats every 'len' bits
64 */
65static Bool
66fbBitsRepeat(FbBits bits, int len, int width)
67{
68	FbBits mask = FbBitsMask(0, len);
69	FbBits orig = bits & mask;
70	int i;
71
72	if (width > FB_UNIT)
73		width = FB_UNIT;
74	for (i = 0; i < width / len; i++) {
75		if ((bits & mask) != orig)
76			return FALSE;
77		bits = FbScrLeft(bits, len);
78	}
79	return TRUE;
80}
81
82/*
83 * Check whether an entire bitmap line is a repetition of
84 * the first 'len' bits
85 */
86static Bool
87fbLineRepeat(FbBits * bits, int len, int width)
88{
89	FbBits first = bits[0];
90
91	if (!fbBitsRepeat(first, len, width))
92		return FALSE;
93	width = (width + FB_UNIT - 1) >> FB_SHIFT;
94	bits++;
95	while (--width)
96		if (READ(bits) != first)
97			return FALSE;
98	return TRUE;
99}
100
101/*
102 * The even stipple code wants the first FB_UNIT/bpp bits on
103 * each scanline to represent the entire stipple
104 */
105static Bool
106fbCanEvenStipple(PixmapPtr pStipple, int bpp)
107{
108	int len = FB_UNIT / bpp;
109	FbBits *bits;
110	int stride;
111	int stip_bpp;
112	_X_UNUSED int stipXoff, stipYoff;
113	int h;
114
115	/* make sure the stipple width is a multiple of the even stipple width */
116	if (pStipple->drawable.width % len != 0)
117		return FALSE;
118
119	fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff,
120		      stipYoff);
121	h = pStipple->drawable.height;
122	/* check to see that the stipple repeats horizontally */
123	while (h--) {
124		if (!fbLineRepeat(bits, len, pStipple->drawable.width))
125			return FALSE;
126
127		bits += stride;
128	}
129	return TRUE;
130}
131
132void
133fbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable)
134{
135	FbGCPrivPtr pgc = fb_gc(gc);
136	FbBits mask;
137
138	DBG(("%s changes=%lx\n", __FUNCTION__, changes));
139
140	if (changes & GCStipple) {
141		pgc->evenStipple = FALSE;
142
143		if (gc->stipple) {
144			/* can we do an even stipple ?? */
145			if (FbEvenStip(gc->stipple->drawable.width,
146				       drawable->bitsPerPixel) &&
147			    (fbCanEvenStipple(gc->stipple, drawable->bitsPerPixel)))
148				pgc->evenStipple = TRUE;
149		}
150	}
151
152	/*
153	 * Recompute reduced rop values
154	 */
155	if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) {
156		int s;
157		FbBits depthMask;
158
159		mask = FbFullMask(drawable->bitsPerPixel);
160		depthMask = FbFullMask(drawable->depth);
161
162		DBG(("%s: computing rrop mask=%08x, depthMask=%08x, fg=%08x, bg=%08x, planemask=%08x\n",
163		     __FUNCTION__, mask, depthMask, (int)gc->fgPixel, (int)gc->bgPixel, (int)gc->planemask));
164
165		pgc->fg = gc->fgPixel & mask;
166		pgc->bg = gc->bgPixel & mask;
167
168		if ((gc->planemask & depthMask) == depthMask)
169			pgc->pm = mask;
170		else
171			pgc->pm = gc->planemask & mask;
172
173		s = drawable->bitsPerPixel;
174		while (s < FB_UNIT) {
175			pgc->fg |= pgc->fg << s;
176			pgc->bg |= pgc->bg << s;
177			pgc->pm |= pgc->pm << s;
178			s <<= 1;
179		}
180		pgc->and = fbAnd(gc->alu, pgc->fg, pgc->pm);
181		pgc->xor = fbXor(gc->alu, pgc->fg, pgc->pm);
182		pgc->bgand = fbAnd(gc->alu, pgc->bg, pgc->pm);
183		pgc->bgxor = fbXor(gc->alu, pgc->bg, pgc->pm);
184
185		DBG(("%s: rrop fg=%08x, bg=%08x, pm=%08x, and=%08x, xor=%08x, bgand=%08x, bgxor=%08x\n",
186		     __FUNCTION__, pgc->fg, pgc->bg, pgc->pm, pgc->and, pgc->xor, pgc->bgand, pgc->bgxor));
187	}
188
189	if (changes & GCDashList) {
190		unsigned short n = gc->numInDashList;
191		unsigned char *dash = gc->dash;
192		unsigned int dashLength = 0;
193
194		while (n--)
195			dashLength += (unsigned int) *dash++;
196		pgc->dashLength = dashLength;
197	}
198}
199