sna_glyphs.c revision 03b705cf
1/*
2 * Copyright © 2010 Intel Corporation
3 * Partly based on code Copyright © 2008 Red Hat, Inc.
4 * Partly based on code Copyright © 2000 SuSE, Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Intel not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission.  Intel makes no representations about the
13 * suitability of this software for any purpose.  It is provided "as is"
14 * without express or implied warranty.
15 *
16 * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INTEL
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Permission to use, copy, modify, distribute, and sell this software and its
24 * documentation for any purpose is hereby granted without fee, provided that
25 * the above copyright notice appear in all copies and that both that
26 * copyright notice and this permission notice appear in supporting
27 * documentation, and that the name of Red Hat not be used in advertising or
28 * publicity pertaining to distribution of the software without specific,
29 * written prior permission.  Red Hat makes no representations about the
30 * suitability of this software for any purpose.  It is provided "as is"
31 * without express or implied warranty.
32 *
33 * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
35 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
36 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
37 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
38 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
39 *
40 * Permission to use, copy, modify, distribute, and sell this software and its
41 * documentation for any purpose is hereby granted without fee, provided that
42 * the above copyright notice appear in all copies and that both that
43 * copyright notice and this permission notice appear in supporting
44 * documentation, and that the name of SuSE not be used in advertising or
45 * publicity pertaining to distribution of the software without specific,
46 * written prior permission.  SuSE makes no representations about the
47 * suitability of this software for any purpose.  It is provided "as is"
48 * without express or implied warranty.
49 *
50 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
52 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
53 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
54 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
55 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
56 *
57 * Author: Chris Wilson <chris@chris-wilson.co.uk>
58 * Based on code by: Keith Packard <keithp@keithp.com> and Owen Taylor <otaylor@fishsoup.net>
59 */
60
61#ifdef HAVE_CONFIG_H
62#include "config.h"
63#endif
64
65#include "sna.h"
66#include "sna_render.h"
67#include "sna_render_inline.h"
68#include "fb/fbpict.h"
69
70#include <mipict.h>
71
72#define FALLBACK 0
73#define NO_GLYPH_CACHE 0
74#define NO_GLYPHS_TO_DST 0
75#define NO_GLYPHS_VIA_MASK 0
76#define NO_SMALL_MASK 0
77#define NO_GLYPHS_SLOW 0
78#define NO_DISCARD_MASK 0
79
80#define CACHE_PICTURE_SIZE 1024
81#define GLYPH_MIN_SIZE 8
82#define GLYPH_MAX_SIZE 64
83#define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE))
84
85#define N_STACK_GLYPHS 512
86
87#define glyph_valid(g) *((uint32_t *)&(g)->info.width)
88#define glyph_copy_size(r, g) *(uint32_t *)&(r)->width = *(uint32_t *)&g->info.width
89
90#if HAS_DEBUG_FULL
91static void _assert_pixmap_contains_box(PixmapPtr pixmap, BoxPtr box, const char *function)
92{
93	if (box->x1 < 0 || box->y1 < 0 ||
94	    box->x2 > pixmap->drawable.width ||
95	    box->y2 > pixmap->drawable.height)
96	{
97		ErrorF("%s: damage box is beyond the pixmap: box=(%d, %d), (%d, %d), pixmap=(%d, %d)\n",
98		       __FUNCTION__,
99		       box->x1, box->y1, box->x2, box->y2,
100		       pixmap->drawable.width,
101		       pixmap->drawable.height);
102		assert(0);
103	}
104}
105#define assert_pixmap_contains_box(p, b) _assert_pixmap_contains_box(p, b, __FUNCTION__)
106#else
107#define assert_pixmap_contains_box(p, b)
108#endif
109
110extern DevPrivateKeyRec sna_glyph_key;
111
112static inline struct sna_glyph *sna_glyph(GlyphPtr glyph)
113{
114	return __get_private(glyph, sna_glyph_key);
115}
116
117static inline struct sna_glyph *sna_glyph0(GlyphPtr glyph)
118{
119	return (struct sna_glyph *)glyph->devPrivates;
120}
121
122static inline bool can_use_glyph0(void)
123{
124#if HAS_DEVPRIVATEKEYREC
125	return sna_glyph_key.offset == 0;
126#else
127	return 0;
128#endif
129}
130
131#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
132
133static bool op_is_bounded(uint8_t op)
134{
135	switch (op) {
136	case PictOpOver:
137	case PictOpOutReverse:
138	case PictOpAdd:
139	case PictOpXor:
140		return true;
141	default:
142		return false;
143	}
144}
145
146void sna_glyphs_close(struct sna *sna)
147{
148	struct sna_render *render = &sna->render;
149	unsigned int i;
150
151	DBG(("%s\n", __FUNCTION__));
152
153	for (i = 0; i < ARRAY_SIZE(render->glyph); i++) {
154		struct sna_glyph_cache *cache = &render->glyph[i];
155
156		if (cache->picture)
157			FreePicture(cache->picture, 0);
158
159		free(cache->glyphs);
160	}
161	memset(render->glyph, 0, sizeof(render->glyph));
162
163	if (render->white_image) {
164		pixman_image_unref(render->white_image);
165		render->white_image = NULL;
166	}
167	if (render->white_picture) {
168		FreePicture(render->white_picture, 0);
169		render->white_picture = NULL;
170	}
171#if HAS_PIXMAN_GLYPHS
172	if (render->glyph_cache) {
173		pixman_glyph_cache_destroy(render->glyph_cache);
174		render->glyph_cache = NULL;
175	}
176#endif
177}
178
179/* All caches for a single format share a single pixmap for glyph storage,
180 * allowing mixing glyphs of different sizes without paying a penalty
181 * for switching between source pixmaps. (Note that for a size of font
182 * right at the border between two sizes, we might be switching for almost
183 * every glyph.)
184 *
185 * This function allocates the storage pixmap, and then fills in the
186 * rest of the allocated structures for all caches with the given format.
187 */
188bool sna_glyphs_create(struct sna *sna)
189{
190	ScreenPtr screen = sna->scrn->pScreen;
191	pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
192	unsigned int formats[] = {
193		PIXMAN_a8,
194		PIXMAN_a8r8g8b8,
195	};
196	unsigned int i;
197	int error;
198
199	DBG(("%s\n", __FUNCTION__));
200
201#if HAS_PIXMAN_GLYPHS
202	sna->render.glyph_cache = pixman_glyph_cache_create();
203	if (sna->render.glyph_cache == NULL)
204		goto bail;
205#endif
206
207	sna->render.white_image = pixman_image_create_solid_fill(&white);
208	if (sna->render.white_image == NULL)
209		goto bail;
210
211	if (!can_render(sna)) {
212		DBG(("%s: no render acceleration, no render glyph caches\n",
213		     __FUNCTION__));
214		return true;
215	}
216
217	if (xf86IsEntityShared(sna->scrn->entityList[0])) {
218		DBG(("%s: shared GlyphPictures, no render glyph caches\n",
219		     __FUNCTION__));
220		return true;
221	}
222
223	for (i = 0; i < ARRAY_SIZE(formats); i++) {
224		struct sna_glyph_cache *cache = &sna->render.glyph[i];
225		struct sna_pixmap *priv;
226		PixmapPtr pixmap;
227		PicturePtr picture = NULL;
228		PictFormatPtr pPictFormat;
229		CARD32 component_alpha;
230		int depth = PIXMAN_FORMAT_DEPTH(formats[i]);
231
232		pPictFormat = PictureMatchFormat(screen, depth, formats[i]);
233		if (!pPictFormat)
234			goto bail;
235
236		/* Now allocate the pixmap and picture */
237		pixmap = screen->CreatePixmap(screen,
238					      CACHE_PICTURE_SIZE,
239					      CACHE_PICTURE_SIZE,
240					      depth,
241					      SNA_CREATE_GLYPHS);
242		if (!pixmap) {
243			DBG(("%s: failed to allocate pixmap for Glyph cache\n",
244			     __FUNCTION__));
245			goto bail;
246		}
247
248		priv = sna_pixmap(pixmap);
249		if (priv != NULL) {
250			/* Prevent the cache from ever being paged out */
251			priv->pinned = PIN_SCANOUT;
252
253			component_alpha = NeedsComponent(pPictFormat->format);
254			picture = CreatePicture(0, &pixmap->drawable, pPictFormat,
255						CPComponentAlpha, &component_alpha,
256						serverClient, &error);
257		}
258
259		screen->DestroyPixmap(pixmap);
260		if (!picture)
261			goto bail;
262
263		ValidatePicture(picture);
264		assert(picture->pDrawable == &pixmap->drawable);
265
266		cache->count = cache->evict = 0;
267		cache->picture = picture;
268		cache->glyphs = calloc(sizeof(struct sna_glyph *),
269				       GLYPH_CACHE_SIZE);
270		if (!cache->glyphs)
271			goto bail;
272
273		cache->evict = rand() % GLYPH_CACHE_SIZE;
274	}
275
276	sna->render.white_picture =
277		CreateSolidPicture(0, (xRenderColor *)&white, &error);
278	if (sna->render.white_picture == NULL)
279		goto bail;
280
281	return true;
282
283bail:
284	sna_glyphs_close(sna);
285	return false;
286}
287
288static void
289glyph_cache_upload(struct sna_glyph_cache *cache,
290		   GlyphPtr glyph, PicturePtr glyph_picture,
291		   int16_t x, int16_t y)
292{
293	DBG(("%s: upload glyph %p to cache (%d, %d)x(%d, %d)\n",
294	     __FUNCTION__,
295	     glyph, x, y,
296	     glyph_picture->pDrawable->width,
297	     glyph_picture->pDrawable->height));
298	sna_composite(PictOpSrc,
299		      glyph_picture, 0, cache->picture,
300		      0, 0,
301		      0, 0,
302		      x, y,
303		      glyph_picture->pDrawable->width,
304		      glyph_picture->pDrawable->height);
305}
306
307static void
308glyph_extents(int nlist,
309	      GlyphListPtr list,
310	      GlyphPtr *glyphs,
311	      BoxPtr extents)
312{
313	int16_t x1, x2, y1, y2;
314	int16_t x, y;
315
316	x1 = y1 = MAXSHORT;
317	x2 = y2 = MINSHORT;
318	x = y = 0;
319	while (nlist--) {
320		int n = list->len;
321		x += list->xOff;
322		y += list->yOff;
323		list++;
324		while (n--) {
325			GlyphPtr glyph = *glyphs++;
326
327			if (glyph_valid(glyph)) {
328				int v;
329
330				v = x - glyph->info.x;
331				if (v < x1)
332					x1 = v;
333				v += glyph->info.width;
334				if (v > x2)
335					x2 = v;
336
337				v = y - glyph->info.y;
338				if (v < y1)
339					y1 = v;
340				v += glyph->info.height;
341				if (v > y2)
342					y2 = v;
343			}
344
345			x += glyph->info.xOff;
346			y += glyph->info.yOff;
347		}
348	}
349
350	extents->x1 = x1;
351	extents->x2 = x2;
352	extents->y1 = y1;
353	extents->y2 = y2;
354}
355
356static inline unsigned int
357glyph_size_to_count(int size)
358{
359	size /= GLYPH_MIN_SIZE;
360	return size * size;
361}
362
363static inline unsigned int
364glyph_count_to_mask(int count)
365{
366	return ~(count - 1);
367}
368
369static inline unsigned int
370glyph_size_to_mask(int size)
371{
372	return glyph_count_to_mask(glyph_size_to_count(size));
373}
374
375static int
376glyph_cache(ScreenPtr screen,
377	    struct sna_render *render,
378	    GlyphPtr glyph)
379{
380	PicturePtr glyph_picture;
381	struct sna_glyph_cache *cache;
382	struct sna_glyph *p;
383	int size, mask, pos, s;
384
385	if (NO_GLYPH_CACHE)
386		return false;
387
388	glyph_picture = GetGlyphPicture(glyph, screen);
389	if (unlikely(glyph_picture == NULL)) {
390		glyph->info.width = glyph->info.height = 0;
391		return false;
392	}
393
394	if (glyph->info.width > GLYPH_MAX_SIZE ||
395	    glyph->info.height > GLYPH_MAX_SIZE) {
396		PixmapPtr pixmap = (PixmapPtr)glyph_picture->pDrawable;
397		assert(glyph_picture->pDrawable->type == DRAWABLE_PIXMAP);
398		if (pixmap->drawable.depth >= 8) {
399			pixmap->usage_hint = 0;
400			sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
401		}
402		return false;
403	}
404
405	for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2)
406		if (glyph->info.width <= size && glyph->info.height <= size)
407			break;
408
409	cache = &render->glyph[PICT_FORMAT_RGB(glyph_picture->format) != 0];
410	s = glyph_size_to_count(size);
411	mask = glyph_count_to_mask(s);
412	pos = (cache->count + s - 1) & mask;
413	if (pos < GLYPH_CACHE_SIZE) {
414		cache->count = pos + s;
415	} else {
416		p = NULL;
417		for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) {
418			int i = cache->evict & glyph_size_to_mask(s);
419			p = cache->glyphs[i];
420			if (p == NULL)
421				continue;
422
423			if (p->size >= s) {
424				cache->glyphs[i] = NULL;
425				p->atlas = NULL;
426				pos = i;
427			} else
428				p = NULL;
429			break;
430		}
431		if (p == NULL) {
432			int count = glyph_size_to_count(size);
433			pos = cache->evict & glyph_count_to_mask(count);
434			for (s = 0; s < count; s++) {
435				p = cache->glyphs[pos + s];
436				if (p != NULL) {
437					p->atlas =NULL;
438					cache->glyphs[pos + s] = NULL;
439				}
440			}
441		}
442
443		/* And pick a new eviction position */
444		cache->evict = rand() % GLYPH_CACHE_SIZE;
445	}
446	assert(cache->glyphs[pos] == NULL);
447
448	p = sna_glyph(glyph);
449	DBG(("%s(%d): adding glyph to cache %d, pos %d\n",
450	     __FUNCTION__, screen->myNum,
451	     PICT_FORMAT_RGB(glyph_picture->format) != 0, pos));
452	cache->glyphs[pos] = p;
453	p->atlas = cache->picture;
454	p->size = size;
455	p->pos = pos << 1 | (PICT_FORMAT_RGB(glyph_picture->format) != 0);
456	s = pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE));
457	p->coordinate.x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE;
458	p->coordinate.y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE;
459	for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) {
460		if (pos & 1)
461			p->coordinate.x += s;
462		if (pos & 2)
463			p->coordinate.y += s;
464		pos >>= 2;
465	}
466
467	glyph_cache_upload(cache, glyph, glyph_picture,
468			   p->coordinate.x, p->coordinate.y);
469
470	return true;
471}
472
473static void apply_damage(struct sna_composite_op *op,
474			 const struct sna_composite_rectangles *r)
475{
476	BoxRec box;
477
478	if (op->damage == NULL)
479		return;
480
481	box.x1 = r->dst.x + op->dst.x;
482	box.y1 = r->dst.y + op->dst.y;
483	box.x2 = box.x1 + r->width;
484	box.y2 = box.y1 + r->height;
485
486	assert_pixmap_contains_box(op->dst.pixmap, &box);
487	sna_damage_add_box(op->damage, &box);
488}
489
490static void apply_damage_clipped_to_dst(struct sna_composite_op *op,
491					const struct sna_composite_rectangles *r,
492					DrawablePtr dst)
493{
494	BoxRec box;
495
496	if (op->damage == NULL)
497		return;
498
499	box.x1 = r->dst.x + op->dst.x;
500	box.y1 = r->dst.y + op->dst.y;
501	box.x2 = box.x1 + r->width;
502	box.y2 = box.y1 + r->height;
503
504	if (box.x1 < dst->x)
505		box.x1 = dst->x;
506
507	if (box.x2 > op->dst.width)
508		box.x2 = op->dst.width;
509
510	if (box.y1 < dst->y)
511		box.y1 = dst->y;
512
513	if (box.y2 > op->dst.height)
514		box.y2 = op->dst.height;
515
516	assert_pixmap_contains_box(op->dst.pixmap, &box);
517	sna_damage_add_box(op->damage, &box);
518}
519
520flatten static bool
521glyphs_to_dst(struct sna *sna,
522	      CARD8 op,
523	      PicturePtr src,
524	      PicturePtr dst,
525	      INT16 src_x, INT16 src_y,
526	      int nlist, GlyphListPtr list, GlyphPtr *glyphs)
527{
528	struct sna_composite_op tmp;
529	ScreenPtr screen = dst->pDrawable->pScreen;
530	PicturePtr glyph_atlas;
531	BoxPtr rects;
532	int nrect;
533	int16_t x, y;
534
535	if (NO_GLYPHS_TO_DST)
536		return false;
537
538	memset(&tmp, 0, sizeof(tmp));
539
540	DBG(("%s(op=%d, src=(%d, %d), nlist=%d,  dst=(%d, %d)+(%d, %d))\n",
541	     __FUNCTION__, op, src_x, src_y, nlist,
542	     list->xOff, list->yOff, dst->pDrawable->x, dst->pDrawable->y));
543
544	if (is_clipped(dst->pCompositeClip, dst->pDrawable)) {
545		rects = REGION_RECTS(dst->pCompositeClip);
546		nrect = REGION_NUM_RECTS(dst->pCompositeClip);
547	} else
548		nrect = 0;
549
550	x = dst->pDrawable->x;
551	y = dst->pDrawable->y;
552	src_x -= list->xOff + x;
553	src_y -= list->yOff + y;
554
555	glyph_atlas = NULL;
556	while (nlist--) {
557		int n = list->len;
558		x += list->xOff;
559		y += list->yOff;
560		while (n--) {
561			GlyphPtr glyph = *glyphs++;
562			struct sna_glyph *p;
563			int i;
564
565			p = sna_glyph(glyph);
566			if (unlikely(p->atlas == NULL)) {
567				if (unlikely(!glyph_valid(glyph)))
568					goto next_glyph;
569
570				if (glyph_atlas) {
571					tmp.done(sna, &tmp);
572					glyph_atlas = NULL;
573				}
574				if (!glyph_cache(screen, &sna->render, glyph)) {
575					/* no cache for this glyph */
576					p->atlas = GetGlyphPicture(glyph, screen);
577					if (unlikely(p->atlas == NULL)) {
578						glyph->info.width = glyph->info.height = 0;
579						goto next_glyph;
580					}
581					p->coordinate.x = p->coordinate.y = 0;
582				}
583			}
584
585			if (p->atlas != glyph_atlas) {
586				if (glyph_atlas)
587					tmp.done(sna, &tmp);
588
589				if (!sna->render.composite(sna,
590							   op, src, p->atlas, dst,
591							   0, 0, 0, 0, 0, 0,
592							   0, 0,
593							   &tmp))
594					return false;
595
596				glyph_atlas = p->atlas;
597			}
598
599			if (nrect) {
600				for (i = 0; i < nrect; i++) {
601					struct sna_composite_rectangles r;
602					int16_t dx, dy;
603					int16_t x2, y2;
604
605					r.dst.x = x - glyph->info.x;
606					r.dst.y = y - glyph->info.y;
607					x2 = r.dst.x + glyph->info.width;
608					y2 = r.dst.y + glyph->info.height;
609					dx = dy = 0;
610
611					DBG(("%s: glyph=(%d, %d), (%d, %d), clip=(%d, %d), (%d, %d)\n",
612					     __FUNCTION__,
613					     r.dst.x, r.dst.y, x2, y2,
614					     rects[i].x1, rects[i].y1,
615					     rects[i].x2, rects[i].y2));
616					if (rects[i].y1 >= y2)
617						break;
618
619					if (r.dst.x < rects[i].x1)
620						dx = rects[i].x1 - r.dst.x, r.dst.x = rects[i].x1;
621					if (x2 > rects[i].x2)
622						x2 = rects[i].x2;
623					if (r.dst.y < rects[i].y1)
624						dy = rects[i].y1 - r.dst.y, r.dst.y = rects[i].y1;
625					if (y2 > rects[i].y2)
626						y2 = rects[i].y2;
627
628					if (r.dst.x < x2 && r.dst.y < y2) {
629						DBG(("%s: blt=(%d, %d), (%d, %d)\n",
630						     __FUNCTION__, r.dst.x, r.dst.y, x2, y2));
631
632						r.src.x = r.dst.x + src_x;
633						r.src.y = r.dst.y + src_y;
634						r.mask.x = dx + p->coordinate.x;
635						r.mask.y = dy + p->coordinate.y;
636						r.width  = x2 - r.dst.x;
637						r.height = y2 - r.dst.y;
638						tmp.blt(sna, &tmp, &r);
639						apply_damage(&tmp, &r);
640					}
641				}
642			} else {
643				struct sna_composite_rectangles r;
644
645				r.dst.x = x - glyph->info.x;
646				r.dst.y = y - glyph->info.y;
647				r.src.x = r.dst.x + src_x;
648				r.src.y = r.dst.y + src_y;
649				r.mask = p->coordinate;
650				glyph_copy_size(&r, glyph);
651
652				DBG(("%s: glyph=(%d, %d)x(%d, %d), unclipped\n",
653				     __FUNCTION__,
654				     r.dst.x, r.dst.y,
655				     r.width, r.height));
656
657				tmp.blt(sna, &tmp, &r);
658				apply_damage_clipped_to_dst(&tmp, &r, dst->pDrawable);
659			}
660
661next_glyph:
662			x += glyph->info.xOff;
663			y += glyph->info.yOff;
664		}
665		list++;
666	}
667	if (glyph_atlas)
668		tmp.done(sna, &tmp);
669
670	return true;
671}
672
673flatten static bool
674glyphs0_to_dst(struct sna *sna,
675	       CARD8 op,
676	       PicturePtr src,
677	       PicturePtr dst,
678	       INT16 src_x, INT16 src_y,
679	       int nlist, GlyphListPtr list, GlyphPtr *glyphs)
680{
681	struct sna_composite_op tmp;
682	ScreenPtr screen = dst->pDrawable->pScreen;
683	PicturePtr glyph_atlas;
684	BoxPtr rects;
685	int nrect;
686	int16_t x, y;
687
688	if (NO_GLYPHS_TO_DST)
689		return false;
690
691	memset(&tmp, 0, sizeof(tmp));
692
693	DBG(("%s(op=%d, src=(%d, %d), nlist=%d,  dst=(%d, %d)+(%d, %d))\n",
694	     __FUNCTION__, op, src_x, src_y, nlist,
695	     list->xOff, list->yOff, dst->pDrawable->x, dst->pDrawable->y));
696
697	if (is_clipped(dst->pCompositeClip, dst->pDrawable)) {
698		rects = REGION_RECTS(dst->pCompositeClip);
699		nrect = REGION_NUM_RECTS(dst->pCompositeClip);
700	} else
701		nrect = 0;
702
703	x = dst->pDrawable->x;
704	y = dst->pDrawable->y;
705	src_x -= list->xOff + x;
706	src_y -= list->yOff + y;
707
708	glyph_atlas = NULL;
709	while (nlist--) {
710		int n = list->len;
711		x += list->xOff;
712		y += list->yOff;
713		while (n--) {
714			GlyphPtr glyph = *glyphs++;
715			struct sna_glyph *p;
716			int i;
717
718			p = sna_glyph0(glyph);
719			if (unlikely(p->atlas == NULL)) {
720				if (unlikely(!glyph_valid(glyph)))
721					goto next_glyph;
722
723				if (glyph_atlas) {
724					tmp.done(sna, &tmp);
725					glyph_atlas = NULL;
726				}
727				if (!glyph_cache(screen, &sna->render, glyph)) {
728					/* no cache for this glyph */
729					p->atlas = GetGlyphPicture(glyph, screen);
730					if (unlikely(p->atlas == NULL)) {
731						glyph->info.width = glyph->info.height = 0;
732						goto next_glyph;
733					}
734					p->coordinate.x = p->coordinate.y = 0;
735				}
736			}
737
738			if (p->atlas != glyph_atlas) {
739				if (glyph_atlas)
740					tmp.done(sna, &tmp);
741
742				if (!sna->render.composite(sna,
743							   op, src, p->atlas, dst,
744							   0, 0, 0, 0, 0, 0,
745							   0, 0,
746							   &tmp))
747					return false;
748
749				glyph_atlas = p->atlas;
750			}
751
752			if (nrect) {
753				for (i = 0; i < nrect; i++) {
754					struct sna_composite_rectangles r;
755					int16_t dx, dy;
756					int16_t x2, y2;
757
758					r.dst.x = x - glyph->info.x;
759					r.dst.y = y - glyph->info.y;
760					x2 = r.dst.x + glyph->info.width;
761					y2 = r.dst.y + glyph->info.height;
762					dx = dy = 0;
763
764					DBG(("%s: glyph=(%d, %d), (%d, %d), clip=(%d, %d), (%d, %d)\n",
765					     __FUNCTION__,
766					     r.dst.x, r.dst.y, x2, y2,
767					     rects[i].x1, rects[i].y1,
768					     rects[i].x2, rects[i].y2));
769					if (rects[i].y1 >= y2)
770						break;
771
772					if (r.dst.x < rects[i].x1)
773						dx = rects[i].x1 - r.dst.x, r.dst.x = rects[i].x1;
774					if (x2 > rects[i].x2)
775						x2 = rects[i].x2;
776					if (r.dst.y < rects[i].y1)
777						dy = rects[i].y1 - r.dst.y, r.dst.y = rects[i].y1;
778					if (y2 > rects[i].y2)
779						y2 = rects[i].y2;
780
781					if (r.dst.x < x2 && r.dst.y < y2) {
782						DBG(("%s: blt=(%d, %d), (%d, %d)\n",
783						     __FUNCTION__, r.dst.x, r.dst.y, x2, y2));
784
785						r.src.x = r.dst.x + src_x;
786						r.src.y = r.dst.y + src_y;
787						r.mask.x = dx + p->coordinate.x;
788						r.mask.y = dy + p->coordinate.y;
789						r.width  = x2 - r.dst.x;
790						r.height = y2 - r.dst.y;
791						tmp.blt(sna, &tmp, &r);
792						apply_damage(&tmp, &r);
793					}
794				}
795			} else {
796				struct sna_composite_rectangles r;
797
798				r.dst.x = x - glyph->info.x;
799				r.dst.y = y - glyph->info.y;
800				r.src.x = r.dst.x + src_x;
801				r.src.y = r.dst.y + src_y;
802				r.mask = p->coordinate;
803				glyph_copy_size(&r, glyph);
804
805				DBG(("%s: glyph=(%d, %d)x(%d, %d), unclipped\n",
806				     __FUNCTION__,
807				     r.dst.x, r.dst.y,
808				     r.width, r.height));
809
810				tmp.blt(sna, &tmp, &r);
811				apply_damage_clipped_to_dst(&tmp, &r, dst->pDrawable);
812			}
813
814next_glyph:
815			x += glyph->info.xOff;
816			y += glyph->info.yOff;
817		}
818		list++;
819	}
820	if (glyph_atlas)
821		tmp.done(sna, &tmp);
822
823	return true;
824}
825
826static bool
827glyphs_slow(struct sna *sna,
828	    CARD8 op,
829	    PicturePtr src,
830	    PicturePtr dst,
831	    INT16 src_x, INT16 src_y,
832	    int nlist, GlyphListPtr list, GlyphPtr *glyphs)
833{
834	struct sna_composite_op tmp;
835	ScreenPtr screen = dst->pDrawable->pScreen;
836	int16_t x, y;
837
838	if (NO_GLYPHS_SLOW)
839		return false;
840
841	DBG(("%s(op=%d, src=(%d, %d), nlist=%d,  dst=(%d, %d)+(%d, %d))\n",
842	     __FUNCTION__, op, src_x, src_y, nlist,
843	     list->xOff, list->yOff, dst->pDrawable->x, dst->pDrawable->y));
844
845	x = dst->pDrawable->x;
846	y = dst->pDrawable->y;
847	src_x -= list->xOff + x;
848	src_y -= list->yOff + y;
849
850	while (nlist--) {
851		int n = list->len;
852		x += list->xOff;
853		y += list->yOff;
854		while (n--) {
855			GlyphPtr glyph = *glyphs++;
856			struct sna_glyph *p;
857			BoxPtr rects;
858			BoxRec box;
859			int nrect;
860
861			box.x1 = x - glyph->info.x;
862			box.y1 = y - glyph->info.y;
863			box.x2 = bound(box.x1, glyph->info.width);
864			box.y2 = bound(box.y1, glyph->info.height);
865
866			if (!box_intersect(&box,
867					   &dst->pCompositeClip->extents))
868				goto next_glyph;
869
870			p = sna_glyph(glyph);
871			if (unlikely(p->atlas == NULL)) {
872				if (unlikely(!glyph_valid(glyph)))
873					goto next_glyph;
874
875				if (!glyph_cache(screen, &sna->render, glyph)) {
876					/* no cache for this glyph */
877					p->atlas = GetGlyphPicture(glyph, screen);
878					if (unlikely(p->atlas == NULL)) {
879						glyph->info.width = glyph->info.height = 0;
880						goto next_glyph;
881					}
882					p->coordinate.x = p->coordinate.y = 0;
883				}
884			}
885
886			DBG(("%s: glyph=(%d, %d)x(%d, %d), src=(%d, %d), mask=(%d, %d)\n",
887			     __FUNCTION__,
888			     x - glyph->info.x,
889			     y - glyph->info.y,
890			     glyph->info.width,
891			     glyph->info.height,
892			     src_x + x - glyph->info.x,
893			     src_y + y - glyph->info.y,
894			     p->coordinate.x, p->coordinate.y));
895
896			if (!sna->render.composite(sna,
897						   op, src, p->atlas, dst,
898						   src_x + x - glyph->info.x,
899						   src_y + y - glyph->info.y,
900						   p->coordinate.x, p->coordinate.y,
901						   x - glyph->info.x,
902						   y - glyph->info.y,
903						   glyph->info.width,
904						   glyph->info.height,
905						   memset(&tmp, 0, sizeof(tmp))))
906				return false;
907
908			rects = REGION_RECTS(dst->pCompositeClip);
909			nrect = REGION_NUM_RECTS(dst->pCompositeClip);
910			do {
911				struct sna_composite_rectangles r;
912				int16_t x2, y2;
913
914				r.dst.x = x - glyph->info.x;
915				r.dst.y = y - glyph->info.y;
916				x2 = r.dst.x + glyph->info.width;
917				y2 = r.dst.y + glyph->info.height;
918
919				DBG(("%s: glyph=(%d, %d), (%d, %d), clip=(%d, %d), (%d, %d)\n",
920				     __FUNCTION__,
921				     r.dst.x, r.dst.y, x2, y2,
922				     rects->x1, rects->y1,
923				     rects->x2, rects->y2));
924				if (rects->y1 >= y2)
925					break;
926
927				if (r.dst.x < rects->x1)
928					r.dst.x = rects->x1;
929				if (x2 > rects->x2)
930					x2 = rects->x2;
931
932				if (r.dst.y < rects->y1)
933					r.dst.y = rects->y1;
934				if (y2 > rects->y2)
935					y2 = rects->y2;
936
937				if (r.dst.x < x2 && r.dst.y < y2) {
938					DBG(("%s: blt=(%d, %d), (%d, %d)\n",
939					     __FUNCTION__, r.dst.x, r.dst.y, x2, y2));
940					r.width  = x2 - r.dst.x;
941					r.height = y2 - r.dst.y;
942					r.src = r.mask = r .dst;
943					tmp.blt(sna, &tmp, &r);
944					apply_damage(&tmp, &r);
945				}
946				rects++;
947			} while (--nrect);
948			tmp.done(sna, &tmp);
949
950next_glyph:
951			x += glyph->info.xOff;
952			y += glyph->info.yOff;
953		}
954		list++;
955	}
956
957	return true;
958}
959
960static bool
961clear_pixmap(struct sna *sna, PixmapPtr pixmap)
962{
963	struct sna_pixmap *priv = sna_pixmap(pixmap);
964	return sna->render.clear(sna, pixmap, priv->gpu_bo);
965}
966
967static bool
968too_large(struct sna *sna, int width, int height)
969{
970	return (width > sna->render.max_3d_size ||
971		height > sna->render.max_3d_size);
972}
973
974static pixman_image_t *
975__sna_glyph_get_image(GlyphPtr g, ScreenPtr s)
976{
977	pixman_image_t *image;
978	PicturePtr p;
979	int dx, dy;
980
981	p = GetGlyphPicture(g, s);
982	if (unlikely(p == NULL))
983		return NULL;
984
985	image = image_from_pict(p, FALSE, &dx, &dy);
986	if (!image)
987		return NULL;
988
989	assert(dx == 0 && dy == 0);
990	return sna_glyph(g)->image = image;
991}
992
993static inline pixman_image_t *
994sna_glyph_get_image(GlyphPtr g, ScreenPtr s)
995{
996	pixman_image_t *image;
997
998	image = sna_glyph(g)->image;
999	if (image == NULL)
1000		image = __sna_glyph_get_image(g, s);
1001
1002	return image;
1003}
1004
1005flatten static bool
1006glyphs_via_mask(struct sna *sna,
1007		CARD8 op,
1008		PicturePtr src,
1009		PicturePtr dst,
1010		PictFormatPtr format,
1011		INT16 src_x, INT16 src_y,
1012		int nlist, GlyphListPtr list, GlyphPtr *glyphs)
1013{
1014	ScreenPtr screen = dst->pDrawable->pScreen;
1015	struct sna_composite_op tmp;
1016	CARD32 component_alpha;
1017	PixmapPtr pixmap;
1018	PicturePtr glyph_atlas, mask;
1019	int16_t x, y, width, height;
1020	int error;
1021	bool ret = false;
1022	BoxRec box;
1023
1024	if (NO_GLYPHS_VIA_MASK)
1025		return false;
1026
1027	DBG(("%s(op=%d, src=(%d, %d), nlist=%d,  dst=(%d, %d)+(%d, %d))\n",
1028	     __FUNCTION__, op, src_x, src_y, nlist,
1029	     list->xOff, list->yOff, dst->pDrawable->x, dst->pDrawable->y));
1030
1031	glyph_extents(nlist, list, glyphs, &box);
1032	if (box.x2 <= box.x1 || box.y2 <= box.y1)
1033		return true;
1034
1035	DBG(("%s: bounds=((%d, %d), (%d, %d))\n", __FUNCTION__,
1036	     box.x1, box.y1, box.x2, box.y2));
1037
1038	if (!sna_compute_composite_extents(&box,
1039					   src, NULL, dst,
1040					   src_x, src_y,
1041					   0, 0,
1042					   box.x1, box.y1,
1043					   box.x2 - box.x1,
1044					   box.y2 - box.y1))
1045		return true;
1046
1047	DBG(("%s: extents=((%d, %d), (%d, %d))\n", __FUNCTION__,
1048	     box.x1, box.y1, box.x2, box.y2));
1049
1050	width  = box.x2 - box.x1;
1051	height = box.y2 - box.y1;
1052	box.x1 -= dst->pDrawable->x;
1053	box.y1 -= dst->pDrawable->y;
1054	x = -box.x1;
1055	y = -box.y1;
1056	src_x += box.x1 - list->xOff;
1057	src_y += box.y1 - list->yOff;
1058
1059	if (format->depth < 8) {
1060		format = PictureMatchFormat(screen, 8, PICT_a8);
1061		if (!format)
1062			return false;
1063	}
1064
1065	component_alpha = NeedsComponent(format->format);
1066	if (!NO_SMALL_MASK &&
1067	    ((uint32_t)width * height * format->depth < 8 * 4096 ||
1068	     too_large(sna, width, height))) {
1069		pixman_image_t *mask_image;
1070
1071		DBG(("%s: small mask [format=%lx, depth=%d, size=%d], rendering glyphs to upload buffer\n",
1072		     __FUNCTION__, (unsigned long)format->format,
1073		     format->depth, (uint32_t)width*height*format->depth));
1074
1075		pixmap = sna_pixmap_create_upload(screen,
1076						  width, height,
1077						  format->depth,
1078						  KGEM_BUFFER_WRITE);
1079		if (!pixmap)
1080			return false;
1081
1082		mask_image =
1083			pixman_image_create_bits(format->depth << 24 | format->format,
1084						 width, height,
1085						 pixmap->devPrivate.ptr,
1086						 pixmap->devKind);
1087		if (mask_image == NULL)
1088			goto err_pixmap;
1089
1090		memset(pixmap->devPrivate.ptr, 0, pixmap->devKind*height);
1091#if HAS_PIXMAN_GLYPHS
1092		if (sna->render.glyph_cache) {
1093			pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
1094			pixman_glyph_t *pglyphs = stack_glyphs;
1095			pixman_glyph_cache_t *cache;
1096			int count, n;
1097
1098			cache = sna->render.glyph_cache;
1099			pixman_glyph_cache_freeze(cache);
1100
1101			count = 0;
1102			for (n = 0; n < nlist; ++n)
1103				count += list[n].len;
1104			if (count > N_STACK_GLYPHS) {
1105				pglyphs = malloc (count * sizeof(pixman_glyph_t));
1106				if (pglyphs == NULL)
1107					goto err_pixmap;
1108			}
1109
1110			count = 0;
1111			do {
1112				n = list->len;
1113				x += list->xOff;
1114				y += list->yOff;
1115				while (n--) {
1116					GlyphPtr g = *glyphs++;
1117					const void *ptr;
1118
1119					if (!glyph_valid(g))
1120						goto next_pglyph;
1121
1122					ptr = pixman_glyph_cache_lookup(cache, g, NULL);
1123					if (ptr == NULL) {
1124						pixman_image_t *glyph_image;
1125
1126						glyph_image = sna_glyph_get_image(g, screen);
1127						if (glyph_image == NULL)
1128							goto next_pglyph;
1129
1130						ptr = pixman_glyph_cache_insert(cache, g, NULL,
1131										g->info.x,
1132										g->info.y,
1133										glyph_image);
1134						if (ptr == NULL)
1135							goto next_pglyph;
1136					}
1137
1138					pglyphs[count].x = x;
1139					pglyphs[count].y = y;
1140					pglyphs[count].glyph = ptr;
1141					count++;
1142
1143next_pglyph:
1144					x += g->info.xOff;
1145					y += g->info.yOff;
1146				}
1147				list++;
1148			} while (--nlist);
1149
1150			pixman_composite_glyphs_no_mask(PIXMAN_OP_ADD,
1151							sna->render.white_image,
1152							mask_image,
1153							0, 0,
1154							0, 0,
1155							cache, count, pglyphs);
1156			pixman_glyph_cache_thaw(cache);
1157			if (pglyphs != stack_glyphs)
1158				free(pglyphs);
1159		} else
1160#endif
1161		do {
1162			int n = list->len;
1163			x += list->xOff;
1164			y += list->yOff;
1165			while (n--) {
1166				GlyphPtr g = *glyphs++;
1167				pixman_image_t *glyph_image;
1168				int16_t xi, yi;
1169
1170				if (!glyph_valid(g))
1171					goto next_image;
1172
1173				/* If the mask has been cropped, it is likely
1174				 * that some of the glyphs fall outside.
1175				 */
1176				xi = x - g->info.x;
1177				yi = y - g->info.y;
1178				if (xi >= width || yi >= height)
1179					goto next_image;
1180				if (xi + g->info.width  <= 0 ||
1181				    yi + g->info.height <= 0)
1182					goto next_image;
1183
1184				glyph_image =
1185					sna_glyph_get_image(g, dst->pDrawable->pScreen);
1186				if (glyph_image == NULL)
1187					goto next_image;
1188
1189				DBG(("%s: glyph to mask (%d, %d)x(%d, %d)\n",
1190				     __FUNCTION__,
1191				     xi, yi,
1192				     g->info.width,
1193				     g->info.height));
1194
1195				if (list->format == format) {
1196					assert(pixman_image_get_format(glyph_image) == pixman_image_get_format(mask_image));
1197					pixman_image_composite(PictOpAdd,
1198							       glyph_image,
1199							       NULL,
1200							       mask_image,
1201							       0, 0,
1202							       0, 0,
1203							       xi, yi,
1204							       g->info.width,
1205							       g->info.height);
1206				} else {
1207					pixman_image_composite(PictOpAdd,
1208							       sna->render.white_image,
1209							       glyph_image,
1210							       mask_image,
1211							       0, 0,
1212							       0, 0,
1213							       xi, yi,
1214							       g->info.width,
1215							       g->info.height);
1216				}
1217
1218next_image:
1219				x += g->info.xOff;
1220				y += g->info.yOff;
1221			}
1222			list++;
1223		} while (--nlist);
1224		pixman_image_unref(mask_image);
1225
1226		mask = CreatePicture(0, &pixmap->drawable,
1227				     format, CPComponentAlpha,
1228				     &component_alpha, serverClient, &error);
1229		if (!mask)
1230			goto err_pixmap;
1231
1232		ValidatePicture(mask);
1233	} else {
1234		pixmap = screen->CreatePixmap(screen,
1235					      width, height, format->depth,
1236					      SNA_CREATE_SCRATCH);
1237		if (!pixmap)
1238			return false;
1239
1240		mask = CreatePicture(0, &pixmap->drawable,
1241				     format, CPComponentAlpha,
1242				     &component_alpha, serverClient, &error);
1243		if (!mask)
1244			goto err_pixmap;
1245
1246		ValidatePicture(mask);
1247		if (!clear_pixmap(sna, pixmap))
1248			goto err_mask;
1249
1250		memset(&tmp, 0, sizeof(tmp));
1251		glyph_atlas = NULL;
1252		do {
1253			int n = list->len;
1254			x += list->xOff;
1255			y += list->yOff;
1256			while (n--) {
1257				GlyphPtr glyph = *glyphs++;
1258				struct sna_glyph *p;
1259				struct sna_composite_rectangles r;
1260
1261				p = sna_glyph(glyph);
1262				if (unlikely(p->atlas == NULL)) {
1263					if (unlikely(!glyph_valid(glyph)))
1264						goto next_glyph;
1265
1266					if (glyph_atlas) {
1267						tmp.done(sna, &tmp);
1268						glyph_atlas = NULL;
1269					}
1270					if (!glyph_cache(screen, &sna->render, glyph)) {
1271						/* no cache for this glyph */
1272						p->atlas = GetGlyphPicture(glyph, screen);
1273						if (unlikely(p->atlas == NULL)) {
1274							glyph->info.width = glyph->info.height = 0;
1275							goto next_glyph;
1276						}
1277						p->coordinate.x = p->coordinate.y = 0;
1278					}
1279				}
1280				if (p->atlas != glyph_atlas) {
1281					bool ok;
1282
1283					if (glyph_atlas)
1284						tmp.done(sna, &tmp);
1285
1286					DBG(("%s: atlas format=%08x, mask format=%08x\n",
1287					     __FUNCTION__,
1288					     (int)p->atlas->format,
1289					     (int)(format->depth << 24 | format->format)));
1290					if (p->atlas->format == (format->depth << 24 | format->format)) {
1291						ok = sna->render.composite(sna, PictOpAdd,
1292									   p->atlas, NULL, mask,
1293									   0, 0, 0, 0, 0, 0,
1294									   0, 0,
1295									   &tmp);
1296					} else {
1297						ok = sna->render.composite(sna, PictOpAdd,
1298									   sna->render.white_picture, p->atlas, mask,
1299									   0, 0, 0, 0, 0, 0,
1300									   0, 0,
1301									   &tmp);
1302					}
1303					if (!ok) {
1304						DBG(("%s: fallback -- can not handle PictOpAdd of glyph onto mask!\n",
1305						     __FUNCTION__));
1306						goto err_mask;
1307					}
1308
1309					glyph_atlas = p->atlas;
1310				}
1311
1312				DBG(("%s: blt glyph origin (%d, %d), offset (%d, %d), src (%d, %d), size (%d, %d)\n",
1313				     __FUNCTION__,
1314				     x, y,
1315				     glyph->info.x, glyph->info.y,
1316				     p->coordinate.x, p->coordinate.y,
1317				     glyph->info.width, glyph->info.height));
1318
1319				r.mask = r.src = p->coordinate;
1320				r.dst.x = x - glyph->info.x;
1321				r.dst.y = y - glyph->info.y;
1322				glyph_copy_size(&r, glyph);
1323				tmp.blt(sna, &tmp, &r);
1324
1325next_glyph:
1326				x += glyph->info.xOff;
1327				y += glyph->info.yOff;
1328			}
1329			list++;
1330		} while (--nlist);
1331		if (glyph_atlas)
1332			tmp.done(sna, &tmp);
1333	}
1334
1335	sna_composite(op,
1336		      src, mask, dst,
1337		      src_x, src_y,
1338		      0, 0,
1339		      box.x1, box.y1,
1340		      width, height);
1341	ret = true;
1342err_mask:
1343	FreePicture(mask, 0);
1344err_pixmap:
1345	sna_pixmap_destroy(pixmap);
1346	return ret;
1347}
1348
1349static PictFormatPtr
1350glyphs_format(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
1351{
1352	PictFormatPtr format = list[0].format;
1353	int16_t x1, x2, y1, y2;
1354	int16_t x, y;
1355	BoxRec stack_extents[64], *list_extents = stack_extents;
1356	int i, j;
1357
1358	if (nlist > ARRAY_SIZE(stack_extents)) {
1359		list_extents = malloc(sizeof(BoxRec) * nlist);
1360		if (list_extents == NULL)
1361			return NULL;
1362	}
1363
1364	x = 0;
1365	y = 0;
1366	for (i = 0; i < nlist; i++) {
1367		BoxRec extents;
1368		bool first = true;
1369		int n = list->len;
1370
1371		/* Check the intersection of each glyph within the list and
1372		 * then each list against the previous lists.
1373		 *
1374		 * If we overlap then we cannot substitute a mask as the
1375		 * rendering will be altered.
1376		 */
1377		extents.x1 = 0;
1378		extents.y1 = 0;
1379		extents.x2 = 0;
1380		extents.y2 = 0;
1381
1382		if (format->format != list->format->format) {
1383			format = NULL;
1384			goto out;
1385		}
1386
1387		x += list->xOff;
1388		y += list->yOff;
1389		list++;
1390		while (n--) {
1391			GlyphPtr glyph = *glyphs++;
1392
1393			if (!glyph_valid(glyph))
1394				goto skip_glyph;
1395
1396			x1 = x - glyph->info.x;
1397			y1 = y - glyph->info.y;
1398			x2 = x1 + glyph->info.width;
1399			y2 = y1 + glyph->info.height;
1400
1401			if (first) {
1402				extents.x1 = x1;
1403				extents.y1 = y1;
1404				extents.x2 = x2;
1405				extents.y2 = y2;
1406				first = false;
1407			} else {
1408				/* Potential overlap?
1409				 * We cheat and ignore the boundary pixels, as
1410				 * the likelihood of an actual overlap of
1411				 * inkedk pixels being noticeable in the
1412				 * boundary is small, yet glyphs frequently
1413				 * overlap on the boundaries.
1414				 */
1415				if (x1 < extents.x2-1 && x2 > extents.x1+1 &&
1416				    y1 < extents.y2-1 && y2 > extents.y1+1) {
1417					format = NULL;
1418					goto out;
1419				}
1420
1421				if (x1 < extents.x1)
1422					extents.x1 = x1;
1423				if (x2 > extents.x2)
1424					extents.x2 = x2;
1425				if (y1 < extents.y1)
1426					extents.y1 = y1;
1427				if (y2 > extents.y2)
1428					extents.y2 = y2;
1429			}
1430skip_glyph:
1431			x += glyph->info.xOff;
1432			y += glyph->info.yOff;
1433		}
1434
1435		/* Incrementally building a region is expensive. We expect
1436		 * the number of lists to be small, so just keep a list
1437		 * of the previous boxes and walk those.
1438		 */
1439		for (j = 0; j < i; j++) {
1440			if (extents.x1 < list_extents[j].x2-1 &&
1441			    extents.x2 > list_extents[j].x1+1 &&
1442			    extents.y1 < list_extents[j].y2-1 &&
1443			    extents.y2 > list_extents[j].y1+1) {
1444				format = NULL;
1445				goto out;
1446			}
1447		}
1448		list_extents[i] = extents;
1449	}
1450
1451out:
1452	if (list_extents != stack_extents)
1453		free(list_extents);
1454	return format;
1455}
1456
1457static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
1458			     int nlist, GlyphListPtr list, GlyphPtr *glyphs)
1459{
1460	PictFormatPtr g;
1461	uint32_t color;
1462
1463	if (NO_DISCARD_MASK)
1464		return false;
1465
1466	if (nlist == 1 && list->len == 1)
1467		return true;
1468
1469	if (!op_is_bounded(op))
1470		return false;
1471
1472	/* No glyphs overlap and we are not performing a mask conversion. */
1473	g = glyphs_format(nlist, list, glyphs);
1474	if (mask == g)
1475		return true;
1476
1477	/* Otherwise if the glyphs are all bitmaps and we have an
1478	 * opaque source we can also render directly to the dst.
1479	 */
1480	if (g == NULL) {
1481		while (nlist--) {
1482			if (list->format->depth != 1)
1483				return false;
1484
1485			list++;
1486		}
1487	} else {
1488		if (PICT_FORMAT_A(mask->format) >= PICT_FORMAT_A(g->format))
1489			return true;
1490
1491		if (g->depth != 1)
1492			return false;
1493	}
1494
1495	if (!sna_picture_is_solid(src, &color))
1496		return false;
1497
1498	return color >> 24 == 0xff;
1499}
1500
1501static void
1502glyphs_fallback(CARD8 op,
1503		PicturePtr src,
1504		PicturePtr dst,
1505		PictFormatPtr mask_format,
1506		int src_x, int src_y,
1507		int nlist, GlyphListPtr list, GlyphPtr *glyphs)
1508{
1509	struct sna *sna = to_sna_from_drawable(dst->pDrawable);
1510	pixman_image_t *src_image, *dst_image;
1511	int src_dx, src_dy;
1512	ScreenPtr screen = dst->pDrawable->pScreen;
1513	RegionRec region;
1514	int x, y, n;
1515
1516	glyph_extents(nlist, list, glyphs, &region.extents);
1517	if (region.extents.x2 <= region.extents.x1 ||
1518	    region.extents.y2 <= region.extents.y1)
1519		return;
1520
1521	DBG(("%s: (%d, %d), (%d, %d)\n", __FUNCTION__,
1522	     region.extents.x1, region.extents.y1,
1523	     region.extents.x2, region.extents.y2));
1524
1525	region.data = NULL;
1526	RegionTranslate(&region, dst->pDrawable->x, dst->pDrawable->y);
1527	if (dst->pCompositeClip)
1528		RegionIntersect(&region, &region, dst->pCompositeClip);
1529	DBG(("%s: clipped extents (%d, %d), (%d, %d)\n",
1530	     __FUNCTION__,
1531	     RegionExtents(&region)->x1, RegionExtents(&region)->y1,
1532	     RegionExtents(&region)->x2, RegionExtents(&region)->y2));
1533	if (RegionNil(&region))
1534		return;
1535
1536	if (!sna_drawable_move_region_to_cpu(dst->pDrawable, &region,
1537					     MOVE_READ | MOVE_WRITE))
1538		return;
1539	if (dst->alphaMap &&
1540	    !sna_drawable_move_to_cpu(dst->alphaMap->pDrawable,
1541				      MOVE_READ | MOVE_WRITE))
1542		return;
1543
1544	if (src->pDrawable) {
1545		if (!sna_drawable_move_to_cpu(src->pDrawable,
1546					      MOVE_READ))
1547			return;
1548
1549		if (src->alphaMap &&
1550		    !sna_drawable_move_to_cpu(src->alphaMap->pDrawable,
1551					      MOVE_READ))
1552			return;
1553	}
1554	RegionTranslate(&region, -dst->pDrawable->x, -dst->pDrawable->y);
1555
1556	if (mask_format &&
1557	    can_discard_mask(op, src, mask_format, nlist, list, glyphs)) {
1558		DBG(("%s: discarding mask\n", __FUNCTION__));
1559		mask_format = NULL;
1560	}
1561
1562#if HAS_PIXMAN_GLYPHS
1563	if (sna->render.glyph_cache) {
1564		pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
1565		pixman_glyph_t *pglyphs = stack_glyphs;
1566		pixman_glyph_cache_t *cache = sna->render.glyph_cache;
1567		int dst_x = list->xOff, dst_y = list->yOff;
1568		int dst_dx, dst_dy, count;
1569
1570		pixman_glyph_cache_freeze(cache);
1571
1572		count = 0;
1573		for (n = 0; n < nlist; ++n)
1574			count += list[n].len;
1575		if (count > N_STACK_GLYPHS) {
1576			pglyphs = malloc (count * sizeof(pixman_glyph_t));
1577			if (pglyphs == NULL)
1578				goto out;
1579		}
1580
1581		count = 0;
1582		x = y = 0;
1583		while (nlist--) {
1584			n = list->len;
1585			x += list->xOff;
1586			y += list->yOff;
1587			while (n--) {
1588				GlyphPtr g = *glyphs++;
1589				const void *ptr;
1590
1591				if (!glyph_valid(g))
1592					goto next;
1593
1594				ptr = pixman_glyph_cache_lookup(cache, g, NULL);
1595				if (ptr == NULL) {
1596					pixman_image_t *glyph_image;
1597
1598					glyph_image = sna_glyph_get_image(g, screen);
1599					if (glyph_image == NULL)
1600						goto next;
1601
1602					ptr = pixman_glyph_cache_insert(cache, g, NULL,
1603									g->info.x,
1604									g->info.y,
1605									glyph_image);
1606					if (ptr == NULL)
1607						goto out;
1608				}
1609
1610				pglyphs[count].x = x;
1611				pglyphs[count].y = y;
1612				pglyphs[count].glyph = ptr;
1613				count++;
1614
1615next:
1616				x += g->info.xOff;
1617				y += g->info.yOff;
1618			}
1619			list++;
1620		}
1621
1622		src_image = image_from_pict(src, FALSE, &src_dx, &src_dy);
1623		if (src_image == NULL)
1624			goto out;
1625
1626		dst_image = image_from_pict(dst, TRUE, &dst_dx, &dst_dy);
1627		if (dst_image == NULL)
1628			goto out_free_src;
1629
1630		if (mask_format) {
1631			pixman_composite_glyphs(op, src_image, dst_image,
1632						mask_format->format | (mask_format->depth << 24),
1633						src_x + src_dx + region.extents.x1 - dst_x,
1634						src_y + src_dy + region.extents.y1 - dst_y,
1635						region.extents.x1, region.extents.y1,
1636						region.extents.x1 + dst_dx, region.extents.y1 + dst_dy,
1637						region.extents.x2 - region.extents.x1,
1638						region.extents.y2 - region.extents.y1,
1639						cache, count, pglyphs);
1640		} else {
1641			pixman_composite_glyphs_no_mask(op, src_image, dst_image,
1642							src_x + src_dx - dst_x, src_y + src_dy - dst_y,
1643							dst_dx, dst_dy,
1644							cache, count, pglyphs);
1645		}
1646
1647		free_pixman_pict(dst, dst_image);
1648
1649out_free_src:
1650		free_pixman_pict(src, src_image);
1651
1652out:
1653		pixman_glyph_cache_thaw(cache);
1654		if (pglyphs != stack_glyphs)
1655			free(pglyphs);
1656	} else
1657#endif
1658	{
1659		pixman_image_t *mask_image;
1660
1661		dst_image = image_from_pict(dst, TRUE, &x, &y);
1662		if (dst_image == NULL)
1663			goto cleanup_region;
1664		DBG(("%s: dst offset (%d, %d)\n", __FUNCTION__, x, y));
1665		if (x | y) {
1666			region.extents.x1 += x;
1667			region.extents.x2 += x;
1668			region.extents.y1 += y;
1669			region.extents.y2 += y;
1670		}
1671
1672		src_image = image_from_pict(src, FALSE, &src_dx, &src_dy);
1673		if (src_image == NULL)
1674			goto cleanup_dst;
1675		DBG(("%s: src offset (%d, %d)\n", __FUNCTION__, src_dx, src_dy));
1676		src_x += src_dx - list->xOff;
1677		src_y += src_dy - list->yOff;
1678
1679		if (mask_format) {
1680			DBG(("%s: create mask (%d, %d)x(%d,%d) + (%d,%d) + (%d,%d), depth=%d, format=%lx [%lx], ca? %d\n",
1681			     __FUNCTION__,
1682			     region.extents.x1, region.extents.y1,
1683			     region.extents.x2 - region.extents.x1,
1684			     region.extents.y2 - region.extents.y1,
1685			     dst->pDrawable->x, dst->pDrawable->y,
1686			     x, y,
1687			     mask_format->depth,
1688			     (long)mask_format->format,
1689			     (long)(mask_format->depth << 24 | mask_format->format),
1690			     NeedsComponent(mask_format->format)));
1691			mask_image =
1692				pixman_image_create_bits(mask_format->depth << 24 | mask_format->format,
1693							 region.extents.x2 - region.extents.x1,
1694							 region.extents.y2 - region.extents.y1,
1695							 NULL, 0);
1696			if (mask_image == NULL)
1697				goto cleanup_src;
1698			if (NeedsComponent(mask_format->format))
1699				pixman_image_set_component_alpha(mask_image, TRUE);
1700
1701			x -= region.extents.x1;
1702			y -= region.extents.y1;
1703		} else {
1704			mask_image = dst_image;
1705			src_x -= x - dst->pDrawable->x;
1706			src_y -= y - dst->pDrawable->y;
1707		}
1708
1709		do {
1710			n = list->len;
1711			x += list->xOff;
1712			y += list->yOff;
1713			while (n--) {
1714				GlyphPtr g = *glyphs++;
1715				pixman_image_t *glyph_image;
1716
1717				if (!glyph_valid(g))
1718					goto next_glyph;
1719
1720				glyph_image = sna_glyph_get_image(g, screen);
1721				if (glyph_image == NULL)
1722					goto next_glyph;
1723
1724				if (mask_format) {
1725					DBG(("%s: glyph to mask (%d, %d)x(%d, %d)\n",
1726					     __FUNCTION__,
1727					     x - g->info.x,
1728					     y - g->info.y,
1729					     g->info.width,
1730					     g->info.height));
1731
1732					if (list->format == mask_format) {
1733						assert(pixman_image_get_format(glyph_image) == pixman_image_get_format(mask_image));
1734						pixman_image_composite(PictOpAdd,
1735								       glyph_image,
1736								       NULL,
1737								       mask_image,
1738								       0, 0,
1739								       0, 0,
1740								       x - g->info.x,
1741								       y - g->info.y,
1742								       g->info.width,
1743								       g->info.height);
1744					} else {
1745						pixman_image_composite(PictOpAdd,
1746								       sna->render.white_image,
1747								       glyph_image,
1748								       mask_image,
1749								       0, 0,
1750								       0, 0,
1751								       x - g->info.x,
1752								       y - g->info.y,
1753								       g->info.width,
1754								       g->info.height);
1755					}
1756				} else {
1757					int xi = x - g->info.x;
1758					int yi = y - g->info.y;
1759
1760					DBG(("%s: glyph to dst (%d, %d)x(%d, %d)/[(%d, %d)x(%d, %d)], src (%d, %d) [op=%d]\n",
1761					     __FUNCTION__,
1762					     xi, yi,
1763					     g->info.width, g->info.height,
1764					     dst->pDrawable->x,
1765					     dst->pDrawable->y,
1766					     dst->pDrawable->width,
1767					     dst->pDrawable->height,
1768					     src_x + xi,
1769					     src_y + yi,
1770					     op));
1771
1772					pixman_image_composite(op,
1773							       src_image,
1774							       glyph_image,
1775							       dst_image,
1776							       src_x + xi,
1777							       src_y + yi,
1778							       0, 0,
1779							       xi, yi,
1780							       g->info.width,
1781							       g->info.height);
1782				}
1783next_glyph:
1784				x += g->info.xOff;
1785				y += g->info.yOff;
1786			}
1787			list++;
1788		} while (--nlist);
1789
1790		if (mask_format) {
1791			DBG(("%s: glyph mask composite src=(%d+%d,%d+%d) dst=(%d, %d)x(%d, %d)\n",
1792			     __FUNCTION__,
1793			     src_x, region.extents.x1, src_y, region.extents.y1,
1794			     region.extents.x1, region.extents.y1,
1795			     region.extents.x2 - region.extents.x1,
1796			     region.extents.y2 - region.extents.y1));
1797			pixman_image_composite(op, src_image, mask_image, dst_image,
1798					       src_x, src_y,
1799					       0, 0,
1800					       region.extents.x1, region.extents.y1,
1801					       region.extents.x2 - region.extents.x1,
1802					       region.extents.y2 - region.extents.y1);
1803			pixman_image_unref(mask_image);
1804		}
1805
1806cleanup_src:
1807		free_pixman_pict(src, src_image);
1808cleanup_dst:
1809		free_pixman_pict(dst, dst_image);
1810	}
1811
1812cleanup_region:
1813	RegionUninit(&region);
1814}
1815
1816void
1817sna_glyphs(CARD8 op,
1818	   PicturePtr src,
1819	   PicturePtr dst,
1820	   PictFormatPtr mask,
1821	   INT16 src_x, INT16 src_y,
1822	   int nlist, GlyphListPtr list, GlyphPtr *glyphs)
1823{
1824	PixmapPtr pixmap = get_drawable_pixmap(dst->pDrawable);
1825	struct sna *sna = to_sna_from_pixmap(pixmap);
1826	struct sna_pixmap *priv;
1827
1828	DBG(("%s(op=%d, nlist=%d, src=(%d, %d))\n",
1829	     __FUNCTION__, op, nlist, src_x, src_y));
1830
1831	if (REGION_NUM_RECTS(dst->pCompositeClip) == 0)
1832		return;
1833
1834	if (FALLBACK)
1835		goto fallback;
1836
1837	if (!can_render(sna)) {
1838		DBG(("%s: wedged\n", __FUNCTION__));
1839		goto fallback;
1840	}
1841
1842	if (dst->alphaMap) {
1843		DBG(("%s: fallback -- dst alpha map\n", __FUNCTION__));
1844		goto fallback;
1845	}
1846
1847	priv = sna_pixmap(pixmap);
1848	if (priv == NULL) {
1849		DBG(("%s: fallback -- destination unattached\n", __FUNCTION__));
1850		goto fallback;
1851	}
1852
1853	if ((too_small(priv) || DAMAGE_IS_ALL(priv->cpu_damage)) &&
1854	    !picture_is_gpu(sna, src)) {
1855		DBG(("%s: fallback -- too small (%dx%d)\n",
1856		     __FUNCTION__, dst->pDrawable->width, dst->pDrawable->height));
1857		goto fallback;
1858	}
1859
1860	/* Try to discard the mask for non-overlapping glyphs */
1861	if (mask == NULL ||
1862	    (dst->pCompositeClip->data == NULL &&
1863	     can_discard_mask(op, src, mask, nlist, list, glyphs))) {
1864		DBG(("%s: discarding mask\n", __FUNCTION__));
1865		if (can_use_glyph0()) {
1866			if (glyphs0_to_dst(sna, op,
1867					   src, dst,
1868					   src_x, src_y,
1869					   nlist, list, glyphs))
1870				return;
1871		} else {
1872			if (glyphs_to_dst(sna, op,
1873					  src, dst,
1874					  src_x, src_y,
1875					  nlist, list, glyphs))
1876				return;
1877		}
1878	}
1879
1880	/* Otherwise see if we can substitute a mask */
1881	if (!mask) {
1882		mask = glyphs_format(nlist, list, glyphs);
1883		DBG(("%s: substituting mask? %d\n", __FUNCTION__, mask!=NULL));
1884	}
1885	if (mask) {
1886		if (glyphs_via_mask(sna, op,
1887				    src, dst, mask,
1888				    src_x, src_y,
1889				    nlist, list, glyphs))
1890			return;
1891	} else {
1892		if (glyphs_slow(sna, op,
1893				src, dst,
1894				src_x, src_y,
1895				nlist, list, glyphs))
1896			return;
1897	}
1898
1899fallback:
1900	glyphs_fallback(op, src, dst, mask, src_x, src_y, nlist, list, glyphs);
1901}
1902
1903static bool
1904glyphs_via_image(struct sna *sna,
1905		 CARD8 op,
1906		 PicturePtr src,
1907		 PicturePtr dst,
1908		 PictFormatPtr format,
1909		 INT16 src_x, INT16 src_y,
1910		 int nlist, GlyphListPtr list, GlyphPtr *glyphs)
1911{
1912	ScreenPtr screen = dst->pDrawable->pScreen;
1913	CARD32 component_alpha;
1914	PixmapPtr pixmap;
1915	PicturePtr mask;
1916	int16_t x, y, width, height;
1917	pixman_image_t *mask_image;
1918	int error;
1919	bool ret = false;
1920	BoxRec box;
1921
1922	if (NO_GLYPHS_VIA_MASK)
1923		return false;
1924
1925	DBG(("%s(op=%d, src=(%d, %d), nlist=%d,  dst=(%d, %d)+(%d, %d))\n",
1926	     __FUNCTION__, op, src_x, src_y, nlist,
1927	     list->xOff, list->yOff, dst->pDrawable->x, dst->pDrawable->y));
1928
1929	glyph_extents(nlist, list, glyphs, &box);
1930	if (box.x2 <= box.x1 || box.y2 <= box.y1)
1931		return true;
1932
1933	DBG(("%s: bounds=((%d, %d), (%d, %d))\n", __FUNCTION__,
1934	     box.x1, box.y1, box.x2, box.y2));
1935
1936	if (!sna_compute_composite_extents(&box,
1937					   src, NULL, dst,
1938					   src_x, src_y,
1939					   0, 0,
1940					   box.x1, box.y1,
1941					   box.x2 - box.x1,
1942					   box.y2 - box.y1))
1943		return true;
1944
1945	DBG(("%s: extents=((%d, %d), (%d, %d))\n", __FUNCTION__,
1946	     box.x1, box.y1, box.x2, box.y2));
1947
1948	width  = box.x2 - box.x1;
1949	height = box.y2 - box.y1;
1950	box.x1 -= dst->pDrawable->x;
1951	box.y1 -= dst->pDrawable->y;
1952	x = -box.x1;
1953	y = -box.y1;
1954	src_x += box.x1 - list->xOff;
1955	src_y += box.y1 - list->yOff;
1956
1957	if (format->depth < 8) {
1958		format = PictureMatchFormat(screen, 8, PICT_a8);
1959		if (!format)
1960			return false;
1961	}
1962
1963	DBG(("%s: small mask [format=%lx, depth=%d, size=%d], rendering glyphs to upload buffer\n",
1964	     __FUNCTION__, (unsigned long)format->format,
1965	     format->depth, (uint32_t)width*height*format->depth));
1966
1967	pixmap = sna_pixmap_create_upload(screen,
1968					  width, height,
1969					  format->depth,
1970					  KGEM_BUFFER_WRITE);
1971	if (!pixmap)
1972		return false;
1973
1974	mask_image =
1975		pixman_image_create_bits(format->depth << 24 | format->format,
1976					 width, height,
1977					 pixmap->devPrivate.ptr,
1978					 pixmap->devKind);
1979	if (mask_image == NULL)
1980		goto err_pixmap;
1981
1982	memset(pixmap->devPrivate.ptr, 0, pixmap->devKind*height);
1983#if HAS_PIXMAN_GLYPHS
1984	if (sna->render.glyph_cache) {
1985		pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
1986		pixman_glyph_t *pglyphs = stack_glyphs;
1987		pixman_glyph_cache_t *cache;
1988		int count, n;
1989
1990		cache = sna->render.glyph_cache;
1991		pixman_glyph_cache_freeze(cache);
1992
1993		count = 0;
1994		for (n = 0; n < nlist; ++n)
1995			count += list[n].len;
1996		if (count > N_STACK_GLYPHS) {
1997			pglyphs = malloc (count * sizeof(pixman_glyph_t));
1998			if (pglyphs == NULL)
1999				goto err_pixmap;
2000		}
2001
2002		count = 0;
2003		do {
2004			n = list->len;
2005			x += list->xOff;
2006			y += list->yOff;
2007			while (n--) {
2008				GlyphPtr g = *glyphs++;
2009				const void *ptr;
2010
2011				if (!glyph_valid(g))
2012					goto next_pglyph;
2013
2014				ptr = pixman_glyph_cache_lookup(cache, g, NULL);
2015				if (ptr == NULL) {
2016					pixman_image_t *glyph_image;
2017
2018					glyph_image = sna_glyph_get_image(g, screen);
2019					if (glyph_image == NULL)
2020						goto next_pglyph;
2021
2022					ptr = pixman_glyph_cache_insert(cache, g, NULL,
2023									g->info.x,
2024									g->info.y,
2025									glyph_image);
2026					if (ptr == NULL)
2027						goto next_pglyph;
2028				}
2029
2030				pglyphs[count].x = x;
2031				pglyphs[count].y = y;
2032				pglyphs[count].glyph = ptr;
2033				count++;
2034
2035next_pglyph:
2036				x += g->info.xOff;
2037				y += g->info.yOff;
2038			}
2039			list++;
2040		} while (--nlist);
2041
2042		pixman_composite_glyphs_no_mask(PIXMAN_OP_ADD,
2043						sna->render.white_image,
2044						mask_image,
2045						0, 0,
2046						0, 0,
2047						cache, count, pglyphs);
2048		pixman_glyph_cache_thaw(cache);
2049		if (pglyphs != stack_glyphs)
2050			free(pglyphs);
2051	} else
2052#endif
2053		do {
2054			int n = list->len;
2055			x += list->xOff;
2056			y += list->yOff;
2057			while (n--) {
2058				GlyphPtr g = *glyphs++;
2059				pixman_image_t *glyph_image;
2060				int16_t xi, yi;
2061
2062				if (!glyph_valid(g))
2063					goto next_image;
2064
2065				/* If the mask has been cropped, it is likely
2066				 * that some of the glyphs fall outside.
2067				 */
2068				xi = x - g->info.x;
2069				yi = y - g->info.y;
2070				if (xi >= width || yi >= height)
2071					goto next_image;
2072				if (xi + g->info.width  <= 0 ||
2073				    yi + g->info.height <= 0)
2074					goto next_image;
2075
2076				glyph_image =
2077					sna_glyph_get_image(g, dst->pDrawable->pScreen);
2078				if (glyph_image == NULL)
2079					goto next_image;
2080
2081				DBG(("%s: glyph to mask (%d, %d)x(%d, %d)\n",
2082				     __FUNCTION__,
2083				     xi, yi,
2084				     g->info.width,
2085				     g->info.height));
2086
2087				if (list->format == format) {
2088					assert(pixman_image_get_format(glyph_image) == pixman_image_get_format(mask_image));
2089					pixman_image_composite(PictOpAdd,
2090							       glyph_image,
2091							       NULL,
2092							       mask_image,
2093							       0, 0,
2094							       0, 0,
2095							       xi, yi,
2096							       g->info.width,
2097							       g->info.height);
2098				} else {
2099					pixman_image_composite(PictOpAdd,
2100							       sna->render.white_image,
2101							       glyph_image,
2102							       mask_image,
2103							       0, 0,
2104							       0, 0,
2105							       xi, yi,
2106							       g->info.width,
2107							       g->info.height);
2108				}
2109
2110next_image:
2111				x += g->info.xOff;
2112				y += g->info.yOff;
2113			}
2114			list++;
2115		} while (--nlist);
2116	pixman_image_unref(mask_image);
2117
2118	component_alpha = NeedsComponent(format->format);
2119
2120	mask = CreatePicture(0, &pixmap->drawable,
2121			     format, CPComponentAlpha,
2122			     &component_alpha, serverClient, &error);
2123	if (!mask)
2124		goto err_pixmap;
2125
2126	ValidatePicture(mask);
2127
2128	sna_composite(op,
2129		      src, mask, dst,
2130		      src_x, src_y,
2131		      0, 0,
2132		      box.x1, box.y1,
2133		      width, height);
2134	FreePicture(mask, 0);
2135	ret = true;
2136err_pixmap:
2137	sna_pixmap_destroy(pixmap);
2138	return ret;
2139}
2140
2141void
2142sna_glyphs__shared(CARD8 op,
2143		   PicturePtr src,
2144		   PicturePtr dst,
2145		   PictFormatPtr mask,
2146		   INT16 src_x, INT16 src_y,
2147		   int nlist, GlyphListPtr list, GlyphPtr *glyphs)
2148{
2149	PixmapPtr pixmap = get_drawable_pixmap(dst->pDrawable);
2150	struct sna *sna = to_sna_from_pixmap(pixmap);
2151	struct sna_pixmap *priv;
2152
2153	DBG(("%s(op=%d, nlist=%d, src=(%d, %d))\n",
2154	     __FUNCTION__, op, nlist, src_x, src_y));
2155
2156	if (REGION_NUM_RECTS(dst->pCompositeClip) == 0)
2157		return;
2158
2159	if (FALLBACK)
2160		goto fallback;
2161
2162	if (!can_render(sna)) {
2163		DBG(("%s: wedged\n", __FUNCTION__));
2164		goto fallback;
2165	}
2166
2167	if (dst->alphaMap) {
2168		DBG(("%s: fallback -- dst alpha map\n", __FUNCTION__));
2169		goto fallback;
2170	}
2171
2172	priv = sna_pixmap(pixmap);
2173	if (priv == NULL) {
2174		DBG(("%s: fallback -- destination unattached\n", __FUNCTION__));
2175		goto fallback;
2176	}
2177
2178	if ((too_small(priv) || DAMAGE_IS_ALL(priv->cpu_damage)) &&
2179	    !picture_is_gpu(sna, src)) {
2180		DBG(("%s: fallback -- too small (%dx%d)\n",
2181		     __FUNCTION__, dst->pDrawable->width, dst->pDrawable->height));
2182		goto fallback;
2183	}
2184
2185	if (!mask) {
2186		mask = glyphs_format(nlist, list, glyphs);
2187		DBG(("%s: substituting mask? %d\n", __FUNCTION__, mask!=NULL));
2188	}
2189	if (mask) {
2190		if (glyphs_via_image(sna, op,
2191				     src, dst, mask,
2192				     src_x, src_y,
2193				     nlist, list, glyphs))
2194			return;
2195	}
2196
2197fallback:
2198	glyphs_fallback(op, src, dst, mask, src_x, src_y, nlist, list, glyphs);
2199}
2200
2201void
2202sna_glyph_unrealize(ScreenPtr screen, GlyphPtr glyph)
2203{
2204	struct sna_glyph *p = sna_glyph(glyph);
2205
2206	DBG(("%s: screen=%d, glyph(image?=%d, atlas?=%d)\n",
2207	     __FUNCTION__, screen->myNum, !!p->image, !!p->atlas));
2208
2209	if (p->image) {
2210#if HAS_PIXMAN_GLYPHS
2211		struct sna *sna = to_sna_from_screen(screen);
2212		if (sna->render.glyph_cache)
2213			pixman_glyph_cache_remove(sna->render.glyph_cache,
2214						  glyph, NULL);
2215#endif
2216		pixman_image_unref(p->image);
2217		p->image = NULL;
2218	}
2219
2220	if (p->atlas && p->atlas != GetGlyphPicture(glyph, screen)) {
2221		struct sna *sna = to_sna_from_screen(screen);
2222		struct sna_glyph_cache *cache = &sna->render.glyph[p->pos&1];
2223		DBG(("%s: releasing glyph pos %d from cache %d\n",
2224		     __FUNCTION__, p->pos >> 1, p->pos & 1));
2225		assert(cache->glyphs[p->pos >> 1] == p);
2226		cache->glyphs[p->pos >> 1] = NULL;
2227		p->atlas = NULL;
2228	}
2229}
2230