Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1891 serge 1
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2
/*
3
 * Copyright © 2000 SuSE, Inc.
4
 * Copyright © 2007 Red Hat, 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 SuSE not be used in advertising or
11
 * publicity pertaining to distribution of the software without specific,
12
 * written prior permission.  SuSE 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
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
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
 * Author:  Keith Packard, SuSE, Inc.
24
 */
25
 
26
#ifdef HAVE_CONFIG_H
27
#include 
28
#endif
29
#include "pixman-private.h"
30
 
31
#include 
32
 
33
static force_inline pixman_implementation_t *
34
get_implementation (void)
35
{
36
    static pixman_implementation_t *global_implementation;
37
 
38
    if (!global_implementation)
39
	global_implementation = _pixman_choose_implementation ();
40
 
41
    return global_implementation;
42
}
43
 
44
typedef struct operator_info_t operator_info_t;
45
 
46
struct operator_info_t
47
{
48
    uint8_t	opaque_info[4];
49
};
50
 
51
#define PACK(neither, src, dest, both)			\
52
    {{	    (uint8_t)PIXMAN_OP_ ## neither,		\
53
	    (uint8_t)PIXMAN_OP_ ## src,			\
54
	    (uint8_t)PIXMAN_OP_ ## dest,		\
55
	    (uint8_t)PIXMAN_OP_ ## both		}}
56
 
57
static const operator_info_t operator_table[] =
58
{
59
    /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
60
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
61
    PACK (SRC,                   SRC,                   SRC,                   SRC),
62
    PACK (DST,                   DST,                   DST,                   DST),
63
    PACK (OVER,                  SRC,                   OVER,                  SRC),
64
    PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
65
    PACK (IN,                    IN,                    SRC,                   SRC),
66
    PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
67
    PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
68
    PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
69
    PACK (ATOP,                  IN,                    OVER,                  SRC),
70
    PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
71
    PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
72
    PACK (ADD,                   ADD,                   ADD,                   ADD),
73
    PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
74
 
75
    {{ 0 /* 0x0e */ }},
76
    {{ 0 /* 0x0f */ }},
77
 
78
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
79
    PACK (SRC,                   SRC,                   SRC,                   SRC),
80
    PACK (DST,                   DST,                   DST,                   DST),
81
    PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
82
    PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
83
    PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
84
    PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
85
    PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
86
    PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
87
    PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
88
    PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
89
    PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
90
 
91
    {{ 0 /* 0x1c */ }},
92
    {{ 0 /* 0x1d */ }},
93
    {{ 0 /* 0x1e */ }},
94
    {{ 0 /* 0x1f */ }},
95
 
96
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
97
    PACK (SRC,                   SRC,                   SRC,                   SRC),
98
    PACK (DST,                   DST,                   DST,                   DST),
99
    PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
100
    PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
101
    PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
102
    PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
103
    PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
104
    PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
105
    PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
106
    PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
107
    PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
108
 
109
    {{ 0 /* 0x2c */ }},
110
    {{ 0 /* 0x2d */ }},
111
    {{ 0 /* 0x2e */ }},
112
    {{ 0 /* 0x2f */ }},
113
 
114
    PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
115
    PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
116
    PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
117
    PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
118
    PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
119
    PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
120
    PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
121
    PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
122
    PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
123
    PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
124
    PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
125
    PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
126
    PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
127
    PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
128
    PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
129
};
130
 
131
/*
132
 * Optimize the current operator based on opacity of source or destination
133
 * The output operator should be mathematically equivalent to the source.
134
 */
135
static pixman_op_t
136
optimize_operator (pixman_op_t     op,
137
		   uint32_t        src_flags,
138
		   uint32_t        mask_flags,
139
		   uint32_t        dst_flags)
140
{
141
    pixman_bool_t is_source_opaque, is_dest_opaque;
142
 
143
#define OPAQUE_SHIFT 13
144
 
145
    COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
146
 
147
    is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
148
    is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
149
 
150
    is_dest_opaque >>= OPAQUE_SHIFT - 1;
151
    is_source_opaque >>= OPAQUE_SHIFT;
152
 
153
    return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
154
}
155
 
156
static void
157
apply_workaround (pixman_image_t *image,
158
		  int32_t *       x,
159
		  int32_t *       y,
160
		  uint32_t **     save_bits,
161
		  int *           save_dx,
162
		  int *           save_dy)
163
{
164
    if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
165
    {
166
	/* Some X servers generate images that point to the
167
	 * wrong place in memory, but then set the clip region
168
	 * to point to the right place. Because of an old bug
169
	 * in pixman, this would actually work.
170
	 *
171
	 * Here we try and undo the damage
172
	 */
173
	int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
174
	pixman_box32_t *extents;
175
	uint8_t *t;
176
	int dx, dy;
177
 
178
	extents = pixman_region32_extents (&(image->common.clip_region));
179
	dx = extents->x1;
180
	dy = extents->y1;
181
 
182
	*save_bits = image->bits.bits;
183
 
184
	*x -= dx;
185
	*y -= dy;
186
	pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
187
 
188
	t = (uint8_t *)image->bits.bits;
189
	t += dy * image->bits.rowstride * 4 + dx * bpp;
190
	image->bits.bits = (uint32_t *)t;
191
 
192
	*save_dx = dx;
193
	*save_dy = dy;
194
    }
195
}
196
 
197
static void
198
unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
199
{
200
    if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
201
    {
202
	image->bits.bits = bits;
203
	pixman_region32_translate (&image->common.clip_region, dx, dy);
204
    }
205
}
206
 
207
/*
208
 * Computing composite region
209
 */
210
static inline pixman_bool_t
211
clip_general_image (pixman_region32_t * region,
212
                    pixman_region32_t * clip,
213
                    int                 dx,
214
                    int                 dy)
215
{
216
    if (pixman_region32_n_rects (region) == 1 &&
217
        pixman_region32_n_rects (clip) == 1)
218
    {
219
	pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
220
	pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
221
	int v;
222
 
223
	if (rbox->x1 < (v = cbox->x1 + dx))
224
	    rbox->x1 = v;
225
	if (rbox->x2 > (v = cbox->x2 + dx))
226
	    rbox->x2 = v;
227
	if (rbox->y1 < (v = cbox->y1 + dy))
228
	    rbox->y1 = v;
229
	if (rbox->y2 > (v = cbox->y2 + dy))
230
	    rbox->y2 = v;
231
	if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
232
	{
233
	    pixman_region32_init (region);
234
	    return FALSE;
235
	}
236
    }
237
    else if (!pixman_region32_not_empty (clip))
238
    {
239
	return FALSE;
240
    }
241
    else
242
    {
243
	if (dx || dy)
244
	    pixman_region32_translate (region, -dx, -dy);
245
 
246
	if (!pixman_region32_intersect (region, region, clip))
247
	    return FALSE;
248
 
249
	if (dx || dy)
250
	    pixman_region32_translate (region, dx, dy);
251
    }
252
 
253
    return pixman_region32_not_empty (region);
254
}
255
 
256
static inline pixman_bool_t
257
clip_source_image (pixman_region32_t * region,
258
                   pixman_image_t *    image,
259
                   int                 dx,
260
                   int                 dy)
261
{
262
    /* Source clips are ignored, unless they are explicitly turned on
263
     * and the clip in question was set by an X client. (Because if
264
     * the clip was not set by a client, then it is a hierarchy
265
     * clip and those should always be ignored for sources).
266
     */
267
    if (!image->common.clip_sources || !image->common.client_clip)
268
	return TRUE;
269
 
270
    return clip_general_image (region,
271
                               &image->common.clip_region,
272
                               dx, dy);
273
}
274
 
275
/*
276
 * returns FALSE if the final region is empty.  Indistinguishable from
277
 * an allocation failure, but rendering ignores those anyways.
278
 */
279
static pixman_bool_t
280
pixman_compute_composite_region32 (pixman_region32_t * region,
281
                                   pixman_image_t *    src_image,
282
                                   pixman_image_t *    mask_image,
283
                                   pixman_image_t *    dst_image,
284
                                   int32_t             src_x,
285
                                   int32_t             src_y,
286
                                   int32_t             mask_x,
287
                                   int32_t             mask_y,
288
                                   int32_t             dest_x,
289
                                   int32_t             dest_y,
290
                                   int32_t             width,
291
                                   int32_t             height)
292
{
293
    region->extents.x1 = dest_x;
294
    region->extents.x2 = dest_x + width;
295
    region->extents.y1 = dest_y;
296
    region->extents.y2 = dest_y + height;
297
 
298
    region->extents.x1 = MAX (region->extents.x1, 0);
299
    region->extents.y1 = MAX (region->extents.y1, 0);
300
    region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
301
    region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
302
 
303
    region->data = 0;
304
 
305
    /* Check for empty operation */
306
    if (region->extents.x1 >= region->extents.x2 ||
307
        region->extents.y1 >= region->extents.y2)
308
    {
309
	region->extents.x1 = 0;
310
	region->extents.x2 = 0;
311
	region->extents.y1 = 0;
312
	region->extents.y2 = 0;
313
	return FALSE;
314
    }
315
 
316
    if (dst_image->common.have_clip_region)
317
    {
318
	if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
319
	    return FALSE;
320
    }
321
 
322
    if (dst_image->common.alpha_map)
323
    {
324
	if (!pixman_region32_intersect_rect (region, region,
325
					     dst_image->common.alpha_origin_x,
326
					     dst_image->common.alpha_origin_y,
327
					     dst_image->common.alpha_map->width,
328
					     dst_image->common.alpha_map->height))
329
	{
330
	    return FALSE;
331
	}
332
	if (!pixman_region32_not_empty (region))
333
	    return FALSE;
334
	if (dst_image->common.alpha_map->common.have_clip_region)
335
	{
336
	    if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
337
				     -dst_image->common.alpha_origin_x,
338
				     -dst_image->common.alpha_origin_y))
339
	    {
340
		return FALSE;
341
	    }
342
	}
343
    }
344
 
345
    /* clip against src */
346
    if (src_image->common.have_clip_region)
347
    {
348
	if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
349
	    return FALSE;
350
    }
351
    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
352
    {
353
	if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
354
	                        dest_x - (src_x - src_image->common.alpha_origin_x),
355
	                        dest_y - (src_y - src_image->common.alpha_origin_y)))
