~ubuntu-branches/ubuntu/saucy/pixman/saucy-security

« back to all changes in this revision

Viewing changes to pixman/pixman-general.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Cristau
  • Date: 2009-09-28 18:12:47 UTC
  • mfrom: (1.1.8 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090928181247-3iehog63i50htejf
Tags: 0.16.2-1
* New upstream release (closes: #546849).
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <config.h>
 
30
#endif
 
31
#include <stdlib.h>
 
32
#include <string.h>
 
33
#include <math.h>
 
34
#include <limits.h>
 
35
#include <stdio.h>
 
36
#include <stdlib.h>
 
37
#include <string.h>
 
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
    uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
 
60
    const pixman_format_code_t src_format =
 
61
        src->type == BITS ? src->bits.format : 0;
 
62
    const pixman_format_code_t mask_format =
 
63
        mask && mask->type == BITS ? mask->bits.format : 0;
 
64
    const pixman_format_code_t dest_format =
 
65
        dest->type == BITS ? dest->bits.format : 0;
 
66
    const int src_wide = PIXMAN_FORMAT_IS_WIDE (src_format);
 
67
    const int mask_wide = mask && PIXMAN_FORMAT_IS_WIDE (mask_format);
 
68
    const int dest_wide = PIXMAN_FORMAT_IS_WIDE (dest_format);
 
69
    const int wide = src_wide || mask_wide || dest_wide;
 
70
    const int Bpp = wide ? 8 : 4;
 
71
    uint8_t *scanline_buffer = stack_scanline_buffer;
 
72
    uint8_t *src_buffer, *mask_buffer, *dest_buffer;
 
73
    fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
 
74
    pixman_combine_32_func_t compose;
 
75
    store_scanline_t store;
 
76
    source_image_class_t src_class, mask_class;
 
77
    pixman_bool_t component_alpha;
 
78
    uint32_t *bits;
 
79
    int32_t stride;
 
80
    int i;
 
81
 
 
82
    if (width * Bpp > SCANLINE_BUFFER_LENGTH)
 
83
    {
 
84
        scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
 
85
 
 
86
        if (!scanline_buffer)
 
87
            return;
 
88
    }
 
89
 
 
90
    src_buffer = scanline_buffer;
 
91
    mask_buffer = src_buffer + width * Bpp;
 
92
    dest_buffer = mask_buffer + width * Bpp;
 
93
 
 
94
    src_class = _pixman_image_classify (src,
 
95
                                        src_x, src_y,
 
96
                                        width, height);
 
97
 
 
98
    mask_class = SOURCE_IMAGE_CLASS_UNKNOWN;
 
99
 
 
100
    if (mask)
 
101
    {
 
102
        mask_class = _pixman_image_classify (mask,
 
103
                                             src_x, src_y,
 
104
                                             width, height);
 
105
    }
 
106
 
 
107
    if (op == PIXMAN_OP_CLEAR)
 
108
        fetch_src = NULL;
 
109
    else if (wide)
 
110
        fetch_src = _pixman_image_get_scanline_64;
 
111
    else
 
112
        fetch_src = _pixman_image_get_scanline_32;
 
113
 
 
114
    if (!mask || op == PIXMAN_OP_CLEAR)
 
115
        fetch_mask = NULL;
 
116
    else if (wide)
 
117
        fetch_mask = _pixman_image_get_scanline_64;
 
118
    else
 
119
        fetch_mask = _pixman_image_get_scanline_32;
 
120
 
 
121
    if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
 
122
        fetch_dest = NULL;
 
123
    else if (wide)
 
124
        fetch_dest = _pixman_image_get_scanline_64;
 
125
    else
 
126
        fetch_dest = _pixman_image_get_scanline_32;
 
127
 
 
128
    if (wide)
 
129
        store = _pixman_image_store_scanline_64;
 
130
    else
 
131
        store = _pixman_image_store_scanline_32;
 
132
 
 
133
    /* Skip the store step and composite directly into the
 
134
     * destination if the output format of the compose func matches
 
135
     * the destination format.
 
136
     */
 
137
    if (!wide &&
 
138
        !dest->common.alpha_map &&
 
139
        !dest->bits.write_func &&
 
140
        (op == PIXMAN_OP_ADD || op == PIXMAN_OP_OVER) &&
 
141
        (dest->bits.format == PIXMAN_a8r8g8b8 ||
 
142
         dest->bits.format == PIXMAN_x8r8g8b8))
 
143
    {
 
144
        store = NULL;
 
145
    }
 
146
 
 
147
    if (!store)
 
148
    {
 
149
        bits = dest->bits.bits;
 
150
        stride = dest->bits.rowstride;
 
151
    }
 
152
    else
 
153
    {
 
154
        bits = NULL;
 
155
        stride = 0;
 
156
    }
 
157
 
 
158
    component_alpha =
 
159
        fetch_src                       &&
 
160
        fetch_mask                      &&
 
161
        mask                            &&
 
162
        mask->common.type == BITS       &&
 
163
        mask->common.component_alpha    &&
 
164
        PIXMAN_FORMAT_RGB (mask->bits.format);
 
165
 
 
166
    if (wide)
 
167
    {
 
168
        if (component_alpha)
 
169
            compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
 
170
        else
 
171
            compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
 
172
    }
 
173
    else
 
174
    {
 
175
        if (component_alpha)
 
176
            compose = _pixman_implementation_combine_32_ca;
 
177
        else
 
178
            compose = _pixman_implementation_combine_32;
 
179
    }
 
180
 
 
181
    if (!compose)
 
182
        return;
 
183
 
 
184
    if (!fetch_mask)
 
185
        mask_buffer = NULL;
 
186
 
 
187
    for (i = 0; i < height; ++i)
 
188
    {
 
189
        /* fill first half of scanline with source */
 
190
        if (fetch_src)
 
191
        {
 
192
            if (fetch_mask)
 
193
            {
 
194
                /* fetch mask before source so that fetching of
 
195
                   source can be optimized */
 
196
                fetch_mask (mask, mask_x, mask_y + i,
 
197
                            width, (void *)mask_buffer, 0, 0);
 
198
 
 
199
                if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
 
200
                    fetch_mask = NULL;
 
201
            }
 
202
 
 
203
            if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
 
204
            {
 
205
                fetch_src (src, src_x, src_y + i,
 
206
                           width, (void *)src_buffer, 0, 0);
 
207
                fetch_src = NULL;
 
208
            }
 
209
            else
 
210
            {
 
211
                fetch_src (src, src_x, src_y + i,
 
212
                           width, (void *)src_buffer, (void *)mask_buffer,
 
213
                           0xffffffff);
 
214
            }
 
215
        }
 
216
        else if (fetch_mask)
 
217
        {
 
218
            fetch_mask (mask, mask_x, mask_y + i,
 
219
                        width, (void *)mask_buffer, 0, 0);
 
220
        }
 
221
 
 
222
        if (store)
 
223
        {
 
224
            /* fill dest into second half of scanline */
 
225
            if (fetch_dest)
 
226
            {
 
227
                fetch_dest (dest, dest_x, dest_y + i,
 
228
                            width, (void *)dest_buffer, 0, 0);
 
229
            }
 
230
 
 
231
            /* blend */
 
232
            compose (imp->toplevel, op,
 
233
                     (void *)dest_buffer,
 
234
                     (void *)src_buffer,
 
235
                     (void *)mask_buffer,
 
236
                     width);
 
237
 
 
238
            /* write back */
 
239
            store (&(dest->bits), dest_x, dest_y + i, width,
 
240
                   (void *)dest_buffer);
 
241
        }
 
242
        else
 
243
        {
 
244
            /* blend */
 
245
            compose (imp->toplevel, op,
 
246
                     bits + (dest_y + i) * stride + dest_x,
 
247
                     (void *)src_buffer, (void *)mask_buffer, width);
 
248
        }
 
249
    }
 
250
 
 
251
    if (scanline_buffer != stack_scanline_buffer)
 
252
        free (scanline_buffer);
 
253
}
 
254
 
 
255
static void
 
256
general_composite (pixman_implementation_t * imp,
 
257
                   pixman_op_t               op,
 
258
                   pixman_image_t *          src,
 
259
                   pixman_image_t *          mask,
 
260
                   pixman_image_t *          dest,
 
261
                   int32_t                   src_x,
 
262
                   int32_t                   src_y,
 
263
                   int32_t                   mask_x,
 
264
                   int32_t                   mask_y,
 
265
                   int32_t                   dest_x,
 
266
                   int32_t                   dest_y,
 
267
                   int32_t                   width,
 
268
                   int32_t                   height)
 
269
{
 
270
    _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
 
271
                                   mask_x, mask_y, dest_x, dest_y,
 
272
                                   width, height,
 
273
                                   general_composite_rect);
 
274
}
 
