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
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.
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
37 #include "pixman-private.h"
38 #include "pixman-vmx.h"
39 #include "pixman-arm-simd.h"
40 #include "pixman-combine32.h"
41 #include "pixman-private.h"
45 general_combine_32 (pixman_implementation_t *imp, pixman_op_t op,
46 uint32_t *dest, const uint32_t *src, const uint32_t *mask,
49 CombineFunc32 f = pixman_composeFunctions.combineU[op];
51 f (dest, src, mask, width);
55 general_combine_32_ca (pixman_implementation_t *imp, pixman_op_t op,
56 uint32_t *dest, const uint32_t *src, const uint32_t *mask,
59 CombineFunc32 f = pixman_composeFunctions.combineC[op];
61 f (dest, src, mask, width);
65 general_combine_64 (pixman_implementation_t *imp, pixman_op_t op,
66 uint64_t *dest, const uint64_t *src, const uint64_t *mask,
69 CombineFunc64 f = pixman_composeFunctions64.combineU[op];
71 f (dest, src, mask, width);
75 general_combine_64_ca (pixman_implementation_t *imp, pixman_op_t op,
76 uint64_t *dest, const uint64_t *src, const uint64_t *mask,
79 CombineFunc64 f = pixman_composeFunctions64.combineC[op];
81 f (dest, src, mask, width);
84 #define SCANLINE_BUFFER_LENGTH 8192
87 general_composite_rect (pixman_implementation_t *imp,
101 return_if_fail (src != NULL);
102 return_if_fail (dest != NULL);
104 uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
105 const pixman_format_code_t srcFormat = src->type == BITS ? src->bits.format : 0;
106 const pixman_format_code_t maskFormat = mask && mask->type == BITS ? mask->bits.format : 0;
107 const pixman_format_code_t destFormat = dest->type == BITS ? dest->bits.format : 0;
108 const int srcWide = PIXMAN_FORMAT_16BPC(srcFormat);
109 const int maskWide = mask && PIXMAN_FORMAT_16BPC(maskFormat);
110 const int destWide = PIXMAN_FORMAT_16BPC(destFormat);
111 const int wide = srcWide || maskWide || destWide;
112 const int Bpp = wide ? 8 : 4;
113 uint8_t *scanline_buffer = stack_scanline_buffer;
114 uint8_t *src_buffer, *mask_buffer, *dest_buffer;
115 scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
116 pixman_combine_32_func_t compose;
118 source_pict_class_t srcClass, maskClass;
119 pixman_bool_t component_alpha;
124 if (width * Bpp > SCANLINE_BUFFER_LENGTH)
126 scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
128 if (!scanline_buffer)
132 src_buffer = scanline_buffer;
133 mask_buffer = src_buffer + width * Bpp;
134 dest_buffer = mask_buffer + width * Bpp;
136 srcClass = _pixman_image_classify (src,
140 maskClass = SOURCE_IMAGE_CLASS_UNKNOWN;
143 maskClass = _pixman_image_classify (mask,
148 if (op == PIXMAN_OP_CLEAR)
151 fetchSrc = _pixman_image_get_scanline_64;
153 fetchSrc = _pixman_image_get_scanline_32;
155 if (!mask || op == PIXMAN_OP_CLEAR)
158 fetchMask = _pixman_image_get_scanline_64;
160 fetchMask = _pixman_image_get_scanline_32;
162 if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
165 fetchDest = _pixman_image_get_scanline_64;
167 fetchDest = _pixman_image_get_scanline_32;
170 store = _pixman_image_store_scanline_64;
172 store = _pixman_image_store_scanline_32;
174 /* Skip the store step and composite directly into the
175 * destination if the output format of the compose func matches
176 * the destination format.
179 !dest->common.alpha_map &&
180 !dest->common.write_func &&
181 (op == PIXMAN_OP_ADD || op == PIXMAN_OP_OVER) &&
182 (dest->bits.format == PIXMAN_a8r8g8b8 ||
183 dest->bits.format == PIXMAN_x8r8g8b8))
190 bits = dest->bits.bits;
191 stride = dest->bits.rowstride;
203 mask->common.type == BITS &&
204 mask->common.component_alpha &&
205 PIXMAN_FORMAT_RGB (mask->bits.format);
210 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
212 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
217 compose = _pixman_implementation_combine_32_ca;
219 compose = _pixman_implementation_combine_32;
228 for (i = 0; i < height; ++i)
230 /* fill first half of scanline with source */
235 /* fetch mask before source so that fetching of
236 source can be optimized */
237 fetchMask (mask, mask_x, mask_y + i,
238 width, (void *)mask_buffer, 0, 0);
240 if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
244 if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
246 fetchSrc (src, src_x, src_y + i,
247 width, (void *)src_buffer, 0, 0);
252 fetchSrc (src, src_x, src_y + i,
253 width, (void *)src_buffer, (void *)mask_buffer,
259 fetchMask (mask, mask_x, mask_y + i,
260 width, (void *)mask_buffer, 0, 0);
265 /* fill dest into second half of scanline */
267 fetchDest (dest, dest_x, dest_y + i,
268 width, (void *)dest_buffer, 0, 0);
271 compose (imp, op, (void *)dest_buffer, (void *)src_buffer, (void *)mask_buffer, width);
274 store (&(dest->bits), dest_x, dest_y + i, width,
275 (void *)dest_buffer);
280 compose (imp, op, bits + (dest_y + i) * stride +
282 (void *)src_buffer, (void *)mask_buffer, width);
286 if (scanline_buffer != stack_scanline_buffer)
287 free (scanline_buffer);
291 general_composite (pixman_implementation_t * imp,
293 pixman_image_t * src,
294 pixman_image_t * mask,
295 pixman_image_t * dest,
305 pixman_bool_t srcRepeat = src->type == BITS && src->common.repeat == PIXMAN_REPEAT_NORMAL;
306 pixman_bool_t maskRepeat = FALSE;
307 pixman_bool_t srcTransform = src->common.transform != NULL;
308 pixman_bool_t maskTransform = FALSE;
314 if (srcRepeat && srcTransform &&
315 src->bits.width == 1 &&
316 src->bits.height == 1)
318 srcTransform = FALSE;
321 if (mask && mask->type == BITS)
323 maskRepeat = mask->common.repeat == PIXMAN_REPEAT_NORMAL;
325 maskTransform = mask->common.transform != 0;
326 if (mask->common.filter == PIXMAN_FILTER_CONVOLUTION)
327 maskTransform = TRUE;
329 if (maskRepeat && maskTransform &&
330 mask->bits.width == 1 &&
331 mask->bits.height == 1)
333 maskTransform = FALSE;
338 if (_pixman_run_fast_path (vmx_fast_paths, imp,
348 if (pixman_have_arm_neon() && _pixman_run_fast_path (arm_neon_fast_paths, imp,
358 if (pixman_have_arm_simd() && _pixman_run_fast_path (arm_simd_fast_paths, imp,
367 /* CompositeGeneral optimizes 1x1 repeating images itself */
368 if (src->type == BITS &&
369 src->bits.width == 1 && src->bits.height == 1)
374 if (mask && mask->type == BITS &&
375 mask->bits.width == 1 && mask->bits.height == 1)
380 /* if we are transforming, repeats are handled in fbFetchTransformed */
387 _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
388 mask_x, mask_y, dest_x, dest_y, width, height,
389 srcRepeat, maskRepeat, general_composite_rect);
393 general_blt (pixman_implementation_t *imp,
400 int src_x, int src_y,
401 int dst_x, int dst_y,
402 int width, int height)
404 /* We can't blit unless we have sse2 or mmx */
410 general_fill (pixman_implementation_t *imp,
423 pixman_implementation_t *
424 _pixman_implementation_create_general (pixman_implementation_t *toplevel)
426 pixman_implementation_t *imp = _pixman_implementation_create (toplevel, NULL);
429 for (i = 0; i < PIXMAN_OP_LAST; ++i)
431 imp->combine_32[i] = general_combine_32;
432 imp->combine_32_ca[i] = general_combine_32_ca;
433 imp->combine_64[i] = general_combine_64;
434 imp->combine_64_ca[i] = general_combine_64_ca;
436 imp->composite = general_composite;
437 imp->blt = general_blt;
438 imp->fill = general_fill;