pixman-general.c revision 6ba797d6
13da084b3Smrg/* 23da084b3Smrg * Copyright © 2009 Red Hat, Inc. 33da084b3Smrg * Copyright © 2000 SuSE, Inc. 43da084b3Smrg * Copyright © 2007 Red Hat, Inc. 53da084b3Smrg * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 63da084b3Smrg * 2005 Lars Knoll & Zack Rusin, Trolltech 73da084b3Smrg * 2008 Aaron Plattner, NVIDIA Corporation 83da084b3Smrg * 93da084b3Smrg * Permission to use, copy, modify, distribute, and sell this software and its 103da084b3Smrg * documentation for any purpose is hereby granted without fee, provided that 113da084b3Smrg * the above copyright notice appear in all copies and that both that 123da084b3Smrg * 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 40static void 41general_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) 42{ 43 pixman_image_t *image = iter->image; 44 45 if (image->type == SOLID) 46 _pixman_solid_fill_iter_init (image, iter); 47 else if (image->type == LINEAR) 48 _pixman_linear_gradient_iter_init (image, iter); 49 else if (image->type == RADIAL) 50 _pixman_radial_gradient_iter_init (image, iter); 51 else if (image->type == CONICAL) 52 _pixman_conical_gradient_iter_init (image, iter); 53 else if (image->type == BITS) 54 _pixman_bits_image_src_iter_init (image, iter); 55 else 56 _pixman_log_error (FUNC, "Pixman bug: unknown image type\n"); 57} 58 59static void 60general_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) 61{ 62 if (iter->image->type == BITS) 63 { 64 _pixman_bits_image_dest_iter_init (iter->image, iter); 65 } 66 else 67 { 68 _pixman_log_error (FUNC, "Trying to write to a non-writable image"); 69 } 70} 71 72typedef struct op_info_t op_info_t; 73struct op_info_t 74{ 75 uint8_t src, dst; 76}; 77 78#define ITER_IGNORE_BOTH \ 79 (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA) 80 81static const op_info_t op_flags[PIXMAN_N_OPERATORS] = 82{ 83 /* Src Dst */ 84 { ITER_IGNORE_BOTH, ITER_IGNORE_BOTH }, /* CLEAR */ 85 { ITER_LOCALIZED_ALPHA, ITER_IGNORE_BOTH }, /* SRC */ 86 { ITER_IGNORE_BOTH, ITER_LOCALIZED_ALPHA }, /* DST */ 87 { 0, ITER_LOCALIZED_ALPHA }, /* OVER */ 88 { ITER_LOCALIZED_ALPHA, 0 }, /* OVER_REVERSE */ 89 { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* IN */ 90 { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* IN_REVERSE */ 91 { ITER_LOCALIZED_ALPHA, ITER_IGNORE_RGB }, /* OUT */ 92 { ITER_IGNORE_RGB, ITER_LOCALIZED_ALPHA }, /* OUT_REVERSE */ 93 { 0, 0 }, /* ATOP */ 94 { 0, 0 }, /* ATOP_REVERSE */ 95 { 0, 0 }, /* XOR */ 96 { ITER_LOCALIZED_ALPHA, ITER_LOCALIZED_ALPHA }, /* ADD */ 97 { 0, 0 }, /* SATURATE */ 98}; 99 100#define SCANLINE_BUFFER_LENGTH 8192 101 102static void 103general_composite_rect (pixman_implementation_t *imp, 104 pixman_composite_info_t *info) 105{ 106 PIXMAN_COMPOSITE_ARGS (info); 107 uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8]; 108 uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; 109 uint8_t *src_buffer, *mask_buffer, *dest_buffer; 110 pixman_iter_t src_iter, mask_iter, dest_iter; 111 pixman_combine_32_func_t compose; 112 pixman_bool_t component_alpha; 113 iter_flags_t narrow, src_flags; 114 int Bpp; 115 int i; 116 117 if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) && 118 (!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) && 119 (dest_image->common.flags & FAST_PATH_NARROW_FORMAT)) 120 { 121 narrow = ITER_NARROW; 122 Bpp = 4; 123 } 124 else 125 { 126 narrow = 0; 127 Bpp = 8; 128 } 129 130 if (width * Bpp > SCANLINE_BUFFER_LENGTH) 131 { 132 scanline_buffer = pixman_malloc_abc (width, 3, Bpp); 133 134 if (!scanline_buffer) 135 return; 136 } 137 138 src_buffer = scanline_buffer; 139 mask_buffer = src_buffer + width * Bpp; 140 dest_buffer = mask_buffer + width * Bpp; 141 142 /* src iter */ 143 src_flags = narrow | op_flags[op].src; 144 145 _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image, 146 src_x, src_y, width, height, 147 src_buffer, src_flags); 148 149 /* mask iter */ 150 if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == 151 (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) 152 { 153 /* If it doesn't matter what the source is, then it doesn't matter 154 * what the mask is 155 */ 156 mask_image = NULL; 157 } 158 159 component_alpha = 160 mask_image && 161 mask_image->common.type == BITS && 162 mask_image->common.component_alpha && 163 PIXMAN_FORMAT_RGB (mask_image->bits.format); 164 165 _pixman_implementation_src_iter_init ( 166 imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height, 167 mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB)); 168 169 /* dest iter */ 170 _pixman_implementation_dest_iter_init ( 171 imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height, 172 dest_buffer, narrow | op_flags[op].dst); 173 174 if (narrow) 175 { 176 if (component_alpha) 177 compose = _pixman_implementation_combine_32_ca; 178 else 179 compose = _pixman_implementation_combine_32; 180 } 181 else 182 { 183 if (component_alpha) 184 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca; 185 else 186 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64; 187 } 188 189 if (!compose) 190 return; 191 192 for (i = 0; i < height; ++i) 193 { 194 uint32_t *s, *m, *d; 195 196 m = mask_iter.get_scanline (&mask_iter, NULL); 197 s = src_iter.get_scanline (&src_iter, m); 198 d = dest_iter.get_scanline (&dest_iter, NULL); 199 200 compose (imp->toplevel, op, d, s, m, width); 201 202 dest_iter.write_back (&dest_iter); 203 } 204 205 if (scanline_buffer != (uint8_t *) stack_scanline_buffer) 206 free (scanline_buffer); 207} 208 209static const pixman_fast_path_t general_fast_path[] = 210{ 211 { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect }, 212 { PIXMAN_OP_NONE } 213}; 214 215static pixman_bool_t 216general_blt (pixman_implementation_t *imp, 217 uint32_t * src_bits, 218 uint32_t * dst_bits, 219 int src_stride, 220 int dst_stride, 221 int src_bpp, 222 int dst_bpp, 223 int src_x, 224 int src_y, 225 int dest_x, 226 int dest_y, 227 int width, 228 int height) 229{ 230 /* We can't blit unless we have sse2 or mmx */ 231 232 return FALSE; 233} 234 235static pixman_bool_t 236general_fill (pixman_implementation_t *imp, 237 uint32_t * bits, 238 int stride, 239 int bpp, 240 int x, 241 int y, 242 int width, 243 int height, 244 uint32_t xor) 245{ 246 return FALSE; 247} 248 249pixman_implementation_t * 250_pixman_implementation_create_general (void) 251{ 252 pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path); 253 254 _pixman_setup_combiner_functions_32 (imp); 255 _pixman_setup_combiner_functions_64 (imp); 256 257 imp->blt = general_blt; 258 imp->fill = general_fill; 259 imp->src_iter_init = general_src_iter_init; 260 imp->dest_iter_init = general_dest_iter_init; 261 262 return imp; 263} 264 265