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