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 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(®ion);
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(®ion, 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(®ion, pDst->pDrawable->x + xoff,
576 pDst->pDrawable->y + yoff);
577 dstReg = ®ion;
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(®ion);
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