1706f2543Smrg/*
2706f2543Smrg * Copyright © 2000 SuSE, Inc.
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 SuSE not be used in advertising or
9706f2543Smrg * publicity pertaining to distribution of the software without specific,
10706f2543Smrg * written prior permission.  SuSE makes no representations about the
11706f2543Smrg * suitability of this software for any purpose.  It is provided "as is"
12706f2543Smrg * without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15706f2543Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
16706f2543Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17706f2543Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18706f2543Smrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19706f2543Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20706f2543Smrg *
21706f2543Smrg * Author:  Keith Packard, SuSE, Inc.
22706f2543Smrg */
23706f2543Smrg
24706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
25706f2543Smrg#include <dix-config.h>
26706f2543Smrg#endif
27706f2543Smrg
28706f2543Smrg#include <string.h>
29706f2543Smrg
30706f2543Smrg#include "fb.h"
31706f2543Smrg
32706f2543Smrg/* X apps don't like 24bpp images, this code exposes 32bpp images */
33706f2543Smrg
34706f2543Smrg/*
35706f2543Smrg * These two functions do a full CopyArea while reformatting
36706f2543Smrg * the data between 24 and 32bpp.  They try to go a bit faster
37706f2543Smrg * by reading/writing aligned CARD32s where it's easy
38706f2543Smrg */
39706f2543Smrg
40706f2543Smrg#define Get8(a)	((CARD32) READ(a))
41706f2543Smrg
42706f2543Smrg#if BITMAP_BIT_ORDER == MSBFirst
43706f2543Smrg#define Get24(a)    ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2))
44706f2543Smrg#define Put24(a,p)  ((WRITE((a+0), (CARD8) ((p) >> 16))), \
45706f2543Smrg		     (WRITE((a+1), (CARD8) ((p) >> 8))), \
46706f2543Smrg		     (WRITE((a+2), (CARD8) (p))))
47706f2543Smrg#else
48706f2543Smrg#define Get24(a)    (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16))
49706f2543Smrg#define Put24(a,p)  ((WRITE((a+0), (CARD8) (p))), \
50706f2543Smrg		     (WRITE((a+1), (CARD8) ((p) >> 8))), \
51706f2543Smrg		     (WRITE((a+2), (CARD8) ((p) >> 16))))
52706f2543Smrg#endif
53706f2543Smrg
54706f2543Smrgtypedef void (*fb24_32BltFunc) (CARD8	    *srcLine,
55706f2543Smrg				FbStride    srcStride,
56706f2543Smrg				int	    srcX,
57706f2543Smrg
58706f2543Smrg				CARD8	    *dstLine,
59706f2543Smrg				FbStride    dstStride,
60706f2543Smrg				int	    dstX,
61706f2543Smrg
62706f2543Smrg				int	    width,
63706f2543Smrg				int	    height,
64706f2543Smrg
65706f2543Smrg				int	    alu,
66706f2543Smrg				FbBits	    pm);
67706f2543Smrg
68706f2543Smrgstatic void
69706f2543Smrgfb24_32BltDown (CARD8	    *srcLine,
70706f2543Smrg		FbStride    srcStride,
71706f2543Smrg		int	    srcX,
72706f2543Smrg
73706f2543Smrg		CARD8	    *dstLine,
74706f2543Smrg		FbStride    dstStride,
75706f2543Smrg		int	    dstX,
76706f2543Smrg
77706f2543Smrg		int	    width,
78706f2543Smrg		int	    height,
79706f2543Smrg
80706f2543Smrg		int	    alu,
81706f2543Smrg		FbBits	    pm)
82706f2543Smrg{
83706f2543Smrg    CARD32  *src;
84706f2543Smrg    CARD8   *dst;
85706f2543Smrg    int	    w;
86706f2543Smrg    Bool    destInvarient;
87706f2543Smrg    CARD32  pixel, dpixel;
88706f2543Smrg    FbDeclareMergeRop ();
89706f2543Smrg
90706f2543Smrg    srcLine += srcX * 4;
91706f2543Smrg    dstLine += dstX * 3;
92706f2543Smrg
93706f2543Smrg    FbInitializeMergeRop(alu, (pm | ~(FbBits) 0xffffff));
94706f2543Smrg    destInvarient = FbDestInvarientMergeRop();
95706f2543Smrg
96706f2543Smrg    while (height--)
97706f2543Smrg    {
98706f2543Smrg	src = (CARD32 *) srcLine;
99706f2543Smrg	dst = dstLine;
100706f2543Smrg	srcLine += srcStride;
101706f2543Smrg	dstLine += dstStride;
102706f2543Smrg	w = width;
103706f2543Smrg	if (destInvarient)
104706f2543Smrg	{
105706f2543Smrg	    while (((long) dst & 3) && w)
106706f2543Smrg	    {
107706f2543Smrg		w--;
108706f2543Smrg		pixel = READ(src++);
109706f2543Smrg		pixel = FbDoDestInvarientMergeRop(pixel);
110706f2543Smrg		Put24 (dst, pixel);
111706f2543Smrg		dst += 3;
112706f2543Smrg	    }
113706f2543Smrg	    /* Do four aligned pixels at a time */
114706f2543Smrg	    while (w >= 4)
115706f2543Smrg	    {
116706f2543Smrg		CARD32  s0, s1;
117706f2543Smrg		s0 = READ(src++);
118706f2543Smrg		s0 = FbDoDestInvarientMergeRop(s0);
119706f2543Smrg		s1 = READ(src++);
120706f2543Smrg		s1 = FbDoDestInvarientMergeRop(s1);
121706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst
122706f2543Smrg		WRITE((CARD32 *)dst, (s0 & 0xffffff) | (s1 << 24));
123706f2543Smrg#else
124706f2543Smrg		WRITE((CARD32 *)dst, (s0 << 8) | ((s1 & 0xffffff) >> 16));
125706f2543Smrg#endif
126706f2543Smrg		s0 = READ(src++);
127706f2543Smrg		s0 = FbDoDestInvarientMergeRop(s0);
128706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst
129706f2543Smrg		WRITE((CARD32 *)(dst+4), ((s1 & 0xffffff) >> 8) | (s0 << 16));
130706f2543Smrg#else
131706f2543Smrg		WRITE((CARD32 *)(dst+4), (s1 << 16) | ((s0 & 0xffffff) >> 8));
132706f2543Smrg#endif
133706f2543Smrg		s1 = READ(src++);
134706f2543Smrg		s1 = FbDoDestInvarientMergeRop(s1);
135706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst
136706f2543Smrg		WRITE((CARD32 *)(dst+8), ((s0 & 0xffffff) >> 16) | (s1 << 8));
137706f2543Smrg#else
138706f2543Smrg		WRITE((CARD32 *)(dst+8), (s0 << 24) | (s1 & 0xffffff));
139706f2543Smrg#endif
140706f2543Smrg		dst += 12;
141706f2543Smrg		w -= 4;
142706f2543Smrg	    }
143706f2543Smrg	    while (w--)
144706f2543Smrg	    {
145706f2543Smrg		pixel = READ(src++);
146706f2543Smrg		pixel = FbDoDestInvarientMergeRop(pixel);
147706f2543Smrg		Put24 (dst, pixel);
148706f2543Smrg		dst += 3;
149706f2543Smrg	    }
150706f2543Smrg	}
151706f2543Smrg	else
152706f2543Smrg	{
153706f2543Smrg	    while (w--)
154706f2543Smrg	    {
155706f2543Smrg		pixel = READ(src++);
156706f2543Smrg		dpixel = Get24 (dst);
157706f2543Smrg		pixel = FbDoMergeRop(pixel, dpixel);
158706f2543Smrg		Put24 (dst, pixel);
159706f2543Smrg		dst += 3;
160706f2543Smrg	    }
161706f2543Smrg	}
162706f2543Smrg    }
163706f2543Smrg}
164706f2543Smrg
165706f2543Smrgstatic void
166706f2543Smrgfb24_32BltUp (CARD8	    *srcLine,
167706f2543Smrg	      FbStride	    srcStride,
168706f2543Smrg	      int	    srcX,
169706f2543Smrg
170706f2543Smrg	      CARD8	    *dstLine,
171706f2543Smrg	      FbStride	    dstStride,
172706f2543Smrg	      int	    dstX,
173706f2543Smrg
174706f2543Smrg	      int	    width,
175706f2543Smrg	      int	    height,
176706f2543Smrg
177706f2543Smrg	      int	    alu,
178706f2543Smrg	      FbBits	    pm)
179706f2543Smrg{
180706f2543Smrg    CARD8   *src;
181706f2543Smrg    CARD32  *dst;
182706f2543Smrg    int	    w;
183706f2543Smrg    Bool    destInvarient;
184706f2543Smrg    CARD32  pixel;
185706f2543Smrg    FbDeclareMergeRop ();
186706f2543Smrg
187706f2543Smrg    FbInitializeMergeRop(alu, (pm | (~(FbBits) 0xffffff)));
188706f2543Smrg    destInvarient = FbDestInvarientMergeRop();
189706f2543Smrg
190706f2543Smrg    srcLine += srcX * 3;
191706f2543Smrg    dstLine += dstX * 4;
192706f2543Smrg
193706f2543Smrg    while (height--)
194706f2543Smrg    {
195706f2543Smrg	w = width;
196706f2543Smrg	src = srcLine;
197706f2543Smrg	dst = (CARD32 *) dstLine;
198706f2543Smrg	srcLine += srcStride;
199706f2543Smrg	dstLine += dstStride;
200706f2543Smrg	if (destInvarient)
201706f2543Smrg	{
202706f2543Smrg	    while (((long) src & 3) && w)
203706f2543Smrg	    {
204706f2543Smrg		w--;
205706f2543Smrg		pixel = Get24(src);
206706f2543Smrg		src += 3;
207706f2543Smrg		WRITE(dst++, FbDoDestInvarientMergeRop(pixel));
208706f2543Smrg	    }
209706f2543Smrg	    /* Do four aligned pixels at a time */
210706f2543Smrg	    while (w >= 4)
211706f2543Smrg	    {
212706f2543Smrg		CARD32  s0, s1;
213706f2543Smrg
214706f2543Smrg		s0 = READ((CARD32 *)src);
215706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst
216706f2543Smrg		pixel = s0 & 0xffffff;
217706f2543Smrg#else
218706f2543Smrg		pixel = s0 >> 8;
219706f2543Smrg#endif
220706f2543Smrg		WRITE(dst++, FbDoDestInvarientMergeRop(pixel));
221706f2543Smrg		s1 = READ((CARD32 *)(src+4));
222706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst
223706f2543Smrg		pixel = (s0 >> 24) | ((s1 << 8) & 0xffffff);
224706f2543Smrg#else
225706f2543Smrg		pixel = ((s0 << 16) & 0xffffff) | (s1 >> 16);
226706f2543Smrg#endif
227706f2543Smrg		WRITE(dst++, FbDoDestInvarientMergeRop(pixel));
228706f2543Smrg		s0 = READ((CARD32 *)(src+8));
229706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst
230706f2543Smrg		pixel = (s1 >> 16) | ((s0 << 16) & 0xffffff);
231706f2543Smrg#else
232706f2543Smrg		pixel = ((s1 << 8) & 0xffffff) | (s0 >> 24);
233706f2543Smrg#endif
234706f2543Smrg		WRITE(dst++, FbDoDestInvarientMergeRop(pixel));
235706f2543Smrg#if BITMAP_BIT_ORDER == LSBFirst
236706f2543Smrg		pixel = s0 >> 8;
237706f2543Smrg#else
238706f2543Smrg		pixel = s0 & 0xffffff;
239706f2543Smrg#endif
240706f2543Smrg		WRITE(dst++, FbDoDestInvarientMergeRop(pixel));
241706f2543Smrg		src += 12;
242706f2543Smrg		w -= 4;
243706f2543Smrg	    }
244706f2543Smrg	    while (w)
245706f2543Smrg	    {
246706f2543Smrg		w--;
247706f2543Smrg		pixel = Get24(src);
248706f2543Smrg		src += 3;
249706f2543Smrg		WRITE(dst++, FbDoDestInvarientMergeRop(pixel));
250706f2543Smrg	    }
251706f2543Smrg	}
252706f2543Smrg	else
253706f2543Smrg	{
254706f2543Smrg	    while (w--)
255706f2543Smrg	    {
256706f2543Smrg		pixel = Get24(src);
257706f2543Smrg		src += 3;
258706f2543Smrg		WRITE(dst, FbDoMergeRop(pixel, READ(dst)));
259706f2543Smrg		dst++;
260706f2543Smrg	    }
261706f2543Smrg	}
262706f2543Smrg    }
263706f2543Smrg}
264706f2543Smrg
265706f2543Smrg/*
266706f2543Smrg * Spans functions; probably unused.
267706f2543Smrg */
268706f2543Smrgvoid
269706f2543Smrgfb24_32GetSpans(DrawablePtr	pDrawable,
270706f2543Smrg		int		wMax,
271706f2543Smrg		DDXPointPtr	ppt,
272706f2543Smrg		int		*pwidth,
273706f2543Smrg		int		nspans,
274706f2543Smrg		char		*pchardstStart)
275706f2543Smrg{
276706f2543Smrg    FbBits	    *srcBits;
277706f2543Smrg    CARD8	    *src;
278706f2543Smrg    FbStride	    srcStride;
279706f2543Smrg    int		    srcBpp;
280706f2543Smrg    int		    srcXoff, srcYoff;
281706f2543Smrg    CARD8	    *dst;
282706f2543Smrg
283706f2543Smrg    fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
284706f2543Smrg    src = (CARD8 *) srcBits;
285706f2543Smrg    srcStride *= sizeof (FbBits);
286706f2543Smrg
287706f2543Smrg    while (nspans--)
288706f2543Smrg    {
289706f2543Smrg	dst = (CARD8 *) pchardstStart;
290706f2543Smrg	fb24_32BltUp (src + (ppt->y + srcYoff) * srcStride, srcStride,
291706f2543Smrg		      ppt->x + srcXoff,
292706f2543Smrg
293706f2543Smrg		      dst,
294706f2543Smrg		      1,
295706f2543Smrg		      0,
296706f2543Smrg
297706f2543Smrg		      *pwidth,
298706f2543Smrg		      1,
299706f2543Smrg
300706f2543Smrg		      GXcopy,
301706f2543Smrg		      FB_ALLONES);
302706f2543Smrg
303706f2543Smrg	pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth);
304706f2543Smrg	ppt++;
305706f2543Smrg	pwidth++;
306706f2543Smrg    }
307706f2543Smrg
308706f2543Smrg    fbFinishAccess (pDrawable);
309706f2543Smrg}
310706f2543Smrg
311706f2543Smrgvoid
312706f2543Smrgfb24_32SetSpans (DrawablePtr	    pDrawable,
313706f2543Smrg		 GCPtr		    pGC,
314706f2543Smrg		 char		    *src,
315706f2543Smrg		 DDXPointPtr	    ppt,
316706f2543Smrg		 int		    *pwidth,
317706f2543Smrg		 int		    nspans,
318706f2543Smrg		 int		    fSorted)
319706f2543Smrg{
320706f2543Smrg    FbGCPrivPtr	    pPriv = fbGetGCPrivate (pGC);
321706f2543Smrg    RegionPtr	    pClip = fbGetCompositeClip(pGC);
322706f2543Smrg    FbBits	    *dstBits;
323706f2543Smrg    CARD8	    *dst, *d, *s;
324706f2543Smrg    FbStride	    dstStride;
325706f2543Smrg    int		    dstBpp;
326706f2543Smrg    int		    dstXoff, dstYoff;
327706f2543Smrg    BoxPtr	    pbox;
328706f2543Smrg    int		    n;
329706f2543Smrg    int		    x1, x2;
330706f2543Smrg
331706f2543Smrg    fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
332706f2543Smrg    dst = (CARD8 *) dstBits;
333706f2543Smrg    dstStride *= sizeof (FbBits);
334706f2543Smrg    while (nspans--)
335706f2543Smrg    {
336706f2543Smrg	d = dst + (ppt->y + dstYoff) * dstStride;
337706f2543Smrg	s = (CARD8 *) src;
338706f2543Smrg	n = RegionNumRects(pClip);
339706f2543Smrg	pbox = RegionRects (pClip);
340706f2543Smrg	while (n--)
341706f2543Smrg	{
342706f2543Smrg	    if (pbox->y1 > ppt->y)
343706f2543Smrg		break;
344706f2543Smrg	    if (pbox->y2 > ppt->y)
345706f2543Smrg	    {
346706f2543Smrg		x1 = ppt->x;
347706f2543Smrg		x2 = x1 + *pwidth;
348706f2543Smrg		if (pbox->x1 > x1)
349706f2543Smrg		    x1 = pbox->x1;
350706f2543Smrg		if (pbox->x2 < x2)
351706f2543Smrg		    x2 = pbox->x2;
352706f2543Smrg		if (x1 < x2)
353706f2543Smrg		    fb24_32BltDown (s,
354706f2543Smrg				    0,
355706f2543Smrg				    (x1 - ppt->x),
356706f2543Smrg				    d,
357706f2543Smrg				    dstStride,
358706f2543Smrg				    x1 + dstXoff,
359706f2543Smrg
360706f2543Smrg				    (x2 - x1),
361706f2543Smrg				    1,
362706f2543Smrg				    pGC->alu,
363706f2543Smrg				    pPriv->pm);
364706f2543Smrg	    }
365706f2543Smrg	}
366706f2543Smrg	src += PixmapBytePad (*pwidth, pDrawable->depth);
367706f2543Smrg	ppt++;
368706f2543Smrg	pwidth++;
369706f2543Smrg    }
370706f2543Smrg
371706f2543Smrg    fbFinishAccess (pDrawable);
372706f2543Smrg}
373706f2543Smrg
374706f2543Smrg/*
375706f2543Smrg * Clip and put 32bpp Z-format images to a 24bpp drawable
376706f2543Smrg */
377706f2543Smrgvoid
378706f2543Smrgfb24_32PutZImage (DrawablePtr	pDrawable,
379706f2543Smrg		  RegionPtr	pClip,
380706f2543Smrg		  int		alu,
381706f2543Smrg		  FbBits	pm,
382706f2543Smrg		  int		x,
383706f2543Smrg		  int		y,
384706f2543Smrg		  int		width,
385706f2543Smrg		  int		height,
386706f2543Smrg		  CARD8		*src,
387706f2543Smrg		  FbStride	srcStride)
388706f2543Smrg{
389706f2543Smrg    FbBits	*dstBits;
390706f2543Smrg    CARD8	*dst;
391706f2543Smrg    FbStride	dstStride;
392706f2543Smrg    int		dstBpp;
393706f2543Smrg    int		dstXoff, dstYoff;
394706f2543Smrg    int		nbox;
395706f2543Smrg    BoxPtr	pbox;
396706f2543Smrg    int		x1, y1, x2, y2;
397706f2543Smrg
398706f2543Smrg    fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
399706f2543Smrg    dstStride *= sizeof(FbBits);
400706f2543Smrg    dst = (CARD8 *) dstBits;
401706f2543Smrg
402706f2543Smrg    for (nbox = RegionNumRects (pClip),
403706f2543Smrg	 pbox = RegionRects(pClip);
404706f2543Smrg	 nbox--;
405706f2543Smrg	 pbox++)
406706f2543Smrg    {
407706f2543Smrg	x1 = x;
408706f2543Smrg	y1 = y;
409706f2543Smrg	x2 = x + width;
410706f2543Smrg	y2 = y + height;
411706f2543Smrg	if (x1 < pbox->x1)
412706f2543Smrg	    x1 = pbox->x1;
413706f2543Smrg	if (y1 < pbox->y1)
414706f2543Smrg	    y1 = pbox->y1;
415706f2543Smrg	if (x2 > pbox->x2)
416706f2543Smrg	    x2 = pbox->x2;
417706f2543Smrg	if (y2 > pbox->y2)
418706f2543Smrg	    y2 = pbox->y2;
419706f2543Smrg	if (x1 >= x2 || y1 >= y2)
420706f2543Smrg	    continue;
421706f2543Smrg	fb24_32BltDown (src + (y1 - y) * srcStride,
422706f2543Smrg			srcStride,
423706f2543Smrg			(x1 - x),
424706f2543Smrg
425706f2543Smrg			dst + (y1 + dstYoff) * dstStride,
426706f2543Smrg			dstStride,
427706f2543Smrg			x1 + dstXoff,
428706f2543Smrg
429706f2543Smrg			(x2 - x1),
430706f2543Smrg			(y2 - y1),
431706f2543Smrg
432706f2543Smrg			alu,
433706f2543Smrg			pm);
434706f2543Smrg    }
435706f2543Smrg
436706f2543Smrg    fbFinishAccess (pDrawable);
437706f2543Smrg}
438706f2543Smrg
439706f2543Smrgvoid
440706f2543Smrgfb24_32GetImage (DrawablePtr     pDrawable,
441706f2543Smrg		 int             x,
442706f2543Smrg		 int             y,
443706f2543Smrg		 int             w,
444706f2543Smrg		 int             h,
445706f2543Smrg		 unsigned int    format,
446706f2543Smrg		 unsigned long   planeMask,
447706f2543Smrg		 char            *d)
448706f2543Smrg{
449706f2543Smrg    FbBits	    *srcBits;
450706f2543Smrg    CARD8	    *src;
451706f2543Smrg    FbStride	    srcStride;
452706f2543Smrg    int		    srcBpp;
453706f2543Smrg    int		    srcXoff, srcYoff;
454706f2543Smrg    FbStride	    dstStride;
455706f2543Smrg    FbBits	    pm;
456706f2543Smrg
457706f2543Smrg    fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
458706f2543Smrg    src = (CARD8 *) srcBits;
459706f2543Smrg    srcStride *= sizeof (FbBits);
460706f2543Smrg
461706f2543Smrg    x += pDrawable->x;
462706f2543Smrg    y += pDrawable->y;
463706f2543Smrg
464706f2543Smrg    pm = fbReplicatePixel (planeMask, 32);
465706f2543Smrg    dstStride = PixmapBytePad(w, pDrawable->depth);
466706f2543Smrg    if (pm != FB_ALLONES)
467706f2543Smrg	memset (d, 0, dstStride * h);
468706f2543Smrg    fb24_32BltUp (src + (y + srcYoff) * srcStride, srcStride, x + srcXoff,
469706f2543Smrg		  (CARD8 *) d, dstStride, 0,
470706f2543Smrg		  w, h, GXcopy, pm);
471706f2543Smrg
472706f2543Smrg    fbFinishAccess (pDrawable);
473706f2543Smrg}
474706f2543Smrg
475706f2543Smrgvoid
476706f2543Smrgfb24_32CopyMtoN (DrawablePtr pSrcDrawable,
477706f2543Smrg		 DrawablePtr pDstDrawable,
478706f2543Smrg		 GCPtr       pGC,
479706f2543Smrg		 BoxPtr      pbox,
480706f2543Smrg		 int         nbox,
481706f2543Smrg		 int         dx,
482706f2543Smrg		 int         dy,
483706f2543Smrg		 Bool        reverse,
484706f2543Smrg		 Bool        upsidedown,
485706f2543Smrg		 Pixel       bitplane,
486706f2543Smrg		 void        *closure)
487706f2543Smrg{
488706f2543Smrg    FbGCPrivPtr	pPriv = fbGetGCPrivate(pGC);
489706f2543Smrg    FbBits	*srcBits;
490706f2543Smrg    CARD8	*src;
491706f2543Smrg    FbStride	srcStride;
492706f2543Smrg    int		srcBpp;
493706f2543Smrg    FbBits	*dstBits;
494706f2543Smrg    CARD8	*dst;
495706f2543Smrg    FbStride	dstStride;
496706f2543Smrg    int		dstBpp;
497706f2543Smrg    fb24_32BltFunc  blt;
498706f2543Smrg    int		srcXoff, srcYoff;
499706f2543Smrg    int		dstXoff, dstYoff;
500706f2543Smrg
501706f2543Smrg    fbGetDrawable (pSrcDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
502706f2543Smrg    src = (CARD8 *) srcBits;
503706f2543Smrg    srcStride *= sizeof (FbBits);
504706f2543Smrg    fbGetDrawable (pDstDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
505706f2543Smrg    dst = (CARD8 *) dstBits;
506706f2543Smrg    dstStride *= sizeof (FbBits);
507706f2543Smrg    if (srcBpp == 24)
508706f2543Smrg	blt = fb24_32BltUp;
509706f2543Smrg    else
510706f2543Smrg	blt = fb24_32BltDown;
511706f2543Smrg
512706f2543Smrg    while (nbox--)
513706f2543Smrg    {
514706f2543Smrg	(*blt) (src + (pbox->y1 + dy + srcYoff) * srcStride,
515706f2543Smrg		srcStride,
516706f2543Smrg		(pbox->x1 + dx + srcXoff),
517706f2543Smrg
518706f2543Smrg		dst + (pbox->y1 + dstYoff) * dstStride,
519706f2543Smrg		dstStride,
520706f2543Smrg		(pbox->x1 + dstXoff),
521706f2543Smrg
522706f2543Smrg		(pbox->x2 - pbox->x1),
523706f2543Smrg		(pbox->y2 - pbox->y1),
524706f2543Smrg
525706f2543Smrg		pGC->alu,
526706f2543Smrg		pPriv->pm);
527706f2543Smrg	pbox++;
528706f2543Smrg    }
529706f2543Smrg
530706f2543Smrg    fbFinishAccess (pSrcDrawable);
531706f2543Smrg    fbFinishAccess (pDstDrawable);
532706f2543Smrg}
533706f2543Smrg
534706f2543SmrgPixmapPtr
535706f2543Smrgfb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel)
536706f2543Smrg{
537706f2543Smrg    ScreenPtr	pScreen = pOldTile->drawable.pScreen;
538706f2543Smrg    PixmapPtr	pNewTile;
539706f2543Smrg    FbBits	*old, *new;
540706f2543Smrg    FbStride	oldStride, newStride;
541706f2543Smrg    int		oldBpp, newBpp;
542706f2543Smrg    fb24_32BltFunc  blt;
543706f2543Smrg    int		oldXoff, oldYoff;
544706f2543Smrg    int		newXoff, newYoff;
545706f2543Smrg
546706f2543Smrg    pNewTile = pScreen->CreatePixmap(pScreen, pOldTile->drawable.width,
547706f2543Smrg				     pOldTile->drawable.height,
548706f2543Smrg				     pOldTile->drawable.depth,
549706f2543Smrg				     pOldTile->usage_hint);
550706f2543Smrg    if (!pNewTile)
551706f2543Smrg	return 0;
552706f2543Smrg    fbGetDrawable (&pOldTile->drawable,
553706f2543Smrg		   old, oldStride, oldBpp, oldXoff, oldYoff);
554706f2543Smrg    fbGetDrawable (&pNewTile->drawable,
555706f2543Smrg		   new, newStride, newBpp, newXoff, newYoff);
556706f2543Smrg    if (oldBpp == 24)
557706f2543Smrg	blt = fb24_32BltUp;
558706f2543Smrg    else
559706f2543Smrg	blt = fb24_32BltDown;
560706f2543Smrg
561706f2543Smrg    (*blt) ((CARD8 *) old,
562706f2543Smrg	    oldStride * sizeof (FbBits),
563706f2543Smrg	    0,
564706f2543Smrg
565706f2543Smrg	    (CARD8 *) new,
566706f2543Smrg	    newStride * sizeof (FbBits),
567706f2543Smrg	    0,
568706f2543Smrg
569706f2543Smrg	    pOldTile->drawable.width,
570706f2543Smrg	    pOldTile->drawable.height,
571706f2543Smrg
572706f2543Smrg	    GXcopy,
573706f2543Smrg	    FB_ALLONES);
574706f2543Smrg
575706f2543Smrg    fbFinishAccess (&pOldTile->drawable);
576706f2543Smrg    fbFinishAccess (&pNewTile->drawable);
577706f2543Smrg
578706f2543Smrg    return pNewTile;
579706f2543Smrg}
580706f2543Smrg
581706f2543Smrgtypedef struct {
582706f2543Smrg    pointer pbits;
583706f2543Smrg    int width;
584706f2543Smrg} miScreenInitParmsRec, *miScreenInitParmsPtr;
585706f2543Smrg
586706f2543SmrgBool
587706f2543Smrgfb24_32CreateScreenResources(ScreenPtr pScreen)
588706f2543Smrg{
589706f2543Smrg    miScreenInitParmsPtr pScrInitParms;
590706f2543Smrg    int pitch;
591706f2543Smrg    Bool retval;
592706f2543Smrg
593706f2543Smrg    /* get the pitch before mi destroys it */
594706f2543Smrg    pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate;
595706f2543Smrg    pitch = BitmapBytePad(pScrInitParms->width * 24);
596706f2543Smrg
597706f2543Smrg    if((retval = miCreateScreenResources(pScreen))) {
598706f2543Smrg	/* fix the screen pixmap */
599706f2543Smrg	PixmapPtr pPix = (PixmapPtr)pScreen->devPrivate;
600706f2543Smrg	pPix->drawable.bitsPerPixel = 24;
601706f2543Smrg	pPix->devKind = pitch;
602706f2543Smrg    }
603706f2543Smrg
604706f2543Smrg    return retval;
605706f2543Smrg}
606706f2543Smrg
607706f2543SmrgBool
608706f2543Smrgfb24_32ModifyPixmapHeader (PixmapPtr   pPixmap,
609706f2543Smrg			   int         width,
610706f2543Smrg			   int         height,
611706f2543Smrg			   int         depth,
612706f2543Smrg			   int         bitsPerPixel,
613706f2543Smrg			   int         devKind,
614706f2543Smrg			   pointer     pPixData)
615706f2543Smrg{
616706f2543Smrg    int	    bpp, w;
617706f2543Smrg
618706f2543Smrg    if (!pPixmap)
619706f2543Smrg	return FALSE;
620706f2543Smrg    bpp = bitsPerPixel;
621706f2543Smrg    if (bpp <= 0)
622706f2543Smrg	bpp = pPixmap->drawable.bitsPerPixel;
623706f2543Smrg    if (bpp == 24)
624706f2543Smrg    {
625706f2543Smrg	if (devKind < 0)
626706f2543Smrg	{
627706f2543Smrg	    w = width;
628706f2543Smrg	    if (w <= 0)
629706f2543Smrg		w = pPixmap->drawable.width;
630706f2543Smrg	    devKind = BitmapBytePad(w * 24);
631706f2543Smrg	}
632706f2543Smrg    }
633706f2543Smrg    return miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel,
634706f2543Smrg				devKind, pPixData);
635706f2543Smrg}
636