1/*
2 * Copyright © 1998 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26
27#include <string.h>
28
29#include "fb.h"
30
31void
32fbPutImage (DrawablePtr	pDrawable,
33	    GCPtr	pGC,
34	    int		depth,
35	    int		x,
36	    int		y,
37	    int		w,
38	    int		h,
39	    int		leftPad,
40	    int		format,
41	    char	*pImage)
42{
43    FbGCPrivPtr	    pPriv = fbGetGCPrivate(pGC);
44    unsigned long   i;
45    FbStride	    srcStride;
46    FbStip	    *src = (FbStip *) pImage;
47
48    x += pDrawable->x;
49    y += pDrawable->y;
50
51    switch (format)
52    {
53    case XYBitmap:
54	srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip);
55	fbPutXYImage (pDrawable,
56		      fbGetCompositeClip(pGC),
57		      pPriv->fg,
58		      pPriv->bg,
59		      pPriv->pm,
60		      pGC->alu,
61		      TRUE,
62		      x, y, w, h,
63		      src,
64		      srcStride,
65		      leftPad);
66	break;
67    case XYPixmap:
68	srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip);
69	for (i = (unsigned long)1 << (pDrawable->depth - 1); i; i >>= 1)
70	{
71	    if (i & pGC->planemask)
72	    {
73		fbPutXYImage (pDrawable,
74			      fbGetCompositeClip(pGC),
75			      FB_ALLONES,
76			      0,
77			      fbReplicatePixel (i, pDrawable->bitsPerPixel),
78			      pGC->alu,
79			      TRUE,
80			      x, y, w, h,
81			      src,
82			      srcStride,
83			      leftPad);
84		src += srcStride * h;
85	    }
86	}
87	break;
88    case ZPixmap:
89#ifdef FB_24_32BIT
90	if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth))
91	{
92	    srcStride = PixmapBytePad(w, pDrawable->depth);
93	    fb24_32PutZImage (pDrawable,
94			      fbGetCompositeClip(pGC),
95			      pGC->alu,
96			      (FbBits) pGC->planemask,
97			      x, y, w, h,
98			      (CARD8 *) pImage,
99			      srcStride);
100	}
101	else
102#endif
103	{
104	    srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof (FbStip);
105	    fbPutZImage (pDrawable,
106			 fbGetCompositeClip(pGC),
107			 pGC->alu,
108			 pPriv->pm,
109			 x, y, w, h,
110			 src, srcStride);
111	}
112    }
113}
114
115void
116fbPutZImage (DrawablePtr	pDrawable,
117	     RegionPtr		pClip,
118	     int		alu,
119	     FbBits		pm,
120	     int		x,
121	     int		y,
122	     int		width,
123	     int		height,
124	     FbStip		*src,
125	     FbStride		srcStride)
126{
127    FbStip	*dst;
128    FbStride	dstStride;
129    int		dstBpp;
130    int		dstXoff, dstYoff;
131    int		nbox;
132    BoxPtr	pbox;
133    int		x1, y1, x2, y2;
134
135    fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
136
137    for (nbox = RegionNumRects (pClip),
138	 pbox = RegionRects(pClip);
139	 nbox--;
140	 pbox++)
141    {
142	x1 = x;
143	y1 = y;
144	x2 = x + width;
145	y2 = y + height;
146	if (x1 < pbox->x1)
147	    x1 = pbox->x1;
148	if (y1 < pbox->y1)
149	    y1 = pbox->y1;
150	if (x2 > pbox->x2)
151	    x2 = pbox->x2;
152	if (y2 > pbox->y2)
153	    y2 = pbox->y2;
154	if (x1 >= x2 || y1 >= y2)
155	    continue;
156	fbBltStip (src + (y1 - y) * srcStride,
157		   srcStride,
158		   (x1 - x) * dstBpp,
159
160		   dst + (y1 + dstYoff) * dstStride,
161		   dstStride,
162		   (x1 + dstXoff) * dstBpp,
163
164		   (x2 - x1) * dstBpp,
165		   (y2 - y1),
166
167		   alu,
168		   pm,
169		   dstBpp);
170    }
171
172    fbFinishAccess (pDrawable);
173}
174
175void
176fbPutXYImage (DrawablePtr	pDrawable,
177	      RegionPtr		pClip,
178	      FbBits		fg,
179	      FbBits		bg,
180	      FbBits		pm,
181	      int		alu,
182	      Bool		opaque,
183
184	      int		x,
185	      int		y,
186	      int		width,
187	      int		height,
188
189	      FbStip		*src,
190	      FbStride		srcStride,
191	      int		srcX)
192{
193    FbBits	*dst;
194    FbStride	dstStride;
195    int		dstBpp;
196    int		dstXoff, dstYoff;
197    int		nbox;
198    BoxPtr	pbox;
199    int		x1, y1, x2, y2;
200    FbBits	fgand = 0, fgxor = 0, bgand = 0, bgxor = 0;
201
202    fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
203
204    if (dstBpp == 1)
205    {
206	if (opaque)
207	    alu = FbOpaqueStipple1Rop(alu,fg,bg);
208	else
209	    alu = FbStipple1Rop(alu,fg);
210    }
211    else
212    {
213	fgand = fbAnd(alu,fg,pm);
214	fgxor = fbXor(alu,fg,pm);
215	if (opaque)
216	{
217	    bgand = fbAnd(alu,bg,pm);
218	    bgxor = fbXor(alu,bg,pm);
219	}
220	else
221	{
222	    bgand = fbAnd(GXnoop,(FbBits)0,FB_ALLONES);
223	    bgxor = fbXor(GXnoop,(FbBits)0,FB_ALLONES);
224	}
225    }
226
227    for (nbox = RegionNumRects (pClip),
228	 pbox = RegionRects(pClip);
229	 nbox--;
230	 pbox++)
231    {
232	x1 = x;
233	y1 = y;
234	x2 = x + width;
235	y2 = y + height;
236	if (x1 < pbox->x1)
237	    x1 = pbox->x1;
238	if (y1 < pbox->y1)
239	    y1 = pbox->y1;
240	if (x2 > pbox->x2)
241	    x2 = pbox->x2;
242	if (y2 > pbox->y2)
243	    y2 = pbox->y2;
244	if (x1 >= x2 || y1 >= y2)
245	    continue;
246	if (dstBpp == 1)
247	{
248	    fbBltStip (src + (y1 - y) * srcStride,
249		       srcStride,
250		       (x1 - x) + srcX,
251
252		       (FbStip *) (dst + (y1 + dstYoff) * dstStride),
253		       FbBitsStrideToStipStride(dstStride),
254		       (x1 + dstXoff) * dstBpp,
255
256		       (x2 - x1) * dstBpp,
257		       (y2 - y1),
258
259		       alu,
260		       pm,
261		       dstBpp);
262	}
263	else
264	{
265	    fbBltOne (src + (y1 - y) * srcStride,
266		      srcStride,
267		      (x1 - x) + srcX,
268
269		      dst + (y1 + dstYoff) * dstStride,
270		      dstStride,
271		      (x1 + dstXoff) * dstBpp,
272		      dstBpp,
273
274		      (x2 - x1) * dstBpp,
275		      (y2 - y1),
276
277		      fgand, fgxor, bgand, bgxor);
278	}
279    }
280
281    fbFinishAccess (pDrawable);
282}
283
284void
285fbGetImage (DrawablePtr	    pDrawable,
286	    int		    x,
287	    int		    y,
288	    int		    w,
289	    int		    h,
290	    unsigned int    format,
291	    unsigned long   planeMask,
292	    char	    *d)
293{
294    FbBits	    *src;
295    FbStride	    srcStride;
296    int		    srcBpp;
297    int		    srcXoff, srcYoff;
298    FbStip	    *dst;
299    FbStride	    dstStride;
300
301    /*
302     * XFree86 DDX empties the root borderClip when the VT is
303     * switched away; this checks for that case
304     */
305    if (!fbDrawableEnabled(pDrawable))
306	return;
307
308#ifdef FB_24_32BIT
309    if (format == ZPixmap &&
310	pDrawable->bitsPerPixel != BitsPerPixel (pDrawable->depth))
311    {
312	fb24_32GetImage (pDrawable, x, y, w, h, format, planeMask, d);
313	return;
314    }
315#endif
316
317    fbGetDrawable (pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
318
319    x += pDrawable->x;
320    y += pDrawable->y;
321
322    dst = (FbStip *) d;
323    if (format == ZPixmap || srcBpp == 1)
324    {
325	FbBits	pm;
326
327	pm = fbReplicatePixel (planeMask, srcBpp);
328	dstStride = PixmapBytePad(w, pDrawable->depth);
329	if (pm != FB_ALLONES)
330	    memset (d, 0, dstStride * h);
331	dstStride /= sizeof (FbStip);
332	fbBltStip ((FbStip *) (src + (y + srcYoff) * srcStride),
333		   FbBitsStrideToStipStride(srcStride),
334		   (x + srcXoff) * srcBpp,
335
336		   dst,
337		   dstStride,
338		   0,
339
340		   w * srcBpp, h,
341
342		   GXcopy,
343		   pm,
344		   srcBpp);
345    }
346    else
347    {
348	dstStride = BitmapBytePad(w) / sizeof (FbStip);
349	fbBltPlane (src + (y + srcYoff) * srcStride,
350		    srcStride,
351		    (x + srcXoff) * srcBpp,
352		    srcBpp,
353
354		    dst,
355		    dstStride,
356		    0,
357
358		    w * srcBpp, h,
359
360		    fbAndStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES),
361		    fbXorStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES),
362		    fbAndStip(GXcopy,0,FB_STIP_ALLONES),
363		    fbXorStip(GXcopy,0,FB_STIP_ALLONES),
364		    planeMask);
365    }
366
367    fbFinishAccess (pDrawable);
368}
369