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