356
	{
357
	    return FALSE;
358
	}
359
    }
360
    /* clip against mask */
361
    if (mask_image && mask_image->common.have_clip_region)
362
    {
363
	if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
364
	    return FALSE;
365
 
366
	if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
367
	{
368
	    if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
369
	                            dest_x - (mask_x - mask_image->common.alpha_origin_x),
370
	                            dest_y - (mask_y - mask_image->common.alpha_origin_y)))
371
	    {
372
		return FALSE;
373
	    }
374
	}
375
    }
376
 
377
    return TRUE;
378
}
379
 
380
#define N_CACHED_FAST_PATHS 8
381
 
382
typedef struct
383
{
384
    struct
385
    {
386
	pixman_implementation_t *	imp;
387
	pixman_fast_path_t		fast_path;
388
    } cache [N_CACHED_FAST_PATHS];
389
} cache_t;
390
 
391
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
392
 
393
static force_inline pixman_bool_t
394
lookup_composite_function (pixman_op_t			op,
395
			   pixman_format_code_t		src_format,
396
			   uint32_t			src_flags,
397
			   pixman_format_code_t		mask_format,
398
			   uint32_t			mask_flags,
399
			   pixman_format_code_t		dest_format,
400
			   uint32_t			dest_flags,
401
			   pixman_implementation_t    **out_imp,
402
			   pixman_composite_func_t     *out_func)
