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     swap(pExaScr, pScreen, SourceValidate);
463     pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
464     swap(pExaScr, pScreen, SourceValidate);
465 }
466 
467 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)468 ExaPrepareCompositeReg(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 
588 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)589 ExaCheckComposite(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  */
659 void
ExaCheckGlyphs(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int nlist,GlyphListPtr list,GlyphPtr * glyphs)660 ExaCheckGlyphs(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 
676 void
ExaCheckAddTraps(PicturePtr pPicture,INT16 x_off,INT16 y_off,int ntrap,xTrap * traps)677 ExaCheckAddTraps(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  */
699 CARD32
exaGetPixmapFirstPixel(PixmapPtr pPixmap)700 exaGetPixmapFirstPixel(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