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(®, pbox, nbox)) {
134 PixmapPtr pPixmap = exaGetDrawablePixmap(pSrc);
135
136 exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
137 RegionTranslate(®, xoff + dx, yoff + dy);
138 pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, ®);
139 RegionUninit(®);
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(®, pbox, nbox)) {
148 PixmapPtr pPixmap = exaGetDrawablePixmap(pDst);
149
150 exaGetDrawableDeltas(pDst, pPixmap, &xoff, &yoff);
151 RegionTranslate(®, xoff, yoff);
152 pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, ®);
153 RegionUninit(®);
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(®, &box, 1);
197 pExaScr->prepare_access_reg(pPixmap, index, ®);
198 RegionUninit(®);
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(®, &box, 1);
459 RegionUnion(dst, dst, ®);
460 RegionUninit(®);
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(®ion);
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(®ion, 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(®ion, pDst->pDrawable->x + xoff,
574 pDst->pDrawable->y + yoff);
575 dstReg = ®ion;
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(®ion);
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