403
{
404
    pixman_implementation_t *imp;
405
    cache_t *cache;
406
    int i;
407
 
408
    /* Check cache for fast paths */
409
    cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
410
 
411
    for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
412
    {
413
	const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
414
 
415
	/* Note that we check for equality here, not whether
416
	 * the cached fast path matches. This is to prevent
417
	 * us from selecting an overly general fast path
418
	 * when a more specific one would work.
419
	 */
420
	if (info->op == op			&&
421
	    info->src_format == src_format	&&
422
	    info->mask_format == mask_format	&&
423
	    info->dest_format == dest_format	&&
424
	    info->src_flags == src_flags	&&
425
	    info->mask_flags == mask_flags	&&
426
	    info->dest_flags == dest_flags	&&
427
	    info->func)
428
	{
429
	    *out_imp = cache->cache[i].imp;
430
	    *out_func = cache->cache[i].fast_path.func;
431
 
432
	    goto update_cache;
433
	}
434
    }
435
 
436
    for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
437
    {
438
	const pixman_fast_path_t *info = imp->fast_paths;
439
 
440
	while (info->op != PIXMAN_OP_NONE)
441
	{
442
	    if ((info->op == op || info->op == PIXMAN_OP_any)		&&
443
		/* Formats */
444
		((info->src_format == src_format) ||
445
		 (info->src_format == PIXMAN_any))			&&
446
		((info->mask_format == mask_format) ||
447
		 (info->mask_format == PIXMAN_any))			&&
448
		((info->dest_format == dest_format) ||
449
		 (info->dest_format == PIXMAN_any))			&&
450
		/* Flags */
451
		(info->src_flags & src_flags) == info->src_flags	&&
452
		(info->mask_flags & mask_flags) == info->mask_flags	&&
453
		(info->dest_flags & dest_flags) == info->dest_flags)
454
	    {
455
		*out_imp = imp;
456
		*out_func = info->func;
457
 
458
		/* Set i to the last spot in the cache so that the
459
		 * move-to-front code below will work
460
		 */
461
		i = N_CACHED_FAST_PATHS - 1;
462
 
463
		goto update_cache;
464
	    }
465
 
466
	    ++info;
467
	}
468
    }
469
    return FALSE;
470
 
471
update_cache:
472
    if (i)
473
    {
474
	while (i--)
475
	    cache->cache[i + 1] = cache->cache[i];
476
 
477
	cache->cache[0].imp = *out_imp;
478
	cache->cache[0].fast_path.op = op;
479
	cache->cache[0].fast_path.src_format = src_format;
480
	cache->cache[0].fast_path.src_flags = src_flags;
481
	cache->cache[0].fast_path.mask_format = mask_format;
482
	cache->cache[0].fast_path.mask_flags = mask_flags;
483
	cache->cache[0].fast_path.dest_format = dest_format;
484
	cache->cache[0].fast_path.dest_flags = dest_flags;
485
	cache->cache[0].fast_path.func = *out_func;
486
    }
487
 
488
    return TRUE;
489
}
490
 
491
static pixman_bool_t
492
compute_sample_extents (pixman_transform_t *transform,
493
			pixman_box32_t *extents, int x, int y,
494
			pixman_fixed_t x_off, pixman_fixed_t y_off,
495
			pixman_fixed_t width, pixman_fixed_t height)
