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