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
104    ExaPixmapPriv(pPixmap);
105
106    EXA_PRE_FALLBACK_GC(pGC);
107    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
108    if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
109        exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
110                              pGC->alu, pGC->clientClip != NULL))
111        exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
112    else
113        pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
114                                    DamagePendingRegion(pExaPixmap->pDamage));
115    pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
116                       bits);
117    exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
118    EXA_POST_FALLBACK_GC(pGC);
119}
120
121void
122ExaCheckCopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
123                 BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
124                 Bool upsidedown, Pixel bitplane, void *closure)
125{
126    RegionRec reg;
127    int xoff, yoff;
128
129    EXA_PRE_FALLBACK_GC(pGC);
130    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
131                  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
132
133    if (pExaScr->prepare_access_reg && RegionInitBoxes(&reg, pbox, nbox)) {
134        PixmapPtr pPixmap = exaGetDrawablePixmap(pSrc);
135
136        exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
137        RegionTranslate(&reg, xoff + dx, yoff + dy);
138        pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, &reg);
139        RegionUninit(&reg);
140    }
141    else
142        exaPrepareAccess(pSrc, EXA_PREPARE_SRC);
143
144    if (pExaScr->prepare_access_reg &&
145        !exaGCReadsDestination(pDst, pGC->planemask, pGC->fillStyle,
146                               pGC->alu, pGC->clientClip != NULL) &&
147        RegionInitBoxes(&reg, pbox, nbox)) {
148        PixmapPtr pPixmap = exaGetDrawablePixmap(pDst);
149
150        exaGetDrawableDeltas(pDst, pPixmap, &xoff, &yoff);
151        RegionTranslate(&reg, xoff, yoff);
152        pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, &reg);
153        RegionUninit(&reg);
154    }
155    else
156        exaPrepareAccess(pDst, EXA_PREPARE_DEST);
157
158    /* This will eventually call fbCopyNtoN, with some calculation overhead. */
159    while (nbox--) {
160        pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx,
161                           pbox->y1 - pSrc->y + dy, pbox->x2 - pbox->x1,
162                           pbox->y2 - pbox->y1, pbox->x1 - pDst->x,
163                           pbox->y1 - pDst->y);
164        pbox++;
165    }
166    exaFinishAccess(pSrc, EXA_PREPARE_SRC);
167    exaFinishAccess(pDst, EXA_PREPARE_DEST);
168    EXA_POST_FALLBACK_GC(pGC);
169}
170
171static void
172ExaFallbackPrepareReg(DrawablePtr pDrawable,
173                      GCPtr pGC,
174                      int x, int y, int width, int height,
175                      int index, Bool checkReads)
176{
177    ScreenPtr pScreen = pDrawable->pScreen;
178
179    ExaScreenPriv(pScreen);
180
181    if (pExaScr->prepare_access_reg &&
182        !(checkReads && exaGCReadsDestination(pDrawable, pGC->planemask,
183                                              pGC->fillStyle, pGC->alu,
184                                              pGC->clientClip != NULL))) {
185        BoxRec box;
186        RegionRec reg;
187        int xoff, yoff;
188        PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
189
190        exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
191        box.x1 = pDrawable->x + x + xoff;
192        box.y1 = pDrawable->y + y + yoff;
193        box.x2 = box.x1 + width;
194        box.y2 = box.y1 + height;
195
196        RegionInit(&reg, &box, 1);
197        pExaScr->prepare_access_reg(pPixmap, index, &reg);
198        RegionUninit(&reg);
199    }
200    else
201        exaPrepareAccess(pDrawable, index);
202}
203
204RegionPtr
205ExaCheckCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
206                 int srcx, int srcy, int w, int h, int dstx, int dsty)
207{
208    RegionPtr ret;
209
210    EXA_PRE_FALLBACK_GC(pGC);
211    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
212                  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
213    ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE);
214    ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE);
215    ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
216    exaFinishAccess(pSrc, EXA_PREPARE_SRC);
217    exaFinishAccess(pDst, EXA_PREPARE_DEST);
218    EXA_POST_FALLBACK_GC(pGC);
219
220    return ret;
221}
222
223RegionPtr
224ExaCheckCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
225                  int srcx, int srcy, int w, int h, int dstx, int dsty,
226                  unsigned long bitPlane)
227{
228    RegionPtr ret;
229
230    EXA_PRE_FALLBACK_GC(pGC);
231    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
232                  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
233    ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE);
234    ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE);
235    ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
236                              bitPlane);
237    exaFinishAccess(pSrc, EXA_PREPARE_SRC);
238    exaFinishAccess(pDst, EXA_PREPARE_DEST);
239    EXA_POST_FALLBACK_GC(pGC);
240
241    return ret;
242}
243
244void
245ExaCheckPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
246                  DDXPointPtr pptInit)
247{
248    EXA_PRE_FALLBACK_GC(pGC);
249    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
250    exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
251    pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit);
252    exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
253    EXA_POST_FALLBACK_GC(pGC);
254}
255
256void
257ExaCheckPolylines(DrawablePtr pDrawable, GCPtr pGC,
258                  int mode, int npt, DDXPointPtr ppt)
259{
260    EXA_PRE_FALLBACK_GC(pGC);
261    EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
262                  pDrawable, exaDrawableLocation(pDrawable),
263                  pGC->lineWidth, mode, npt));
264
265    exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
266    exaPrepareAccessGC(pGC);
267    pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt);
268    exaFinishAccessGC(pGC);
269    exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
270    EXA_POST_FALLBACK_GC(pGC);
271}
272
273void
274ExaCheckPolySegment(DrawablePtr pDrawable, GCPtr pGC,
275                    int nsegInit, xSegment * pSegInit)
276{
277    EXA_PRE_FALLBACK_GC(pGC);
278    EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
279                  exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit));
280
281    exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
282    exaPrepareAccessGC(pGC);
283    pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit);
284    exaFinishAccessGC(pGC);
285    exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
286    EXA_POST_FALLBACK_GC(pGC);
287}
288
289void
290ExaCheckPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
291{
292    EXA_PRE_FALLBACK_GC(pGC);
293    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
294
295    exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
296    exaPrepareAccessGC(pGC);
297    pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs);
298    exaFinishAccessGC(pGC);
299    exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
300    EXA_POST_FALLBACK_GC(pGC);
301}
302
303void
304ExaCheckPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
305                     int nrect, xRectangle *prect)
306{
307    EXA_PRE_FALLBACK_GC(pGC);
308    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
309
310    exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
311    exaPrepareAccessGC(pGC);
312    pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect);
313    exaFinishAccessGC(pGC);
314    exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
315    EXA_POST_FALLBACK_GC(pGC);
316}
317
318void
319ExaCheckImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
320                      int x, int y, unsigned int nglyph,
321                      CharInfoPtr * ppci, void *pglyphBase)
322{
323    EXA_PRE_FALLBACK_GC(pGC);
324    EXA_FALLBACK(("to %p (%c)\n", pDrawable, 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, void *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, int w, int h, int x, int y)
352{
353    EXA_PRE_FALLBACK_GC(pGC);
354    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
355                  exaDrawableLocation(&pBitmap->drawable),
356                  exaDrawableLocation(pDrawable)));
357    ExaFallbackPrepareReg(pDrawable, pGC, x, y, w, h, EXA_PREPARE_DEST, TRUE);
358    ExaFallbackPrepareReg(&pBitmap->drawable, pGC, 0, 0, w, h,
359                          EXA_PREPARE_SRC, FALSE);
360    exaPrepareAccessGC(pGC);
361    pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
362    exaFinishAccessGC(pGC);
363    exaFinishAccess(&pBitmap->drawable, EXA_PREPARE_SRC);
364    exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
365    EXA_POST_FALLBACK_GC(pGC);
366}
367
368void
369ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
370{
371    DrawablePtr pDrawable = &pWin->drawable;
372    ScreenPtr pScreen = pDrawable->pScreen;
373
374    EXA_PRE_FALLBACK(pScreen);
375    EXA_FALLBACK(("from %p\n", pWin));
376
377    /* Only need the source bits, the destination region will be overwritten */
378    if (pExaScr->prepare_access_reg) {
379        PixmapPtr pPixmap = pScreen->GetWindowPixmap(pWin);
380        int xoff, yoff;
381
382        exaGetDrawableDeltas(&pWin->drawable, pPixmap, &xoff, &yoff);
383        RegionTranslate(prgnSrc, xoff, yoff);
384        pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, prgnSrc);
385        RegionTranslate(prgnSrc, -xoff, -yoff);
386    }
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
403    EXA_PRE_FALLBACK(pScreen);
404    EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
405
406    ExaFallbackPrepareReg(pDrawable, NULL, x, y, w, h, EXA_PREPARE_SRC, FALSE);
407    swap(pExaScr, pScreen, GetImage);
408    pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d);
409    swap(pExaScr, pScreen, GetImage);
410    exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
411    EXA_POST_FALLBACK(pScreen);
412}
413
414void
415ExaCheckGetSpans(DrawablePtr pDrawable,
416                 int wMax,
417                 DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
418{
419    ScreenPtr pScreen = pDrawable->pScreen;
420
421    EXA_PRE_FALLBACK(pScreen);
422    EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
423    exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
424    swap(pExaScr, pScreen, GetSpans);
425    pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
426    swap(pExaScr, pScreen, GetSpans);
427    exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
428    EXA_POST_FALLBACK(pScreen);
429}
430
431static void
432ExaSrcValidate(DrawablePtr pDrawable,
433               int x, int y, int width, int height, unsigned int subWindowMode)
434{
435    ScreenPtr pScreen = pDrawable->pScreen;
436
437    ExaScreenPriv(pScreen);
438    PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);
439    BoxRec box;
440    RegionRec reg;
441    RegionPtr dst;
442    int xoff, yoff;
443
444    if (pExaScr->srcPix == pPix)
445        dst = &pExaScr->srcReg;
446    else if (pExaScr->maskPix == pPix)
447        dst = &pExaScr->maskReg;
448    else
449        return;
450
451    exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
452
453    box.x1 = x + xoff;
454    box.y1 = y + yoff;
455    box.x2 = box.x1 + width;
456    box.y2 = box.y1 + height;
457
458    RegionInit(&reg, &box, 1);
459    RegionUnion(dst, dst, &reg);
460    RegionUninit(&reg);
461
462    swap(pExaScr, pScreen, SourceValidate);
463    pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
464    swap(pExaScr, pScreen, SourceValidate);
465}
466
467static Bool
468ExaPrepareCompositeReg(ScreenPtr pScreen,
469                       CARD8 op,
470                       PicturePtr pSrc,
471                       PicturePtr pMask,
472                       PicturePtr pDst,
473                       INT16 xSrc,
474                       INT16 ySrc,
475                       INT16 xMask,
476                       INT16 yMask,
477                       INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
478{
479    RegionRec region;
480    RegionPtr dstReg = NULL;
481    RegionPtr srcReg = NULL;
482    RegionPtr maskReg = NULL;
483    PixmapPtr pSrcPix = NULL;
484    PixmapPtr pMaskPix = NULL;
485    PixmapPtr pDstPix;
486
487    ExaScreenPriv(pScreen);
488    Bool ret;
489
490    RegionNull(&region);
491
492    if (pSrc->pDrawable) {
493        pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
494        RegionNull(&pExaScr->srcReg);
495        srcReg = &pExaScr->srcReg;
496        pExaScr->srcPix = pSrcPix;
497        if (pSrc != pDst)
498            RegionTranslate(pSrc->pCompositeClip,
499                            -pSrc->pDrawable->x, -pSrc->pDrawable->y);
500    } else
501        pExaScr->srcPix = NULL;
502
503    if (pMask && pMask->pDrawable) {
504        pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
505        RegionNull(&pExaScr->maskReg);
506        maskReg = &pExaScr->maskReg;
507        pExaScr->maskPix = pMaskPix;
508        if (pMask != pDst && pMask != pSrc)
509            RegionTranslate(pMask->pCompositeClip,
510                            -pMask->pDrawable->x, -pMask->pDrawable->y);
511    } else
512        pExaScr->maskPix = NULL;
513
514    RegionTranslate(pDst->pCompositeClip,
515                    -pDst->pDrawable->x, -pDst->pDrawable->y);
516
517    pExaScr->SavedSourceValidate = ExaSrcValidate;
518    swap(pExaScr, pScreen, SourceValidate);
519    ret = miComputeCompositeRegion(&region, pSrc, pMask, pDst,
520                                   xSrc, ySrc, xMask, yMask,
521                                   xDst, yDst, width, height);
522    swap(pExaScr, pScreen, SourceValidate);
523
524    RegionTranslate(pDst->pCompositeClip,
525                    pDst->pDrawable->x, pDst->pDrawable->y);
526    if (pSrc->pDrawable && pSrc != pDst)
527        RegionTranslate(pSrc->pCompositeClip,
528                        pSrc->pDrawable->x, pSrc->pDrawable->y);
529    if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
530        RegionTranslate(pMask->pCompositeClip,
531                        pMask->pDrawable->x, pMask->pDrawable->y);
532
533    if (!ret) {
534        if (srcReg)
535            RegionUninit(srcReg);
536        if (maskReg)
537            RegionUninit(maskReg);
538
539        return FALSE;
540    }
541
542    /**
543     * Don't limit alphamaps readbacks for now until we've figured out how that
544     * should be done.
545     */
546
547    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
548        pExaScr->
549            prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable),
550                               EXA_PREPARE_AUX_SRC, NULL);
551    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
552        pExaScr->
553            prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable),
554                               EXA_PREPARE_AUX_MASK, NULL);
555
556    if (pSrcPix)
557        pExaScr->prepare_access_reg(pSrcPix, EXA_PREPARE_SRC, srcReg);
558
559    if (pMaskPix)
560        pExaScr->prepare_access_reg(pMaskPix, EXA_PREPARE_MASK, maskReg);
561
562    if (srcReg)
563        RegionUninit(srcReg);
564    if (maskReg)
565        RegionUninit(maskReg);
566
567    pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
568    if (!exaOpReadsDestination(op)) {
569        int xoff;
570        int yoff;
571
572        exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &xoff, &yoff);
573        RegionTranslate(&region, pDst->pDrawable->x + xoff,
574                        pDst->pDrawable->y + yoff);
575        dstReg = &region;
576    }
577
578    if (pDst->alphaMap && pDst->alphaMap->pDrawable)
579        pExaScr->
580            prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
581                               EXA_PREPARE_AUX_DEST, dstReg);
582    pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg);
583
584    RegionUninit(&region);
585    return TRUE;
586}
587
588void
589ExaCheckComposite(CARD8 op,
590                  PicturePtr pSrc,
591                  PicturePtr pMask,
592                  PicturePtr pDst,
593                  INT16 xSrc,
594                  INT16 ySrc,
595                  INT16 xMask,
596                  INT16 yMask,
597                  INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
598{
599    ScreenPtr pScreen = pDst->pDrawable->pScreen;
600    PictureScreenPtr ps = GetPictureScreen(pScreen);
601
602    EXA_PRE_FALLBACK(pScreen);
603
604    if (pExaScr->prepare_access_reg) {
605        if (!ExaPrepareCompositeReg(pScreen, op, pSrc, pMask, pDst, xSrc,
606                                    ySrc, xMask, yMask, xDst, yDst, width,
607                                    height))
608            goto out_no_clip;
609    }
610    else {
611
612        /* We need to prepare access to any separate alpha maps first,
613         * in case the driver doesn't support EXA_PREPARE_AUX*,
614         * in which case EXA_PREPARE_SRC may be used for moving them out.
615         */
616
617        if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
618            exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
619        if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
620            exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
621        if (pDst->alphaMap && pDst->alphaMap->pDrawable)
622            exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
623
624        exaPrepareAccess(pDst->pDrawable, EXA_PREPARE_DEST);
625
626        EXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst));
627
628        if (pSrc->pDrawable != NULL)
629            exaPrepareAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
630        if (pMask && pMask->pDrawable != NULL)
631            exaPrepareAccess(pMask->pDrawable, EXA_PREPARE_MASK);
632    }
633
634    swap(pExaScr, ps, Composite);
635    ps->Composite(op,
636                  pSrc,
637                  pMask,
638                  pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
639    swap(pExaScr, ps, Composite);
640    if (pMask && pMask->pDrawable != NULL)
641        exaFinishAccess(pMask->pDrawable, EXA_PREPARE_MASK);
642    if (pSrc->pDrawable != NULL)
643        exaFinishAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
644    exaFinishAccess(pDst->pDrawable, EXA_PREPARE_DEST);
645    if (pDst->alphaMap && pDst->alphaMap->pDrawable)
646        exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
647    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
648        exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
649    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
650        exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
651
652 out_no_clip:
653    EXA_POST_FALLBACK(pScreen);
654}
655
656/**
657 * Avoid migration ping-pong when using a mask.
658 */
659void
660ExaCheckGlyphs(CARD8 op,
661               PicturePtr pSrc,
662               PicturePtr pDst,
663               PictFormatPtr maskFormat,
664               INT16 xSrc,
665               INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
666{
667    ScreenPtr pScreen = pDst->pDrawable->pScreen;
668
669    EXA_PRE_FALLBACK(pScreen);
670
671    miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
672
673    EXA_POST_FALLBACK(pScreen);
674}
675
676void
677ExaCheckAddTraps(PicturePtr pPicture,
678                 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
679{
680    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
681    PictureScreenPtr ps = GetPictureScreen(pScreen);
682
683    EXA_PRE_FALLBACK(pScreen);
684
685    EXA_FALLBACK(("to pict %p (%c)\n", pPicture,
686                  exaDrawableLocation(pPicture->pDrawable)));
687    exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
688    swap(pExaScr, ps, AddTraps);
689    ps->AddTraps(pPicture, x_off, y_off, ntrap, traps);
690    swap(pExaScr, ps, AddTraps);
691    exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
692    EXA_POST_FALLBACK(pScreen);
693}
694
695/**
696 * Gets the 0,0 pixel of a pixmap.  Used for doing solid fills of tiled pixmaps
697 * that happen to be 1x1.  Pixmap must be at least 8bpp.
698 */
699CARD32
700exaGetPixmapFirstPixel(PixmapPtr pPixmap)
701{
702    switch (pPixmap->drawable.bitsPerPixel) {
703    case 32:
704    {
705        CARD32 pixel;
706
707        pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
708                                            ZPixmap, ~0, (char *) &pixel);
709        return pixel;
710    }
711    case 16:
712    {
713        CARD16 pixel;
714
715        pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
716                                            ZPixmap, ~0, (char *) &pixel);
717        return pixel;
718    }
719    case 8:
720    case 4:
721    case 1:
722    {
723        CARD8 pixel;
724
725        pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
726                                            ZPixmap, ~0, (char *) &pixel);
727        return pixel;
728    }
729    default:
730        FatalError("%s called for invalid bpp %d\n", __func__,
731                   pPixmap->drawable.bitsPerPixel);
732    }
733}
734