Subversion Repositories Kolibri OS

Rev

Rev 4349 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * Copyright © 2009 Red Hat, Inc.
3
 *
4
 * Permission to use, copy, modify, distribute, and sell this software and its
5
 * documentation for any purpose is hereby granted without fee, provided that
6
 * the above copyright notice appear in all copies and that both that
7
 * copyright notice and this permission notice appear in supporting
8
 * documentation, and that the name of Red Hat not be used in advertising or
9
 * publicity pertaining to distribution of the software without specific,
10
 * written prior permission.  Red Hat makes no representations about the
11
 * suitability of this software for any purpose.  It is provided "as is"
12
 * without express or implied warranty.
13
 *
14
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
19
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
20
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21
 * SOFTWARE.
22
 */
23
 
24
#ifdef HAVE_CONFIG_H
25
#include 
26
#endif
27
#include 
28
#include "pixman-private.h"
29
 
30
pixman_implementation_t *
31
_pixman_implementation_create (pixman_implementation_t *fallback,
32
			       const pixman_fast_path_t *fast_paths)
33
{
34
    pixman_implementation_t *imp;
35
 
36
    assert (fast_paths);
37
 
38
    if ((imp = malloc (sizeof (pixman_implementation_t))))
39
    {
40
	pixman_implementation_t *d;
41
 
42
	memset (imp, 0, sizeof *imp);
43
 
44
	imp->fallback = fallback;
45
	imp->fast_paths = fast_paths;
46
 
47
	/* Make sure the whole fallback chain has the right toplevel */
48
	for (d = imp; d != NULL; d = d->fallback)
49
	    d->toplevel = imp;
50
    }
51
 
52
    return imp;
53
}
54
 
55
#define N_CACHED_FAST_PATHS 8
56
 
57
typedef struct
58
{
59
    struct
60
    {
61
	pixman_implementation_t *	imp;
62
	pixman_fast_path_t		fast_path;
63
    } cache [N_CACHED_FAST_PATHS];
64
} cache_t;
65
 
66
PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
67
 
68
static void
69
dummy_composite_rect (pixman_implementation_t *imp,
70
		      pixman_composite_info_t *info)
71
{
72
}
73
 
74
void
75
_pixman_implementation_lookup_composite (pixman_implementation_t  *toplevel,
76
					 pixman_op_t               op,
77
					 pixman_format_code_t      src_format,
78
					 uint32_t                  src_flags,
79
					 pixman_format_code_t      mask_format,
80
					 uint32_t                  mask_flags,
81
					 pixman_format_code_t      dest_format,
82
					 uint32_t                  dest_flags,
83
					 pixman_implementation_t **out_imp,
84
					 pixman_composite_func_t  *out_func)