496
{
497
    pixman_fixed_t x1, y1, x2, y2;
498
    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
499
 
500
    /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
501
    x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
502
    y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
503
    x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
504
    y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
505
 
506
    if (!transform)
507
    {
508
	tx1 = (pixman_fixed_48_16_t)x1;
509
	ty1 = (pixman_fixed_48_16_t)y1;
510
	tx2 = (pixman_fixed_48_16_t)x2;
511
	ty2 = (pixman_fixed_48_16_t)y2;
512
    }
513
    else
514
    {
515
	int i;
516
 
517
	/* Silence GCC */
518
	tx1 = ty1 = tx2 = ty2 = 0;
519
 
520
	for (i = 0; i < 4; ++i)
521
	{
522
	    pixman_fixed_48_16_t tx, ty;
523
	    pixman_vector_t v;
524
 
525
	    v.vector[0] = (i & 0x01)? x1 : x2;
526
	    v.vector[1] = (i & 0x02)? y1 : y2;
527
	    v.vector[2] = pixman_fixed_1;
528
 
529
	    if (!pixman_transform_point (transform, &v))
530
		return FALSE;
531
 
532
	    tx = (pixman_fixed_48_16_t)v.vector[0];
533
	    ty = (pixman_fixed_48_16_t)v.vector[1];
534
 
535
	    if (i == 0)
536
	    {
537
		tx1 = tx;
538
		ty1 = ty;
539
		tx2 = tx;
540
		ty2 = ty;
541
	    }
542
	    else
543
	    {
544
		if (tx < tx1)
545
		    tx1 = tx;
546
		if (ty < ty1)
547
		    ty1 = ty;
548
		if (tx > tx2)
549
		    tx2 = tx;
550
		if (ty > ty2)
551
		    ty2 = ty;
552
	    }
553
	}
554
    }
555
 
556
    /* Expand the source area by a tiny bit so account of different rounding that
557
     * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
558
     * 0.5 so this won't cause the area computed to be overly pessimistic.
559
     */
560
    tx1 += x_off - 8 * pixman_fixed_e;
561
    ty1 += y_off - 8 * pixman_fixed_e;
562
    tx2 += x_off + width + 8 * pixman_fixed_e;
563
    ty2 += y_off + height + 8 * pixman_fixed_e;
564
 
565
    if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
566
	ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
567
	tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
568
	ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
569
    {
570
	return FALSE;
571
    }
572
    else
573
    {
574
	extents->x1 = pixman_fixed_to_int (tx1);
575
	extents->y1 = pixman_fixed_to_int (ty1);
576
	extents->x2 = pixman_fixed_to_int (tx2) + 1;
577
	extents->y2 = pixman_fixed_to_int (ty2) + 1;
578
 
579
	return TRUE;
580
    }
581
}
582
 
583
#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
584
 
585
static pixman_bool_t
586
analyze_extent (pixman_image_t *image, int x, int y,
587
		const pixman_box32_t *extents, uint32_t *flags)
588
{
589
    pixman_transform_t *transform;
590
    pixman_fixed_t *params;
591
    pixman_fixed_t x_off, y_off;
592
    pixman_fixed_t width, height;
593
    pixman_box32_t ex;
594
 
595
    if (!image)
596
	return TRUE;
597
 
598
    /* Some compositing functions walk one step
599
     * outside the destination rectangle, so we
600
     * check here that the expanded-by-one source
601
     * extents in destination space fits in 16 bits
602
     */
603
    if (!IS_16BIT (extents->x1 - x - 1)		||
604
	!IS_16BIT (extents->y1 - y - 1)		||
605
	!IS_16BIT (extents->x2 - x + 1)		||
606
	!IS_16BIT (extents->y2 - y + 1))
607
    {
608
	return FALSE;
609
    }
610
 
611
    transform = image->common.transform;
612
    if (image->common.type == BITS)
613
    {
614
	/* During repeat mode calculations we might convert the
615
	 * width/height of an image to fixed 16.16, so we need
616
	 * them to be smaller than 16 bits.
617
	 */
618
	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
619
	    return FALSE;
620
 
621
#define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER)
622
 
623
	if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST &&
624
	    extents->x1 - x >= 0 &&
625
	    extents->y1 - y >= 0 &&
626
	    extents->x2 - x <= image->bits.width &&
627
	    extents->y2 - y <= image->bits.height)
628
	{
629
	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
630
	    return TRUE;
631
	}
632
 
633
	switch (image->common.filter)
634
	{
635
	case PIXMAN_FILTER_CONVOLUTION:
636
	    params = image->common.filter_params;
637
	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
638
	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
639
	    width = params[0];
640
	    height = params[1];
641
	    break;
642
 
643
	case PIXMAN_FILTER_GOOD:
644
	case PIXMAN_FILTER_BEST:
645
	case PIXMAN_FILTER_BILINEAR:
646
	    x_off = - pixman_fixed_1 / 2;
647
	    y_off = - pixman_fixed_1 / 2;
648
	    width = pixman_fixed_1;
649
	    height = pixman_fixed_1;
650
	    break;
651
 
652
	case PIXMAN_FILTER_FAST:
653
	case PIXMAN_FILTER_NEAREST:
654
	    x_off = - pixman_fixed_e;
655
	    y_off = - pixman_fixed_e;
656
	    width = 0;
657
	    height = 0;
658
	    break;
659
 
660
	default:
661
	    return FALSE;
662
	}
663
 
664
	/* Check whether the non-expanded, transformed extent is entirely within
665
	 * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
666
	 */
667
	ex = *extents;
668
	if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) &&
