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  */
42 void
exaPrepareAccessGC(GCPtr pGC)43 exaPrepareAccessGC(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  */
54 void
exaFinishAccessGC(GCPtr pGC)55 exaFinishAccessGC(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
64 char
exaDrawableLocation(DrawablePtr pDrawable)65 exaDrawableLocation(DrawablePtr pDrawable)
66 {
67     return exaDrawableIsOffscreen(pDrawable) ? 's' : 'm';
68 }
69 #endif                          /* DEBUG_TRACE_FALL */
70 
71 void
ExaCheckFillSpans(DrawablePtr pDrawable,GCPtr pGC,int nspans,DDXPointPtr ppt,int * pwidth,int fSorted)72 ExaCheckFillSpans(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 
85 void
ExaCheckSetSpans(DrawablePtr pDrawable,GCPtr pGC,char * psrc,DDXPointPtr ppt,int * pwidth,int nspans,int fSorted)86 ExaCheckSetSpans(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 
97 void
ExaCheckPutImage(DrawablePtr pDrawable,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * bits)98 ExaCheckPutImage(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 
121 void
ExaCheckCopyNtoN(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,BoxPtr pbox,int nbox,int dx,int dy,Bool reverse,Bool upsidedown,Pixel bitplane,void * closure)122 ExaCheckCopyNtoN(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 
171 static void
ExaFallbackPrepareReg(DrawablePtr pDrawable,GCPtr pGC,int x,int y,int width,int height,int index,Bool checkReads)172 ExaFallbackPrepareReg(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 
204 RegionPtr
ExaCheckCopyArea(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty)205 ExaCheckCopyArea(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 
223 RegionPtr
ExaCheckCopyPlane(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long bitPlane)224 ExaCheckCopyPlane(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 
244 void
ExaCheckPolyPoint(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)245 ExaCheckPolyPoint(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 
256 void
ExaCheckPolylines(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr ppt)257 ExaCheckPolylines(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 
273 void
ExaCheckPolySegment(DrawablePtr pDrawable,GCPtr pGC,int nsegInit,xSegment * pSegInit)274 ExaCheckPolySegment(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 
289 void
ExaCheckPolyArc(DrawablePtr pDrawable,GCPtr pGC,int narcs,xArc * pArcs)290 ExaCheckPolyArc(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 
303 void
ExaCheckPolyFillRect(DrawablePtr pDrawable,GCPtr pGC,int nrect,xRectangle * prect)304 ExaCheckPolyFillRect(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 
318 void
ExaCheckImageGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,void * pglyphBase)319 ExaCheckImageGlyphBlt(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 
333 void
ExaCheckPolyGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,void * pglyphBase)334 ExaCheckPolyGlyphBlt(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 
349 void
ExaCheckPushPixels(GCPtr pGC,PixmapPtr pBitmap,DrawablePtr pDrawable,int w,int h,int x,int y)350 ExaCheckPushPixels(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 
368 void
ExaCheckCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc)369 ExaCheckCopyWindow(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 
397 void
ExaCheckGetImage(DrawablePtr pDrawable,int x,int y,int w,int h,unsigned int format,unsigned long planeMask,char * d)398 ExaCheckGetImage(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 
414 void
ExaCheckGetSpans(DrawablePtr pDrawable,int wMax,DDXPointPtr ppt,int * pwidth,int nspans,char * pdstStart)415 ExaCheckGetSpans(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 
431 static void
ExaSrcValidate(DrawablePtr pDrawable,int x,int y,int width,int height,unsigned int subWindowMode)432 ExaSrcValidate(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 
469 static Bool
ExaPrepareCompositeReg(ScreenPtr pScreen,CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)470 ExaPrepareCompositeReg(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 
590 void
ExaCheckComposite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)591 ExaCheckComposite(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  */
661 void
ExaCheckGlyphs(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int nlist,GlyphListPtr list,GlyphPtr * glyphs)662 ExaCheckGlyphs(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 
678 void
ExaCheckAddTraps(PicturePtr pPicture,INT16 x_off,INT16 y_off,int ntrap,xTrap * traps)679 ExaCheckAddTraps(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  */
701 CARD32
exaGetPixmapFirstPixel(PixmapPtr pPixmap)702 exaGetPixmapFirstPixel(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