85
{
86
    pixman_implementation_t *imp;
87
    cache_t *cache;
88
    int i;
89
 
90
    /* Check cache for fast paths */
91
    cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
92
 
93
    for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
94
    {
95
	const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
96
 
97
	/* Note that we check for equality here, not whether
98
	 * the cached fast path matches. This is to prevent
99
	 * us from selecting an overly general fast path
100
	 * when a more specific one would work.
101
	 */
102
	if (info->op == op			&&
103
	    info->src_format == src_format	&&
104
	    info->mask_format == mask_format	&&
105
	    info->dest_format == dest_format	&&
106
	    info->src_flags == src_flags	&&
107
	    info->mask_flags == mask_flags	&&
108
	    info->dest_flags == dest_flags	&&
109
	    info->func)
110
	{
111
	    *out_imp = cache->cache[i].imp;
112
	    *out_func = cache->cache[i].fast_path.func;
113
 
114
	    goto update_cache;
115
	}
116
    }
117
 
118
    for (imp = toplevel; imp != NULL; imp = imp->fallback)
119
    {
120
	const pixman_fast_path_t *info = imp->fast_paths;
121
 
122
	while (info->op != PIXMAN_OP_NONE)
123
	{
124
	    if ((info->op == op || info->op == PIXMAN_OP_any)		&&
125
		/* Formats */
126
		((info->src_format == src_format) ||
127
		 (info->src_format == PIXMAN_any))			&&
128
		((info->mask_format == mask_format) ||
129
		 (info->mask_format == PIXMAN_any))			&&
130
		((info->dest_format == dest_format) ||
131
		 (info->dest_format == PIXMAN_any))			&&
132
		/* Flags */
133
		(info->src_flags & src_flags) == info->src_flags	&&
134
		(info->mask_flags & mask_flags) == info->mask_flags	&&
135
		(info->dest_flags & dest_flags) == info->dest_flags)
136
	    {
137
		*out_imp = imp;
138
		*out_func = info->func;
139
 
140
		/* Set i to the last spot in the cache so that the
141
		 * move-to-front code below will work
142
		 */
143
		i = N_CACHED_FAST_PATHS - 1;
144
 
145
		goto update_cache;
146
	    }
147
 
148
	    ++info;
149
	}
150
    }
151
 
152
    /* We should never reach this point */
153
    _pixman_log_error (
154
        FUNC,
155
        "No composite function found\n"
156
        "\n"
157
        "The most likely cause of this is that this system has issues with\n"
158
        "thread local storage\n");
159
 
160
    *out_imp = NULL;
161
    *out_func = dummy_composite_rect;
162
    return;
163
 
164
update_cache:
165
    if (i)
166
    {
167
	while (i--)
168
	    cache->cache[i + 1] = cache->cache[i];
169
 
170
	cache->cache[0].imp = *out_imp;
171
	cache->cache[0].fast_path.op = op;
172
	cache->cache[0].fast_path.src_format = src_format;
173
	cache->cache[0].fast_path.src_flags = src_flags;
174
	cache->cache[0].fast_path.mask_format = mask_format;
175
	cache->cache[0].fast_path.mask_flags = mask_flags;
176
	cache->cache[0].fast_path.dest_format = dest_format;
177
	cache->cache[0].fast_path.dest_flags = dest_flags;
178
	cache->cache[0].fast_path.func = *out_func;
179
    }
180
}
181
 
182
static void
183
dummy_combine (pixman_implementation_t *imp,
184
	       pixman_op_t              op,
185
	       uint32_t *               pd,
186
	       const uint32_t *         ps,
187
	       const uint32_t *         pm,
188
	       int                      w)
189
{
190
}
191
 
192
pixman_combine_32_func_t
193
_pixman_implementation_lookup_combiner (pixman_implementation_t *imp,
194
					pixman_op_t		 op,
195
					pixman_bool_t		 component_alpha,
196
					pixman_bool_t		 narrow)
197
{
198
    while (imp)
199
    {
200
	pixman_combine_32_func_t f = NULL;
201
 
202
	switch ((narrow << 1) | component_alpha)
203
	{
204
	case 0: /* not narrow, not component alpha */
205
	    f = (pixman_combine_32_func_t)imp->combine_float[op];
206
	    break;
207
 
208
	case 1: /* not narrow, component_alpha */
209
	    f = (pixman_combine_32_func_t)imp->combine_float_ca[op];
210
	    break;
211
 
212
	case 2: /* narrow, not component alpha */
213
	    f = imp->combine_32[op];
214
	    break;
215
 
216
	case 3: /* narrow, component_alpha */
217
	    f = imp->combine_32_ca[op];
218
	    break;
219
	}
220
 
221
	if (f)
222
	    return f;
223
 
224
	imp = imp->fallback;
225
    }
226
 
227
    /* We should never reach this point */
228
    _pixman_log_error (FUNC, "No known combine function\n");
229
    return dummy_combine;
230
}
231
 
232
pixman_bool_t
233
_pixman_implementation_blt (pixman_implementation_t * imp,
234
                            uint32_t *                src_bits,
235
                            uint32_t *                dst_bits,
236
                            int                       src_stride,
237
                            int                       dst_stride,
238
                            int                       src_bpp,
239
                            int                       dst_bpp,
240
                            int                       src_x,
241
                            int                       src_y,
242
                            int                       dest_x,
243
                            int                       dest_y,
244
                            int                       width,
245
                            int                       height)
246
{
247
    while (imp)
248
    {
249
	if (imp->blt &&
250
	    (*imp->blt) (imp, src_bits, dst_bits, src_stride, dst_stride,
251
			 src_bpp, dst_bpp, src_x, src_y, dest_x, dest_y,
252
			 width, height))
253
	{
254
	    return TRUE;
255
	}
256
 
257
	imp = imp->fallback;
258
    }
259
 
260
    return FALSE;
261
}
262
 
