1706f2543Smrg/*
2706f2543Smrg * Copyright © 1998 Keith Packard
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Keith Packard not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Keith Packard makes no
11706f2543Smrg * representations about the suitability of this software for any purpose.  It
12706f2543Smrg * is provided "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg */
22706f2543Smrg
23706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
24706f2543Smrg#include <dix-config.h>
25706f2543Smrg#endif
26706f2543Smrg
27706f2543Smrg#include <string.h>
28706f2543Smrg
29706f2543Smrg#include "fb.h"
30706f2543Smrg
31706f2543Smrgvoid
32706f2543SmrgfbPutImage (DrawablePtr	pDrawable,
33706f2543Smrg	    GCPtr	pGC,
34706f2543Smrg	    int		depth,
35706f2543Smrg	    int		x,
36706f2543Smrg	    int		y,
37706f2543Smrg	    int		w,
38706f2543Smrg	    int		h,
39706f2543Smrg	    int		leftPad,
40706f2543Smrg	    int		format,
41706f2543Smrg	    char	*pImage)
42706f2543Smrg{
43706f2543Smrg    FbGCPrivPtr	    pPriv = fbGetGCPrivate(pGC);
44706f2543Smrg    unsigned long   i;
45706f2543Smrg    FbStride	    srcStride;
46706f2543Smrg    FbStip	    *src = (FbStip *) pImage;
47706f2543Smrg
48706f2543Smrg    x += pDrawable->x;
49706f2543Smrg    y += pDrawable->y;
50706f2543Smrg
51706f2543Smrg    switch (format)
52706f2543Smrg    {
53706f2543Smrg    case XYBitmap:
54706f2543Smrg	srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip);
55706f2543Smrg	fbPutXYImage (pDrawable,
56706f2543Smrg		      fbGetCompositeClip(pGC),
57706f2543Smrg		      pPriv->fg,
58706f2543Smrg		      pPriv->bg,
59706f2543Smrg		      pPriv->pm,
60706f2543Smrg		      pGC->alu,
61706f2543Smrg		      TRUE,
62706f2543Smrg		      x, y, w, h,
63706f2543Smrg		      src,
64706f2543Smrg		      srcStride,
65706f2543Smrg		      leftPad);
66706f2543Smrg	break;
67706f2543Smrg    case XYPixmap:
68706f2543Smrg	srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip);
69706f2543Smrg	for (i = (unsigned long)1 << (pDrawable->depth - 1); i; i >>= 1)
70706f2543Smrg	{
71706f2543Smrg	    if (i & pGC->planemask)
72706f2543Smrg	    {
73706f2543Smrg		fbPutXYImage (pDrawable,
74706f2543Smrg			      fbGetCompositeClip(pGC),
75706f2543Smrg			      FB_ALLONES,
76706f2543Smrg			      0,
77706f2543Smrg			      fbReplicatePixel (i, pDrawable->bitsPerPixel),
78706f2543Smrg			      pGC->alu,
79706f2543Smrg			      TRUE,
80706f2543Smrg			      x, y, w, h,
81706f2543Smrg			      src,
82706f2543Smrg			      srcStride,
83706f2543Smrg			      leftPad);
84706f2543Smrg		src += srcStride * h;
85706f2543Smrg	    }
86706f2543Smrg	}
87706f2543Smrg	break;
88706f2543Smrg    case ZPixmap:
89706f2543Smrg#ifdef FB_24_32BIT
90706f2543Smrg	if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth))
91706f2543Smrg	{
92706f2543Smrg	    srcStride = PixmapBytePad(w, pDrawable->depth);
93706f2543Smrg	    fb24_32PutZImage (pDrawable,
94706f2543Smrg			      fbGetCompositeClip(pGC),
95706f2543Smrg			      pGC->alu,
96706f2543Smrg			      (FbBits) pGC->planemask,
97706f2543Smrg			      x, y, w, h,
98706f2543Smrg			      (CARD8 *) pImage,
99706f2543Smrg			      srcStride);
100706f2543Smrg	}
101706f2543Smrg	else
102706f2543Smrg#endif
103706f2543Smrg	{
104706f2543Smrg	    srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof (FbStip);
105706f2543Smrg	    fbPutZImage (pDrawable,
106706f2543Smrg			 fbGetCompositeClip(pGC),
107706f2543Smrg			 pGC->alu,
108706f2543Smrg			 pPriv->pm,
109706f2543Smrg			 x, y, w, h,
110706f2543Smrg			 src, srcStride);
111706f2543Smrg	}
112706f2543Smrg    }
113706f2543Smrg}
114706f2543Smrg
115706f2543Smrgvoid
116706f2543SmrgfbPutZImage (DrawablePtr	pDrawable,
117706f2543Smrg	     RegionPtr		pClip,
118706f2543Smrg	     int		alu,
119706f2543Smrg	     FbBits		pm,
120706f2543Smrg	     int		x,
121706f2543Smrg	     int		y,
122706f2543Smrg	     int		width,
123706f2543Smrg	     int		height,
124706f2543Smrg	     FbStip		*src,
125706f2543Smrg	     FbStride		srcStride)
126706f2543Smrg{
127706f2543Smrg    FbStip	*dst;
128706f2543Smrg    FbStride	dstStride;
129706f2543Smrg    int		dstBpp;
130706f2543Smrg    int		dstXoff, dstYoff;
131706f2543Smrg    int		nbox;
132706f2543Smrg    BoxPtr	pbox;
133706f2543Smrg    int		x1, y1, x2, y2;
134706f2543Smrg
135706f2543Smrg    fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
136706f2543Smrg
137706f2543Smrg    for (nbox = RegionNumRects (pClip),
138706f2543Smrg	 pbox = RegionRects(pClip);
139706f2543Smrg	 nbox--;
140706f2543Smrg	 pbox++)
141706f2543Smrg    {
142706f2543Smrg	x1 = x;
143706f2543Smrg	y1 = y;
144706f2543Smrg	x2 = x + width;
145706f2543Smrg	y2 = y + height;
146706f2543Smrg	if (x1 < pbox->x1)
147706f2543Smrg	    x1 = pbox->x1;
148706f2543Smrg	if (y1 < pbox->y1)
149706f2543Smrg	    y1 = pbox->y1;
150706f2543Smrg	if (x2 > pbox->x2)
151706f2543Smrg	    x2 = pbox->x2;
152706f2543Smrg	if (y2 > pbox->y2)
153706f2543Smrg	    y2 = pbox->y2;
154706f2543Smrg	if (x1 >= x2 || y1 >= y2)
155706f2543Smrg	    continue;
156706f2543Smrg	fbBltStip (src + (y1 - y) * srcStride,
157706f2543Smrg		   srcStride,
158706f2543Smrg		   (x1 - x) * dstBpp,
159706f2543Smrg
160706f2543Smrg		   dst + (y1 + dstYoff) * dstStride,
161706f2543Smrg		   dstStride,
162706f2543Smrg		   (x1 + dstXoff) * dstBpp,
163706f2543Smrg
164706f2543Smrg		   (x2 - x1) * dstBpp,
165706f2543Smrg		   (y2 - y1),
166706f2543Smrg
167706f2543Smrg		   alu,
168706f2543Smrg		   pm,
169706f2543Smrg		   dstBpp);
170706f2543Smrg    }
171706f2543Smrg
172706f2543Smrg    fbFinishAccess (pDrawable);
173706f2543Smrg}
174706f2543Smrg
175706f2543Smrgvoid
176706f2543SmrgfbPutXYImage (DrawablePtr	pDrawable,
177706f2543Smrg	      RegionPtr		pClip,
178706f2543Smrg	      FbBits		fg,
179706f2543Smrg	      FbBits		bg,
180706f2543Smrg	      FbBits		pm,
181706f2543Smrg	      int		alu,
182706f2543Smrg	      Bool		opaque,
183706f2543Smrg
184706f2543Smrg	      int		x,
185706f2543Smrg	      int		y,
186706f2543Smrg	      int		width,
187706f2543Smrg	      int		height,
188706f2543Smrg
189706f2543Smrg	      FbStip		*src,
190706f2543Smrg	      FbStride		srcStride,
191706f2543Smrg	      int		srcX)
192706f2543Smrg{
193706f2543Smrg    FbBits	*dst;
194706f2543Smrg    FbStride	dstStride;
195706f2543Smrg    int		dstBpp;
196706f2543Smrg    int		dstXoff, dstYoff;
197706f2543Smrg    int		nbox;
198706f2543Smrg    BoxPtr	pbox;
199706f2543Smrg    int		x1, y1, x2, y2;
200706f2543Smrg    FbBits	fgand = 0, fgxor = 0, bgand = 0, bgxor = 0;
201706f2543Smrg
202706f2543Smrg    fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
203706f2543Smrg
204706f2543Smrg    if (dstBpp == 1)
205706f2543Smrg    {
206706f2543Smrg	if (opaque)
207706f2543Smrg	    alu = FbOpaqueStipple1Rop(alu,fg,bg);
208706f2543Smrg	else
209706f2543Smrg	    alu = FbStipple1Rop(alu,fg);
210706f2543Smrg    }
211706f2543Smrg    else
212706f2543Smrg    {
213706f2543Smrg	fgand = fbAnd(alu,fg,pm);
214706f2543Smrg	fgxor = fbXor(alu,fg,pm);
215706f2543Smrg	if (opaque)
216706f2543Smrg	{
217706f2543Smrg	    bgand = fbAnd(alu,bg,pm);
218706f2543Smrg	    bgxor = fbXor(alu,bg,pm);
219706f2543Smrg	}
220706f2543Smrg	else
221706f2543Smrg	{
222706f2543Smrg	    bgand = fbAnd(GXnoop,(FbBits)0,FB_ALLONES);
223706f2543Smrg	    bgxor = fbXor(GXnoop,(FbBits)0,FB_ALLONES);
224706f2543Smrg	}
225706f2543Smrg    }
226706f2543Smrg
227706f2543Smrg    for (nbox = RegionNumRects (pClip),
228706f2543Smrg	 pbox = RegionRects(pClip);
229706f2543Smrg	 nbox--;
230706f2543Smrg	 pbox++)
231706f2543Smrg    {
232706f2543Smrg	x1 = x;
233706f2543Smrg	y1 = y;
234706f2543Smrg	x2 = x + width;
235706f2543Smrg	y2 = y + height;
236706f2543Smrg	if (x1 < pbox->x1)
237706f2543Smrg	    x1 = pbox->x1;
238706f2543Smrg	if (y1 < pbox->y1)
239706f2543Smrg	    y1 = pbox->y1;
240706f2543Smrg	if (x2 > pbox->x2)
241706f2543Smrg	    x2 = pbox->x2;
242706f2543Smrg	if (y2 > pbox->y2)
243706f2543Smrg	    y2 = pbox->y2;
244706f2543Smrg	if (x1 >= x2 || y1 >= y2)
245706f2543Smrg	    continue;
246706f2543Smrg	if (dstBpp == 1)
247706f2543Smrg	{
248706f2543Smrg	    fbBltStip (src + (y1 - y) * srcStride,
249706f2543Smrg		       srcStride,
250706f2543Smrg		       (x1 - x) + srcX,
251706f2543Smrg
252706f2543Smrg		       (FbStip *) (dst + (y1 + dstYoff) * dstStride),
253706f2543Smrg		       FbBitsStrideToStipStride(dstStride),
254706f2543Smrg		       (x1 + dstXoff) * dstBpp,
255706f2543Smrg
256706f2543Smrg		       (x2 - x1) * dstBpp,
257706f2543Smrg		       (y2 - y1),
258706f2543Smrg
259706f2543Smrg		       alu,
260706f2543Smrg		       pm,
261706f2543Smrg		       dstBpp);
262706f2543Smrg	}
263706f2543Smrg	else
264706f2543Smrg	{
265706f2543Smrg	    fbBltOne (src + (y1 - y) * srcStride,
266706f2543Smrg		      srcStride,
267706f2543Smrg		      (x1 - x) + srcX,
268706f2543Smrg
269706f2543Smrg		      dst + (y1 + dstYoff) * dstStride,
270706f2543Smrg		      dstStride,
271706f2543Smrg		      (x1 + dstXoff) * dstBpp,
272706f2543Smrg		      dstBpp,
273706f2543Smrg
274706f2543Smrg		      (x2 - x1) * dstBpp,
275706f2543Smrg		      (y2 - y1),
276706f2543Smrg
277706f2543Smrg		      fgand, fgxor, bgand, bgxor);
278706f2543Smrg	}
279706f2543Smrg    }
280706f2543Smrg
281706f2543Smrg    fbFinishAccess (pDrawable);
282706f2543Smrg}
283706f2543Smrg
284706f2543Smrgvoid
285706f2543SmrgfbGetImage (DrawablePtr	    pDrawable,
286706f2543Smrg	    int		    x,
287706f2543Smrg	    int		    y,
288706f2543Smrg	    int		    w,
289706f2543Smrg	    int		    h,
290706f2543Smrg	    unsigned int    format,
291706f2543Smrg	    unsigned long   planeMask,
292706f2543Smrg	    char	    *d)
293706f2543Smrg{
294706f2543Smrg    FbBits	    *src;
295706f2543Smrg    FbStride	    srcStride;
296706f2543Smrg    int		    srcBpp;
297706f2543Smrg    int		    srcXoff, srcYoff;
298706f2543Smrg    FbStip	    *dst;
299706f2543Smrg    FbStride	    dstStride;
300706f2543Smrg
301706f2543Smrg    /*
302706f2543Smrg     * XFree86 DDX empties the root borderClip when the VT is
303706f2543Smrg     * switched away; this checks for that case
304706f2543Smrg     */
305706f2543Smrg    if (!fbDrawableEnabled(pDrawable))
306706f2543Smrg	return;
307706f2543Smrg
308706f2543Smrg#ifdef FB_24_32BIT
309706f2543Smrg    if (format == ZPixmap &&
310706f2543Smrg	pDrawable->bitsPerPixel != BitsPerPixel (pDrawable->depth))
311706f2543Smrg    {
312706f2543Smrg	fb24_32GetImage (pDrawable, x, y, w, h, format, planeMask, d);
313706f2543Smrg	return;
314706f2543Smrg    }
315706f2543Smrg#endif
316706f2543Smrg
317706f2543Smrg    fbGetDrawable (pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
318706f2543Smrg
319706f2543Smrg    x += pDrawable->x;
320706f2543Smrg    y += pDrawable->y;
321706f2543Smrg
322706f2543Smrg    dst = (FbStip *) d;
323706f2543Smrg    if (format == ZPixmap || srcBpp == 1)
324706f2543Smrg    {
325706f2543Smrg	FbBits	pm;
326706f2543Smrg
327706f2543Smrg	pm = fbReplicatePixel (planeMask, srcBpp);
328706f2543Smrg	dstStride = PixmapBytePad(w, pDrawable->depth);
329706f2543Smrg	if (pm != FB_ALLONES)
330706f2543Smrg	    memset (d, 0, dstStride * h);
331706f2543Smrg	dstStride /= sizeof (FbStip);
332706f2543Smrg	fbBltStip ((FbStip *) (src + (y + srcYoff) * srcStride),
333706f2543Smrg		   FbBitsStrideToStipStride(srcStride),
334706f2543Smrg		   (x + srcXoff) * srcBpp,
335706f2543Smrg
336706f2543Smrg		   dst,
337706f2543Smrg		   dstStride,
338706f2543Smrg		   0,
339706f2543Smrg
340706f2543Smrg		   w * srcBpp, h,
341706f2543Smrg
342706f2543Smrg		   GXcopy,
343706f2543Smrg		   pm,
344706f2543Smrg		   srcBpp);
345706f2543Smrg    }
346706f2543Smrg    else
347706f2543Smrg    {
348706f2543Smrg	dstStride = BitmapBytePad(w) / sizeof (FbStip);
349706f2543Smrg	fbBltPlane (src + (y + srcYoff) * srcStride,
350706f2543Smrg		    srcStride,
351706f2543Smrg		    (x + srcXoff) * srcBpp,
352706f2543Smrg		    srcBpp,
353706f2543Smrg
354706f2543Smrg		    dst,
355706f2543Smrg		    dstStride,
356706f2543Smrg		    0,
357706f2543Smrg
358706f2543Smrg		    w * srcBpp, h,
359706f2543Smrg
360706f2543Smrg		    fbAndStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES),
361706f2543Smrg		    fbXorStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES),
362706f2543Smrg		    fbAndStip(GXcopy,0,FB_STIP_ALLONES),
363706f2543Smrg		    fbXorStip(GXcopy,0,FB_STIP_ALLONES),
364706f2543Smrg		    planeMask);
365706f2543Smrg    }
366706f2543Smrg
367706f2543Smrg    fbFinishAccess (pDrawable);
368706f2543Smrg}
369