Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1891 serge 1
/*
2
 * Copyright © 2009 Red Hat, Inc.
3
 * Copyright © 2000 SuSE, Inc.
4
 * Copyright © 2007 Red Hat, Inc.
5
 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
6
 *             2005 Lars Knoll & Zack Rusin, Trolltech
7
 *             2008 Aaron Plattner, NVIDIA Corporation
8
 *
9
 * Permission to use, copy, modify, distribute, and sell this software and its
10
 * documentation for any purpose is hereby granted without fee, provided that
11
 * the above copyright notice appear in all copies and that both that
12
 * copyright notice and this permission notice appear in supporting
13
 * documentation, and that the name of Red Hat not be used in advertising or
14
 * publicity pertaining to distribution of the software without specific,
15
 * written prior permission.  Red Hat makes no representations about the
16
 * suitability of this software for any purpose.  It is provided "as is"
17
 * without express or implied warranty.
18
 *
19
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
25
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26
 * SOFTWARE.
27
 */
28
#ifdef HAVE_CONFIG_H
29
#include 
30
#endif
31
#include 
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
#include 
38
#include "pixman-private.h"
39
#include "pixman-combine32.h"
40
#include "pixman-private.h"
41
 
42
#define SCANLINE_BUFFER_LENGTH 8192
43
 
44
static void
45
general_composite_rect  (pixman_implementation_t *imp,
46
                         pixman_op_t              op,
47
                         pixman_image_t *         src,
48
                         pixman_image_t *         mask,
49
                         pixman_image_t *         dest,
50
                         int32_t                  src_x,
51
                         int32_t                  src_y,
52
                         int32_t                  mask_x,
53
                         int32_t                  mask_y,
54
                         int32_t                  dest_x,
55
                         int32_t                  dest_y,
56
                         int32_t                  width,
57
                         int32_t                  height)