263
pixman_bool_t
264
_pixman_implementation_fill (pixman_implementation_t *imp,
265
                             uint32_t *               bits,
266
                             int                      stride,
267
                             int                      bpp,
268
                             int                      x,
269
                             int                      y,
270
                             int                      width,
271
                             int                      height,
272
                             uint32_t                 filler)
273
{
274
    while (imp)
275
    {
276
	if (imp->fill &&
277
	    ((*imp->fill) (imp, bits, stride, bpp, x, y, width, height, filler)))
278
	{
279
	    return TRUE;
280
	}
281
 
282
	imp = imp->fallback;
283
    }
284
 
285
    return FALSE;
286
}
287
 
288
pixman_bool_t
289
_pixman_implementation_src_iter_init (pixman_implementation_t	*imp,
290
				      pixman_iter_t             *iter,
291
				      pixman_image_t		*image,
292
				      int			 x,
293
				      int			 y,
294
				      int			 width,
295
				      int			 height,
296
				      uint8_t			*buffer,
297
				      iter_flags_t		 iter_flags,
298
				      uint32_t                   image_flags)
299
{
300
    iter->image = image;
301
    iter->buffer = (uint32_t *)buffer;
302
    iter->x = x;
303
    iter->y = y;
304
    iter->width = width;
305
    iter->height = height;
306
    iter->iter_flags = iter_flags;
307
    iter->image_flags = image_flags;
308
 
309
    while (imp)
310
    {
311
	if (imp->src_iter_init && (*imp->src_iter_init) (imp, iter))
312
	    return TRUE;
313
 
314
	imp = imp->fallback;
315
    }
316
 
317
    return FALSE;
318
}
319
 
320
pixman_bool_t
321
_pixman_implementation_dest_iter_init (pixman_implementation_t	*imp,
322
				       pixman_iter_t            *iter,
323
				       pixman_image_t		*image,
324
				       int			 x,
325
				       int			 y,
326
				       int			 width,
327
				       int			 height,
328
				       uint8_t			*buffer,
329
				       iter_flags_t		 iter_flags,
330
				       uint32_t                  image_flags)
331
{
332
    iter->image = image;
333
    iter->buffer = (uint32_t *)buffer;
334
    iter->x = x;
335
    iter->y = y;
336
    iter->width = width;
337
    iter->height = height;
338
    iter->iter_flags = iter_flags;
339
    iter->image_flags = image_flags;
340
 
341
    while (imp)
342
    {
343
	if (imp->dest_iter_init && (*imp->dest_iter_init) (imp, iter))
344
	    return TRUE;
345
 
346
	imp = imp->fallback;
347
    }
348
 
349
    return FALSE;
350
}
351
 
352
pixman_bool_t
353
_pixman_disabled (const char *name)
354
{
355
    const char *env;
356
 
357
    if ((env = getenv ("PIXMAN_DISABLE")))
358
    {
359
	do
360
	{
361
	    const char *end;
362
	    int len;
363
 
364
	    if ((end = strchr (env, ' ')))
365
		len = end - env;
366
	    else
367
		len = strlen (env);
368
 
369
	    if (strlen (name) == len && strncmp (name, env, len) == 0)
370
	    {
6073 serge 371
        fprintf (stderr, "pixman: Disabled %s implementation\n", name);
4349 Serge 372
		return TRUE;
373
	    }
374
 
375
	    env += len;
376
	}
377
	while (*env++);
378
    }
379
 
380
    return FALSE;
381
}
382
 
383
pixman_implementation_t *
384
_pixman_choose_implementation (void)
385
{
386
    pixman_implementation_t *imp;
387
 
388
    imp = _pixman_implementation_create_general();
389
 
390
    if (!_pixman_disabled ("fast"))
391
        imp = _pixman_implementation_create_fast_path (imp);
392
 
393
    imp = _pixman_x86_get_implementations (imp);
394
 
395
    imp = _pixman_implementation_create_noop (imp);
396
 
397
    return imp;
398
}