3 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
4 * 2005 Lars Knoll & Zack Rusin, Trolltech
5 * 2008 Aaron Plattner, NVIDIA Corporation
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Keith Packard not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Keith Packard makes no
14 * representations about the suitability of this software for any purpose. It
15 * is provided "as is" without express or implied warranty.
17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
37 #include "pixman-private.h"
39 #ifdef PIXMAN_FB_ACCESSORS
40 #define PIXMAN_COMPOSITE_RECT_GENERAL pixman_composite_rect_general_accessors
42 #define PIXMAN_COMPOSITE_RECT_GENERAL pixman_composite_rect_general_no_accessors
45 #ifndef PIXMAN_FB_ACCESSORS
49 PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data,
50 void *src_buffer, void *mask_buffer,
51 void *dest_buffer, const int wide)
55 scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
59 source_pict_class_t srcClass, maskClass;
61 srcClass = _pixman_image_classify (data->src,
62 data->xSrc, data->ySrc,
63 data->width, data->height);
65 maskClass = SOURCE_IMAGE_CLASS_UNKNOWN;
68 maskClass = _pixman_image_classify (data->mask,
69 data->xSrc, data->ySrc,
70 data->width, data->height);
73 if (data->op == PIXMAN_OP_CLEAR)
76 fetchSrc = _pixman_image_get_fetcher (data->src, wide);
78 if (!data->mask || data->op == PIXMAN_OP_CLEAR)
81 fetchMask = _pixman_image_get_fetcher (data->mask, wide);
83 if (data->op == PIXMAN_OP_CLEAR || data->op == PIXMAN_OP_SRC)
86 fetchDest = _pixman_image_get_fetcher (data->dest, wide);
88 store = _pixman_image_get_storer (data->dest, wide);
90 #ifndef PIXMAN_FB_ACCESSORS
91 // Skip the store step and composite directly into the
92 // destination if the output format of the compose func matches
93 // the destination format.
95 !data->dest->common.alpha_map &&
96 (data->op == PIXMAN_OP_ADD || data->op == PIXMAN_OP_OVER) &&
97 (data->dest->bits.format == PIXMAN_a8r8g8b8 ||
98 data->dest->bits.format == PIXMAN_x8r8g8b8))
106 bits = data->dest->bits.bits;
107 stride = data->dest->bits.rowstride;
120 data->mask->common.type == BITS &&
121 data->mask->common.component_alpha &&
122 PIXMAN_FORMAT_RGB (data->mask->bits.format))
124 CombineFuncC32 compose =
125 wide ? (CombineFuncC32)pixman_composeFunctions64.combineC[data->op] :
126 pixman_composeFunctions.combineC[data->op];
130 for (i = 0; i < data->height; ++i) {
131 /* fill first half of scanline with source */
136 /* fetch mask before source so that fetching of
137 source can be optimized */
138 fetchMask (data->mask, data->xMask, data->yMask + i,
139 data->width, mask_buffer, 0, 0);
141 if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
145 if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
147 fetchSrc (data->src, data->xSrc, data->ySrc + i,
148 data->width, src_buffer, 0, 0);
153 fetchSrc (data->src, data->xSrc, data->ySrc + i,
154 data->width, src_buffer, mask_buffer,
160 fetchMask (data->mask, data->xMask, data->yMask + i,
161 data->width, mask_buffer, 0, 0);
166 /* fill dest into second half of scanline */
168 fetchDest (data->dest, data->xDest, data->yDest + i,
169 data->width, dest_buffer, 0, 0);
172 compose (dest_buffer, src_buffer, mask_buffer, data->width);
175 store (data->dest, data->xDest, data->yDest + i, data->width,
181 compose (bits + (data->yDest + i+ yoff) * stride +
183 src_buffer, mask_buffer, data->width);
189 void *src_mask_buffer = 0;
190 const int useMask = (fetchMask != NULL);
191 CombineFuncU32 compose =
192 wide ? (CombineFuncU32)pixman_composeFunctions64.combineU[data->op] :
193 pixman_composeFunctions.combineU[data->op];
197 for (i = 0; i < data->height; ++i) {
198 /* fill first half of scanline with source */
203 /* fetch mask before source so that fetching of
204 source can be optimized */
205 fetchMask (data->mask, data->xMask, data->yMask + i,
206 data->width, mask_buffer, 0, 0);
208 if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
212 if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
214 fetchSrc (data->src, data->xSrc, data->ySrc + i,
215 data->width, src_buffer, 0, 0);
220 pixman_composeFunctions64.combineU[PIXMAN_OP_IN] (mask_buffer, src_buffer, data->width);
222 pixman_composeFunctions.combineU[PIXMAN_OP_IN] (mask_buffer, src_buffer, data->width);
224 src_mask_buffer = mask_buffer;
227 src_mask_buffer = src_buffer;
233 fetchSrc (data->src, data->xSrc, data->ySrc + i,
234 data->width, src_buffer,
235 useMask ? mask_buffer : NULL, 0xff000000);
239 pixman_composeFunctions64.combineMaskU (src_buffer,
243 pixman_composeFunctions.combineMaskU (src_buffer,
248 src_mask_buffer = src_buffer;
253 fetchMask (data->mask, data->xMask, data->yMask + i,
254 data->width, mask_buffer, 0, 0);
257 pixman_composeFunctions64.combineU[PIXMAN_OP_IN] (mask_buffer, src_buffer, data->width);
259 pixman_composeFunctions.combineU[PIXMAN_OP_IN] (mask_buffer, src_buffer, data->width);
261 src_mask_buffer = mask_buffer;
266 /* fill dest into second half of scanline */
268 fetchDest (data->dest, data->xDest, data->yDest + i,
269 data->width, dest_buffer, 0, 0);
272 compose (dest_buffer, src_mask_buffer, data->width);
275 store (data->dest, data->xDest, data->yDest + i, data->width,
281 compose (bits + (data->yDest + i+ yoff) * stride +
283 src_mask_buffer, data->width);
289 #ifndef PIXMAN_FB_ACCESSORS
291 #define SCANLINE_BUFFER_LENGTH 8192
294 pixman_composite_rect_general (const FbComposeData *data)
296 uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
297 const pixman_format_code_t srcFormat = data->src->type == BITS ? data->src->bits.format : 0;
298 const pixman_format_code_t maskFormat = data->mask && data->mask->type == BITS ? data->mask->bits.format : 0;
299 const pixman_format_code_t destFormat = data->dest->type == BITS ? data->dest->bits.format : 0;
300 const int srcWide = PIXMAN_FORMAT_16BPC(srcFormat);
301 const int maskWide = data->mask && PIXMAN_FORMAT_16BPC(maskFormat);
302 const int destWide = PIXMAN_FORMAT_16BPC(destFormat);
303 const int wide = srcWide || maskWide || destWide;
304 const int Bpp = wide ? 8 : 4;
305 uint8_t *scanline_buffer = stack_scanline_buffer;
306 uint8_t *src_buffer, *mask_buffer, *dest_buffer;
308 if (data->width * Bpp > SCANLINE_BUFFER_LENGTH)
310 scanline_buffer = pixman_malloc_abc (data->width, 3, Bpp);
312 if (!scanline_buffer)
316 src_buffer = scanline_buffer;
317 mask_buffer = src_buffer + data->width * Bpp;
318 dest_buffer = mask_buffer + data->width * Bpp;
320 if (data->src->common.read_func ||
321 data->src->common.write_func ||
322 (data->mask && data->mask->common.read_func) ||
323 (data->mask && data->mask->common.write_func) ||
324 data->dest->common.read_func ||
325 data->dest->common.write_func)
327 pixman_composite_rect_general_accessors (data, src_buffer, mask_buffer,
332 pixman_composite_rect_general_no_accessors (data, src_buffer,
333 mask_buffer, dest_buffer,
337 if (scanline_buffer != stack_scanline_buffer)
338 free (scanline_buffer);