exa_unaccel.c revision e9ed4b75
1/*
2 *
3 * Copyright � 1999 Keith Packard
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Keith Packard makes no
12 * representations about the suitability of this software for any purpose.  It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include "exa_priv.h"
25
26#include "mipict.h"
27
28/*
29 * These functions wrap the low-level fb rendering functions and
30 * synchronize framebuffer/accelerated drawing by stalling until
31 * the accelerator is idle
32 */
33
34/**
35 * Calls exaPrepareAccess with EXA_PREPARE_SRC for the tile, if that is the
36 * current fill style.
37 *
38 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
39 * 1bpp and never in fb, so we don't worry about them.
40 * We should worry about them for completeness sake and going forward.
41 */
42void
43exaPrepareAccessGC(GCPtr pGC)
44{
45    if (pGC->stipple)
46        exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
47    if (pGC->fillStyle == FillTiled)
48	exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
49}
50
51/**
52 * Finishes access to the tile in the GC, if used.
53 */
54void
55exaFinishAccessGC(GCPtr pGC)
56{
57    if (pGC->fillStyle == FillTiled)
58	exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
59    if (pGC->stipple)
60        exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
61}
62
63#if DEBUG_TRACE_FALL
64char
65exaDrawableLocation(DrawablePtr pDrawable)
66{
67    return exaDrawableIsOffscreen(pDrawable) ? 's' : 'm';
68}
69#endif /* DEBUG_TRACE_FALL */
70
71void
72ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
73		   DDXPointPtr ppt, int *pwidth, int fSorted)
74{
75    EXA_PRE_FALLBACK_GC(pGC);
76    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
77    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
78    exaPrepareAccessGC (pGC);
79    pGC->ops->FillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
80    exaFinishAccessGC (pGC);
81    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
82    EXA_POST_FALLBACK_GC(pGC);
83}
84
85void
86ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
87		 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
88{
89    EXA_PRE_FALLBACK_GC(pGC);
90    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
91    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
92    pGC->ops->SetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
93    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
94    EXA_POST_FALLBACK_GC(pGC);
95}
96
97void
98ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
99		 int x, int y, int w, int h, int leftPad, int format,
100		 char *bits)
101{
102    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
103    ExaPixmapPriv(pPixmap);
104
105    EXA_PRE_FALLBACK_GC(pGC);
106    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
107    if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
108	exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
109			      pGC->alu, pGC->clientClipType))
110	exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
111    else
112	pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
113				    DamagePendingRegion(pExaPixmap->pDamage));
114    pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
115    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
116    EXA_POST_FALLBACK_GC(pGC);
117}
118
119void
120ExaCheckCopyNtoN (DrawablePtr pSrc, DrawablePtr pDst,  GCPtr pGC,
121	     BoxPtr	pbox, int nbox, int dx, int dy, Bool	reverse,
122	     Bool upsidedown, Pixel bitplane, void *closure)
123{
124    RegionRec reg;
125    int xoff, yoff;
126    EXA_PRE_FALLBACK_GC(pGC);
127    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
128		  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
129
130    if (pExaScr->prepare_access_reg && RegionInitBoxes(&reg, pbox, nbox)) {
131	PixmapPtr pPixmap = exaGetDrawablePixmap(pSrc);
132
133	exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
134	RegionTranslate(&reg, xoff + dx, yoff + dy);
135	pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, &reg);
136	RegionUninit(&reg);
137    } else
138	exaPrepareAccess (pSrc, EXA_PREPARE_SRC);
139
140    if (pExaScr->prepare_access_reg &&
141	!exaGCReadsDestination(pDst, pGC->planemask, pGC->fillStyle,
142			       pGC->alu, pGC->clientClipType) &&
143			       RegionInitBoxes (&reg, pbox, nbox)) {
144	PixmapPtr pPixmap = exaGetDrawablePixmap(pDst);
145
146	exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
147	RegionTranslate(&reg, xoff, yoff);
148	pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, &reg);
149	RegionUninit(&reg);
150    } else
151	exaPrepareAccess (pDst, EXA_PREPARE_DEST);
152
153    /* This will eventually call fbCopyNtoN, with some calculation overhead. */
154    while (nbox--) {
155	pGC->ops->CopyArea (pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx, pbox->y1 - pSrc->y + dy,
156			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, pbox->x1 - pDst->x, pbox->y1 - pDst->y);
157	pbox++;
158    }
159    exaFinishAccess (pSrc, EXA_PREPARE_SRC);
160    exaFinishAccess (pDst, EXA_PREPARE_DEST);
161    EXA_POST_FALLBACK_GC(pGC);
162}
163
164static void
165ExaFallbackPrepareReg(DrawablePtr pDrawable,
166		      GCPtr pGC,
167		      int x, int y, int width, int height,
168		      int index, Bool checkReads)
169{
170    ScreenPtr pScreen = pDrawable->pScreen;
171    ExaScreenPriv(pScreen);
172
173    if (pExaScr->prepare_access_reg &&
174	!(checkReads && exaGCReadsDestination(pDrawable,
175					      pGC->planemask,
176					      pGC->fillStyle,
177					      pGC->alu,
178					      pGC->clientClipType))) {
179	BoxRec box;
180	RegionRec reg;
181	int xoff, yoff;
182	PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
183
184	exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
185	box.x1 = pDrawable->x + x + xoff;
186	box.y1 = pDrawable->y + y + yoff;
187	box.x2 = box.x1 + width;
188	box.y2 = box.y1 + height;
189
190	RegionInit(&reg, &box, 1);
191	pExaScr->prepare_access_reg(pPixmap, index, &reg);
192	RegionUninit(&reg);
193    } else
194	exaPrepareAccess(pDrawable, index);
195}
196
197
198RegionPtr
199ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
200		 int srcx, int srcy, int w, int h, int dstx, int dsty)
201{
202    RegionPtr ret;
203
204    EXA_PRE_FALLBACK_GC(pGC);
205    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
206		  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
207    ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h,
208			  EXA_PREPARE_SRC, FALSE);
209    ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h,
210			  EXA_PREPARE_DEST, TRUE);
211    ret = pGC->ops->CopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
212    exaFinishAccess (pSrc, EXA_PREPARE_SRC);
213    exaFinishAccess (pDst, EXA_PREPARE_DEST);
214    EXA_POST_FALLBACK_GC(pGC);
215
216    return ret;
217}
218
219RegionPtr
220ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
221		  int srcx, int srcy, int w, int h, int dstx, int dsty,
222		  unsigned long bitPlane)
223{
224    RegionPtr ret;
225
226    EXA_PRE_FALLBACK_GC(pGC);
227    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
228		  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
229    ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h,
230			  EXA_PREPARE_SRC, FALSE);
231    ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h,
232			  EXA_PREPARE_DEST, TRUE);
233    ret = pGC->ops->CopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
234		       bitPlane);
235    exaFinishAccess (pSrc, EXA_PREPARE_SRC);
236    exaFinishAccess (pDst, EXA_PREPARE_DEST);
237    EXA_POST_FALLBACK_GC(pGC);
238
239    return ret;
240}
241
242void
243ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
244		  DDXPointPtr pptInit)
245{
246    EXA_PRE_FALLBACK_GC(pGC);
247    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
248    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
249    pGC->ops->PolyPoint (pDrawable, pGC, mode, npt, pptInit);
250    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
251    EXA_POST_FALLBACK_GC(pGC);
252}
253
254void
255ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC,
256		  int mode, int npt, DDXPointPtr ppt)
257{
258    EXA_PRE_FALLBACK_GC(pGC);
259    EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
260		  pDrawable, exaDrawableLocation(pDrawable),
261		  pGC->lineWidth, mode, npt));
262
263    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
264    exaPrepareAccessGC (pGC);
265    pGC->ops->Polylines (pDrawable, pGC, mode, npt, ppt);
266    exaFinishAccessGC (pGC);
267    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
268    EXA_POST_FALLBACK_GC(pGC);
269}
270
271void
272ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC,
273		    int nsegInit, xSegment *pSegInit)
274{
275    EXA_PRE_FALLBACK_GC(pGC);
276    EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
277		  exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit));
278
279    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
280    exaPrepareAccessGC (pGC);
281    pGC->ops->PolySegment (pDrawable, pGC, nsegInit, pSegInit);
282    exaFinishAccessGC (pGC);
283    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
284    EXA_POST_FALLBACK_GC(pGC);
285}
286
287void
288ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC,
289		int narcs, xArc *pArcs)
290{
291    EXA_PRE_FALLBACK_GC(pGC);
292    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
293
294    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
295    exaPrepareAccessGC (pGC);
296    pGC->ops->PolyArc (pDrawable, pGC, narcs, pArcs);
297    exaFinishAccessGC (pGC);
298    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
299    EXA_POST_FALLBACK_GC(pGC);
300}
301
302void
303ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
304		     int nrect, xRectangle *prect)
305{
306    EXA_PRE_FALLBACK_GC(pGC);
307    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
308
309    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
310    exaPrepareAccessGC (pGC);
311    pGC->ops->PolyFillRect (pDrawable, pGC, nrect, prect);
312    exaFinishAccessGC (pGC);
313    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
314    EXA_POST_FALLBACK_GC(pGC);
315}
316
317void
318ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
319		      int x, int y, unsigned int nglyph,
320		      CharInfoPtr *ppci, pointer pglyphBase)
321{
322    EXA_PRE_FALLBACK_GC(pGC);
323    EXA_FALLBACK(("to %p (%c)\n", pDrawable,
324		  exaDrawableLocation(pDrawable)));
325    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
326    exaPrepareAccessGC (pGC);
327    pGC->ops->ImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
328    exaFinishAccessGC (pGC);
329    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
330    EXA_POST_FALLBACK_GC(pGC);
331}
332
333void
334ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
335		     int x, int y, unsigned int nglyph,
336		     CharInfoPtr *ppci, pointer pglyphBase)
337{
338    EXA_PRE_FALLBACK_GC(pGC);
339    EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
340		  exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu));
341    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
342    exaPrepareAccessGC (pGC);
343    pGC->ops->PolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
344    exaFinishAccessGC (pGC);
345    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
346    EXA_POST_FALLBACK_GC(pGC);
347}
348
349void
350ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap,
351		   DrawablePtr pDrawable,
352		   int w, int h, int x, int y)
353{
354    EXA_PRE_FALLBACK_GC(pGC);
355    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
356		  exaDrawableLocation(&pBitmap->drawable),
357		  exaDrawableLocation(pDrawable)));
358    ExaFallbackPrepareReg(pDrawable, pGC, x, y, w, h,
359			  EXA_PREPARE_DEST, TRUE);
360    ExaFallbackPrepareReg(&pBitmap->drawable, pGC, 0, 0, w, h,
361			  EXA_PREPARE_SRC, FALSE);
362    exaPrepareAccessGC (pGC);
363    pGC->ops->PushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
364    exaFinishAccessGC (pGC);
365    exaFinishAccess (&pBitmap->drawable, EXA_PREPARE_SRC);
366    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
367    EXA_POST_FALLBACK_GC(pGC);
368}
369
370void
371ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
372{
373    DrawablePtr pDrawable = &pWin->drawable;
374    ScreenPtr pScreen = pDrawable->pScreen;
375    EXA_PRE_FALLBACK(pScreen);
376    EXA_FALLBACK(("from %p\n", pWin));
377
378    /* Only need the source bits, the destination region will be overwritten */
379    if (pExaScr->prepare_access_reg) {
380	PixmapPtr pPixmap = pScreen->GetWindowPixmap(pWin);
381	int xoff, yoff;
382
383	exaGetDrawableDeltas(&pWin->drawable, pPixmap, &xoff, &yoff);
384	RegionTranslate(prgnSrc, xoff, yoff);
385	pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, prgnSrc);
386	RegionTranslate(prgnSrc, -xoff, -yoff);
387    } else
388	exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
389
390    swap(pExaScr, pScreen, CopyWindow);
391    pScreen->CopyWindow (pWin, ptOldOrg, prgnSrc);
392    swap(pExaScr, pScreen, CopyWindow);
393    exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
394    EXA_POST_FALLBACK(pScreen);
395}
396
397void
398ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
399		unsigned int format, unsigned long planeMask, char *d)
400{
401    ScreenPtr pScreen = pDrawable->pScreen;
402    EXA_PRE_FALLBACK(pScreen);
403    EXA_FALLBACK(("from %p (%c)\n", pDrawable,
404		  exaDrawableLocation(pDrawable)));
405
406    ExaFallbackPrepareReg(pDrawable, NULL, x, y, w, h,
407			  EXA_PREPARE_SRC, FALSE);
408    swap(pExaScr, pScreen, GetImage);
409    pScreen->GetImage (pDrawable, x, y, w, h, format, planeMask, d);
410    swap(pExaScr, pScreen, GetImage);
411    exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
412    EXA_POST_FALLBACK(pScreen);
413}
414
415void
416ExaCheckGetSpans (DrawablePtr pDrawable,
417		 int wMax,
418		 DDXPointPtr ppt,
419		 int *pwidth,
420		 int nspans,
421		 char *pdstStart)
422{
423    ScreenPtr pScreen = pDrawable->pScreen;
424
425    EXA_PRE_FALLBACK(pScreen);
426    EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
427    exaPrepareAccess (pDrawable, EXA_PREPARE_SRC);
428    swap(pExaScr, pScreen, GetSpans);
429    pScreen->GetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
430    swap(pExaScr, pScreen, GetSpans);
431    exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
432    EXA_POST_FALLBACK(pScreen);
433}
434
435static void
436ExaSrcValidate(DrawablePtr pDrawable,
437	       int x,
438	       int y,
439	       int width,
440	       int height,
441	       unsigned int subWindowMode)
442{
443    ScreenPtr pScreen = pDrawable->pScreen;
444    ExaScreenPriv(pScreen);
445    PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
446    BoxRec box;
447    RegionRec reg;
448    RegionPtr dst;
449    int xoff, yoff;
450
451    if (pExaScr->srcPix == pPix)
452        dst = &pExaScr->srcReg;
453    else if (pExaScr->maskPix == pPix)
454        dst = &pExaScr->maskReg;
455    else
456        return;
457
458    exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
459
460    box.x1 = x + xoff;
461    box.y1 = y + yoff;
462    box.x2 = box.x1 + width;
463    box.y2 = box.y1 + height;
464
465    RegionInit(&reg, &box, 1);
466    RegionUnion(dst, dst, &reg);
467    RegionUninit(&reg);
468
469    if (pExaScr->SavedSourceValidate) {
470        swap(pExaScr, pScreen, SourceValidate);
471        pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
472        swap(pExaScr, pScreen, SourceValidate);
473    }
474}
475
476static Bool
477ExaPrepareCompositeReg(ScreenPtr  pScreen,
478		       CARD8      op,
479		       PicturePtr pSrc,
480		       PicturePtr pMask,
481		       PicturePtr pDst,
482		       INT16      xSrc,
483		       INT16      ySrc,
484		       INT16      xMask,
485		       INT16      yMask,
486		       INT16      xDst,
487		       INT16      yDst,
488		       CARD16     width,
489		       CARD16     height)
490{
491    RegionRec region;
492    RegionPtr dstReg = NULL;
493    RegionPtr srcReg = NULL;
494    RegionPtr maskReg = NULL;
495    PixmapPtr pSrcPix = NULL;
496    PixmapPtr pMaskPix = NULL;
497    PixmapPtr pDstPix;
498    ExaScreenPriv(pScreen);
499    Bool ret;
500
501
502    RegionNull(&region);
503
504    if (pSrc->pDrawable) {
505	pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
506	RegionNull(&pExaScr->srcReg);
507	srcReg = &pExaScr->srcReg;
508	pExaScr->srcPix = pSrcPix;
509	if (pSrc != pDst)
510	    RegionTranslate(pSrc->pCompositeClip,
511			     -pSrc->pDrawable->x,
512			     -pSrc->pDrawable->y);
513    } else
514        pExaScr->srcPix = NULL;
515
516    if (pMask && pMask->pDrawable) {
517	pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
518	RegionNull(&pExaScr->maskReg);
519	maskReg = &pExaScr->maskReg;
520        pExaScr->maskPix = pMaskPix;
521	if (pMask != pDst && pMask != pSrc)
522	    RegionTranslate(pMask->pCompositeClip,
523			     -pMask->pDrawable->x,
524			     -pMask->pDrawable->y);
525    } else
526        pExaScr->maskPix = NULL;
527
528    RegionTranslate(pDst->pCompositeClip,
529		     -pDst->pDrawable->x,
530		     -pDst->pDrawable->y);
531
532    pExaScr->SavedSourceValidate = ExaSrcValidate;
533    swap(pExaScr, pScreen, SourceValidate);
534    ret = miComputeCompositeRegion (&region, pSrc, pMask, pDst,
535				    xSrc, ySrc, xMask, yMask,
536				    xDst,
537				    yDst,
538				    width, height);
539    swap(pExaScr, pScreen, SourceValidate);
540
541    RegionTranslate(pDst->pCompositeClip,
542		     pDst->pDrawable->x,
543		     pDst->pDrawable->y);
544    if (pSrc->pDrawable && pSrc != pDst)
545	RegionTranslate(pSrc->pCompositeClip,
546			 pSrc->pDrawable->x,
547			 pSrc->pDrawable->y);
548    if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
549	RegionTranslate(pMask->pCompositeClip,
550			 pMask->pDrawable->x,
551			 pMask->pDrawable->y);
552
553    if (!ret) {
554	if (srcReg)
555	    RegionUninit(srcReg);
556	if (maskReg)
557	    RegionUninit(maskReg);
558
559	return FALSE;
560    }
561
562    /**
563     * Don't limit alphamaps readbacks for now until we've figured out how that
564     * should be done.
565     */
566
567    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
568	pExaScr->prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable),
569				    EXA_PREPARE_AUX_SRC,
570				    NULL);
571    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
572	pExaScr->prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable),
573				    EXA_PREPARE_AUX_MASK,
574				    NULL);
575
576    if (pSrcPix)
577	pExaScr->prepare_access_reg(pSrcPix,
578				    EXA_PREPARE_SRC,
579				    srcReg);
580
581    if (pMaskPix)
582	pExaScr->prepare_access_reg(pMaskPix,
583				    EXA_PREPARE_MASK,
584				    maskReg);
585
586    if (srcReg)
587	RegionUninit(srcReg);
588    if (maskReg)
589	RegionUninit(maskReg);
590
591    pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
592    if (!exaOpReadsDestination(op)) {
593	int xoff;
594	int yoff;
595
596	exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &xoff, &yoff);
597	RegionTranslate(&region, pDst->pDrawable->x + xoff,
598			 pDst->pDrawable->y + yoff);
599	dstReg = &region;
600    }
601
602    if (pDst->alphaMap && pDst->alphaMap->pDrawable)
603	pExaScr->prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
604				    EXA_PREPARE_AUX_DEST,
605				    dstReg);
606    pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg);
607
608    RegionUninit(&region);
609    return TRUE;
610}
611
612void
613ExaCheckComposite (CARD8      op,
614                   PicturePtr pSrc,
615                   PicturePtr pMask,
616                   PicturePtr pDst,
617                   INT16      xSrc,
618                   INT16      ySrc,
619                   INT16      xMask,
620                   INT16      yMask,
621                   INT16      xDst,
622                   INT16      yDst,
623                   CARD16     width,
624                   CARD16     height)
625{
626    ScreenPtr pScreen = pDst->pDrawable->pScreen;
627    PictureScreenPtr	ps = GetPictureScreen(pScreen);
628    EXA_PRE_FALLBACK(pScreen);
629
630    if (pExaScr->prepare_access_reg) {
631	if (!ExaPrepareCompositeReg(pScreen, op, pSrc, pMask, pDst, xSrc,
632				   ySrc, xMask, yMask, xDst, yDst, width,
633				   height))
634	    goto out_no_clip;
635    } else {
636
637	/* We need to prepare access to any separate alpha maps first,
638	 * in case the driver doesn't support EXA_PREPARE_AUX*,
639	 * in which case EXA_PREPARE_SRC may be used for moving them out.
640	 */
641
642	if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
643	    exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
644	if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
645	    exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
646	if (pDst->alphaMap && pDst->alphaMap->pDrawable)
647	    exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
648
649	exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST);
650
651	EXA_FALLBACK(("from picts %p/%p to pict %p\n",
652		      pSrc, pMask, pDst));
653
654	if (pSrc->pDrawable != NULL)
655	    exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
656	if (pMask && pMask->pDrawable != NULL)
657	    exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK);
658    }
659
660    swap(pExaScr, ps, Composite);
661    ps->Composite (op,
662                 pSrc,
663                 pMask,
664                 pDst,
665                 xSrc,
666                 ySrc,
667                 xMask,
668                 yMask,
669                 xDst,
670                 yDst,
671                 width,
672                 height);
673    swap(pExaScr, ps, Composite);
674    if (pMask && pMask->pDrawable != NULL)
675	exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK);
676    if (pSrc->pDrawable != NULL)
677	exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
678    exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST);
679    if (pDst->alphaMap && pDst->alphaMap->pDrawable)
680	exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
681    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
682	exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
683    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
684	exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
685
686out_no_clip:
687    EXA_POST_FALLBACK(pScreen);
688}
689
690/**
691 * Avoid migration ping-pong when using a mask.
692 */
693void
694ExaCheckGlyphs (CARD8	      op,
695		PicturePtr    pSrc,
696		PicturePtr    pDst,
697		PictFormatPtr maskFormat,
698		INT16	      xSrc,
699		INT16	      ySrc,
700		int	      nlist,
701		GlyphListPtr  list,
702		GlyphPtr      *glyphs)
703{
704    ScreenPtr pScreen = pDst->pDrawable->pScreen;
705    EXA_PRE_FALLBACK(pScreen);
706
707    miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
708
709    EXA_POST_FALLBACK(pScreen);
710}
711
712void
713ExaCheckAddTraps (PicturePtr	pPicture,
714		  INT16		x_off,
715		  INT16		y_off,
716		  int		ntrap,
717		  xTrap		*traps)
718{
719    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
720    PictureScreenPtr	ps = GetPictureScreen(pScreen);
721    EXA_PRE_FALLBACK(pScreen);
722
723    EXA_FALLBACK(("to pict %p (%c)\n",
724		  exaDrawableLocation(pPicture->pDrawable)));
725    exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
726    swap(pExaScr, ps, AddTraps);
727    ps->AddTraps (pPicture, x_off, y_off, ntrap, traps);
728    swap(pExaScr, ps, AddTraps);
729    exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
730    EXA_POST_FALLBACK(pScreen);
731}
732
733/**
734 * Gets the 0,0 pixel of a pixmap.  Used for doing solid fills of tiled pixmaps
735 * that happen to be 1x1.  Pixmap must be at least 8bpp.
736 */
737CARD32
738exaGetPixmapFirstPixel (PixmapPtr pPixmap)
739{
740    switch (pPixmap->drawable.bitsPerPixel) {
741    case 32:
742	{
743	    CARD32 pixel;
744
745	    pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
746						ZPixmap, ~0, (char*)&pixel);
747	    return pixel;
748	}
749    case 16:
750	{
751	    CARD16 pixel;
752
753	    pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
754						ZPixmap, ~0, (char*)&pixel);
755	    return pixel;
756	}
757    case 8:
758    case 4:
759    case 1:
760	{
761	    CARD8 pixel;
762
763	    pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
764						ZPixmap, ~0, (char*)&pixel);
765	    return pixel;
766	}
767    default:
768	FatalError("%s called for invalid bpp %d\n", __func__,
769		   pPixmap->drawable.bitsPerPixel);
770    }
771}
772