exa_unaccel.c revision f7df2e56
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    if (pExaScr->SavedSourceValidate) {
463        swap(pExaScr, pScreen, SourceValidate);
464        pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
465        swap(pExaScr, pScreen, SourceValidate);
466    }
467}
468
469static Bool
470ExaPrepareCompositeReg(ScreenPtr pScreen,
471                       CARD8 op,
472                       PicturePtr pSrc,
473                       PicturePtr pMask,
474                       PicturePtr pDst,
475                       INT16 xSrc,
476                       INT16 ySrc,
477                       INT16 xMask,
478                       INT16 yMask,
479                       INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
480{
481    RegionRec region;
482    RegionPtr dstReg = NULL;
483    RegionPtr srcReg = NULL;
484    RegionPtr maskReg = NULL;
485    PixmapPtr pSrcPix = NULL;
486    PixmapPtr pMaskPix = NULL;
487    PixmapPtr pDstPix;
488
489    ExaScreenPriv(pScreen);
490    Bool ret;
491
492    RegionNull(&region);
493
494    if (pSrc->pDrawable) {
495        pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
496        RegionNull(&pExaScr->srcReg);
497        srcReg = &pExaScr->srcReg;
498        pExaScr->srcPix = pSrcPix;
499        if (pSrc != pDst)
500            RegionTranslate(pSrc->pCompositeClip,
501                            -pSrc->pDrawable->x, -pSrc->pDrawable->y);
502    } else
503        pExaScr->srcPix = NULL;
504
505    if (pMask && pMask->pDrawable) {
506        pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
507        RegionNull(&pExaScr->maskReg);
508        maskReg = &pExaScr->maskReg;
509        pExaScr->maskPix = pMaskPix;
510        if (pMask != pDst && pMask != pSrc)
511            RegionTranslate(pMask->pCompositeClip,
512                            -pMask->pDrawable->x, -pMask->pDrawable->y);
513    } else
514        pExaScr->maskPix = NULL;
515
516    RegionTranslate(pDst->pCompositeClip,
517                    -pDst->pDrawable->x, -pDst->pDrawable->y);
518
519    pExaScr->SavedSourceValidate = ExaSrcValidate;
520    swap(pExaScr, pScreen, SourceValidate);
521    ret = miComputeCompositeRegion(&region, pSrc, pMask, pDst,
522                                   xSrc, ySrc, xMask, yMask,
523                                   xDst, yDst, width, height);
524    swap(pExaScr, pScreen, SourceValidate);
525
526    RegionTranslate(pDst->pCompositeClip,
527                    pDst->pDrawable->x, pDst->pDrawable->y);
528    if (pSrc->pDrawable && pSrc != pDst)
529        RegionTranslate(pSrc->pCompositeClip,
530                        pSrc->pDrawable->x, pSrc->pDrawable->y);
531    if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
532        RegionTranslate(pMask->pCompositeClip,
533                        pMask->pDrawable->x, pMask->pDrawable->y);
534
535    if (!ret) {
536        if (srcReg)
537            RegionUninit(srcReg);
538        if (maskReg)
539            RegionUninit(maskReg);
540
541        return FALSE;
542    }
543
544    /**
545     * Don't limit alphamaps readbacks for now until we've figured out how that
546     * should be done.
547     */
548
549    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
550        pExaScr->
551            prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable),
552                               EXA_PREPARE_AUX_SRC, NULL);
553    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
554        pExaScr->
555            prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable),
556                               EXA_PREPARE_AUX_MASK, NULL);
557
558    if (pSrcPix)
559        pExaScr->prepare_access_reg(pSrcPix, EXA_PREPARE_SRC, srcReg);
560
561    if (pMaskPix)
562        pExaScr->prepare_access_reg(pMaskPix, EXA_PREPARE_MASK, maskReg);
563
564    if (srcReg)
565        RegionUninit(srcReg);
566    if (maskReg)
567        RegionUninit(maskReg);
568
569    pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
570    if (!exaOpReadsDestination(op)) {
571        int xoff;
572        int yoff;
573
574        exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &xoff, &yoff);
575        RegionTranslate(&region, pDst->pDrawable->x + xoff,
576                        pDst->pDrawable->y + yoff);
577        dstReg = &region;
578    }
579
580    if (pDst->alphaMap && pDst->alphaMap->pDrawable)
581        pExaScr->
582            prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
583                               EXA_PREPARE_AUX_DEST, dstReg);
584    pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg);
585
586    RegionUninit(&region);
587    return TRUE;
588}
589
590void
591ExaCheckComposite(CARD8 op,
592                  PicturePtr pSrc,
593                  PicturePtr pMask,
594                  PicturePtr pDst,
595                  INT16 xSrc,
596                  INT16 ySrc,
597                  INT16 xMask,
598                  INT16 yMask,
599                  INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
600{
601    ScreenPtr pScreen = pDst->pDrawable->pScreen;
602    PictureScreenPtr ps = GetPictureScreen(pScreen);
603
604    EXA_PRE_FALLBACK(pScreen);
605
606    if (pExaScr->prepare_access_reg) {
607        if (!ExaPrepareCompositeReg(pScreen, op, pSrc, pMask, pDst, xSrc,
608                                    ySrc, xMask, yMask, xDst, yDst, width,
609                                    height))
610            goto out_no_clip;
611    }
612    else {
613
614        /* We need to prepare access to any separate alpha maps first,
615         * in case the driver doesn't support EXA_PREPARE_AUX*,
616         * in which case EXA_PREPARE_SRC may be used for moving them out.
617         */
618
619        if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
620            exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
621        if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
622            exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
623        if (pDst->alphaMap && pDst->alphaMap->pDrawable)
624            exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
625
626        exaPrepareAccess(pDst->pDrawable, EXA_PREPARE_DEST);
627
628        EXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst));
629
630        if (pSrc->pDrawable != NULL)
631            exaPrepareAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
632        if (pMask && pMask->pDrawable != NULL)
633            exaPrepareAccess(pMask->pDrawable, EXA_PREPARE_MASK);
634    }
635
636    swap(pExaScr, ps, Composite);
637    ps->Composite(op,
638                  pSrc,
639                  pMask,
640                  pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
641    swap(pExaScr, ps, Composite);
642    if (pMask && pMask->pDrawable != NULL)
643        exaFinishAccess(pMask->pDrawable, EXA_PREPARE_MASK);
644    if (pSrc->pDrawable != NULL)
645        exaFinishAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
646    exaFinishAccess(pDst->pDrawable, EXA_PREPARE_DEST);
647    if (pDst->alphaMap && pDst->alphaMap->pDrawable)
648        exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
649    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
650        exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
651    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
652        exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
653
654 out_no_clip:
655    EXA_POST_FALLBACK(pScreen);
656}
657
658/**
659 * Avoid migration ping-pong when using a mask.
660 */
661void
662ExaCheckGlyphs(CARD8 op,
663               PicturePtr pSrc,
664               PicturePtr pDst,
665               PictFormatPtr maskFormat,
666               INT16 xSrc,
667               INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
668{
669    ScreenPtr pScreen = pDst->pDrawable->pScreen;
670
671    EXA_PRE_FALLBACK(pScreen);
672
673    miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
674
675    EXA_POST_FALLBACK(pScreen);
676}
677
678void
679ExaCheckAddTraps(PicturePtr pPicture,
680                 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
681{
682    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
683    PictureScreenPtr ps = GetPictureScreen(pScreen);
684
685    EXA_PRE_FALLBACK(pScreen);
686
687    EXA_FALLBACK(("to pict %p (%c)\n", pPicture,
688                  exaDrawableLocation(pPicture->pDrawable)));
689    exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
690    swap(pExaScr, ps, AddTraps);
691    ps->AddTraps(pPicture, x_off, y_off, ntrap, traps);
692    swap(pExaScr, ps, AddTraps);
693    exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
694    EXA_POST_FALLBACK(pScreen);
695}
696
697/**
698 * Gets the 0,0 pixel of a pixmap.  Used for doing solid fills of tiled pixmaps
699 * that happen to be 1x1.  Pixmap must be at least 8bpp.
700 */
701CARD32
702exaGetPixmapFirstPixel(PixmapPtr pPixmap)
703{
704    switch (pPixmap->drawable.bitsPerPixel) {
705    case 32:
706    {
707        CARD32 pixel;
708
709        pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
710                                            ZPixmap, ~0, (char *) &pixel);
711        return pixel;
712    }
713    case 16:
714    {
715        CARD16 pixel;
716
717        pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
718                                            ZPixmap, ~0, (char *) &pixel);
719        return pixel;
720    }
721    case 8:
722    case 4:
723    case 1:
724    {
725        CARD8 pixel;
726
727        pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
728                                            ZPixmap, ~0, (char *) &pixel);
729        return pixel;
730    }
731    default:
732        FatalError("%s called for invalid bpp %d\n", __func__,
733                   pPixmap->drawable.bitsPerPixel);
734    }
735}
736