669
	    ex.x1 >= 0 && ex.y1 >= 0 &&
670
	    ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
671
	{
672
	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
673
	}
674
    }
675
    else
676
    {
677
	x_off = 0;
678
	y_off = 0;
679
	width = 0;
680
	height = 0;
681
    }
682
 
683
    /* Check that the extents expanded by one don't overflow. This ensures that
684
     * compositing functions can simply walk the source space using 16.16
685
     * variables without worrying about overflow.
686
     */
687
    ex.x1 = extents->x1 - 1;
688
    ex.y1 = extents->y1 - 1;
689
    ex.x2 = extents->x2 + 1;
690
    ex.y2 = extents->y2 + 1;
691
 
692
    if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
693
	return FALSE;
694
 
695
    return TRUE;
696
}
697
 
698
/*
699
 * Work around GCC bug causing crashes in Mozilla with SSE2
700
 *
701
 * When using -msse, gcc generates movdqa instructions assuming that
702
 * the stack is 16 byte aligned. Unfortunately some applications, such
703
 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
704
 * causes the movdqa instructions to fail.
705
 *
706
 * The __force_align_arg_pointer__ makes gcc generate a prologue that
707
 * realigns the stack pointer to 16 bytes.
708
 *
709
 * On x86-64 this is not necessary because the standard ABI already
710
 * calls for a 16 byte aligned stack.
711
 *
712
 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
713
 */
714
#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
715
__attribute__((__force_align_arg_pointer__))
716
#endif
717
PIXMAN_EXPORT void
718
pixman_image_composite32 (pixman_op_t      op,
719
                          pixman_image_t * src,
720
                          pixman_image_t * mask,
721
                          pixman_image_t * dest,
722
                          int32_t          src_x,
723
                          int32_t          src_y,
724
                          int32_t          mask_x,
725
                          int32_t          mask_y,
726
                          int32_t          dest_x,
727
                          int32_t          dest_y,
728
                          int32_t          width,
729
                          int32_t          height)
730
{
731
    pixman_format_code_t src_format, mask_format, dest_format;
732
    uint32_t src_flags, mask_flags, dest_flags;
733
    pixman_region32_t region;
734
    pixman_box32_t *extents;
735
    uint32_t *src_bits;
736
    int src_dx, src_dy;
737
    uint32_t *mask_bits;
738
    int mask_dx, mask_dy;
739
    uint32_t *dest_bits;
740
    int dest_dx, dest_dy;
741
    pixman_bool_t need_workaround;
742
    pixman_implementation_t *imp;
743
    pixman_composite_func_t func;
744
 
745
    _pixman_image_validate (src);
746
    if (mask)
747
	_pixman_image_validate (mask);
748
    _pixman_image_validate (dest);
749
 
750
    src_format = src->common.extended_format_code;
751
    src_flags = src->common.flags;
752
 
753
    if (mask)
754
    {
755
	mask_format = mask->common.extended_format_code;
756
	mask_flags = mask->common.flags;
757
    }
758
    else
759
    {
760
	mask_format = PIXMAN_null;
761
	mask_flags = FAST_PATH_IS_OPAQUE;
762
    }
763
 
764
    dest_format = dest->common.extended_format_code;
765
    dest_flags = dest->common.flags;
766
 
767
    /* Check for pixbufs */
768
    if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
769
	(src->type == BITS && src->bits.bits == mask->bits.bits)	   &&
770
	(src->common.repeat == mask->common.repeat)			   &&
771
	(src_x == mask_x && src_y == mask_y))
772
    {
773
	if (src_format == PIXMAN_x8b8g8r8)
774
	    src_format = mask_format = PIXMAN_pixbuf;
775
	else if (src_format == PIXMAN_x8r8g8b8)
776
	    src_format = mask_format = PIXMAN_rpixbuf;
777
    }
778
 
779
    /* Check for workaround */
780
    need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
781
 
782
    if (need_workaround)
783
    {
784
	apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
785
	apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
786
	apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
787
    }
788
 
789
    pixman_region32_init (®ion);
790
 