275
 
 
276
static pixman_bool_t
 
277
general_blt (pixman_implementation_t *imp,
 
278
             uint32_t *               src_bits,
 
279
             uint32_t *               dst_bits,
 
280
             int                      src_stride,
 
281
             int                      dst_stride,
 
282
             int                      src_bpp,
 
283
             int                      dst_bpp,
 
284
             int                      src_x,
 
285
             int                      src_y,
 
286
             int                      dst_x,
 
287
             int                      dst_y,
 
288
             int                      width,
 
289
             int                      height)
 
290
{
 
291
    /* We can't blit unless we have sse2 or mmx */
 
292
 
 
293
    return FALSE;
 
294
}
 
295
 
 
296
static pixman_bool_t
 
297
general_fill (pixman_implementation_t *imp,
 
298
              uint32_t *               bits,
 
299
              int                      stride,
 
300
              int                      bpp,
 
301
              int                      x,
 
302
              int                      y,
 
303
              int                      width,
 
304
              int                      height,
 
305
              uint32_t xor)
 
306
{
 
307
    return FALSE;
 
308
}
 
309
 
 
310
pixman_implementation_t *
 
311
_pixman_implementation_create_general (void)
 
312
{
 
313
    pixman_implementation_t *imp = _pixman_implementation_create (NULL);
 
314
 
 
315
    _pixman_setup_combiner_functions_32 (imp);
 
316
    _pixman_setup_combiner_functions_64 (imp);
 
317
 
 
318
    imp->composite = general_composite;
 
319
    imp->blt = general_blt;
 
320
    imp->fill = general_fill;
 
321
 
 
322
    return imp;
 
323
}
 
324