1fa225cbcSrjs/*
2fa225cbcSrjs * Copyright ® 2001 Keith Packard
3fa225cbcSrjs *
4fa225cbcSrjs * Partly based on code that is Copyright ® The XFree86 Project Inc.
5fa225cbcSrjs *
6fa225cbcSrjs * Permission to use, copy, modify, distribute, and sell this software and its
7fa225cbcSrjs * documentation for any purpose is hereby granted without fee, provided that
8fa225cbcSrjs * the above copyright notice appear in all copies and that both that
9fa225cbcSrjs * copyright notice and this permission notice appear in supporting
10fa225cbcSrjs * documentation, and that the name of Keith Packard not be used in
11fa225cbcSrjs * advertising or publicity pertaining to distribution of the software without
12fa225cbcSrjs * specific, written prior permission.  Keith Packard makes no
13fa225cbcSrjs * representations about the suitability of this software for any purpose.  It
14fa225cbcSrjs * is provided "as is" without express or implied warranty.
15fa225cbcSrjs *
16fa225cbcSrjs * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17fa225cbcSrjs * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18fa225cbcSrjs * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19fa225cbcSrjs * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20fa225cbcSrjs * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21fa225cbcSrjs * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22fa225cbcSrjs * PERFORMANCE OF THIS SOFTWARE.
23fa225cbcSrjs *
24fa225cbcSrjs * Authors:
25fa225cbcSrjs *    Eric Anholt <eric@anholt.net>
26fa225cbcSrjs *    Michel Dänzer <michel@tungstengraphics.com>
27fa225cbcSrjs *
28fa225cbcSrjs */
29fa225cbcSrjs
30fa225cbcSrjs#ifdef HAVE_DIX_CONFIG_H
31fa225cbcSrjs#include <dix-config.h>
32fa225cbcSrjs#endif
33fa225cbcSrjs#include "uxa-priv.h"
34fa225cbcSrjs#include <X11/fonts/fontstruct.h>
35fa225cbcSrjs#include "dixfontstr.h"
36fa225cbcSrjs#include "uxa.h"
37fa225cbcSrjs
38fa225cbcSrjsstatic void
39fa225cbcSrjsuxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
40fa225cbcSrjs	       DDXPointPtr ppt, int *pwidth, int fSorted)
41fa225cbcSrjs{
42fa225cbcSrjs    ScreenPtr	    pScreen = pDrawable->pScreen;
43fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(pScreen);
44fa225cbcSrjs    RegionPtr	    pClip = fbGetCompositeClip(pGC);
45fa225cbcSrjs    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap (pDrawable);
46fa225cbcSrjs    BoxPtr	    pextent, pbox;
47fa225cbcSrjs    int		    nbox;
48fa225cbcSrjs    int		    extentX1, extentX2, extentY1, extentY2;
49fa225cbcSrjs    int		    fullX1, fullX2, fullY1;
50fa225cbcSrjs    int		    partX1, partX2;
51fa225cbcSrjs    int		    off_x, off_y;
52fa225cbcSrjs
53fa225cbcSrjs    if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid ||
54fa225cbcSrjs	!(pPixmap = uxa_get_offscreen_pixmap (pDrawable, &off_x, &off_y)) ||
55fa225cbcSrjs	!(*uxa_screen->info->prepare_solid) (pPixmap,
56fa225cbcSrjs					     pGC->alu,
57fa225cbcSrjs					     pGC->planemask,
58fa225cbcSrjs					     pGC->fgPixel))
59fa225cbcSrjs    {
60fa225cbcSrjs	uxa_check_fill_spans (pDrawable, pGC, n, ppt, pwidth, fSorted);
61fa225cbcSrjs	return;
62fa225cbcSrjs    }
63fa225cbcSrjs
64fa225cbcSrjs    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
65fa225cbcSrjs    extentX1 = pextent->x1;
66fa225cbcSrjs    extentY1 = pextent->y1;
67fa225cbcSrjs    extentX2 = pextent->x2;
68fa225cbcSrjs    extentY2 = pextent->y2;
69fa225cbcSrjs    while (n--)
70fa225cbcSrjs    {
71fa225cbcSrjs	fullX1 = ppt->x;
72fa225cbcSrjs	fullY1 = ppt->y;
73fa225cbcSrjs	fullX2 = fullX1 + (int) *pwidth;
74fa225cbcSrjs	ppt++;
75fa225cbcSrjs	pwidth++;
76fa225cbcSrjs
77fa225cbcSrjs	if (fullY1 < extentY1 || extentY2 <= fullY1)
78fa225cbcSrjs	    continue;
79fa225cbcSrjs
80fa225cbcSrjs	if (fullX1 < extentX1)
81fa225cbcSrjs	    fullX1 = extentX1;
82fa225cbcSrjs
83fa225cbcSrjs	if (fullX2 > extentX2)
84fa225cbcSrjs	    fullX2 = extentX2;
85fa225cbcSrjs
86fa225cbcSrjs	if (fullX1 >= fullX2)
87fa225cbcSrjs	    continue;
88fa225cbcSrjs
89fa225cbcSrjs	nbox = REGION_NUM_RECTS (pClip);
90fa225cbcSrjs	if (nbox == 1)
91fa225cbcSrjs	{
92fa225cbcSrjs	    (*uxa_screen->info->solid) (pPixmap,
93fa225cbcSrjs					fullX1 + off_x, fullY1 + off_y,
94fa225cbcSrjs					fullX2 + off_x, fullY1 + 1 + off_y);
95fa225cbcSrjs	}
96fa225cbcSrjs	else
97fa225cbcSrjs	{
98fa225cbcSrjs	    pbox = REGION_RECTS(pClip);
99fa225cbcSrjs	    while(nbox--)
100fa225cbcSrjs	    {
101fa225cbcSrjs		if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
102fa225cbcSrjs		{
103fa225cbcSrjs		    partX1 = pbox->x1;
104fa225cbcSrjs		    if (partX1 < fullX1)
105fa225cbcSrjs			partX1 = fullX1;
106fa225cbcSrjs		    partX2 = pbox->x2;
107fa225cbcSrjs		    if (partX2 > fullX2)
108fa225cbcSrjs			partX2 = fullX2;
109fa225cbcSrjs		    if (partX2 > partX1) {
110fa225cbcSrjs			(*uxa_screen->info->solid) (pPixmap,
111fa225cbcSrjs						    partX1 + off_x, fullY1 + off_y,
112fa225cbcSrjs						    partX2 + off_x, fullY1 + 1 + off_y);
113fa225cbcSrjs		    }
114fa225cbcSrjs		}
115fa225cbcSrjs		pbox++;
116fa225cbcSrjs	    }
117fa225cbcSrjs	}
118fa225cbcSrjs    }
119fa225cbcSrjs    (*uxa_screen->info->done_solid) (pPixmap);
120fa225cbcSrjs}
121fa225cbcSrjs
122fa225cbcSrjsstatic Bool
123fa225cbcSrjsuxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
124fa225cbcSrjs		  int w, int h, int format, char *bits, int src_stride)
125fa225cbcSrjs{
126fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
127fa225cbcSrjs    PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable);
128fa225cbcSrjs    RegionPtr pClip;
129fa225cbcSrjs    BoxPtr pbox;
130fa225cbcSrjs    int nbox;
131fa225cbcSrjs    int xoff, yoff;
132fa225cbcSrjs    int bpp = pDrawable->bitsPerPixel;
133fa225cbcSrjs    Bool access_prepared = FALSE;
134fa225cbcSrjs
135fa225cbcSrjs    /* Don't bother with under 8bpp, XYPixmaps. */
136fa225cbcSrjs    if (format != ZPixmap || bpp < 8)
137fa225cbcSrjs	return FALSE;
138fa225cbcSrjs
139fa225cbcSrjs    /* Only accelerate copies: no rop or planemask. */
140fa225cbcSrjs    if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
141fa225cbcSrjs	return FALSE;
142fa225cbcSrjs
143fa225cbcSrjs    if (uxa_screen->swappedOut)
144fa225cbcSrjs	return FALSE;
145fa225cbcSrjs
146fa225cbcSrjs    pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
147fa225cbcSrjs
148fa225cbcSrjs    if (!pPix || !uxa_screen->info->put_image)
149fa225cbcSrjs	return FALSE;
150fa225cbcSrjs
151fa225cbcSrjs    x += pDrawable->x;
152fa225cbcSrjs    y += pDrawable->y;
153fa225cbcSrjs
154fa225cbcSrjs    pClip = fbGetCompositeClip(pGC);
155fa225cbcSrjs    for (nbox = REGION_NUM_RECTS(pClip),
156fa225cbcSrjs	 pbox = REGION_RECTS(pClip);
157fa225cbcSrjs	 nbox--;
158fa225cbcSrjs	 pbox++)
159fa225cbcSrjs    {
160fa225cbcSrjs	int x1 = x;
161fa225cbcSrjs	int y1 = y;
162fa225cbcSrjs	int x2 = x + w;
163fa225cbcSrjs	int y2 = y + h;
164fa225cbcSrjs	char *src;
165fa225cbcSrjs	Bool ok;
166fa225cbcSrjs
167fa225cbcSrjs	if (x1 < pbox->x1)
168fa225cbcSrjs	    x1 = pbox->x1;
169fa225cbcSrjs	if (y1 < pbox->y1)
170fa225cbcSrjs	    y1 = pbox->y1;
171fa225cbcSrjs	if (x2 > pbox->x2)
172fa225cbcSrjs	    x2 = pbox->x2;
173fa225cbcSrjs	if (y2 > pbox->y2)
174fa225cbcSrjs	    y2 = pbox->y2;
175fa225cbcSrjs	if (x1 >= x2 || y1 >= y2)
176fa225cbcSrjs	    continue;
177fa225cbcSrjs
178fa225cbcSrjs	src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
179fa225cbcSrjs	ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff,
180fa225cbcSrjs					 x2 - x1, y2 - y1, src, src_stride);
181fa225cbcSrjs	/* If we fail to accelerate the upload, fall back to using unaccelerated
182fa225cbcSrjs	 * fb calls.
183fa225cbcSrjs	 */
184fa225cbcSrjs	if (!ok) {
185fa225cbcSrjs	    FbStip *dst;
186fa225cbcSrjs	    FbStride dst_stride;
187fa225cbcSrjs	    int	dstBpp;
188fa225cbcSrjs	    int	dstXoff, dstYoff;
189fa225cbcSrjs
190fa225cbcSrjs	    if (!access_prepared) {
191fa225cbcSrjs		if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW))
192fa225cbcSrjs		    return FALSE;
193fa225cbcSrjs		access_prepared = TRUE;
194fa225cbcSrjs	    }
195fa225cbcSrjs
196fa225cbcSrjs	    fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
197fa225cbcSrjs			      dstXoff, dstYoff);
198fa225cbcSrjs
199fa225cbcSrjs	    fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
200fa225cbcSrjs		      src_stride / sizeof(FbStip),
201fa225cbcSrjs		      (x1 - x) * dstBpp,
202fa225cbcSrjs		      dst + (y1 + dstYoff) * dst_stride,
203fa225cbcSrjs		      dst_stride,
204fa225cbcSrjs		      (x1 + dstXoff) * dstBpp,
205fa225cbcSrjs		      (x2 - x1) * dstBpp,
206fa225cbcSrjs		      y2 - y1,
207fa225cbcSrjs		      GXcopy, FB_ALLONES, dstBpp);
208fa225cbcSrjs	}
209fa225cbcSrjs    }
210fa225cbcSrjs
211fa225cbcSrjs    if (access_prepared)
212fa225cbcSrjs	uxa_finish_access(pDrawable);
213fa225cbcSrjs
214fa225cbcSrjs    return TRUE;
215fa225cbcSrjs}
216fa225cbcSrjs
217fa225cbcSrjs#ifdef MITSHM
218fa225cbcSrjs
219fa225cbcSrjs#include "xorgVersion.h"
220fa225cbcSrjs
221fa225cbcSrjsstatic Bool
222fa225cbcSrjsuxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
223fa225cbcSrjs		 unsigned int format, int w, int h, int sx, int sy, int sw,
224fa225cbcSrjs		 int sh, int dx, int dy, char *data)
225fa225cbcSrjs{
226fa225cbcSrjs    int src_stride = PixmapBytePad(w, depth);
227fa225cbcSrjs
228fa225cbcSrjs    if (uxa_do_put_image(pDrawable, pGC, depth, dx, dy, sw, sh, format, data +
229fa225cbcSrjs			 sy * src_stride + sx * BitsPerPixel(depth) / 8,
230fa225cbcSrjs			 src_stride))
231fa225cbcSrjs	return TRUE;
232fa225cbcSrjs
233fa225cbcSrjs    if (format == ZPixmap)
234fa225cbcSrjs    {
235fa225cbcSrjs	PixmapPtr pPixmap;
236fa225cbcSrjs
237fa225cbcSrjs	pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
238fa225cbcSrjs					 BitsPerPixel(depth), PixmapBytePad(w, depth),
239fa225cbcSrjs					 (pointer)data);
240fa225cbcSrjs	if (!pPixmap)
241fa225cbcSrjs	    return FALSE;
242fa225cbcSrjs
243fa225cbcSrjs        if (!uxa_prepare_access (pDrawable, UXA_ACCESS_RW))
244fa225cbcSrjs	    return FALSE;
245fa225cbcSrjs	fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy);
246fa225cbcSrjs	uxa_finish_access(pDrawable);
247fa225cbcSrjs
248fa225cbcSrjs	FreeScratchPixmapHeader(pPixmap);
249fa225cbcSrjs
250fa225cbcSrjs	return TRUE;
251fa225cbcSrjs    }
252fa225cbcSrjs
253fa225cbcSrjs    return FALSE;
254fa225cbcSrjs}
255fa225cbcSrjs
256fa225cbcSrjs#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
257fa225cbcSrjs
258fa225cbcSrjs/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to
259fa225cbcSrjs * inform any interested parties of the damage incurred to the drawable.
260fa225cbcSrjs *
261fa225cbcSrjs * We also need to set the pending damage to ensure correct migration in all
262fa225cbcSrjs * cases.
263fa225cbcSrjs */
264fa225cbcSrjsvoid
265fa225cbcSrjsuxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format,
266fa225cbcSrjs		  int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
267fa225cbcSrjs		  char *data)
268fa225cbcSrjs{
269fa225cbcSrjs    if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh,
270fa225cbcSrjs			      dx, dy, data)) {
271fa225cbcSrjs	if (!uxa_prepare_access (pDrawable, UXA_ACCESS_RW))
272fa225cbcSrjs	    return;
273fa225cbcSrjs	fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
274fa225cbcSrjs		      data);
275fa225cbcSrjs	uxa_finish_access(pDrawable);
276fa225cbcSrjs    }
277fa225cbcSrjs}
278fa225cbcSrjs#else
279fa225cbcSrjs#define uxa_shm_put_image NULL
280fa225cbcSrjs#endif
281fa225cbcSrjs
282fa225cbcSrjsShmFuncs uxa_shm_funcs = { NULL, uxa_shm_put_image };
283fa225cbcSrjs
284fa225cbcSrjs#endif
285fa225cbcSrjs
286fa225cbcSrjsstatic void
287fa225cbcSrjsuxa_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
288fa225cbcSrjs	     int w, int h, int leftPad, int format, char *bits)
289fa225cbcSrjs{
290fa225cbcSrjs#ifdef MITSHM
291fa225cbcSrjs    if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y,
292fa225cbcSrjs			  bits))
293fa225cbcSrjs#else
294fa225cbcSrjs    if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits,
295fa225cbcSrjs		       PixmapBytePad(w, pDrawable->depth)))
296fa225cbcSrjs#endif
297fa225cbcSrjs	uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
298fa225cbcSrjs			 bits);
299fa225cbcSrjs}
300fa225cbcSrjs
301fa225cbcSrjsstatic Bool inline
302fa225cbcSrjsuxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
303fa225cbcSrjs		   GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
304fa225cbcSrjs{
305fa225cbcSrjs    uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
306fa225cbcSrjs    PixmapPtr pSrcPixmap, pDstPixmap;
307fa225cbcSrjs    int src_off_x, src_off_y, dst_off_x, dst_off_y;
308fa225cbcSrjs    int dirsetup;
309fa225cbcSrjs
310fa225cbcSrjs    /* Need to get both pixmaps to call the driver routines */
311fa225cbcSrjs    pSrcPixmap = uxa_get_offscreen_pixmap (pSrcDrawable, &src_off_x, &src_off_y);
312fa225cbcSrjs    pDstPixmap = uxa_get_offscreen_pixmap (pDstDrawable, &dst_off_x, &dst_off_y);
313fa225cbcSrjs    if (!pSrcPixmap || !pDstPixmap)
314fa225cbcSrjs	return FALSE;
315fa225cbcSrjs
316fa225cbcSrjs    /*
317fa225cbcSrjs     * Now the case of a chip that only supports xdir = ydir = 1 or
318fa225cbcSrjs     * xdir = ydir = -1, but we have xdir != ydir.
319fa225cbcSrjs     */
320fa225cbcSrjs    dirsetup = 0;	/* No direction set up yet. */
321fa225cbcSrjs    for (; nbox; pbox++, nbox--) {
322fa225cbcSrjs	if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
323fa225cbcSrjs	    /* Do a xdir = ydir = -1 blit instead. */
324fa225cbcSrjs	    if (dirsetup != -1) {
325fa225cbcSrjs		if (dirsetup != 0)
326fa225cbcSrjs		    uxa_screen->info->done_copy(pDstPixmap);
327fa225cbcSrjs		dirsetup = -1;
328fa225cbcSrjs		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
329fa225cbcSrjs						   pDstPixmap,
330fa225cbcSrjs						   -1, -1,
331fa225cbcSrjs						   pGC ? pGC->alu : GXcopy,
332fa225cbcSrjs						   pGC ? pGC->planemask :
333fa225cbcSrjs							 FB_ALLONES))
334fa225cbcSrjs		    return FALSE;
335fa225cbcSrjs	    }
336fa225cbcSrjs	    (*uxa_screen->info->copy)(pDstPixmap,
337fa225cbcSrjs				   src_off_x + pbox->x1 + dx,
338fa225cbcSrjs				   src_off_y + pbox->y1 + dy,
339fa225cbcSrjs				   dst_off_x + pbox->x1,
340fa225cbcSrjs				   dst_off_y + pbox->y1,
341fa225cbcSrjs				   pbox->x2 - pbox->x1,
342fa225cbcSrjs				   pbox->y2 - pbox->y1);
343fa225cbcSrjs	} else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
344fa225cbcSrjs	    /* Do a xdir = ydir = 1 blit instead. */
345fa225cbcSrjs	    if (dirsetup != 1) {
346fa225cbcSrjs		if (dirsetup != 0)
347fa225cbcSrjs		    uxa_screen->info->done_copy(pDstPixmap);
348fa225cbcSrjs		dirsetup = 1;
349fa225cbcSrjs		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
350fa225cbcSrjs						   pDstPixmap,
351fa225cbcSrjs						   1, 1,
352fa225cbcSrjs						   pGC ? pGC->alu : GXcopy,
353fa225cbcSrjs						   pGC ? pGC->planemask :
354fa225cbcSrjs							 FB_ALLONES))
355fa225cbcSrjs		    return FALSE;
356fa225cbcSrjs	    }
357fa225cbcSrjs	    (*uxa_screen->info->copy)(pDstPixmap,
358fa225cbcSrjs				   src_off_x + pbox->x1 + dx,
359fa225cbcSrjs				   src_off_y + pbox->y1 + dy,
360fa225cbcSrjs				   dst_off_x + pbox->x1,
361fa225cbcSrjs				   dst_off_y + pbox->y1,
362fa225cbcSrjs				   pbox->x2 - pbox->x1,
363fa225cbcSrjs				   pbox->y2 - pbox->y1);
364fa225cbcSrjs	} else if (dx >= 0) {
365fa225cbcSrjs	    /*
366fa225cbcSrjs	     * xdir = 1, ydir = -1.
367fa225cbcSrjs	     * Perform line-by-line xdir = ydir = 1 blits, going up.
368fa225cbcSrjs	     */
369fa225cbcSrjs	    int i;
370fa225cbcSrjs	    if (dirsetup != 1) {
371fa225cbcSrjs		if (dirsetup != 0)
372fa225cbcSrjs		    uxa_screen->info->done_copy(pDstPixmap);
373fa225cbcSrjs		dirsetup = 1;
374fa225cbcSrjs		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
375fa225cbcSrjs						   pDstPixmap,
376fa225cbcSrjs						   1, 1,
377fa225cbcSrjs						   pGC ? pGC->alu : GXcopy,
378fa225cbcSrjs						   pGC ? pGC->planemask :
379fa225cbcSrjs							 FB_ALLONES))
380fa225cbcSrjs		    return FALSE;
381fa225cbcSrjs	    }
382fa225cbcSrjs	    for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
383fa225cbcSrjs		(*uxa_screen->info->copy)(pDstPixmap,
384fa225cbcSrjs				       src_off_x + pbox->x1 + dx,
385fa225cbcSrjs				       src_off_y + pbox->y1 + dy + i,
386fa225cbcSrjs				       dst_off_x + pbox->x1,
387fa225cbcSrjs				       dst_off_y + pbox->y1 + i,
388fa225cbcSrjs				       pbox->x2 - pbox->x1, 1);
389fa225cbcSrjs	} else {
390fa225cbcSrjs	    /*
391fa225cbcSrjs	     * xdir = -1, ydir = 1.
392fa225cbcSrjs	     * Perform line-by-line xdir = ydir = -1 blits, going down.
393fa225cbcSrjs	     */
394fa225cbcSrjs	    int i;
395fa225cbcSrjs	    if (dirsetup != -1) {
396fa225cbcSrjs		if (dirsetup != 0)
397fa225cbcSrjs		    uxa_screen->info->done_copy(pDstPixmap);
398fa225cbcSrjs		dirsetup = -1;
399fa225cbcSrjs		if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap,
400fa225cbcSrjs						   pDstPixmap,
401fa225cbcSrjs						   -1, -1,
402fa225cbcSrjs						   pGC ? pGC->alu : GXcopy,
403fa225cbcSrjs						   pGC ? pGC->planemask :
404fa225cbcSrjs							 FB_ALLONES))
405fa225cbcSrjs		    return FALSE;
406fa225cbcSrjs	    }
407fa225cbcSrjs	    for (i = 0; i < pbox->y2 - pbox->y1; i++)
408fa225cbcSrjs		(*uxa_screen->info->copy)(pDstPixmap,
409fa225cbcSrjs				       src_off_x + pbox->x1 + dx,
410fa225cbcSrjs				       src_off_y + pbox->y1 + dy + i,
411fa225cbcSrjs				       dst_off_x + pbox->x1,
412fa225cbcSrjs				       dst_off_y + pbox->y1 + i,
413fa225cbcSrjs				       pbox->x2 - pbox->x1, 1);
414fa225cbcSrjs	}
415fa225cbcSrjs    }
416fa225cbcSrjs    if (dirsetup != 0)
417fa225cbcSrjs	uxa_screen->info->done_copy(pDstPixmap);
418fa225cbcSrjs    return TRUE;
419fa225cbcSrjs}
420fa225cbcSrjs
421fa225cbcSrjsvoid
422fa225cbcSrjsuxa_copy_n_to_n (DrawablePtr    pSrcDrawable,
423fa225cbcSrjs		 DrawablePtr    pDstDrawable,
424fa225cbcSrjs		 GCPtr		pGC,
425fa225cbcSrjs		 BoxPtr		pbox,
426fa225cbcSrjs		 int		nbox,
427fa225cbcSrjs		 int		dx,
428fa225cbcSrjs		 int		dy,
429fa225cbcSrjs		 Bool		reverse,
430fa225cbcSrjs		 Bool		upsidedown,
431fa225cbcSrjs		 Pixel		bitplane,
432fa225cbcSrjs		 void		*closure)
433fa225cbcSrjs{
434fa225cbcSrjs    ScreenPtr       screen = pDstDrawable->pScreen;
435fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(screen);
436fa225cbcSrjs    int		    src_off_x, src_off_y;
437fa225cbcSrjs    int		    dst_off_x, dst_off_y;
438fa225cbcSrjs    PixmapPtr	    pSrcPixmap, pDstPixmap;
439fa225cbcSrjs
440fa225cbcSrjs    pSrcPixmap = uxa_get_drawable_pixmap (pSrcDrawable);
441fa225cbcSrjs    pDstPixmap = uxa_get_drawable_pixmap (pDstDrawable);
442fa225cbcSrjs
443fa225cbcSrjs    uxa_get_drawable_deltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
444fa225cbcSrjs    uxa_get_drawable_deltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);
445fa225cbcSrjs
446fa225cbcSrjs    /* Mixed directions must be handled specially if the card is lame */
447fa225cbcSrjs    if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) &&
448fa225cbcSrjs	reverse != upsidedown) {
449fa225cbcSrjs	if (uxa_copy_n_to_n_two_dir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
450fa225cbcSrjs			       dx, dy))
451fa225cbcSrjs	    return;
452fa225cbcSrjs	goto fallback;
453fa225cbcSrjs    }
454fa225cbcSrjs
455fa225cbcSrjs    if (!uxa_pixmap_is_offscreen(pSrcPixmap) ||
456fa225cbcSrjs	!uxa_pixmap_is_offscreen(pDstPixmap) ||
457fa225cbcSrjs	!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
458fa225cbcSrjs					   upsidedown ? -1 : 1,
459fa225cbcSrjs					   pGC ? pGC->alu : GXcopy,
460fa225cbcSrjs					   pGC ? pGC->planemask : FB_ALLONES)) {
461fa225cbcSrjs	goto fallback;
462fa225cbcSrjs    }
463fa225cbcSrjs
464fa225cbcSrjs    while (nbox--)
465fa225cbcSrjs    {
466fa225cbcSrjs	(*uxa_screen->info->copy) (pDstPixmap,
467fa225cbcSrjs				   pbox->x1 + dx + src_off_x,
468fa225cbcSrjs				   pbox->y1 + dy + src_off_y,
469fa225cbcSrjs				   pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
470fa225cbcSrjs				   pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
471fa225cbcSrjs	pbox++;
472fa225cbcSrjs    }
473fa225cbcSrjs
474fa225cbcSrjs    (*uxa_screen->info->done_copy) (pDstPixmap);
475fa225cbcSrjs
476fa225cbcSrjs    return;
477fa225cbcSrjs
478fa225cbcSrjsfallback:
479fa225cbcSrjs    UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
480fa225cbcSrjs		  uxa_drawable_location(pSrcDrawable),
481fa225cbcSrjs		  uxa_drawable_location(pDstDrawable)));
482fa225cbcSrjs    if (uxa_prepare_access (pDstDrawable, UXA_ACCESS_RW)) {
483fa225cbcSrjs	if (uxa_prepare_access (pSrcDrawable, UXA_ACCESS_RO)) {
484fa225cbcSrjs	    fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy,
485fa225cbcSrjs			reverse, upsidedown, bitplane, closure);
486fa225cbcSrjs	    uxa_finish_access (pSrcDrawable);
487fa225cbcSrjs	}
488fa225cbcSrjs	uxa_finish_access (pDstDrawable);
489fa225cbcSrjs    }
490fa225cbcSrjs}
491fa225cbcSrjs
492fa225cbcSrjsRegionPtr
493fa225cbcSrjsuxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
494fa225cbcSrjs	    int srcx, int srcy, int width, int height, int dstx, int dsty)
495fa225cbcSrjs{
496fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(pDstDrawable->pScreen);
497fa225cbcSrjs
498fa225cbcSrjs    if (uxa_screen->swappedOut) {
499fa225cbcSrjs        return  uxa_check_copy_area(pSrcDrawable, pDstDrawable, pGC,
500fa225cbcSrjs                                 srcx, srcy, width, height, dstx, dsty);
501fa225cbcSrjs    }
502fa225cbcSrjs
503fa225cbcSrjs    return miDoCopy (pSrcDrawable, pDstDrawable, pGC,
504fa225cbcSrjs		     srcx, srcy, width, height,
505fa225cbcSrjs		     dstx, dsty, uxa_copy_n_to_n, 0, NULL);
506fa225cbcSrjs}
507fa225cbcSrjs
508fa225cbcSrjsstatic void
509fa225cbcSrjsuxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
510fa225cbcSrjs	     DDXPointPtr ppt)
511fa225cbcSrjs{
512fa225cbcSrjs    int i;
513fa225cbcSrjs    xRectangle *prect;
514fa225cbcSrjs
515fa225cbcSrjs    /* If we can't reuse the current GC as is, don't bother accelerating the
516fa225cbcSrjs     * points.
517fa225cbcSrjs     */
518fa225cbcSrjs    if (pGC->fillStyle != FillSolid) {
519fa225cbcSrjs	uxa_check_poly_point(pDrawable, pGC, mode, npt, ppt);
520fa225cbcSrjs	return;
521fa225cbcSrjs    }
522fa225cbcSrjs
523fa225cbcSrjs    prect = xalloc(sizeof(xRectangle) * npt);
524fa225cbcSrjs    if (!prect)
525fa225cbcSrjs	return;
526fa225cbcSrjs    for (i = 0; i < npt; i++) {
527fa225cbcSrjs	prect[i].x = ppt[i].x;
528fa225cbcSrjs	prect[i].y = ppt[i].y;
529fa225cbcSrjs	if (i > 0 && mode == CoordModePrevious) {
530fa225cbcSrjs	    prect[i].x += prect[i - 1].x;
531fa225cbcSrjs	    prect[i].y += prect[i - 1].y;
532fa225cbcSrjs	}
533fa225cbcSrjs	prect[i].width = 1;
534fa225cbcSrjs	prect[i].height = 1;
535fa225cbcSrjs    }
536fa225cbcSrjs    pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
537fa225cbcSrjs    xfree(prect);
538fa225cbcSrjs}
539fa225cbcSrjs
540fa225cbcSrjs/**
541fa225cbcSrjs * uxa_poly_lines() checks if it can accelerate the lines as a group of
542fa225cbcSrjs * horizontal or vertical lines (rectangles), and uses existing rectangle fill
543fa225cbcSrjs * acceleration if so.
544fa225cbcSrjs */
545fa225cbcSrjsstatic void
546fa225cbcSrjsuxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
547fa225cbcSrjs	       DDXPointPtr ppt)
548fa225cbcSrjs{
549fa225cbcSrjs    xRectangle *prect;
550fa225cbcSrjs    int x1, x2, y1, y2;
551fa225cbcSrjs    int i;
552fa225cbcSrjs
553fa225cbcSrjs    /* Don't try to do wide lines or non-solid fill style. */
554fa225cbcSrjs    if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
555fa225cbcSrjs	pGC->fillStyle != FillSolid) {
556fa225cbcSrjs	uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
557fa225cbcSrjs	return;
558fa225cbcSrjs    }
559fa225cbcSrjs
560fa225cbcSrjs    prect = xalloc(sizeof(xRectangle) * (npt - 1));
561fa225cbcSrjs    if (!prect)
562fa225cbcSrjs	return;
563fa225cbcSrjs    x1 = ppt[0].x;
564fa225cbcSrjs    y1 = ppt[0].y;
565fa225cbcSrjs    /* If we have any non-horizontal/vertical, fall back. */
566fa225cbcSrjs    for (i = 0; i < npt - 1; i++) {
567fa225cbcSrjs	if (mode == CoordModePrevious) {
568fa225cbcSrjs	    x2 = x1 + ppt[i + 1].x;
569fa225cbcSrjs	    y2 = y1 + ppt[i + 1].y;
570fa225cbcSrjs	} else {
571fa225cbcSrjs	    x2 = ppt[i + 1].x;
572fa225cbcSrjs	    y2 = ppt[i + 1].y;
573fa225cbcSrjs	}
574fa225cbcSrjs
575fa225cbcSrjs	if (x1 != x2 && y1 != y2) {
576fa225cbcSrjs	    xfree(prect);
577fa225cbcSrjs	    uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
578fa225cbcSrjs	    return;
579fa225cbcSrjs	}
580fa225cbcSrjs
581fa225cbcSrjs	if (x1 < x2) {
582fa225cbcSrjs	    prect[i].x = x1;
583fa225cbcSrjs	    prect[i].width = x2 - x1 + 1;
584fa225cbcSrjs	} else {
585fa225cbcSrjs	    prect[i].x = x2;
586fa225cbcSrjs	    prect[i].width = x1 - x2 + 1;
587fa225cbcSrjs	}
588fa225cbcSrjs	if (y1 < y2) {
589fa225cbcSrjs	    prect[i].y = y1;
590fa225cbcSrjs	    prect[i].height = y2 - y1 + 1;
591fa225cbcSrjs	} else {
592fa225cbcSrjs	    prect[i].y = y2;
593fa225cbcSrjs	    prect[i].height = y1 - y2 + 1;
594fa225cbcSrjs	}
595fa225cbcSrjs
596fa225cbcSrjs	x1 = x2;
597fa225cbcSrjs	y1 = y2;
598fa225cbcSrjs    }
599fa225cbcSrjs    pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
600fa225cbcSrjs    xfree(prect);
601fa225cbcSrjs}
602fa225cbcSrjs
603fa225cbcSrjs/**
604fa225cbcSrjs * uxa_poly_segment() checks if it can accelerate the lines as a group of
605fa225cbcSrjs * horizontal or vertical lines (rectangles), and uses existing rectangle fill
606fa225cbcSrjs * acceleration if so.
607fa225cbcSrjs */
608fa225cbcSrjsstatic void
609fa225cbcSrjsuxa_poly_segment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
610fa225cbcSrjs		xSegment *pSeg)
611fa225cbcSrjs{
612fa225cbcSrjs    xRectangle *prect;
613fa225cbcSrjs    int i;
614fa225cbcSrjs
615fa225cbcSrjs    /* Don't try to do wide lines or non-solid fill style. */
616fa225cbcSrjs    if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
617fa225cbcSrjs	pGC->fillStyle != FillSolid)
618fa225cbcSrjs    {
619fa225cbcSrjs	uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
620fa225cbcSrjs	return;
621fa225cbcSrjs    }
622fa225cbcSrjs
623fa225cbcSrjs    /* If we have any non-horizontal/vertical, fall back. */
624fa225cbcSrjs    for (i = 0; i < nseg; i++) {
625fa225cbcSrjs	if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
626fa225cbcSrjs	    uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg);
627fa225cbcSrjs	    return;
628fa225cbcSrjs	}
629fa225cbcSrjs    }
630fa225cbcSrjs
631fa225cbcSrjs    prect = xalloc(sizeof(xRectangle) * nseg);
632fa225cbcSrjs    if (!prect)
633fa225cbcSrjs	return;
634fa225cbcSrjs    for (i = 0; i < nseg; i++) {
635fa225cbcSrjs	if (pSeg[i].x1 < pSeg[i].x2) {
636fa225cbcSrjs	    prect[i].x = pSeg[i].x1;
637fa225cbcSrjs	    prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
638fa225cbcSrjs	} else {
639fa225cbcSrjs	    prect[i].x = pSeg[i].x2;
640fa225cbcSrjs	    prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
641fa225cbcSrjs	}
642fa225cbcSrjs	if (pSeg[i].y1 < pSeg[i].y2) {
643fa225cbcSrjs	    prect[i].y = pSeg[i].y1;
644fa225cbcSrjs	    prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
645fa225cbcSrjs	} else {
646fa225cbcSrjs	    prect[i].y = pSeg[i].y2;
647fa225cbcSrjs	    prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
648fa225cbcSrjs	}
649fa225cbcSrjs
650fa225cbcSrjs	/* don't paint last pixel */
651fa225cbcSrjs	if (pGC->capStyle == CapNotLast) {
652fa225cbcSrjs	    if (prect[i].width == 1)
653fa225cbcSrjs		prect[i].height--;
654fa225cbcSrjs	    else
655fa225cbcSrjs		prect[i].width--;
656fa225cbcSrjs	}
657fa225cbcSrjs    }
658fa225cbcSrjs    pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
659fa225cbcSrjs    xfree(prect);
660fa225cbcSrjs}
661fa225cbcSrjs
662fa225cbcSrjsstatic Bool uxa_fill_region_solid (DrawablePtr pDrawable, RegionPtr pRegion,
663fa225cbcSrjs				Pixel pixel, CARD32 planemask, CARD32 alu);
664fa225cbcSrjs
665fa225cbcSrjsstatic void
666fa225cbcSrjsuxa_poly_fill_rect(DrawablePtr pDrawable,
667fa225cbcSrjs		GCPtr	    pGC,
668fa225cbcSrjs		int	    nrect,
669fa225cbcSrjs		xRectangle  *prect)
670fa225cbcSrjs{
671fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
672fa225cbcSrjs    RegionPtr	    pClip = fbGetCompositeClip(pGC);
673fa225cbcSrjs    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap(pDrawable);
674fa225cbcSrjs    register BoxPtr pbox;
675fa225cbcSrjs    BoxPtr	    pextent;
676fa225cbcSrjs    int		    extentX1, extentX2, extentY1, extentY2;
677fa225cbcSrjs    int		    fullX1, fullX2, fullY1, fullY2;
678fa225cbcSrjs    int		    partX1, partX2, partY1, partY2;
679fa225cbcSrjs    int		    xoff, yoff;
680fa225cbcSrjs    int		    xorg, yorg;
681fa225cbcSrjs    int		    n;
682fa225cbcSrjs    RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
683fa225cbcSrjs
684fa225cbcSrjs    /* Compute intersection of rects and clip region */
685fa225cbcSrjs    REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y);
686fa225cbcSrjs    REGION_INTERSECT(pScreen, pReg, pClip, pReg);
687fa225cbcSrjs
688fa225cbcSrjs    if (!REGION_NUM_RECTS(pReg))
689fa225cbcSrjs	goto out;
690fa225cbcSrjs
691fa225cbcSrjs    uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
692fa225cbcSrjs
693fa225cbcSrjs    if (uxa_screen->swappedOut)
694fa225cbcSrjs	goto fallback;
695fa225cbcSrjs
696fa225cbcSrjs    /* For ROPs where overlaps don't matter, convert rectangles to region and
697fa225cbcSrjs     * call uxa_fill_region_{solid,tiled}.
698fa225cbcSrjs     */
699fa225cbcSrjs    if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
700fa225cbcSrjs	(nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear ||
701fa225cbcSrjs	 pGC->alu == GXnoop || pGC->alu == GXcopyInverted ||
702fa225cbcSrjs	 pGC->alu == GXset)) {
703fa225cbcSrjs	if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
704fa225cbcSrjs	     uxa_fill_region_solid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
705fa225cbcSrjs				pGC->fgPixel : pGC->tile.pixel,	pGC->planemask,
706fa225cbcSrjs				pGC->alu)) ||
707fa225cbcSrjs	    (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
708fa225cbcSrjs	     uxa_fill_region_tiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
709fa225cbcSrjs				pGC->planemask, pGC->alu))) {
710fa225cbcSrjs	    goto out;
711fa225cbcSrjs	}
712fa225cbcSrjs    }
713fa225cbcSrjs
714fa225cbcSrjs    if (pGC->fillStyle != FillSolid &&
715fa225cbcSrjs	!(pGC->tileIsPixel && pGC->fillStyle == FillTiled))
716fa225cbcSrjs    {
717fa225cbcSrjs	goto fallback;
718fa225cbcSrjs    }
719fa225cbcSrjs
720fa225cbcSrjs    if (!uxa_pixmap_is_offscreen (pPixmap) ||
721fa225cbcSrjs	!(*uxa_screen->info->prepare_solid) (pPixmap,
722fa225cbcSrjs					 pGC->alu,
723fa225cbcSrjs					 pGC->planemask,
724fa225cbcSrjs					 pGC->fgPixel))
725fa225cbcSrjs    {
726fa225cbcSrjsfallback:
727fa225cbcSrjs	uxa_check_poly_fill_rect (pDrawable, pGC, nrect, prect);
728fa225cbcSrjs	goto out;
729fa225cbcSrjs    }
730fa225cbcSrjs
731fa225cbcSrjs    xorg = pDrawable->x;
732fa225cbcSrjs    yorg = pDrawable->y;
733fa225cbcSrjs
734fa225cbcSrjs    pextent = REGION_EXTENTS(pGC->pScreen, pClip);
735fa225cbcSrjs    extentX1 = pextent->x1;
736fa225cbcSrjs    extentY1 = pextent->y1;
737fa225cbcSrjs    extentX2 = pextent->x2;
738fa225cbcSrjs    extentY2 = pextent->y2;
739fa225cbcSrjs    while (nrect--)
740fa225cbcSrjs    {
741fa225cbcSrjs	fullX1 = prect->x + xorg;
742fa225cbcSrjs	fullY1 = prect->y + yorg;
743fa225cbcSrjs	fullX2 = fullX1 + (int) prect->width;
744fa225cbcSrjs	fullY2 = fullY1 + (int) prect->height;
745fa225cbcSrjs	prect++;
746fa225cbcSrjs
747fa225cbcSrjs	if (fullX1 < extentX1)
748fa225cbcSrjs	    fullX1 = extentX1;
749fa225cbcSrjs
750fa225cbcSrjs	if (fullY1 < extentY1)
751fa225cbcSrjs	    fullY1 = extentY1;
752fa225cbcSrjs
753fa225cbcSrjs	if (fullX2 > extentX2)
754fa225cbcSrjs	    fullX2 = extentX2;
755fa225cbcSrjs
756fa225cbcSrjs	if (fullY2 > extentY2)
757fa225cbcSrjs	    fullY2 = extentY2;
758fa225cbcSrjs
759fa225cbcSrjs	if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
760fa225cbcSrjs	    continue;
761fa225cbcSrjs	n = REGION_NUM_RECTS (pClip);
762fa225cbcSrjs	if (n == 1)
763fa225cbcSrjs	{
764fa225cbcSrjs	    (*uxa_screen->info->solid) (pPixmap,
765fa225cbcSrjs				     fullX1 + xoff, fullY1 + yoff,
766fa225cbcSrjs				     fullX2 + xoff, fullY2 + yoff);
767fa225cbcSrjs	}
768fa225cbcSrjs	else
769fa225cbcSrjs	{
770fa225cbcSrjs	    pbox = REGION_RECTS(pClip);
771fa225cbcSrjs	    /*
772fa225cbcSrjs	     * clip the rectangle to each box in the clip region
773fa225cbcSrjs	     * this is logically equivalent to calling Intersect(),
774fa225cbcSrjs	     * but rectangles may overlap each other here.
775fa225cbcSrjs	     */
776fa225cbcSrjs	    while(n--)
777fa225cbcSrjs	    {
778fa225cbcSrjs		partX1 = pbox->x1;
779fa225cbcSrjs		if (partX1 < fullX1)
780fa225cbcSrjs		    partX1 = fullX1;
781fa225cbcSrjs		partY1 = pbox->y1;
782fa225cbcSrjs		if (partY1 < fullY1)
783fa225cbcSrjs		    partY1 = fullY1;
784fa225cbcSrjs		partX2 = pbox->x2;
785fa225cbcSrjs		if (partX2 > fullX2)
786fa225cbcSrjs		    partX2 = fullX2;
787fa225cbcSrjs		partY2 = pbox->y2;
788fa225cbcSrjs		if (partY2 > fullY2)
789fa225cbcSrjs		    partY2 = fullY2;
790fa225cbcSrjs
791fa225cbcSrjs		pbox++;
792fa225cbcSrjs
793fa225cbcSrjs		if (partX1 < partX2 && partY1 < partY2) {
794fa225cbcSrjs		    (*uxa_screen->info->solid) (pPixmap,
795fa225cbcSrjs					     partX1 + xoff, partY1 + yoff,
796fa225cbcSrjs					     partX2 + xoff, partY2 + yoff);
797fa225cbcSrjs		}
798fa225cbcSrjs	    }
799fa225cbcSrjs	}
800fa225cbcSrjs    }
801fa225cbcSrjs    (*uxa_screen->info->done_solid) (pPixmap);
802fa225cbcSrjs
803fa225cbcSrjsout:
804fa225cbcSrjs    REGION_UNINIT(pScreen, pReg);
805fa225cbcSrjs    REGION_DESTROY(pScreen, pReg);
806fa225cbcSrjs}
807fa225cbcSrjs
808fa225cbcSrjsconst GCOps uxa_ops = {
809fa225cbcSrjs    uxa_fill_spans,
810fa225cbcSrjs    uxa_check_set_spans,
811fa225cbcSrjs    uxa_put_image,
812fa225cbcSrjs    uxa_copy_area,
813fa225cbcSrjs    uxa_check_copy_plane,
814fa225cbcSrjs    uxa_poly_point,
815fa225cbcSrjs    uxa_poly_lines,
816fa225cbcSrjs    uxa_poly_segment,
817fa225cbcSrjs    miPolyRectangle,
818fa225cbcSrjs    uxa_check_poly_arc,
819fa225cbcSrjs    miFillPolygon,
820fa225cbcSrjs    uxa_poly_fill_rect,
821fa225cbcSrjs    miPolyFillArc,
822fa225cbcSrjs    miPolyText8,
823fa225cbcSrjs    miPolyText16,
824fa225cbcSrjs    miImageText8,
825fa225cbcSrjs    miImageText16,
826fa225cbcSrjs    uxa_check_image_glyph_blt,
827fa225cbcSrjs    uxa_check_poly_glyph_blt,
828fa225cbcSrjs    uxa_check_push_pixels,
829fa225cbcSrjs};
830fa225cbcSrjs
831fa225cbcSrjsvoid
832fa225cbcSrjsuxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
833fa225cbcSrjs{
834fa225cbcSrjs    RegionRec	rgnDst;
835fa225cbcSrjs    int		dx, dy;
836fa225cbcSrjs    PixmapPtr	pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
837fa225cbcSrjs
838fa225cbcSrjs    dx = ptOldOrg.x - pWin->drawable.x;
839fa225cbcSrjs    dy = ptOldOrg.y - pWin->drawable.y;
840fa225cbcSrjs    REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
841fa225cbcSrjs
842fa225cbcSrjs    REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
843fa225cbcSrjs
844fa225cbcSrjs    REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
845fa225cbcSrjs#ifdef COMPOSITE
846fa225cbcSrjs    if (pPixmap->screen_x || pPixmap->screen_y)
847fa225cbcSrjs	REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
848fa225cbcSrjs			  -pPixmap->screen_x, -pPixmap->screen_y);
849fa225cbcSrjs#endif
850fa225cbcSrjs
851fa225cbcSrjs    miCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
852fa225cbcSrjs		  NULL,
853fa225cbcSrjs		  &rgnDst, dx, dy, uxa_copy_n_to_n, 0, NULL);
854fa225cbcSrjs
855fa225cbcSrjs    REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
856fa225cbcSrjs}
857fa225cbcSrjs
858fa225cbcSrjsstatic Bool
859fa225cbcSrjsuxa_fill_region_solid (DrawablePtr	pDrawable,
860fa225cbcSrjs		    RegionPtr	pRegion,
861fa225cbcSrjs		    Pixel	pixel,
862fa225cbcSrjs		    CARD32	planemask,
863fa225cbcSrjs		    CARD32	alu)
864fa225cbcSrjs{
865fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
866fa225cbcSrjs    PixmapPtr	    pPixmap = uxa_get_drawable_pixmap (pDrawable);
867fa225cbcSrjs    int		    xoff, yoff;
868fa225cbcSrjs    Bool	    ret = FALSE;
869fa225cbcSrjs
870fa225cbcSrjs    uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
871fa225cbcSrjs    REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
872fa225cbcSrjs
873fa225cbcSrjs    if (uxa_pixmap_is_offscreen (pPixmap) &&
874fa225cbcSrjs	(*uxa_screen->info->prepare_solid) (pPixmap, alu, planemask, pixel))
875fa225cbcSrjs    {
876fa225cbcSrjs	int nbox;
877fa225cbcSrjs	BoxPtr pBox;
878fa225cbcSrjs
879fa225cbcSrjs	nbox = REGION_NUM_RECTS (pRegion);
880fa225cbcSrjs	pBox = REGION_RECTS (pRegion);
881fa225cbcSrjs
882fa225cbcSrjs	while (nbox--)
883fa225cbcSrjs	{
884fa225cbcSrjs	    (*uxa_screen->info->solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
885fa225cbcSrjs				     pBox->y2);
886fa225cbcSrjs	    pBox++;
887fa225cbcSrjs	}
888fa225cbcSrjs	(*uxa_screen->info->done_solid) (pPixmap);
889fa225cbcSrjs
890fa225cbcSrjs	ret = TRUE;
891fa225cbcSrjs    }
892fa225cbcSrjs
893fa225cbcSrjs    REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
894fa225cbcSrjs
895fa225cbcSrjs    return ret;
896fa225cbcSrjs}
897fa225cbcSrjs
898fa225cbcSrjs/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
899fa225cbcSrjs * Based on fbFillRegionTiled(), fbTile().
900fa225cbcSrjs */
901fa225cbcSrjsBool
902fa225cbcSrjsuxa_fill_region_tiled (DrawablePtr	pDrawable,
903fa225cbcSrjs		       RegionPtr	pRegion,
904fa225cbcSrjs		       PixmapPtr	pTile,
905fa225cbcSrjs		       DDXPointPtr	pPatOrg,
906fa225cbcSrjs		       CARD32		planemask,
907fa225cbcSrjs		       CARD32		alu)
908fa225cbcSrjs{
909fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(pDrawable->pScreen);
910fa225cbcSrjs    PixmapPtr	    pPixmap;
911fa225cbcSrjs    int		    xoff, yoff;
912fa225cbcSrjs    int		    tileWidth, tileHeight;
913fa225cbcSrjs    int		    nbox = REGION_NUM_RECTS (pRegion);
914fa225cbcSrjs    BoxPtr	    pBox = REGION_RECTS (pRegion);
915fa225cbcSrjs    Bool	    ret = FALSE;
916fa225cbcSrjs
917fa225cbcSrjs    tileWidth = pTile->drawable.width;
918fa225cbcSrjs    tileHeight = pTile->drawable.height;
919fa225cbcSrjs
920fa225cbcSrjs    /* If we're filling with a solid color, grab it out and go to
921fa225cbcSrjs     * FillRegionsolid, saving numerous copies.
922fa225cbcSrjs     */
923fa225cbcSrjs    if (tileWidth == 1 && tileHeight == 1)
924fa225cbcSrjs	return uxa_fill_region_solid(pDrawable, pRegion,
925fa225cbcSrjs				     uxa_get_pixmap_first_pixel (pTile), planemask,
926fa225cbcSrjs				     alu);
927fa225cbcSrjs
928fa225cbcSrjs    pPixmap = uxa_get_drawable_pixmap (pDrawable);
929fa225cbcSrjs    uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
930fa225cbcSrjs    REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
931fa225cbcSrjs
932fa225cbcSrjs    pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
933fa225cbcSrjs
934fa225cbcSrjs    if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
935fa225cbcSrjs	goto out;
936fa225cbcSrjs
937fa225cbcSrjs    if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, planemask))
938fa225cbcSrjs    {
939fa225cbcSrjs	while (nbox--)
940fa225cbcSrjs	{
941fa225cbcSrjs	    int height = pBox->y2 - pBox->y1;
942fa225cbcSrjs	    int dstY = pBox->y1;
943fa225cbcSrjs	    int tileY;
944fa225cbcSrjs
945fa225cbcSrjs	    modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);
946fa225cbcSrjs
947fa225cbcSrjs	    while (height > 0) {
948fa225cbcSrjs		int width = pBox->x2 - pBox->x1;
949fa225cbcSrjs		int dstX = pBox->x1;
950fa225cbcSrjs		int tileX;
951fa225cbcSrjs		int h = tileHeight - tileY;
952fa225cbcSrjs
953fa225cbcSrjs		if (h > height)
954fa225cbcSrjs		    h = height;
955fa225cbcSrjs		height -= h;
956fa225cbcSrjs
957fa225cbcSrjs		modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth,
958fa225cbcSrjs			tileX);
959fa225cbcSrjs
960fa225cbcSrjs		while (width > 0) {
961fa225cbcSrjs		    int w = tileWidth - tileX;
962fa225cbcSrjs		    if (w > width)
963fa225cbcSrjs			w = width;
964fa225cbcSrjs		    width -= w;
965fa225cbcSrjs
966fa225cbcSrjs		    (*uxa_screen->info->copy) (pPixmap, tileX, tileY, dstX, dstY,
967fa225cbcSrjs					    w, h);
968fa225cbcSrjs		    dstX += w;
969fa225cbcSrjs		    tileX = 0;
970fa225cbcSrjs		}
971fa225cbcSrjs		dstY += h;
972fa225cbcSrjs		tileY = 0;
973fa225cbcSrjs	    }
974fa225cbcSrjs	    pBox++;
975fa225cbcSrjs	}
976fa225cbcSrjs	(*uxa_screen->info->done_copy) (pPixmap);
977fa225cbcSrjs
978fa225cbcSrjs	ret = TRUE;
979fa225cbcSrjs    }
980fa225cbcSrjs
981fa225cbcSrjsout:
982fa225cbcSrjs    REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
983fa225cbcSrjs
984fa225cbcSrjs    return ret;
985fa225cbcSrjs}
986fa225cbcSrjs
987fa225cbcSrjs/**
988fa225cbcSrjs * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
989fa225cbcSrjs *
990fa225cbcSrjs * This is probably the only case we actually care about.  The rest fall through
991fa225cbcSrjs * to migration and fbGetImage, which hopefully will result in migration pushing
992fa225cbcSrjs * the pixmap out of framebuffer.
993fa225cbcSrjs */
994fa225cbcSrjsvoid
995fa225cbcSrjsuxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h,
996fa225cbcSrjs	       unsigned int format, unsigned long planeMask, char *d)
997fa225cbcSrjs{
998fa225cbcSrjs    ScreenPtr       screen = pDrawable->pScreen;
999fa225cbcSrjs    uxa_screen_t    *uxa_screen = uxa_get_screen(screen);
1000fa225cbcSrjs    BoxRec	    Box;
1001fa225cbcSrjs    PixmapPtr	    pPix = uxa_get_drawable_pixmap (pDrawable);
1002fa225cbcSrjs    int		    xoff, yoff;
1003fa225cbcSrjs    Bool	    ok;
1004fa225cbcSrjs
1005fa225cbcSrjs    uxa_get_drawable_deltas (pDrawable, pPix, &xoff, &yoff);
1006fa225cbcSrjs
1007fa225cbcSrjs    Box.x1 = pDrawable->y + x + xoff;
1008fa225cbcSrjs    Box.y1 = pDrawable->y + y + yoff;
1009fa225cbcSrjs    Box.x2 = Box.x1 + w;
1010fa225cbcSrjs    Box.y2 = Box.y1 + h;
1011fa225cbcSrjs
1012fa225cbcSrjs    if (uxa_screen->swappedOut)
1013fa225cbcSrjs	goto fallback;
1014fa225cbcSrjs
1015fa225cbcSrjs    pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
1016fa225cbcSrjs
1017fa225cbcSrjs    if (pPix == NULL || uxa_screen->info->get_image == NULL)
1018fa225cbcSrjs	goto fallback;
1019fa225cbcSrjs
1020fa225cbcSrjs    /* Only cover the ZPixmap, solid copy case. */
1021fa225cbcSrjs    if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask))
1022fa225cbcSrjs	goto fallback;
1023fa225cbcSrjs
1024fa225cbcSrjs    /* Only try to handle the 8bpp and up cases, since we don't want to think
1025fa225cbcSrjs     * about <8bpp.
1026fa225cbcSrjs     */
1027fa225cbcSrjs    if (pDrawable->bitsPerPixel < 8)
1028fa225cbcSrjs	goto fallback;
1029fa225cbcSrjs
1030fa225cbcSrjs    ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff,
1031fa225cbcSrjs					   pDrawable->y + y + yoff, w, h, d,
1032fa225cbcSrjs					   PixmapBytePad(w, pDrawable->depth));
1033fa225cbcSrjs    if (ok)
1034fa225cbcSrjs	return;
1035fa225cbcSrjs
1036fa225cbcSrjsfallback:
1037fa225cbcSrjs    UXA_FALLBACK(("from %p (%c)\n", pDrawable,
1038fa225cbcSrjs		  uxa_drawable_location(pDrawable)));
1039fa225cbcSrjs
1040fa225cbcSrjs    if (uxa_prepare_access (pDrawable, UXA_ACCESS_RO)) {
1041fa225cbcSrjs	fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
1042fa225cbcSrjs	uxa_finish_access (pDrawable);
1043fa225cbcSrjs    }
1044fa225cbcSrjs
1045fa225cbcSrjs   return;
1046fa225cbcSrjs}
1047