pixman-general.c revision 953d7d37
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 42static void 43general_src_iter_init (pixman_implementation_t *imp, 44 pixman_iter_t *iter, 45 pixman_image_t *image, 46 int x, int y, int width, int height, 47 uint8_t *buffer, iter_flags_t flags) 48{ 49 iter->image = image; 50 iter->x = x; 51 iter->y = y; 52 iter->width = width; 53 iter->buffer = (uint32_t *)buffer; 54 55 if (image->type == SOLID) 56 { 57 _pixman_solid_fill_iter_init ( 58 image, iter, x, y, width, height, buffer, flags); 59 } 60 else if (image->type == LINEAR) 61 { 62 _pixman_linear_gradient_iter_init ( 63 image, iter, x, y, width, height, buffer, flags); 64 } 65 else if (image->type == RADIAL) 66 { 67 _pixman_radial_gradient_iter_init ( 68 image, iter, x, y, width, height, buffer, flags); 69 } 70 else if (image->type == CONICAL) 71 { 72 _pixman_conical_gradient_iter_init ( 73 image, iter, x, y, width, height, buffer, flags); 74 } 75 else if (image->type == BITS) 76 { 77 _pixman_bits_image_src_iter_init ( 78 image, iter, x, y, width, height, buffer, flags); 79 } 80 else 81 { 82 _pixman_log_error (FUNC, "Pixman bug: unknown image type\n"); 83 } 84} 85 86static void 87general_dest_iter_init (pixman_implementation_t *imp, 88 pixman_iter_t *iter, 89 pixman_image_t *image, 90 int x, int y, int width, int height, 91 uint8_t *buffer, iter_flags_t flags) 92{ 93 iter->image = image; 94 iter->x = x; 95 iter->y = y; 96 iter->width = width; 97 iter->buffer = (uint32_t *)buffer; 98 99 if (image->type == BITS) 100 { 101 _pixman_bits_image_dest_iter_init ( 102 image, iter, x, y, width, height, buffer, flags); 103 } 104 else 105 { 106 _pixman_log_error (FUNC, "Trying to write to a non-writable image"); 107 } 108} 109 110typedef struct op_info_t op_info_t; 111struct op_info_t 112{ 113 uint8_t src, dst; 114}; 115 116#define ITER_IGNORE_BOTH \ 117 (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA) 118 119static const op_info_t op_flags[PIXMAN_N_OPERATORS] = 120{ 121 /* Src Dst */ 122 { ITER_IGNORE_BOTH, ITER_IGNORE_BOTH }, /* CLEAR */ 123 { ITER_LOCALIZED_ALPHA, ITER_IGNORE_BOTH }, /* SRC */ 124 { ITER_IGNORE_BOTH, ITER_LOCALIZED_ALPHA }, /* DST */ 125 { 0, ITER_LOCALIZED_ALPHA }, /* OVER */ 126 { ITER_LOCALIZED_ALPHA, 0 }, /* OVER_REVERSE */ 127 { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* IN */ 128 { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* IN_REVERSE */ 129 { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* OUT */ 130 { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* OUT_REVERSE */ 131 { 0, 0 }, /* ATOP */ 132 { 0, 0 }, /* ATOP_REVERSE */ 133 { 0, 0 }, /* XOR */ 134 { ITER_LOCALIZED_ALPHA, ITER_LOCALIZED_ALPHA }, /* ADD */ 135 { 0, 0 }, /* SATURATE */ 136}; 137 138#define SCANLINE_BUFFER_LENGTH 8192 139 140static void 141general_composite_rect (pixman_implementation_t *imp, 142 pixman_op_t op, 143 pixman_image_t * src, 144 pixman_image_t * mask, 145 pixman_image_t * dest, 146 int32_t src_x, 147 int32_t src_y, 148 int32_t mask_x, 149 int32_t mask_y, 150 int32_t dest_x, 151 int32_t dest_y, 152 int32_t width, 153 int32_t height) 154{ 155 uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8]; 156 uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; 157 uint8_t *src_buffer, *mask_buffer, *dest_buffer; 158 pixman_iter_t src_iter, mask_iter, dest_iter; 159 pixman_combine_32_func_t compose; 160 pixman_bool_t component_alpha; 161 iter_flags_t narrow, src_flags; 162 int Bpp; 163 int i; 164 165 if ((src->common.flags & FAST_PATH_NARROW_FORMAT) && 166 (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) && 167 (dest->common.flags & FAST_PATH_NARROW_FORMAT)) 168 { 169 narrow = ITER_NARROW; 170 Bpp = 4; 171 } 172 else 173 { 174 narrow = 0; 175 Bpp = 8; 176 } 177 178 if (width * Bpp > SCANLINE_BUFFER_LENGTH) 179 { 180 scanline_buffer = pixman_malloc_abc (width, 3, Bpp); 181 182 if (!scanline_buffer) 183 return; 184 } 185 186 src_buffer = scanline_buffer; 187 mask_buffer = src_buffer + width * Bpp; 188 dest_buffer = mask_buffer + width * Bpp; 189 190 /* src iter */ 191 src_flags = narrow | op_flags[op].src; 192 193 _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src, 194 src_x, src_y, width, height, 195 src_buffer, src_flags); 196 197 /* mask iter */ 198 if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == 199 (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) 200 { 201 /* If it doesn't matter what the source is, then it doesn't matter 202 * what the mask is 203 */ 204 mask = NULL; 205 } 206 207 component_alpha = 208 mask && 209 mask->common.type == BITS && 210 mask->common.component_alpha && 211 PIXMAN_FORMAT_RGB (mask->bits.format); 212 213 _pixman_implementation_src_iter_init ( 214 imp->toplevel, &mask_iter, mask, mask_x, mask_y, width, height, 215 mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB)); 216 217 /* dest iter */ 218 _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest, 219 dest_x, dest_y, width, height, 220 dest_buffer, 221 narrow | op_flags[op].dst); 222 223 if (narrow) 224 { 225 if (component_alpha) 226 compose = _pixman_implementation_combine_32_ca; 227 else 228 compose = _pixman_implementation_combine_32; 229 } 230 else 231 { 232 if (component_alpha) 233 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca; 234 else 235 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64; 236 } 237 238 if (!compose) 239 return; 240 241 for (i = 0; i < height; ++i) 242 { 243 uint32_t *s, *m, *d; 244 245 m = mask_iter.get_scanline (&mask_iter, NULL); 246 s = src_iter.get_scanline (&src_iter, m); 247 d = dest_iter.get_scanline (&dest_iter, NULL); 248 249 compose (imp->toplevel, op, d, s, m, width); 250 251 dest_iter.write_back (&dest_iter); 252 } 253 254 if (scanline_buffer != (uint8_t *) stack_scanline_buffer) 255 free (scanline_buffer); 256} 257 258static const pixman_fast_path_t general_fast_path[] = 259{ 260 { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect }, 261 { PIXMAN_OP_NONE } 262}; 263 264static pixman_bool_t 265general_blt (pixman_implementation_t *imp, 266 uint32_t * src_bits, 267 uint32_t * dst_bits, 268 int src_stride, 269 int dst_stride, 270 int src_bpp, 271 int dst_bpp, 272 int src_x, 273 int src_y, 274 int dst_x, 275 int dst_y, 276 int width, 277 int height) 278{ 279 /* We can't blit unless we have sse2 or mmx */ 280 281 return FALSE; 282} 283 284static pixman_bool_t 285general_fill (pixman_implementation_t *imp, 286 uint32_t * bits, 287 int stride, 288 int bpp, 289 int x, 290 int y, 291 int width, 292 int height, 293 uint32_t xor) 294{ 295 return FALSE; 296} 297 298pixman_implementation_t * 299_pixman_implementation_create_general (void) 300{ 301 pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path); 302 303 _pixman_setup_combiner_functions_32 (imp); 304 _pixman_setup_combiner_functions_64 (imp); 305 306 imp->blt = general_blt; 307 imp->fill = general_fill; 308 imp->src_iter_init = general_src_iter_init; 309 imp->dest_iter_init = general_dest_iter_init; 310 311 return imp; 312} 313 314