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 "fbclip.h"
26
27static void
28fbPushPattern(DrawablePtr drawable, GCPtr gc,
29              FbStip *src, FbStride srcStride, int srcX,
30	      int x, int y, int width, int height)
31{
32	FbStip *s, bitsMask, bitsMask0, bits;
33	int xspan;
34	int w;
35	int lenspan;
36
37	src += srcX >> FB_STIP_SHIFT;
38	srcX &= FB_STIP_MASK;
39
40	bitsMask0 = FbStipMask(srcX, 1);
41
42	while (height--) {
43		bitsMask = bitsMask0;
44		w = width;
45		s = src;
46		src += srcStride;
47		bits = READ(s++);
48		xspan = x;
49		while (w) {
50			if (bits & bitsMask) {
51				lenspan = 0;
52				do {
53					if (++lenspan == w)
54						break;
55
56					bitsMask = FbStipRight(bitsMask, 1);
57					if (!bitsMask) {
58						bits = READ(s++);
59						bitsMask = FbBitsMask(0, 1);
60					}
61				} while (bits & bitsMask);
62				fbFill(drawable, gc, xspan, y, lenspan, 1);
63				xspan += lenspan;
64				w -= lenspan;
65			} else {
66				do {
67					xspan++;
68					if (!--w)
69						break;
70
71					bitsMask = FbStipRight(bitsMask, 1);
72					if (!bitsMask) {
73						bits = READ(s++);
74						bitsMask = FbBitsMask(0, 1);
75					}
76				} while (!(bits & bitsMask));
77			}
78		}
79		y++;
80	}
81}
82
83static void
84fbPushFill(DrawablePtr drawable, GCPtr gc,
85           FbStip *src, FbStride srcStride, int srcX,
86	   int x, int y, int width, int height)
87{
88	FbGCPrivPtr pgc = fb_gc(gc);
89
90	if (gc->fillStyle == FillSolid) {
91		FbBits *dst;
92		FbStride dstStride;
93		int dstBpp;
94		int dstXoff, dstYoff;
95		int dstX;
96		int dstWidth;
97
98		fbGetDrawable(drawable, dst,
99			      dstStride, dstBpp, dstXoff, dstYoff);
100		dst = dst + (y + dstYoff) * dstStride;
101		dstX = (x + dstXoff) * dstBpp;
102		dstWidth = width * dstBpp;
103		if (dstBpp == 1) {
104			fbBltStip(src, srcStride, srcX,
105				  (FbStip *)dst, dstStride, dstX,
106				  dstWidth, height,
107				  FbStipple1Rop(gc->alu, gc->fgPixel), pgc->pm, dstBpp);
108		} else {
109			fbBltOne(src, srcStride, srcX,
110				 dst, dstStride, dstX, dstBpp,
111				 dstWidth, height,
112				 pgc->and, pgc->xor,
113				 fbAnd(GXnoop, (FbBits) 0, FB_ALLONES),
114				 fbXor(GXnoop, (FbBits) 0, FB_ALLONES));
115		}
116	} else
117		fbPushPattern(drawable, gc, src, srcStride, srcX,
118			      x, y, width, height);
119}
120
121struct fbPushImage {
122	FbStip *src;
123	FbStride stride;
124	int x0, y0;
125};
126
127inline static void
128_fbPushImage(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data)
129{
130	struct fbPushImage *data = _data;
131
132	fbPushFill(drawable, gc,
133		   data->src + (b->y1 - data->y0) * data->stride, data->stride,
134		   b->x1 - data->x0,
135		   b->x1, b->y1,
136		   b->x2 - b->x1, b->y2 - b->y1);
137}
138
139void
140fbPushImage(DrawablePtr drawable, GCPtr gc,
141            FbStip *src, FbStride stride, int dx,
142	    int x, int y, int width, int height)
143{
144	struct fbPushImage data;
145	BoxRec box;
146
147	DBG(("%s (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, width, height));
148
149	data.src = src;
150	data.stride = stride;
151	data.y0 = y;
152	data.x0 = x - dx;
153
154	box.x1 = x;
155	box.y1 = y;
156	box.x2 = x + width;
157	box.y2 = y + height;
158	fbDrawableRun(drawable, gc, &box, _fbPushImage, &data);
159}
160
161void
162fbPushPixels(GCPtr gc, PixmapPtr bitmap, DrawablePtr drawable,
163	     int dx, int dy, int xOrg, int yOrg)
164{
165	FbStip *stip;
166	FbStride stipStride;
167	int stipBpp;
168	_X_UNUSED int stipXoff, stipYoff;
169
170	DBG(("%s bitmap=%x%d\n", __FUNCTION__,
171	     bitmap->drawable.width, bitmap->drawable.height));
172
173	fbGetStipDrawable(&bitmap->drawable, stip,
174			  stipStride, stipBpp, stipXoff, stipYoff);
175
176	fbPushImage(drawable, gc, stip, stipStride, 0, xOrg, yOrg, dx, dy);
177}
178