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 <stdlib.h>
28
29#include "fb.h"
30
31/* Compatibility wrapper, to be removed at next ABI change. */
32void
33fbCopyRegion (DrawablePtr   pSrcDrawable,
34             DrawablePtr   pDstDrawable,
35             GCPtr         pGC,
36             RegionPtr     pDstRegion,
37             int           dx,
38             int           dy,
39             fbCopyProc    copyProc,
40             Pixel         bitPlane,
41             void          *closure)
42{
43    miCopyRegion(pSrcDrawable, pDstDrawable, pGC, pDstRegion, dx, dy, copyProc, bitPlane, closure);
44}
45
46/* Compatibility wrapper, to be removed at next ABI change. */
47RegionPtr
48fbDoCopy (DrawablePtr  pSrcDrawable,
49         DrawablePtr   pDstDrawable,
50         GCPtr         pGC,
51         int           xIn,
52         int           yIn,
53         int           widthSrc,
54         int           heightSrc,
55         int           xOut,
56         int           yOut,
57         fbCopyProc    copyProc,
58         Pixel         bitPlane,
59         void          *closure)
60{
61    return miDoCopy(pSrcDrawable, pDstDrawable, pGC, xIn, yIn, widthSrc, heightSrc, xOut, yOut, copyProc, bitPlane, closure);
62}
63
64void
65fbCopyNtoN (DrawablePtr	pSrcDrawable,
66	    DrawablePtr	pDstDrawable,
67	    GCPtr	pGC,
68	    BoxPtr	pbox,
69	    int		nbox,
70	    int		dx,
71	    int		dy,
72	    Bool	reverse,
73	    Bool	upsidedown,
74	    Pixel	bitplane,
75	    void	*closure)
76{
77    CARD8	alu = pGC ? pGC->alu : GXcopy;
78    FbBits	pm = pGC ? fbGetGCPrivate(pGC)->pm : FB_ALLONES;
79    FbBits	*src;
80    FbStride	srcStride;
81    int		srcBpp;
82    int		srcXoff, srcYoff;
83    FbBits	*dst;
84    FbStride	dstStride;
85    int		dstBpp;
86    int		dstXoff, dstYoff;
87
88    fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
89    fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
90
91    while (nbox--)
92    {
93#ifndef FB_ACCESS_WRAPPER /* pixman_blt() doesn't support accessors yet */
94	if (pm == FB_ALLONES && alu == GXcopy && !reverse &&
95	    !upsidedown)
96	{
97	    if (!pixman_blt ((uint32_t *)src, (uint32_t *)dst, srcStride, dstStride, srcBpp, dstBpp,
98			     (pbox->x1 + dx + srcXoff),
99			     (pbox->y1 + dy + srcYoff),
100			     (pbox->x1 + dstXoff),
101			     (pbox->y1 + dstYoff),
102			     (pbox->x2 - pbox->x1),
103			     (pbox->y2 - pbox->y1)))
104		goto fallback;
105	    else
106		goto next;
107	}
108    fallback:
109#endif
110	fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride,
111	       srcStride,
112	       (pbox->x1 + dx + srcXoff) * srcBpp,
113
114	       dst + (pbox->y1 + dstYoff) * dstStride,
115	       dstStride,
116	       (pbox->x1 + dstXoff) * dstBpp,
117
118	       (pbox->x2 - pbox->x1) * dstBpp,
119	       (pbox->y2 - pbox->y1),
120
121	       alu,
122	       pm,
123	       dstBpp,
124
125	       reverse,
126	       upsidedown);
127#ifndef FB_ACCESS_WRAPPER
128    next:
129#endif
130	pbox++;
131    }
132    fbFinishAccess (pDstDrawable);
133    fbFinishAccess (pSrcDrawable);
134}
135
136void
137fbCopy1toN (DrawablePtr	pSrcDrawable,
138	    DrawablePtr	pDstDrawable,
139	    GCPtr	pGC,
140	    BoxPtr	pbox,
141	    int		nbox,
142	    int		dx,
143	    int		dy,
144	    Bool	reverse,
145	    Bool	upsidedown,
146	    Pixel	bitplane,
147	    void	*closure)
148{
149    FbGCPrivPtr	pPriv = fbGetGCPrivate(pGC);
150    FbBits	*src;
151    FbStride	srcStride;
152    int		srcBpp;
153    int		srcXoff, srcYoff;
154    FbBits	*dst;
155    FbStride	dstStride;
156    int		dstBpp;
157    int		dstXoff, dstYoff;
158
159    fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
160    fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
161
162    while (nbox--)
163    {
164	if (dstBpp == 1)
165	{
166	    fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride,
167		   srcStride,
168		   (pbox->x1 + dx + srcXoff) * srcBpp,
169
170		   dst + (pbox->y1 + dstYoff) * dstStride,
171		   dstStride,
172		   (pbox->x1 + dstXoff) * dstBpp,
173
174		   (pbox->x2 - pbox->x1) * dstBpp,
175		   (pbox->y2 - pbox->y1),
176
177		   FbOpaqueStipple1Rop(pGC->alu,
178				       pGC->fgPixel,pGC->bgPixel),
179		   pPriv->pm,
180		   dstBpp,
181
182		   reverse,
183		   upsidedown);
184	}
185	else
186	{
187	    fbBltOne ((FbStip *) (src + (pbox->y1 + dy + srcYoff) * srcStride),
188		      srcStride*(FB_UNIT/FB_STIP_UNIT),
189		      (pbox->x1 + dx + srcXoff),
190
191		      dst + (pbox->y1 + dstYoff) * dstStride,
192		      dstStride,
193		      (pbox->x1 + dstXoff) * dstBpp,
194		      dstBpp,
195
196		      (pbox->x2 - pbox->x1) * dstBpp,
197		      (pbox->y2 - pbox->y1),
198
199		      pPriv->and, pPriv->xor,
200		      pPriv->bgand, pPriv->bgxor);
201	}
202	pbox++;
203    }
204
205    fbFinishAccess (pDstDrawable);
206    fbFinishAccess (pSrcDrawable);
207}
208
209void
210fbCopyNto1 (DrawablePtr	pSrcDrawable,
211	    DrawablePtr	pDstDrawable,
212	    GCPtr	pGC,
213	    BoxPtr	pbox,
214	    int		nbox,
215	    int		dx,
216	    int		dy,
217	    Bool	reverse,
218	    Bool	upsidedown,
219	    Pixel	bitplane,
220	    void	*closure)
221{
222    FbGCPrivPtr	pPriv = fbGetGCPrivate (pGC);
223
224    while (nbox--)
225    {
226	if (pDstDrawable->bitsPerPixel == 1)
227	{
228	    FbBits	*src;
229	    FbStride    srcStride;
230	    int		srcBpp;
231	    int		srcXoff, srcYoff;
232
233	    FbStip	*dst;
234	    FbStride    dstStride;
235	    int		dstBpp;
236	    int		dstXoff, dstYoff;
237
238	    fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
239	    fbGetStipDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
240	    fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride,
241			srcStride,
242			(pbox->x1 + dx + srcXoff) * srcBpp,
243			srcBpp,
244
245			dst + (pbox->y1 + dstYoff) * dstStride,
246			dstStride,
247			(pbox->x1 + dstXoff) * dstBpp,
248
249			(pbox->x2 - pbox->x1) * srcBpp,
250			(pbox->y2 - pbox->y1),
251
252			(FbStip) pPriv->and, (FbStip) pPriv->xor,
253			(FbStip) pPriv->bgand, (FbStip) pPriv->bgxor,
254			bitplane);
255	    fbFinishAccess (pDstDrawable);
256	    fbFinishAccess (pSrcDrawable);
257	}
258	else
259	{
260	    FbBits	*src;
261	    FbStride    srcStride;
262	    int		srcBpp;
263	    int         srcXoff, srcYoff;
264
265	    FbBits	*dst;
266	    FbStride    dstStride;
267	    int		dstBpp;
268	    int		dstXoff, dstYoff;
269
270	    FbStip	*tmp;
271	    FbStride    tmpStride;
272	    int		width, height;
273
274	    width = pbox->x2 - pbox->x1;
275	    height = pbox->y2 - pbox->y1;
276
277	    tmpStride = ((width + FB_STIP_MASK) >> FB_STIP_SHIFT);
278	    tmp = malloc(tmpStride * height * sizeof (FbStip));
279	    if (!tmp)
280		return;
281
282	    fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
283	    fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
284
285	    fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride,
286			srcStride,
287			(pbox->x1 + dx + srcXoff) * srcBpp,
288			srcBpp,
289
290			tmp,
291			tmpStride,
292			0,
293
294			width * srcBpp,
295			height,
296
297			fbAndStip(GXcopy,FB_ALLONES,FB_ALLONES),
298			fbXorStip(GXcopy,FB_ALLONES,FB_ALLONES),
299			fbAndStip(GXcopy,0,FB_ALLONES),
300			fbXorStip(GXcopy,0,FB_ALLONES),
301			bitplane);
302	    fbBltOne (tmp,
303		      tmpStride,
304		      0,
305
306		      dst + (pbox->y1 + dstYoff) * dstStride,
307		      dstStride,
308		      (pbox->x1 + dstXoff) * dstBpp,
309		      dstBpp,
310
311		      width * dstBpp,
312		      height,
313
314		      pPriv->and, pPriv->xor,
315		      pPriv->bgand, pPriv->bgxor);
316	    free(tmp);
317
318	    fbFinishAccess (pDstDrawable);
319	    fbFinishAccess (pSrcDrawable);
320	}
321	pbox++;
322    }
323}
324
325RegionPtr
326fbCopyArea (DrawablePtr	pSrcDrawable,
327	    DrawablePtr	pDstDrawable,
328	    GCPtr	pGC,
329	    int		xIn,
330	    int		yIn,
331	    int		widthSrc,
332	    int		heightSrc,
333	    int		xOut,
334	    int		yOut)
335{
336    miCopyProc	copy;
337
338#ifdef FB_24_32BIT
339    if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
340	copy = fb24_32CopyMtoN;
341    else
342#endif
343	copy = fbCopyNtoN;
344    return miDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
345		     widthSrc, heightSrc, xOut, yOut, copy, 0, 0);
346}
347
348RegionPtr
349fbCopyPlane (DrawablePtr    pSrcDrawable,
350	     DrawablePtr    pDstDrawable,
351	     GCPtr	    pGC,
352	     int	    xIn,
353	     int	    yIn,
354	     int	    widthSrc,
355	     int	    heightSrc,
356	     int	    xOut,
357	     int	    yOut,
358	     unsigned long  bitplane)
359{
360    if (pSrcDrawable->bitsPerPixel > 1)
361	return miDoCopy (pSrcDrawable, pDstDrawable, pGC,
362			 xIn, yIn, widthSrc, heightSrc,
363			 xOut, yOut, fbCopyNto1, (Pixel) bitplane, 0);
364    else if (bitplane & 1)
365	return miDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
366			 widthSrc, heightSrc, xOut, yOut, fbCopy1toN,
367			 (Pixel) bitplane, 0);
368    else
369	return miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
370				 xIn, yIn,
371				 widthSrc,
372				 heightSrc,
373				 xOut, yOut, bitplane);
374}
375