]>
Commit | Line | Data |
---|---|---|
055b6688 AM |
1 | --- xorg/exa/exa_render.c~ 2009-02-25 20:12:11.000000000 +0100 |
2 | +++ xorg/exa/exa_render.c 2009-02-28 18:09:52.562970685 +0100 | |
3 | @@ -342,7 +342,6 @@ | |
4 | int src_off_x, src_off_y, dst_off_x, dst_off_y; | |
5 | PixmapPtr pSrcPix, pDstPix; | |
6 | ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; | |
7 | - struct _Pixmap scratch; | |
8 | ExaMigrationRec pixmaps[2]; | |
9 | ||
10 | if (!pExaScr->info->PrepareComposite) | |
11 | @@ -386,13 +385,6 @@ | |
12 | if (!exaPixmapIsOffscreen(pDstPix)) | |
13 | return 0; | |
14 | ||
15 | - if (!pSrcPix && pExaScr->info->UploadToScratch) | |
16 | - { | |
17 | - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); | |
18 | - if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch)) | |
19 | - pSrcPix = &scratch; | |
20 | - } | |
21 | - | |
22 | if (!pSrcPix) | |
23 | return 0; | |
24 | ||
25 | @@ -573,7 +565,6 @@ | |
26 | int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; | |
27 | PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; | |
28 | ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; | |
29 | - struct _Pixmap scratch; | |
30 | ExaMigrationRec pixmaps[3]; | |
31 | ||
32 | pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); | |
33 | @@ -652,16 +643,6 @@ | |
34 | return 0; | |
35 | } | |
36 | ||
37 | - if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->UploadToScratch) { | |
38 | - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); | |
39 | - if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch)) | |
40 | - pSrcPix = &scratch; | |
41 | - } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->UploadToScratch) { | |
42 | - pMaskPix = exaGetDrawablePixmap (pMask->pDrawable); | |
43 | - if ((*pExaScr->info->UploadToScratch) (pMaskPix, &scratch)) | |
44 | - pMaskPix = &scratch; | |
45 | - } | |
46 | - | |
47 | if (!pSrcPix || (pMask && !pMaskPix)) { | |
48 | REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); | |
49 | return 0; | |
50 | commit f07f18231a921d3ae9dd9b75881c9e58e9e2e235 | |
51 | Author: Michel Dänzer <daenzer@vmware.com> | |
52 | Date: Thu Feb 26 10:35:44 2009 +0100 | |
453260b6 | 53 | |
055b6688 AM |
54 | EXA: Allow using exaCompositeRects also when we can't use a mask in exaGlyphs. |
55 | ||
56 | This should give the full benefits of the glyph cache even when we can't use a | |
57 | mask. | |
58 | ||
59 | This also means we no longer need to scan the glyphs to see if they overlap, | |
60 | we can just use a mask or not as the client asks. | |
61 | ||
62 | Signed-off-by: Michel Dänzer <daenzer@vmware.com> | |
453260b6 | 63 | |
055b6688 AM |
64 | diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c |
65 | index 688081d..918fd85 100644 | |
66 | --- a/exa/exa_glyphs.c | |
67 | +++ b/exa/exa_glyphs.c | |
68 | @@ -68,7 +68,7 @@ | |
69 | #define GLYPH_BUFFER_SIZE 256 | |
33d29f3f | 70 | |
055b6688 AM |
71 | typedef struct { |
72 | - PicturePtr source; | |
73 | + PicturePtr mask; | |
74 | ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE]; | |
75 | int count; | |
76 | } ExaGlyphBuffer, *ExaGlyphBufferPtr; | |
77 | @@ -144,7 +144,7 @@ exaUnrealizeGlyphCaches(ScreenPtr pScreen, | |
78 | ||
79 | /* All caches for a single format share a single pixmap for glyph storage, | |
80 | * allowing mixing glyphs of different sizes without paying a penalty | |
81 | - * for switching between source pixmaps. (Note that for a size of font | |
82 | + * for switching between mask pixmaps. (Note that for a size of font | |
83 | * right at the border between two sizes, we might be switching for almost | |
84 | * every glyph.) | |
85 | * | |
86 | @@ -417,13 +417,19 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, | |
87 | ExaGlyphCachePtr cache, | |
88 | ExaGlyphBufferPtr buffer, | |
89 | GlyphPtr pGlyph, | |
90 | - int xGlyph, | |
91 | - int yGlyph) | |
92 | + PicturePtr pSrc, | |
93 | + PicturePtr pDst, | |
94 | + INT16 xSrc, | |
95 | + INT16 ySrc, | |
96 | + INT16 xMask, | |
97 | + INT16 yMask, | |
98 | + INT16 xDst, | |
99 | + INT16 yDst) | |
100 | { | |
101 | ExaCompositeRectPtr rect; | |
102 | int pos; | |
103 | ||
104 | - if (buffer->source && buffer->source != cache->picture) | |
105 | + if (buffer->mask && buffer->mask != cache->picture) | |
106 | return ExaGlyphNeedFlush; | |
33d29f3f | 107 | |
055b6688 AM |
108 | if (!cache->picture) { |
109 | @@ -497,13 +503,28 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, | |
33d29f3f | 110 | |
055b6688 | 111 | } |
33d29f3f | 112 | |
055b6688 AM |
113 | - buffer->source = cache->picture; |
114 | + buffer->mask = cache->picture; | |
115 | ||
116 | rect = &buffer->rects[buffer->count]; | |
117 | - rect->xSrc = CACHE_X(pos); | |
118 | - rect->ySrc = CACHE_Y(pos); | |
119 | - rect->xDst = xGlyph - pGlyph->info.x; | |
120 | - rect->yDst = yGlyph - pGlyph->info.y; | |
33d29f3f | 121 | + |
055b6688 AM |
122 | + if (pSrc) |
123 | + { | |
124 | + rect->xSrc = xSrc; | |
125 | + rect->ySrc = ySrc; | |
126 | + rect->xMask = CACHE_X(pos); | |
127 | + rect->yMask = CACHE_Y(pos); | |
33d29f3f | 128 | + } |
055b6688 AM |
129 | + else |
130 | + { | |
131 | + rect->xSrc = CACHE_X(pos); | |
132 | + rect->ySrc = CACHE_Y(pos); | |
133 | + rect->xMask = 0; | |
134 | + rect->yMask = 0; | |
33d29f3f | 135 | + } |
055b6688 AM |
136 | + |
137 | + rect->pDst = pDst; | |
138 | + rect->xDst = xDst - pGlyph->info.x; | |
139 | + rect->yDst = yDst - pGlyph->info.y; | |
140 | rect->width = pGlyph->info.width; | |
141 | rect->height = pGlyph->info.height; | |
142 | ||
143 | @@ -519,15 +540,21 @@ static ExaGlyphCacheResult | |
144 | exaBufferGlyph(ScreenPtr pScreen, | |
145 | ExaGlyphBufferPtr buffer, | |
146 | GlyphPtr pGlyph, | |
147 | - int xGlyph, | |
148 | - int yGlyph) | |
149 | + PicturePtr pSrc, | |
150 | + PicturePtr pDst, | |
151 | + INT16 xSrc, | |
152 | + INT16 ySrc, | |
153 | + INT16 xMask, | |
154 | + INT16 yMask, | |
155 | + INT16 xDst, | |
156 | + INT16 yDst) | |
157 | { | |
158 | ExaScreenPriv(pScreen); | |
159 | unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format; | |
160 | int width = pGlyph->info.width; | |
161 | int height = pGlyph->info.height; | |
162 | ExaCompositeRectPtr rect; | |
163 | - PicturePtr source; | |
164 | + PicturePtr mask; | |
165 | int i; | |
166 | ||
167 | if (buffer->count == GLYPH_BUFFER_SIZE) | |
168 | @@ -542,9 +569,15 @@ exaBufferGlyph(ScreenPtr pScreen, | |
169 | if (format == cache->format && | |
170 | width <= cache->glyphWidth && | |
171 | height <= cache->glyphHeight) { | |
172 | - ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i], | |
173 | + ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, | |
174 | + &pExaScr->glyphCaches[i], | |
175 | buffer, | |
176 | - pGlyph, xGlyph, yGlyph); | |
177 | + pGlyph, | |
178 | + pSrc, | |
179 | + pDst, | |
180 | + xSrc, ySrc, | |
181 | + xMask, yMask, | |
182 | + xDst, yDst); | |
183 | switch (result) { | |
184 | case ExaGlyphFail: | |
185 | break; | |
186 | @@ -557,19 +590,21 @@ exaBufferGlyph(ScreenPtr pScreen, | |
187 | ||
188 | /* Couldn't find the glyph in the cache, use the glyph picture directly */ | |
189 | ||
190 | - source = GlyphPicture(pGlyph)[pScreen->myNum]; | |
191 | - if (buffer->source && buffer->source != source) | |
192 | + mask = GlyphPicture(pGlyph)[pScreen->myNum]; | |
193 | + if (buffer->mask && buffer->mask != mask) | |
194 | return ExaGlyphNeedFlush; | |
195 | ||
196 | - buffer->source = source; | |
197 | - | |
198 | + buffer->mask = mask; | |
199 | + | |
200 | rect = &buffer->rects[buffer->count]; | |
201 | - rect->xSrc = 0; | |
202 | - rect->ySrc = 0; | |
203 | - rect->xDst = xGlyph - pGlyph->info.x; | |
204 | - rect->yDst = yGlyph - pGlyph->info.y; | |
205 | - rect->width = pGlyph->info.width; | |
206 | - rect->height = pGlyph->info.height; | |
207 | + rect->xSrc = xSrc; | |
208 | + rect->ySrc = ySrc; | |
209 | + rect->xMask = xMask; | |
210 | + rect->yMask = yMask; | |
211 | + rect->xDst = xDst - pGlyph->info.x; | |
212 | + rect->yDst = yDst - pGlyph->info.y; | |
213 | + rect->width = width; | |
214 | + rect->height = height; | |
215 | ||
216 | buffer->count++; | |
217 | ||
218 | @@ -580,44 +615,23 @@ static void | |
219 | exaGlyphsToMask(PicturePtr pMask, | |
220 | ExaGlyphBufferPtr buffer) | |
221 | { | |
222 | - exaCompositeRects(PictOpAdd, buffer->source, pMask, | |
223 | + exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask, | |
224 | buffer->count, buffer->rects); | |
225 | ||
226 | buffer->count = 0; | |
227 | - buffer->source = NULL; | |
228 | + buffer->mask = NULL; | |
33d29f3f AM |
229 | } |
230 | ||
055b6688 AM |
231 | static void |
232 | -exaGlyphsToDst(CARD8 op, | |
233 | - PicturePtr pSrc, | |
234 | +exaGlyphsToDst(PicturePtr pSrc, | |
235 | PicturePtr pDst, | |
236 | - ExaGlyphBufferPtr buffer, | |
237 | - INT16 xSrc, | |
238 | - INT16 ySrc, | |
239 | - INT16 xDst, | |
240 | - INT16 yDst) | |
241 | + ExaGlyphBufferPtr buffer) | |
33d29f3f | 242 | { |
055b6688 AM |
243 | - int i; |
244 | - | |
245 | - for (i = 0; i < buffer->count; i++) { | |
246 | - ExaCompositeRectPtr rect = &buffer->rects[i]; | |
247 | - | |
248 | - CompositePicture (op, | |
249 | - pSrc, | |
250 | - buffer->source, | |
251 | - pDst, | |
252 | - xSrc + rect->xDst - xDst, | |
253 | - ySrc + rect->yDst - yDst, | |
254 | - rect->xSrc, | |
255 | - rect->ySrc, | |
256 | - rect->xDst, | |
257 | - rect->yDst, | |
258 | - rect->width, | |
259 | - rect->height); | |
260 | - } | |
261 | + exaCompositeRects(PictOpOver, pSrc, buffer->mask, pDst, buffer->count, | |
262 | + buffer->rects); | |
263 | ||
264 | buffer->count = 0; | |
265 | - buffer->source = NULL; | |
266 | + buffer->mask = NULL; | |
33d29f3f AM |
267 | } |
268 | ||
055b6688 AM |
269 | /* Cut and paste from render/glyph.c - probably should export it instead */ |
270 | @@ -673,79 +687,6 @@ GlyphExtents (int nlist, | |
453260b6 | 271 | } |
055b6688 | 272 | } |
453260b6 | 273 | |
055b6688 AM |
274 | -/** |
275 | - * Returns TRUE if the glyphs in the lists intersect. Only checks based on | |
276 | - * bounding box, which appears to be good enough to catch most cases at least. | |
277 | - */ | |
278 | -static Bool | |
279 | -exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs) | |
280 | -{ | |
281 | - int x1, x2, y1, y2; | |
282 | - int n; | |
283 | - GlyphPtr glyph; | |
284 | - int x, y; | |
285 | - BoxRec extents; | |
286 | - Bool first = TRUE; | |
33d29f3f | 287 | - |
055b6688 AM |
288 | - x = 0; |
289 | - y = 0; | |
290 | - while (nlist--) { | |
291 | - x += list->xOff; | |
292 | - y += list->yOff; | |
293 | - n = list->len; | |
294 | - list++; | |
295 | - while (n--) { | |
296 | - glyph = *glyphs++; | |
33d29f3f | 297 | - |
055b6688 AM |
298 | - if (glyph->info.width == 0 || glyph->info.height == 0) { |
299 | - x += glyph->info.xOff; | |
300 | - y += glyph->info.yOff; | |
301 | - continue; | |
302 | - } | |
33d29f3f | 303 | - |
055b6688 AM |
304 | - x1 = x - glyph->info.x; |
305 | - if (x1 < MINSHORT) | |
306 | - x1 = MINSHORT; | |
307 | - y1 = y - glyph->info.y; | |
308 | - if (y1 < MINSHORT) | |
309 | - y1 = MINSHORT; | |
310 | - x2 = x1 + glyph->info.width; | |
311 | - if (x2 > MAXSHORT) | |
312 | - x2 = MAXSHORT; | |
313 | - y2 = y1 + glyph->info.height; | |
314 | - if (y2 > MAXSHORT) | |
315 | - y2 = MAXSHORT; | |
316 | - | |
317 | - if (first) { | |
318 | - extents.x1 = x1; | |
319 | - extents.y1 = y1; | |
320 | - extents.x2 = x2; | |
321 | - extents.y2 = y2; | |
322 | - first = FALSE; | |
323 | - } else { | |
324 | - if (x1 < extents.x2 && x2 > extents.x1 && | |
325 | - y1 < extents.y2 && y2 > extents.y1) | |
326 | - { | |
327 | - return TRUE; | |
328 | - } | |
329 | - | |
330 | - if (x1 < extents.x1) | |
331 | - extents.x1 = x1; | |
332 | - if (x2 > extents.x2) | |
333 | - extents.x2 = x2; | |
334 | - if (y1 < extents.y1) | |
335 | - extents.y1 = y1; | |
336 | - if (y2 > extents.y2) | |
337 | - extents.y2 = y2; | |
338 | - } | |
339 | - x += glyph->info.xOff; | |
340 | - y += glyph->info.yOff; | |
341 | - } | |
342 | - } | |
343 | - | |
344 | - return FALSE; | |
345 | -} | |
33d29f3f AM |
346 | - |
347 | void | |
055b6688 AM |
348 | exaGlyphs (CARD8 op, |
349 | PicturePtr pSrc, | |
350 | @@ -759,7 +700,7 @@ exaGlyphs (CARD8 op, | |
351 | { | |
352 | PicturePtr pPicture; | |
353 | PixmapPtr pMaskPixmap = 0; | |
354 | - PicturePtr pMask; | |
355 | + PicturePtr pMask = NULL; | |
356 | ScreenPtr pScreen = pDst->pDrawable->pScreen; | |
357 | int width = 0, height = 0; | |
358 | int x, y; | |
359 | @@ -771,29 +712,6 @@ exaGlyphs (CARD8 op, | |
360 | CARD32 component_alpha; | |
361 | ExaGlyphBuffer buffer; | |
362 | ||
363 | - /* If we don't have a mask format but all the glyphs have the same format | |
364 | - * and don't intersect, use the glyph format as mask format for the full | |
365 | - * benefits of the glyph cache. | |
366 | - */ | |
367 | - if (!maskFormat) { | |
368 | - Bool sameFormat = TRUE; | |
369 | - int i; | |
361c468e | 370 | - |
055b6688 | 371 | - maskFormat = list[0].format; |
33d29f3f | 372 | - |
055b6688 AM |
373 | - for (i = 0; i < nlist; i++) { |
374 | - if (maskFormat->format != list[i].format->format) { | |
375 | - sameFormat = FALSE; | |
376 | - break; | |
377 | - } | |
378 | - } | |
379 | - | |
380 | - if (!sameFormat || (maskFormat->depth != 1 && | |
381 | - exaGlyphsIntersect(nlist, list, glyphs))) { | |
382 | - maskFormat = NULL; | |
383 | - } | |
384 | - } | |
385 | - | |
386 | if (maskFormat) | |
33d29f3f | 387 | { |
055b6688 AM |
388 | GCPtr pGC; |
389 | @@ -840,12 +758,11 @@ exaGlyphs (CARD8 op, | |
33d29f3f | 390 | } |
055b6688 | 391 | else |
33d29f3f | 392 | { |
055b6688 AM |
393 | - pMask = pDst; |
394 | x = 0; | |
395 | y = 0; | |
33d29f3f | 396 | } |
055b6688 AM |
397 | buffer.count = 0; |
398 | - buffer.source = NULL; | |
399 | + buffer.mask = NULL; | |
400 | while (nlist--) | |
401 | { | |
402 | x += list->xOff; | |
403 | @@ -856,16 +773,31 @@ exaGlyphs (CARD8 op, | |
404 | glyph = *glyphs++; | |
405 | pPicture = GlyphPicture (glyph)[pScreen->myNum]; | |
406 | ||
407 | - if (glyph->info.width > 0 && glyph->info.height > 0 && | |
408 | - exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush) | |
409 | + if (glyph->info.width > 0 && glyph->info.height > 0) | |
410 | { | |
411 | if (maskFormat) | |
412 | - exaGlyphsToMask(pMask, &buffer); | |
413 | + { | |
414 | + if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, | |
415 | + 0, 0, 0, 0, x, y) == ExaGlyphNeedFlush) | |
416 | + { | |
417 | + exaGlyphsToMask(pMask, &buffer); | |
418 | + exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, | |
419 | + 0, 0, 0, 0, x, y); | |
420 | + } | |
421 | + } | |
422 | else | |
423 | - exaGlyphsToDst(op, pSrc, pDst, &buffer, | |
424 | - xSrc, ySrc, xDst, yDst); | |
33d29f3f | 425 | - |
055b6688 AM |
426 | - exaBufferGlyph(pScreen, &buffer, glyph, x, y); |
427 | + { | |
428 | + if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, | |
429 | + xSrc + x - xDst, ySrc + y - yDst, | |
430 | + x, y, x + extents.x1, y + extents.y1) | |
431 | + == ExaGlyphNeedFlush) | |
432 | + { | |
433 | + exaGlyphsToDst(pSrc, pDst, &buffer); | |
434 | + exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, | |
435 | + xSrc + x - xDst, ySrc + y - yDst, | |
436 | + x, y, x + extents.x1, y + extents.y1); | |
453260b6 AM |
437 | + } |
438 | + } | |
055b6688 | 439 | } |
33d29f3f | 440 | |
055b6688 AM |
441 | x += glyph->info.xOff; |
442 | @@ -878,8 +810,7 @@ exaGlyphs (CARD8 op, | |
443 | if (maskFormat) | |
444 | exaGlyphsToMask(pMask, &buffer); | |
445 | else | |
446 | - exaGlyphsToDst(op, pSrc, pDst, &buffer, | |
447 | - xSrc, ySrc, xDst, yDst); | |
448 | + exaGlyphsToDst(pSrc, pDst, &buffer); | |
449 | } | |
33d29f3f | 450 | |
055b6688 | 451 | if (maskFormat) |
453260b6 | 452 | diff --git a/exa/exa_priv.h b/exa/exa_priv.h |
055b6688 | 453 | index ea8c3da..8f83701 100644 |
453260b6 AM |
454 | --- a/exa/exa_priv.h |
455 | +++ b/exa/exa_priv.h | |
055b6688 | 456 | @@ -287,8 +287,11 @@ typedef struct _ExaMigrationRec { |
453260b6 AM |
457 | } ExaMigrationRec, *ExaMigrationPtr; |
458 | ||
055b6688 AM |
459 | typedef struct { |
460 | + PicturePtr pDst; | |
461 | INT16 xSrc; | |
462 | INT16 ySrc; | |
463 | + INT16 xMask; | |
464 | + INT16 yMask; | |
465 | INT16 xDst; | |
466 | INT16 yDst; | |
467 | INT16 width; | |
468 | @@ -519,6 +522,7 @@ exaComposite(CARD8 op, | |
33d29f3f | 469 | void |
055b6688 AM |
470 | exaCompositeRects(CARD8 op, |
471 | PicturePtr Src, | |
472 | + PicturePtr pMask, | |
473 | PicturePtr pDst, | |
474 | int nrect, | |
475 | ExaCompositeRectPtr rects); | |
453260b6 | 476 | diff --git a/exa/exa_render.c b/exa/exa_render.c |
055b6688 | 477 | index bdc1ed1..d53f13b 100644 |
453260b6 AM |
478 | --- a/exa/exa_render.c |
479 | +++ b/exa/exa_render.c | |
055b6688 | 480 | @@ -334,15 +334,16 @@ exaTryDriverSolidFill(PicturePtr pSrc, |
453260b6 | 481 | static int |
055b6688 AM |
482 | exaTryDriverCompositeRects(CARD8 op, |
483 | PicturePtr pSrc, | |
484 | + PicturePtr pMask, | |
485 | PicturePtr pDst, | |
486 | int nrect, | |
487 | ExaCompositeRectPtr rects) | |
488 | { | |
489 | ExaScreenPriv (pDst->pDrawable->pScreen); | |
490 | - int src_off_x, src_off_y, dst_off_x, dst_off_y; | |
491 | - PixmapPtr pSrcPix, pDstPix; | |
492 | - ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; | |
493 | - ExaMigrationRec pixmaps[2]; | |
494 | + int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; | |
495 | + PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; | |
496 | + ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; | |
497 | + ExaMigrationRec pixmaps[3]; | |
498 | ||
499 | if (!pExaScr->info->PrepareComposite) | |
500 | return -1; | |
501 | @@ -350,6 +351,11 @@ exaTryDriverCompositeRects(CARD8 op, | |
502 | pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); | |
503 | pSrcExaPix = ExaGetPixmapPriv(pSrcPix); | |
504 | ||
505 | + if (pMask) { | |
506 | + pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); | |
507 | + pMaskExaPix = ExaGetPixmapPriv(pMaskPix); | |
33d29f3f | 508 | + } |
453260b6 | 509 | + |
055b6688 AM |
510 | pDstPix = exaGetDrawablePixmap(pDst->pDrawable); |
511 | pDstExaPix = ExaGetPixmapPriv(pDstPix); | |
453260b6 | 512 | |
055b6688 AM |
513 | @@ -357,20 +363,18 @@ exaTryDriverCompositeRects(CARD8 op, |
514 | * FIXME: If it cannot, use temporary pixmaps so that the drawing | |
515 | * happens within limits. | |
516 | */ | |
517 | - if (pSrcExaPix->accel_blocked || | |
518 | - pDstExaPix->accel_blocked) | |
519 | + if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked || | |
520 | + (pMask && pMaskExaPix->accel_blocked)) | |
521 | { | |
522 | return -1; | |
453260b6 | 523 | } |
055b6688 AM |
524 | |
525 | if (pExaScr->info->CheckComposite && | |
526 | - !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst)) | |
527 | + !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) | |
33d29f3f | 528 | { |
055b6688 AM |
529 | return -1; |
530 | } | |
531 | ||
532 | - exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); | |
33d29f3f | 533 | - |
055b6688 AM |
534 | pixmaps[0].as_dst = TRUE; |
535 | pixmaps[0].as_src = exaOpReadsDestination(op); | |
536 | pixmaps[0].pPix = pDstPix; | |
537 | @@ -379,32 +383,49 @@ exaTryDriverCompositeRects(CARD8 op, | |
538 | pixmaps[1].as_src = TRUE; | |
539 | pixmaps[1].pPix = pSrcPix; | |
540 | pixmaps[1].pReg = NULL; | |
541 | - exaDoMigration(pixmaps, 2, TRUE); | |
542 | + if (pMask) { | |
543 | + pixmaps[2].as_dst = FALSE; | |
544 | + pixmaps[2].as_src = TRUE; | |
545 | + pixmaps[2].pPix = pMaskPix; | |
546 | + pixmaps[2].pReg = NULL; | |
547 | + exaDoMigration(pixmaps, 3, TRUE); | |
548 | + } else | |
549 | + exaDoMigration(pixmaps, 2, TRUE); | |
550 | ||
551 | - pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); | |
552 | - if (!exaPixmapIsOffscreen(pDstPix)) | |
553 | + pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); | |
554 | + if (!pDstPix) | |
555 | return 0; | |
556 | ||
557 | + pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); | |
558 | if (!pSrcPix) | |
559 | return 0; | |
453260b6 | 560 | |
055b6688 AM |
561 | - if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix, |
562 | - NULL, pDstPix)) | |
563 | + if (pMask) { | |
564 | + pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y); | |
33d29f3f | 565 | + |
055b6688 AM |
566 | + if (!pMaskPix) |
567 | + return 0; | |
568 | + } | |
453260b6 | 569 | + |
055b6688 AM |
570 | + if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix, |
571 | + pMaskPix, pDstPix)) | |
572 | return -1; | |
33d29f3f | 573 | |
055b6688 AM |
574 | while (nrect--) |
575 | { | |
576 | INT16 xDst = rects->xDst + pDst->pDrawable->x; | |
577 | INT16 yDst = rects->yDst + pDst->pDrawable->y; | |
578 | + INT16 xMask = pMask ? rects->xMask + pMask->pDrawable->x : 0; | |
579 | + INT16 yMask = pMask ? rects->yMask + pMask->pDrawable->y : 0; | |
580 | INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; | |
581 | INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; | |
582 | ||
583 | RegionRec region; | |
584 | BoxPtr pbox; | |
585 | int nbox; | |
33d29f3f | 586 | - |
055b6688 AM |
587 | - if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, |
588 | - xSrc, ySrc, 0, 0, xDst, yDst, | |
589 | + | |
590 | + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, | |
591 | + xSrc, ySrc, xMask, yMask, xDst, yDst, | |
592 | rects->width, rects->height)) | |
593 | goto next_rect; | |
594 | ||
595 | @@ -413,6 +434,8 @@ exaTryDriverCompositeRects(CARD8 op, | |
596 | nbox = REGION_NUM_RECTS(®ion); | |
597 | pbox = REGION_RECTS(®ion); | |
598 | ||
599 | + xMask = xMask + mask_off_x - xDst - dst_off_x; | |
600 | + yMask = yMask + mask_off_y - yDst - dst_off_y; | |
601 | xSrc = xSrc + src_off_x - xDst - dst_off_x; | |
602 | ySrc = ySrc + src_off_y - yDst - dst_off_y; | |
603 | ||
604 | @@ -421,7 +444,8 @@ exaTryDriverCompositeRects(CARD8 op, | |
605 | (*pExaScr->info->Composite) (pDstPix, | |
606 | pbox->x1 + xSrc, | |
607 | pbox->y1 + ySrc, | |
608 | - 0, 0, | |
609 | + pbox->x1 + xMask, | |
610 | + pbox->y1 + yMask, | |
611 | pbox->x1, | |
612 | pbox->y1, | |
613 | pbox->x2 - pbox->x1, | |
614 | @@ -443,25 +467,30 @@ exaTryDriverCompositeRects(CARD8 op, | |
615 | ||
33d29f3f | 616 | /** |
055b6688 AM |
617 | * Copy a number of rectangles from source to destination in a single |
618 | - * operation. This is specialized for building a glyph mask: we don'y | |
619 | - * have a mask argument because we don't need it for that, and we | |
620 | - * don't have he special-case fallbacks found in exaComposite() - if the | |
621 | - * driver can support it, we use the driver functionality, otherwise we | |
622 | - * fallback straight to software. | |
623 | + * operation. This is specialized for glyph rendering: we don't have the | |
624 | + * special-case fallbacks found in exaComposite() - if the driver can support | |
625 | + * it, we use the driver functionality, otherwise we fall back straight to | |
626 | + * software. | |
627 | */ | |
628 | void | |
629 | exaCompositeRects(CARD8 op, | |
630 | PicturePtr pSrc, | |
631 | + PicturePtr pMask, | |
632 | PicturePtr pDst, | |
633 | int nrect, | |
634 | ExaCompositeRectPtr rects) | |
33d29f3f | 635 | { |
055b6688 AM |
636 | + ExaScreenPriv (pDst->pDrawable->pScreen); |
637 | PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable); | |
638 | ExaPixmapPriv(pPixmap); | |
639 | int n; | |
640 | ExaCompositeRectPtr r; | |
641 | - | |
642 | - if (pExaPixmap->pDamage) { | |
643 | + int ret; | |
644 | + | |
645 | + /* If we get a mask, that means we're rendering to the exaGlyphs | |
646 | + * destination directly, so the damage layer takes care of this. | |
647 | + */ | |
648 | + if (!pMask && pExaPixmap->pDamage) { | |
649 | RegionRec region; | |
650 | int x1 = MAXSHORT; | |
651 | int y1 = MAXSHORT; | |
652 | @@ -518,24 +547,44 @@ exaCompositeRects(CARD8 op, | |
653 | /************************************************************/ | |
33d29f3f | 654 | |
055b6688 AM |
655 | ValidatePicture (pSrc); |
656 | + if (pMask) | |
657 | + ValidatePicture (pMask); | |
658 | ValidatePicture (pDst); | |
659 | - | |
660 | - if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) { | |
661 | - n = nrect; | |
662 | - r = rects; | |
663 | - while (n--) { | |
664 | - ExaCheckComposite (op, pSrc, NULL, pDst, | |
665 | - r->xSrc, r->ySrc, | |
666 | - 0, 0, | |
667 | - r->xDst, r->yDst, | |
668 | - r->width, r->height); | |
669 | - r++; | |
670 | + | |
671 | + ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, rects); | |
672 | + | |
673 | + if (ret != 1) { | |
674 | + if (ret == -1 && op == PictOpOver && pMask && pMask->componentAlpha && | |
675 | + (!pExaScr->info->CheckComposite || | |
676 | + ((*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask, | |
677 | + pDst) && | |
678 | + (*pExaScr->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))) { | |
679 | + ret = exaTryDriverCompositeRects(PictOpOutReverse, pSrc, pMask, | |
680 | + pDst, nrect, rects); | |
681 | + if (ret == 1) { | |
682 | + op = PictOpAdd; | |
683 | + ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, | |
684 | + rects); | |
685 | + } | |
686 | + } | |
687 | + | |
688 | + if (ret != 1) { | |
689 | + n = nrect; | |
690 | + r = rects; | |
691 | + while (n--) { | |
692 | + ExaCheckComposite (op, pSrc, pMask, pDst, | |
693 | + r->xSrc, r->ySrc, | |
694 | + r->xMask, r->yMask, | |
695 | + r->xDst, r->yDst, | |
696 | + r->width, r->height); | |
697 | + r++; | |
698 | + } | |
699 | } | |
33d29f3f | 700 | } |
453260b6 | 701 | |
055b6688 AM |
702 | /************************************************************/ |
703 | ||
704 | - if (pExaPixmap->pDamage) { | |
705 | + if (!pMask && pExaPixmap->pDamage) { | |
706 | /* Now we have to flush the damage out from pendingDamage => damage | |
707 | * Calling DamageRegionProcessPending has that effect. | |
708 | */ | |
709 | commit 265d20068af5434489752b6dba0bf0065b3cc3ec | |
710 | Author: Michel Dänzer <daenzer@vmware.com> | |
711 | Date: Fri Feb 27 16:41:39 2009 +0100 | |
1de84ad0 | 712 | |
055b6688 AM |
713 | EXA: Fix check for whether the glyph we're evicting from the cache is in use. |
714 | ||
715 | Since commit f07f18231a921d3ae9dd9b75881c9e58e9e2e235 ('EXA: Allow using | |
716 | exaCompositeRects also when we can't use a mask in exaGlyphs.') we were | |
717 | checking the wrong set of coordinates in the buffer where glyphs to be rendered | |
718 | are accumulated when no mask is used in exaGlyphs. | |
719 | ||
720 | This fixes occasional glyph corruption which can be corrected with redraws, in | |
721 | particular with Qt4. | |
1de84ad0 | 722 | |
055b6688 AM |
723 | Thanks to Maarten Maathuis for asking the right question: 'where do we protect |
724 | against evicting glyphs that are still needed?' | |
1de84ad0 | 725 | |
055b6688 | 726 | Signed-off-by: Michel Dänzer <daenzer@vmware.com> |
1de84ad0 | 727 | |
055b6688 AM |
728 | diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c |
729 | index 918fd85..d55839c 100644 | |
730 | --- a/exa/exa_glyphs.c | |
731 | +++ b/exa/exa_glyphs.c | |
732 | @@ -469,7 +469,9 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, | |
733 | y = CACHE_Y(pos); | |
734 | ||
735 | for (i = 0; i < buffer->count; i++) { | |
736 | - if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) { | |
737 | + if (pSrc ? | |
738 | + (buffer->rects[i].xMask == x && buffer->rects[i].yMask == y) : | |
739 | + (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y)) { | |
740 | DBG_GLYPH_CACHE((" must flush buffer\n")); | |
741 | return ExaGlyphNeedFlush; | |
742 | } |