]>
Commit | Line | Data |
---|---|---|
a7622652 AM |
1 | commit 9cbcb5bd6a5360a128d15b77a02d8d3351f74366 |
2 | Author: Søren Sandmann Pedersen <ssp@redhat.com> | |
3 | Date: Wed May 30 05:19:08 2012 -0400 | |
4 | ||
5 | Use new pixman_glyph_cache_t API that will be in pixman 0.28.0 | |
6 | ||
7 | This new API allows glyphs to be cached in a data structure in pixman, | |
8 | and entire glyph strings to be composited in one go. | |
9 | ||
10 | Also bump pixman dependency to 0.27.2. | |
11 | ||
12 | Results from the cairo peformance test suite running against Xvfb with | |
13 | a screen size of 1680x1050@32bpp: | |
14 | ||
15 | Speedups | |
16 | ======== | |
17 | xlib firefox-talos-gfx 12416.63 -> 3603.93 3.45x speedup | |
18 | ██▌ | |
19 | xlib xfce4-terminal-a1 1727.57 -> 1048.85: 1.65x speedup | |
20 | ▋ | |
21 | xlib evolution 1370.49 -> 869.34: 1.58x speedup | |
22 | ▋ | |
23 | xlib gnome-terminal-vim 1832.83 -> 1251.94: 1.46x speedup | |
24 | ▌ | |
25 | xlib poppler 1519.70 -> 1204.05: 1.26x speedup | |
26 | ▎ | |
27 | xlib firefox-planet-gnome 6982.55 -> 5598.16: 1.25x speedup | |
28 | ▎ | |
29 | xlib ocitysmap 1142.77 -> 1071.53: 1.07x speedup | |
30 | ▏ | |
31 | ||
32 | No slowdowns were reported. | |
33 | ||
34 | Results of x11perf -aa10text: | |
35 | ||
36 | Before: | |
37 | ||
38 | 8000000 reps @ 0.0007 msec (1450000.0/sec) | |
39 | 8000000 reps @ 0.0007 msec (1460000.0/sec) | |
40 | 8000000 reps @ 0.0007 msec (1460000.0/sec) | |
41 | 8000000 reps @ 0.0007 msec (1470000.0/sec) | |
42 | 8000000 reps @ 0.0007 msec (1480000.0/sec) | |
43 | 40000000 trep @ 0.0007 msec (1460000.0/sec) | |
44 | ||
45 | After: | |
46 | ||
47 | 32000000 reps @ 0.0002 msec (4910000.0/sec) | |
48 | 32000000 reps @ 0.0002 msec (4830000.0/sec) | |
49 | 32000000 reps @ 0.0002 msec (4890000.0/sec) | |
50 | 32000000 reps @ 0.0002 msec (4830000.0/sec) | |
51 | 32000000 reps @ 0.0002 msec (4900000.0/sec) | |
52 | 160000000 trep @ 0.0002 msec (4870000.0/sec) | |
53 | ||
54 | Version 2: Destroy the glyph cache at server regen time | |
55 | ||
56 | Acked-by: Aaron Plattner <aplattner@nvidia.com> | |
57 | Reviewed-by: Keith Packard <keithp@keithp.com> | |
58 | Signed-off-by: Soren Sandmann <ssp@redhat.com> | |
59 | ||
60 | diff --git a/configure.ac b/configure.ac | |
61 | index e686614..b6ed92c 100644 | |
62 | --- a/configure.ac | |
63 | +++ b/configure.ac | |
64 | @@ -811,7 +811,7 @@ LIBPCIACCESS="pciaccess >= 0.12.901" | |
65 | LIBUDEV="libudev >= 143" | |
66 | LIBSELINUX="libselinux >= 2.0.86" | |
67 | LIBDBUS="dbus-1 >= 1.0" | |
68 | -LIBPIXMAN="pixman-1 >= 0.21.8" | |
69 | +LIBPIXMAN="pixman-1 >= 0.27.2" | |
70 | ||
71 | dnl Pixman is always required, but we separate it out so we can link | |
72 | dnl specific modules against it | |
73 | diff --git a/fb/fb.h b/fb/fb.h | |
74 | index 75596c5..b869d12 100644 | |
75 | --- a/fb/fb.h | |
76 | +++ b/fb/fb.h | |
77 | @@ -1344,6 +1344,9 @@ extern _X_EXPORT void | |
78 | extern _X_EXPORT Bool | |
79 | fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats); | |
80 | ||
81 | +extern _X_EXPORT void | |
82 | +fbDestroyGlyphCache(void); | |
83 | + | |
84 | /* | |
85 | * fbpixmap.c | |
86 | */ | |
87 | diff --git a/fb/fbpict.c b/fb/fbpict.c | |
88 | index 097a1a6..2804ff4 100644 | |
89 | --- a/fb/fbpict.c | |
90 | +++ b/fb/fbpict.c | |
91 | @@ -70,6 +70,156 @@ fbComposite(CARD8 op, | |
92 | free_pixman_pict(pDst, dest); | |
93 | } | |
94 | ||
95 | +static pixman_glyph_cache_t *glyphCache; | |
96 | + | |
97 | +void | |
98 | +fbDestroyGlyphCache(void) | |
99 | +{ | |
100 | + if (glyphCache) | |
101 | + { | |
102 | + pixman_glyph_cache_destroy (glyphCache); | |
103 | + glyphCache = NULL; | |
104 | + } | |
105 | +} | |
106 | + | |
107 | +static void | |
108 | +fbUnrealizeGlyph(ScreenPtr pScreen, | |
109 | + GlyphPtr pGlyph) | |
110 | +{ | |
111 | + if (glyphCache) | |
112 | + pixman_glyph_cache_remove (glyphCache, pGlyph, NULL); | |
113 | +} | |
114 | + | |
115 | +static void | |
116 | +fbGlyphs(CARD8 op, | |
117 | + PicturePtr pSrc, | |
118 | + PicturePtr pDst, | |
119 | + PictFormatPtr maskFormat, | |
120 | + INT16 xSrc, | |
121 | + INT16 ySrc, int nlist, | |
122 | + GlyphListPtr list, | |
123 | + GlyphPtr *glyphs) | |
124 | +{ | |
125 | +#define N_STACK_GLYPHS 512 | |
126 | + ScreenPtr pScreen = pDst->pDrawable->pScreen; | |
127 | + pixman_glyph_t stack_glyphs[N_STACK_GLYPHS]; | |
128 | + pixman_glyph_t *pglyphs = stack_glyphs; | |
129 | + pixman_image_t *srcImage, *dstImage; | |
130 | + int srcXoff, srcYoff, dstXoff, dstYoff; | |
131 | + GlyphPtr glyph; | |
132 | + int n_glyphs; | |
133 | + int x, y; | |
134 | + int i, n; | |
135 | + int xDst = list->xOff, yDst = list->yOff; | |
136 | + | |
137 | + miCompositeSourceValidate(pSrc); | |
138 | + | |
139 | + n_glyphs = 0; | |
140 | + for (i = 0; i < nlist; ++i) | |
141 | + n_glyphs += list[i].len; | |
142 | + | |
143 | + if (!glyphCache) | |
144 | + glyphCache = pixman_glyph_cache_create(); | |
145 | + | |
146 | + pixman_glyph_cache_freeze (glyphCache); | |
147 | + | |
148 | + if (n_glyphs > N_STACK_GLYPHS) { | |
149 | + if (!(pglyphs = malloc (n_glyphs * sizeof (pixman_glyph_t)))) | |
150 | + goto out; | |
151 | + } | |
152 | + | |
153 | + i = 0; | |
154 | + x = y = 0; | |
155 | + while (nlist--) { | |
156 | + x += list->xOff; | |
157 | + y += list->yOff; | |
158 | + n = list->len; | |
159 | + while (n--) { | |
160 | + const void *g; | |
161 | + | |
162 | + glyph = *glyphs++; | |
163 | + | |
164 | + if (!(g = pixman_glyph_cache_lookup (glyphCache, glyph, NULL))) { | |
165 | + pixman_image_t *glyphImage; | |
166 | + PicturePtr pPicture; | |
167 | + int xoff, yoff; | |
168 | + | |
169 | + pPicture = GetGlyphPicture(glyph, pScreen); | |
170 | + if (!pPicture) { | |
171 | + n_glyphs--; | |
172 | + goto next; | |
173 | + } | |
174 | + | |
175 | + if (!(glyphImage = image_from_pict(pPicture, FALSE, &xoff, &yoff))) | |
176 | + goto out; | |
177 | + | |
178 | + g = pixman_glyph_cache_insert(glyphCache, glyph, NULL, | |
179 | + glyph->info.x, | |
180 | + glyph->info.y, | |
181 | + glyphImage); | |
182 | + | |
183 | + free_pixman_pict(pPicture, glyphImage); | |
184 | + | |
185 | + if (!g) | |
186 | + goto out; | |
187 | + } | |
188 | + | |
189 | + pglyphs[i].x = x; | |
190 | + pglyphs[i].y = y; | |
191 | + pglyphs[i].glyph = g; | |
192 | + i++; | |
193 | + | |
194 | + next: | |
195 | + x += glyph->info.xOff; | |
196 | + y += glyph->info.yOff; | |
197 | + } | |
198 | + list++; | |
199 | + } | |
200 | + | |
201 | + if (!(srcImage = image_from_pict(pSrc, FALSE, &srcXoff, &srcYoff))) | |
202 | + goto out; | |
203 | + | |
204 | + if (!(dstImage = image_from_pict(pDst, TRUE, &dstXoff, &dstYoff))) | |
205 | + goto out_free_src; | |
206 | + | |
207 | + if (maskFormat) { | |
208 | + pixman_format_code_t format; | |
209 | + pixman_box32_t extents; | |
210 | + int x, y; | |
211 | + | |
212 | + format = maskFormat->format | (maskFormat->depth << 24); | |
213 | + | |
214 | + pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents); | |
215 | + | |
216 | + x = extents.x1; | |
217 | + y = extents.y1; | |
218 | + | |
219 | + pixman_composite_glyphs(op, srcImage, dstImage, format, | |
220 | + xSrc + srcXoff + xDst, ySrc + srcYoff + yDst, | |
221 | + x, y, | |
222 | + x + dstXoff, y + dstYoff, | |
223 | + extents.x2 - extents.x1, | |
224 | + extents.y2 - extents.y1, | |
225 | + glyphCache, n_glyphs, pglyphs); | |
226 | + } | |
227 | + else { | |
228 | + pixman_composite_glyphs_no_mask(op, srcImage, dstImage, | |
229 | + xSrc + srcXoff - xDst, ySrc + srcYoff - yDst, | |
230 | + dstXoff, dstYoff, | |
231 | + glyphCache, n_glyphs, pglyphs); | |
232 | + } | |
233 | + | |
234 | + free_pixman_pict(pDst, dstImage); | |
235 | + | |
236 | +out_free_src: | |
237 | + free_pixman_pict(pSrc, srcImage); | |
238 | + | |
239 | +out: | |
240 | + pixman_glyph_cache_thaw(glyphCache); | |
241 | + if (pglyphs != stack_glyphs) | |
242 | + free(pglyphs); | |
243 | +} | |
244 | + | |
245 | static pixman_image_t * | |
246 | create_solid_fill_image(PicturePtr pict) | |
247 | { | |
248 | @@ -357,7 +507,8 @@ fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats) | |
249 | return FALSE; | |
250 | ps = GetPictureScreen(pScreen); | |
251 | ps->Composite = fbComposite; | |
252 | - ps->Glyphs = miGlyphs; | |
253 | + ps->Glyphs = fbGlyphs; | |
254 | + ps->UnrealizeGlyph = fbUnrealizeGlyph; | |
255 | ps->CompositeRects = miCompositeRects; | |
256 | ps->RasterizeTrapezoid = fbRasterizeTrapezoid; | |
257 | ps->Trapezoids = fbTrapezoids; | |
258 | diff --git a/fb/fbscreen.c b/fb/fbscreen.c | |
259 | index 7c7d656..f9080a4 100644 | |
260 | --- a/fb/fbscreen.c | |
261 | +++ b/fb/fbscreen.c | |
262 | @@ -32,6 +32,7 @@ fbCloseScreen(ScreenPtr pScreen) | |
263 | int d; | |
264 | DepthPtr depths = pScreen->allowedDepths; | |
265 | ||
266 | + fbDestroyGlyphCache(); | |
267 | for (d = 0; d < pScreen->numDepths; d++) | |
268 | free(depths[d].vids); | |
269 | free(depths); |