791
    if (!pixman_compute_composite_region32 (
792
	    ®ion, src, mask, dest,
793
	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
794
    {
795
	goto out;
796
    }
797
 
798
    extents = pixman_region32_extents (®ion);
799
 
800
    if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
801
	goto out;
802
 
803
    if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
804
	goto out;
805
 
806
    /* If the clip is within the source samples, and the samples are opaque,
807
     * then the source is effectively opaque.
808
     */
809
#define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP)
810
 
811
    if ((src_flags & BOTH) == BOTH)
812
	src_flags |= FAST_PATH_IS_OPAQUE;
813
 
814
    if ((mask_flags & BOTH) == BOTH)
815
	mask_flags |= FAST_PATH_IS_OPAQUE;
816
 
817
    /*
818
     * Check if we can replace our operator by a simpler one
819
     * if the src or dest are opaque. The output operator should be
820
     * mathematically equivalent to the source.
821
     */
822
    op = optimize_operator (op, src_flags, mask_flags, dest_flags);
823
    if (op == PIXMAN_OP_DST)
824
	goto out;
825
 
826
    if (lookup_composite_function (op,
827
				   src_format, src_flags,
828
				   mask_format, mask_flags,
829
				   dest_format, dest_flags,
830
				   &imp, &func))
831
    {
832
	const pixman_box32_t *pbox;
833
	int n;
834
 
835
	pbox = pixman_region32_rectangles (®ion, &n);
836
 
837
	while (n--)
838
	{
839
	    func (imp, op,
840
		  src, mask, dest,
841
		  pbox->x1 + src_x - dest_x,
842
		  pbox->y1 + src_y - dest_y,
843
		  pbox->x1 + mask_x - dest_x,
844
		  pbox->y1 + mask_y - dest_y,
845
		  pbox->x1,
846
		  pbox->y1,
847
		  pbox->x2 - pbox->x1,
848
		  pbox->y2 - pbox->y1);
849
 
850
	    pbox++;
851
	}
852
    }
853
 
854
out:
855
    if (need_workaround)
856
    {
857
	unapply_workaround (src, src_bits, src_dx, src_dy);
858
	unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
859
	unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
860
    }
861
 
862
    pixman_region32_fini (®ion);
863
}
864
 
865
PIXMAN_EXPORT void
866
pixman_image_composite (pixman_op_t      op,
867
                        pixman_image_t * src,
868
                        pixman_image_t * mask,
869
                        pixman_image_t * dest,
870
                        int16_t          src_x,
871
                        int16_t          src_y,
872
                        int16_t          mask_x,
873
                        int16_t          mask_y,
874
                        int16_t          dest_x,
875
                        int16_t          dest_y,
876
                        uint16_t         width,
877
                        uint16_t         height)
878
{
879
    pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
880
                              mask_x, mask_y, dest_x, dest_y, width, height);
881
}
882
 
883
PIXMAN_EXPORT pixman_bool_t
884
pixman_blt (uint32_t *src_bits,
885
            uint32_t *dst_bits,
886
            int       src_stride,
887
            int       dst_stride,
888
            int       src_bpp,
889
            int       dst_bpp,
890
            int       src_x,
891
            int       src_y,
892
            int       dst_x,
893
            int       dst_y,
894
            int       width,
895
            int       height)
896
{
897
    return _pixman_implementation_blt (get_implementation(),
898
				       src_bits, dst_bits, src_stride, dst_stride,
899
                                       src_bpp, dst_bpp,
900
                                       src_x, src_y,
901
                                       dst_x, dst_y,
902
                                       width, height);
903
}
904
 
905
PIXMAN_EXPORT pixman_bool_t
906
pixman_fill (uint32_t *bits,
907
             int       stride,
908
             int       bpp,
909
             int       x,
910
             int       y,
911
             int       width,
912
             int       height,
913
             uint32_t xor)
914
{
915
    return _pixman_implementation_fill (
916
	get_implementation(), bits, stride, bpp, x, y, width, height, xor);
917
}
918
 
919
static uint32_t
920
color_to_uint32 (const pixman_color_t *color)
921
{
922
    return
923
        (color->alpha >> 8 << 24) |
924
        (color->red >> 8 << 16) |
925
        (color->green & 0xff00) |
926
        (color->blue >> 8);
927
}
928
 
929
static pixman_bool_t
930
color_to_pixel (pixman_color_t *     color,
931
                uint32_t *           pixel,
932
                pixman_format_code_t format)
933
{
934
    uint32_t c = color_to_uint32 (color);
935
 
936
    if (!(format == PIXMAN_a8r8g8b8     ||
937
          format == PIXMAN_x8r8g8b8     ||
938
          format == PIXMAN_a8b8g8r8     ||
939
          format == PIXMAN_x8b8g8r8     ||
940
          format == PIXMAN_b8g8r8a8     ||
941
          format == PIXMAN_b8g8r8x8     ||
942
          format == PIXMAN_r5g6b5       ||
943
          format == PIXMAN_b5g6r5       ||
944
          format == PIXMAN_a8))
945
    {
946
	return FALSE;
947
    }
948
 
949
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
950
    {
951
	c = ((c & 0xff000000) >>  0) |
952
	    ((c & 0x00ff0000) >> 16) |
953
	    ((c & 0x0000ff00) >>  0) |
954
	    ((c & 0x000000ff) << 16);
955
    }
956
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
957
    {
958
	c = ((c & 0xff000000) >> 24) |
959
	    ((c & 0x00ff0000) >>  8) |
960
	    ((c & 0x0000ff00) <<  8) |
961
	    ((c & 0x000000ff) << 24);
962
    }
963
 
964
    if (format == PIXMAN_a8)
965
	c = c >> 24;
966
    else if (format == PIXMAN_r5g6b5 ||
967
             format == PIXMAN_b5g6r5)
968
	c = CONVERT_8888_TO_0565 (c);
969
 
970
#if 0
971
    printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
972
    printf ("pixel: %x\n", c);
973
#endif
974
 
975
    *pixel = c;
976
    return TRUE;
977
}
978
 
