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