Line data Source code
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 :
40 : static pixman_bool_t
41 0 : general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
42 : {
43 0 : pixman_image_t *image = iter->image;
44 :
45 0 : if (image->type == LINEAR)
46 0 : _pixman_linear_gradient_iter_init (image, iter);
47 0 : else if (image->type == RADIAL)
48 0 : _pixman_radial_gradient_iter_init (image, iter);
49 0 : else if (image->type == CONICAL)
50 0 : _pixman_conical_gradient_iter_init (image, iter);
51 0 : else if (image->type == BITS)
52 0 : _pixman_bits_image_src_iter_init (image, iter);
53 0 : else if (image->type == SOLID)
54 : _pixman_log_error (FUNC, "Solid image not handled by noop");
55 : else
56 : _pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
57 :
58 0 : return TRUE;
59 : }
60 :
61 : static pixman_bool_t
62 0 : general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter)
63 : {
64 0 : if (iter->image->type == BITS)
65 : {
66 0 : _pixman_bits_image_dest_iter_init (iter->image, iter);
67 :
68 0 : return TRUE;
69 : }
70 : else
71 : {
72 : _pixman_log_error (FUNC, "Trying to write to a non-writable image");
73 :
74 0 : return FALSE;
75 : }
76 : }
77 :
78 : typedef struct op_info_t op_info_t;
79 : struct op_info_t
80 : {
81 : uint8_t src, dst;
82 : };
83 :
84 : #define ITER_IGNORE_BOTH \
85 : (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
86 :
87 : static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
88 : {
89 : /* Src Dst */
90 : { ITER_IGNORE_BOTH, ITER_IGNORE_BOTH }, /* CLEAR */
91 : { ITER_LOCALIZED_ALPHA, ITER_IGNORE_BOTH }, /* SRC */
92 : { ITER_IGNORE_BOTH, ITER_LOCALIZED_ALPHA }, /* DST */
93 : { 0, ITER_LOCALIZED_ALPHA }, /* OVER */
94 : { ITER_LOCALIZED_ALPHA, 0 }, /* OVER_REVERSE */
95 : { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* IN */
96 : { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* IN_REVERSE */
97 : { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* OUT */
98 : { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* OUT_REVERSE */
99 : { 0, 0 }, /* ATOP */
100 : { 0, 0 }, /* ATOP_REVERSE */
101 : { 0, 0 }, /* XOR */
102 : { ITER_LOCALIZED_ALPHA, ITER_LOCALIZED_ALPHA }, /* ADD */
103 : { 0, 0 }, /* SATURATE */
104 : };
105 :
106 : #define SCANLINE_BUFFER_LENGTH 8192
107 :
108 : static void
109 0 : general_composite_rect (pixman_implementation_t *imp,
110 : pixman_composite_info_t *info)
111 : {
112 0 : PIXMAN_COMPOSITE_ARGS (info);
113 : uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
114 0 : uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
115 : uint8_t *src_buffer, *mask_buffer, *dest_buffer;
116 : pixman_iter_t src_iter, mask_iter, dest_iter;
117 : pixman_combine_32_func_t compose;
118 : pixman_bool_t component_alpha;
119 : iter_flags_t narrow, src_iter_flags;
120 : iter_flags_t rgb16;
121 : int Bpp;
122 : int i;
123 :
124 0 : if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
125 0 : (!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) &&
126 0 : (dest_image->common.flags & FAST_PATH_NARROW_FORMAT))
127 : {
128 0 : narrow = ITER_NARROW;
129 0 : Bpp = 4;
130 : }
131 : else
132 : {
133 0 : narrow = 0;
134 0 : Bpp = 16;
135 : }
136 :
137 : // XXX: This special casing is bad. Ideally, we'd keep the general code general perhaps
138 : // by having it deal more specifically with different intermediate formats
139 0 : if (
140 0 : (dest_image->common.flags & FAST_PATH_16_FORMAT && (src_image->type == LINEAR || src_image->type == RADIAL)) &&
141 0 : ( op == PIXMAN_OP_SRC ||
142 0 : (op == PIXMAN_OP_OVER && (src_image->common.flags & FAST_PATH_IS_OPAQUE))
143 : )
144 : ) {
145 0 : rgb16 = ITER_16;
146 : } else {
147 0 : rgb16 = 0;
148 : }
149 :
150 :
151 0 : if (width * Bpp > SCANLINE_BUFFER_LENGTH)
152 : {
153 0 : scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
154 :
155 0 : if (!scanline_buffer)
156 0 : return;
157 : }
158 :
159 0 : src_buffer = scanline_buffer;
160 0 : mask_buffer = src_buffer + width * Bpp;
161 0 : dest_buffer = mask_buffer + width * Bpp;
162 :
163 0 : if (!narrow)
164 : {
165 : /* To make sure there aren't any NANs in the buffers */
166 0 : memset (src_buffer, 0, width * Bpp);
167 0 : memset (mask_buffer, 0, width * Bpp);
168 0 : memset (dest_buffer, 0, width * Bpp);
169 : }
170 :
171 : /* src iter */
172 0 : src_iter_flags = narrow | op_flags[op].src | rgb16;
173 :
174 0 : _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image,
175 : src_x, src_y, width, height,
176 : src_buffer, src_iter_flags, info->src_flags);
177 :
178 : /* mask iter */
179 0 : if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
180 : (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
181 : {
182 : /* If it doesn't matter what the source is, then it doesn't matter
183 : * what the mask is
184 : */
185 0 : mask_image = NULL;
186 : }
187 :
188 0 : component_alpha =
189 0 : mask_image &&
190 0 : mask_image->common.type == BITS &&
191 0 : mask_image->common.component_alpha &&
192 0 : PIXMAN_FORMAT_RGB (mask_image->bits.format);
193 :
194 0 : _pixman_implementation_src_iter_init (
195 : imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height,
196 0 : mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags);
197 :
198 : /* dest iter */
199 0 : _pixman_implementation_dest_iter_init (
200 : imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height,
201 0 : dest_buffer, narrow | op_flags[op].dst | rgb16, info->dest_flags);
202 :
203 0 : compose = _pixman_implementation_lookup_combiner (
204 : imp->toplevel, op, component_alpha, narrow, !!rgb16);
205 :
206 0 : for (i = 0; i < height; ++i)
207 : {
208 : uint32_t *s, *m, *d;
209 :
210 0 : m = mask_iter.get_scanline (&mask_iter, NULL);
211 0 : s = src_iter.get_scanline (&src_iter, m);
212 0 : d = dest_iter.get_scanline (&dest_iter, NULL);
213 :
214 0 : compose (imp->toplevel, op, d, s, m, width);
215 :
216 0 : dest_iter.write_back (&dest_iter);
217 : }
218 :
219 0 : if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
220 0 : free (scanline_buffer);
221 : }
222 :
223 : static const pixman_fast_path_t general_fast_path[] =
224 : {
225 : { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
226 : { PIXMAN_OP_NONE }
227 : };
228 :
229 : pixman_implementation_t *
230 1 : _pixman_implementation_create_general (void)
231 : {
232 1 : pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
233 :
234 1 : _pixman_setup_combiner_functions_16 (imp);
235 1 : _pixman_setup_combiner_functions_32 (imp);
236 1 : _pixman_setup_combiner_functions_float (imp);
237 :
238 1 : imp->src_iter_init = general_src_iter_init;
239 1 : imp->dest_iter_init = general_dest_iter_init;
240 :
241 1 : return imp;
242 : }
243 :
|