979
PIXMAN_EXPORT pixman_bool_t
980
pixman_image_fill_rectangles (pixman_op_t                 op,
981
                              pixman_image_t *            dest,
982
                              pixman_color_t *            color,
983
                              int                         n_rects,
984
                              const pixman_rectangle16_t *rects)
985
{
986
    pixman_box32_t stack_boxes[6];
987
    pixman_box32_t *boxes;
988
    pixman_bool_t result;
989
    int i;
990
 
991
    if (n_rects > 6)
992
    {
993
        boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
994
        if (boxes == NULL)
995
            return FALSE;
996
    }
997
    else
998
    {
999
        boxes = stack_boxes;
1000
    }
1001
 
1002
    for (i = 0; i < n_rects; ++i)
1003
    {
1004
        boxes[i].x1 = rects[i].x;
1005
        boxes[i].y1 = rects[i].y;
1006
        boxes[i].x2 = boxes[i].x1 + rects[i].width;
1007
        boxes[i].y2 = boxes[i].y1 + rects[i].height;
1008
    }
1009
 
1010
    result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
1011
 
1012
    if (boxes != stack_boxes)
1013
        free (boxes);
1014
 
1015
    return result;
1016
}
1017
 
1018
PIXMAN_EXPORT pixman_bool_t
1019
pixman_image_fill_boxes (pixman_op_t           op,
1020
                         pixman_image_t *      dest,
1021
                         pixman_color_t *      color,
1022
                         int                   n_boxes,
1023
                         const pixman_box32_t *boxes)
1024
{
1025
    pixman_image_t *solid;
1026
    pixman_color_t c;
1027
    int i;
1028
 
1029
    _pixman_image_validate (dest);
1030
 
1031
    if (color->alpha == 0xffff)
1032
    {
1033
        if (op == PIXMAN_OP_OVER)
1034
            op = PIXMAN_OP_SRC;
1035
    }
1036
 
1037
    if (op == PIXMAN_OP_CLEAR)
1038
    {
1039
        c.red = 0;
1040
        c.green = 0;
1041
        c.blue = 0;
1042
        c.alpha = 0;
1043
 
1044
        color = &c;
1045
 
1046
        op = PIXMAN_OP_SRC;
1047
    }
1048
 
1049
    if (op == PIXMAN_OP_SRC)
1050
    {
1051
        uint32_t pixel;
1052
 
1053
        if (color_to_pixel (color, &pixel, dest->bits.format))
1054
        {
1055
            pixman_region32_t fill_region;
1056
            int n_rects, j;
1057
            pixman_box32_t *rects;
1058
 
1059
            if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
1060
                return FALSE;
1061
 
1062
            if (dest->common.have_clip_region)
1063
            {
1064
                if (!pixman_region32_intersect (&fill_region,
1065
                                                &fill_region,
1066
                                                &dest->common.clip_region))
1067
                    return FALSE;
1068
            }
1069
 
1070
            rects = pixman_region32_rectangles (&fill_region, &n_rects);
1071
            for (j = 0; j < n_rects; ++j)
1072
            {
1073
                const pixman_box32_t *rect = &(rects[j]);
1074
                pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
1075
                             rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
1076
                             pixel);
1077
            }
1078
 
1079
            pixman_region32_fini (&fill_region);
1080
            return TRUE;
1081
        }
1082
    }
1083
 
1084
    solid = pixman_image_create_solid_fill (color);
1085
    if (!solid)
1086
        return FALSE;
1087
 
1088
    for (i = 0; i < n_boxes; ++i)
1089
    {
1090
        const pixman_box32_t *box = &(boxes[i]);
1091
 
1092
        pixman_image_composite32 (op, solid, NULL, dest,
1093
                                  0, 0, 0, 0,
1094
                                  box->x1, box->y1,
1095
                                  box->x2 - box->x1, box->y2 - box->y1);
1096
    }
1097
 
1098
    pixman_image_unref (solid);
1099
 
1100
    return TRUE;
1101
}
1102
 
1103
/**
1104
 * pixman_version:
1105
 *
1106
 * Returns the version of the pixman library encoded in a single
1107
 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1108
 * later versions compare greater than earlier versions.
1109
 *
1110
 * A run-time comparison to check that pixman's version is greater than
1111
 * or equal to version X.Y.Z could be performed as follows:
1112
 *
1113
 * 
1114
 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1115
 * 
1116
 *
1117
 * See also pixman_version_string() as well as the compile-time
1118
 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1119
 *
1120
 * Return value: the encoded version.
1121
 **/
1122
PIXMAN_EXPORT int
1123
pixman_version (void)
1124
{
1125
    return PIXMAN_VERSION;
1126
}
1127
 
1128
/**
1129
 * pixman_version_string:
1130
 *
1131
 * Returns the version of the pixman library as a human-readable string
1132
 * of the form "X.Y.Z".
1133
 *
1134
 * See also pixman_version() as well as the compile-time equivalents
1135
 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1136
 *
1137
 * Return value: a string containing the version.
1138
 **/
1139
PIXMAN_EXPORT const char*
1140
pixman_version_string (void)
1141
{
1142
    return PIXMAN_VERSION_STRING;
1143
}
1144
 