58
{
59
    uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
60
    uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
61
    uint8_t *src_buffer, *mask_buffer, *dest_buffer;
62
    fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
63
    pixman_combine_32_func_t compose;
64
    store_scanline_t store;
65
    source_image_class_t src_class, mask_class;
66
    pixman_bool_t component_alpha;
67
    uint32_t *bits;
68
    int32_t stride;
69
    int narrow, Bpp;
70
    int i;
71
 
72
    narrow =
73
	(src->common.flags & FAST_PATH_NARROW_FORMAT)		&&
74
	(!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT)	&&
75
	(dest->common.flags & FAST_PATH_NARROW_FORMAT);
76
    Bpp = narrow ? 4 : 8;
77
 
78
    if (width * Bpp > SCANLINE_BUFFER_LENGTH)
79
    {
80
	scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
81
 
82
	if (!scanline_buffer)
83
	    return;
84
    }
85
 
86
    src_buffer = scanline_buffer;
87
    mask_buffer = src_buffer + width * Bpp;
88
    dest_buffer = mask_buffer + width * Bpp;
89
 
90
    src_class = _pixman_image_classify (src,
91
                                        src_x, src_y,
92
                                        width, height);
93
 
94
    mask_class = SOURCE_IMAGE_CLASS_UNKNOWN;
95
 
96
    if (mask)
97
    {
98
	mask_class = _pixman_image_classify (mask,
99
	                                     src_x, src_y,
100
	                                     width, height);
101
    }
102
 
103
    if (op == PIXMAN_OP_CLEAR)
104
	fetch_src = NULL;
105
    else if (narrow)
106
	fetch_src = _pixman_image_get_scanline_32;
107
    else
108
	fetch_src = _pixman_image_get_scanline_64;
109
 
110
    if (!mask || op == PIXMAN_OP_CLEAR)
111
	fetch_mask = NULL;
112
    else if (narrow)
113
	fetch_mask = _pixman_image_get_scanline_32;
114
    else
115
	fetch_mask = _pixman_image_get_scanline_64;
116
 
117
    if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
118
	fetch_dest = NULL;
119
    else if (narrow)
120
	fetch_dest = _pixman_image_get_scanline_32;
121
    else
122
	fetch_dest = _pixman_image_get_scanline_64;
123
 
124
    if (narrow)
125
	store = _pixman_image_store_scanline_32;
126
    else
127
	store = _pixman_image_store_scanline_64;
128
 
129
    /* Skip the store step and composite directly into the
130
     * destination if the output format of the compose func matches
131
     * the destination format.
132
     *
133
     * If the destination format is a8r8g8b8 then we can always do
134
     * this. If it is x8r8g8b8, then we can only do it if the
135
     * operator doesn't make use of destination alpha.
136
     */
137
    if ((dest->bits.format == PIXMAN_a8r8g8b8)	||
138
	(dest->bits.format == PIXMAN_x8r8g8b8	&&
139
	 (op == PIXMAN_OP_OVER		||
140
	  op == PIXMAN_OP_ADD		||
141
	  op == PIXMAN_OP_SRC		||
142
	  op == PIXMAN_OP_CLEAR		||
143
	  op == PIXMAN_OP_IN_REVERSE	||
144
	  op == PIXMAN_OP_OUT_REVERSE	||
145
	  op == PIXMAN_OP_DST)))
146
    {
147
	if (narrow &&
148
	    !dest->common.alpha_map &&
149
	    !dest->bits.write_func)
150
	{
151
	    store = NULL;
152
	}
153
    }
154
 
155
    if (!store)
156
    {
157
	bits = dest->bits.bits;
158
	stride = dest->bits.rowstride;
159
    }
160
    else
161
    {
162
	bits = NULL;
163
	stride = 0;
164
    }
165
 
166
    component_alpha =
167
        fetch_src                       &&
168
        fetch_mask                      &&
169
        mask                            &&
170
        mask->common.type == BITS       &&
171
        mask->common.component_alpha    &&
172
        PIXMAN_FORMAT_RGB (mask->bits.format);
173
 
174
    if (narrow)
175
    {
176
	if (component_alpha)
177
	    compose = _pixman_implementation_combine_32_ca;
178
	else
179
	    compose = _pixman_implementation_combine_32;
180
    }
181
    else
182
    {
183
	if (component_alpha)
184
	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
185
	else
186
	    compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
187
    }
188
 
189
    if (!compose)
190
	return;
191
 
192
    if (!fetch_mask)
193
	mask_buffer = NULL;
194
 
195
    for (i = 0; i < height; ++i)
196
    {
197
	/* fill first half of scanline with source */
198
	if (fetch_src)
199
	{
200
	    if (fetch_mask)
201
	    {
202
		/* fetch mask before source so that fetching of
203
		   source can be optimized */
204
		fetch_mask (mask, mask_x, mask_y + i,
205
		            width, (void *)mask_buffer, 0);
206
 
207
		if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
208
		    fetch_mask = NULL;
209
	    }
210
 
211
	    if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
212
	    {
213
		fetch_src (src, src_x, src_y + i,
214
		           width, (void *)src_buffer, 0);
215
		fetch_src = NULL;
216
	    }
217
	    else
218
	    {
219
		fetch_src (src, src_x, src_y + i,
220
		           width, (void *)src_buffer, (void *)mask_buffer);
221
	    }
222
	}
223
	else if (fetch_mask)
224
	{
225
	    fetch_mask (mask, mask_x, mask_y + i,
226
	                width, (void *)mask_buffer, 0);
227
	}
228
 
229
	if (store)
230
	{
231
	    /* fill dest into second half of scanline */
232
	    if (fetch_dest)
233
	    {
234
		fetch_dest (dest, dest_x, dest_y + i,
235
		            width, (void *)dest_buffer, 0);
236
	    }
237
 
238
	    /* blend */
239
	    compose (imp->toplevel, op,
240
		     (void *)dest_buffer,
241
		     (void *)src_buffer,
242
		     (void *)mask_buffer,
243
		     width);
244
 
245
	    /* write back */
246
	    store (&(dest->bits), dest_x, dest_y + i, width,
247
	           (void *)dest_buffer);
248
	}
249
	else
250
	{
251
	    /* blend */
252
	    compose (imp->toplevel, op,
253
		     bits + (dest_y + i) * stride + dest_x,
254
	             (void *)src_buffer, (void *)mask_buffer, width);
255
	}
256
    }
257
 
258
    if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
259
	free (scanline_buffer);
260
}
261
 
262
static const pixman_fast_path_t general_fast_path[] =
263
{
264
    { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any,	0, PIXMAN_any, 0, general_composite_rect },
265
    { PIXMAN_OP_NONE }
266
};
267
 
268
static pixman_bool_t
269
general_blt (pixman_implementation_t *imp,
270
             uint32_t *               src_bits,
271
             uint32_t *               dst_bits,
272
             int                      src_stride,
273
             int                      dst_stride,
274
             int                      src_bpp,
275
             int                      dst_bpp,
276
             int                      src_x,
277
             int                      src_y,
278
             int                      dst_x,
279
             int                      dst_y,
280
             int                      width,
281
             int                      height)
282
{
283
    /* We can't blit unless we have sse2 or mmx */
284
 
285
    return FALSE;
286
}
287
 
288
static pixman_bool_t
289
general_fill (pixman_implementation_t *imp,
290
              uint32_t *               bits,
291
              int                      stride,
292
              int                      bpp,
293
              int                      x,
294
              int                      y,
295
              int                      width,
296
              int                      height,
297
              uint32_t xor)
298
{
299
    return FALSE;
300
}
301
 
302
pixman_implementation_t *
303
_pixman_implementation_create_general (void)
304
{
305
    pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
306
 
307
    _pixman_setup_combiner_functions_32 (imp);
308
    _pixman_setup_combiner_functions_64 (imp);
309
 
310
    imp->blt = general_blt;
311
    imp->fill = general_fill;
312
 
313
    return imp;
314
}
315