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