1145
/**
1146
 * pixman_format_supported_source:
1147
 * @format: A pixman_format_code_t format
1148
 *
1149
 * Return value: whether the provided format code is a supported
1150
 * format for a pixman surface used as a source in
1151
 * rendering.
1152
 *
1153
 * Currently, all pixman_format_code_t values are supported.
1154
 **/
1155
PIXMAN_EXPORT pixman_bool_t
1156
pixman_format_supported_source (pixman_format_code_t format)
1157
{
1158
    switch (format)
1159
    {
1160
    /* 32 bpp formats */
1161
    case PIXMAN_a2b10g10r10:
1162
    case PIXMAN_x2b10g10r10:
1163
    case PIXMAN_a2r10g10b10:
1164
    case PIXMAN_x2r10g10b10:
1165
    case PIXMAN_a8r8g8b8:
1166
    case PIXMAN_x8r8g8b8:
1167
    case PIXMAN_a8b8g8r8:
1168
    case PIXMAN_x8b8g8r8:
1169
    case PIXMAN_b8g8r8a8:
1170
    case PIXMAN_b8g8r8x8:
1171
    case PIXMAN_r8g8b8:
1172
    case PIXMAN_b8g8r8:
1173
    case PIXMAN_r5g6b5:
1174
    case PIXMAN_b5g6r5:
1175
    case PIXMAN_x14r6g6b6:
1176
    /* 16 bpp formats */
1177
    case PIXMAN_a1r5g5b5:
1178
    case PIXMAN_x1r5g5b5:
1179
    case PIXMAN_a1b5g5r5:
1180
    case PIXMAN_x1b5g5r5:
1181
    case PIXMAN_a4r4g4b4:
1182
    case PIXMAN_x4r4g4b4:
1183
    case PIXMAN_a4b4g4r4:
1184
    case PIXMAN_x4b4g4r4:
1185
    /* 8bpp formats */
1186
    case PIXMAN_a8:
1187
    case PIXMAN_r3g3b2:
1188
    case PIXMAN_b2g3r3:
1189
    case PIXMAN_a2r2g2b2:
1190
    case PIXMAN_a2b2g2r2:
1191
    case PIXMAN_c8:
1192
    case PIXMAN_g8:
1193
    case PIXMAN_x4a4:
1194
    /* Collides with PIXMAN_c8
1195
       case PIXMAN_x4c4:
1196
     */
1197
    /* Collides with PIXMAN_g8
1198
       case PIXMAN_x4g4:
1199
     */
1200
    /* 4bpp formats */
1201
    case PIXMAN_a4:
1202
    case PIXMAN_r1g2b1:
1203
    case PIXMAN_b1g2r1:
1204
    case PIXMAN_a1r1g1b1:
1205
    case PIXMAN_a1b1g1r1:
1206
    case PIXMAN_c4:
1207
    case PIXMAN_g4:
1208
    /* 1bpp formats */
1209
    case PIXMAN_a1:
1210
    case PIXMAN_g1:
1211
    /* YUV formats */
1212
    case PIXMAN_yuy2:
1213
    case PIXMAN_yv12:
1214
	return TRUE;
1215
 
1216
    default:
1217
	return FALSE;
1218
    }
1219
}
1220
 
1221
/**
1222
 * pixman_format_supported_destination:
1223
 * @format: A pixman_format_code_t format
1224
 *
1225
 * Return value: whether the provided format code is a supported
1226
 * format for a pixman surface used as a destination in
1227
 * rendering.
1228
 *
1229
 * Currently, all pixman_format_code_t values are supported
1230
 * except for the YUV formats.
1231
 **/
1232
PIXMAN_EXPORT pixman_bool_t
1233
pixman_format_supported_destination (pixman_format_code_t format)
1234
{
1235
    /* YUV formats cannot be written to at the moment */
1236
    if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1237
	return FALSE;
1238
 
1239
    return pixman_format_supported_source (format);
1240
}
1241
 
1242
PIXMAN_EXPORT pixman_bool_t
1243
pixman_compute_composite_region (pixman_region16_t * region,
1244
                                 pixman_image_t *    src_image,
1245
                                 pixman_image_t *    mask_image,
1246
                                 pixman_image_t *    dst_image,
1247
                                 int16_t             src_x,
1248
                                 int16_t             src_y,
1249
                                 int16_t             mask_x,
1250
                                 int16_t             mask_y,
1251
                                 int16_t             dest_x,
1252
                                 int16_t             dest_y,
1253
                                 uint16_t            width,
1254
                                 uint16_t            height)
1255
{
1256
    pixman_region32_t r32;
1257
    pixman_bool_t retval;
1258
 
1259
    pixman_region32_init (&r32);
1260
 
1261
    retval = pixman_compute_composite_region32 (
1262
	&r32, src_image, mask_image, dst_image,
1263
	src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1264
	width, height);
1265
 
1266
    if (retval)
1267
    {
1268
	if (!pixman_region16_copy_from_region32 (region, &r32))
1269
	    retval = FALSE;
1270
    }
1271
 
1272
    pixman_region32_fini (&r32);
1273
    return retval;
1274
}