cairo_content_t _cairo_content_from_pixman_format (pixman_format_code_t pixman_format) { cairo_content_t content; content = 0; if (PIXMAN_FORMAT_RGB (pixman_format)) content |= CAIRO_CONTENT_COLOR; if (PIXMAN_FORMAT_A (pixman_format)) content |= CAIRO_CONTENT_ALPHA; return content; }
static void general_composite_rect (pixman_implementation_t *imp, pixman_composite_info_t *info) { PIXMAN_COMPOSITE_ARGS (info); uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8]; uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; pixman_iter_t src_iter, mask_iter, dest_iter; pixman_combine_32_func_t compose; pixman_bool_t component_alpha; iter_flags_t narrow, src_flags; iter_flags_t rgb16; int Bpp; int i; if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) && (!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) && (dest_image->common.flags & FAST_PATH_NARROW_FORMAT)) { narrow = ITER_NARROW; Bpp = 4; } else { narrow = 0; Bpp = 8; } // XXX: This special casing is bad. Ideally, we'd keep the general code general perhaps // by having it deal more specifically with different intermediate formats if ( (dest_image->common.flags & FAST_PATH_16_FORMAT && (src_image->type == LINEAR || src_image->type == RADIAL)) && ( op == PIXMAN_OP_SRC || (op == PIXMAN_OP_OVER && (src_image->common.flags & FAST_PATH_IS_OPAQUE)) ) ) { rgb16 = ITER_16; } else { rgb16 = 0; } if (width * Bpp > SCANLINE_BUFFER_LENGTH) { scanline_buffer = pixman_malloc_abc (width, 3, Bpp); if (!scanline_buffer) return; } src_buffer = scanline_buffer; mask_buffer = src_buffer + width * Bpp; dest_buffer = mask_buffer + width * Bpp; /* src iter */ src_flags = narrow | op_flags[op].src | rgb16; _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image, src_x, src_y, width, height, src_buffer, src_flags); /* mask iter */ if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) { /* If it doesn't matter what the source is, then it doesn't matter * what the mask is */ mask_image = NULL; } component_alpha = mask_image && mask_image->common.type == BITS && mask_image->common.component_alpha && PIXMAN_FORMAT_RGB (mask_image->bits.format); _pixman_implementation_src_iter_init ( imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height, mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB)); /* dest iter */ _pixman_implementation_dest_iter_init ( imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height, dest_buffer, narrow | op_flags[op].dst | rgb16); compose = _pixman_implementation_lookup_combiner ( imp->toplevel, op, component_alpha, narrow, !!rgb16); if (!compose) return; for (i = 0; i < height; ++i) { uint32_t *s, *m, *d; m = mask_iter.get_scanline (&mask_iter, NULL); s = src_iter.get_scanline (&src_iter, m); d = dest_iter.get_scanline (&dest_iter, NULL); compose (imp->toplevel, op, d, s, m, width); dest_iter.write_back (&dest_iter); } if (scanline_buffer != (uint8_t *) stack_scanline_buffer) free (scanline_buffer); }
static void i915_composite_emit_shader(intel_screen_private *intel, CARD8 op) { PicturePtr mask_picture = intel->render_mask_picture; PixmapPtr mask = intel->render_mask; int src_reg, mask_reg; Bool is_solid_src, is_solid_mask; Bool dest_is_alpha = PIXMAN_FORMAT_RGB(intel->render_dest_picture->format) == 0; int tex_unit, t; FS_LOCALS(); is_solid_src = intel->render_source_is_solid; is_solid_mask = intel->render_mask_is_solid; FS_BEGIN(); /* Declare the registers necessary for our program. */ t = 0; if (is_solid_src) { i915_fs_dcl(FS_T8); src_reg = FS_T8; } else { i915_fs_dcl(FS_T0); i915_fs_dcl(FS_S0); t++; } if (!mask) { /* No mask, so load directly to output color */ if (! is_solid_src) { if (dest_is_alpha) src_reg = FS_R0; else src_reg = FS_OC; if (intel_transform_is_affine(intel->transform[0])) i915_fs_texld(src_reg, FS_S0, FS_T0); else i915_fs_texldp(src_reg, FS_S0, FS_T0); } if (src_reg != FS_OC) { if (dest_is_alpha) i915_fs_mov(FS_OC, i915_fs_operand(src_reg, W, W, W, W)); else i915_fs_mov(FS_OC, i915_fs_operand_reg(src_reg)); } } else { if (is_solid_mask) { i915_fs_dcl(FS_T9); mask_reg = FS_T9; } else { i915_fs_dcl(FS_T0 + t); i915_fs_dcl(FS_S0 + t); } tex_unit = 0; if (! is_solid_src) { /* Load the source_picture texel */ if (intel_transform_is_affine(intel->transform[tex_unit])) i915_fs_texld(FS_R0, FS_S0, FS_T0); else i915_fs_texldp(FS_R0, FS_S0, FS_T0); src_reg = FS_R0; tex_unit++; } if (! is_solid_mask) { /* Load the mask_picture texel */ if (intel_transform_is_affine(intel->transform[tex_unit])) i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t); else i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t); mask_reg = FS_R1; } if (dest_is_alpha) { i915_fs_mul(FS_OC, i915_fs_operand(src_reg, W, W, W, W), i915_fs_operand(mask_reg, W, W, W, W)); } else { /* If component alpha is active in the mask and the blend * operation uses the source alpha, then we know we don't * need the source value (otherwise we would have hit a * fallback earlier), so we provide the source alpha (src.A * * mask.X) as output color. * Conversely, if CA is set and we don't need the source alpha, * then we produce the source value (src.X * mask.X) and the * source alpha is unused. Otherwise, we provide the non-CA * source value (src.X * mask.A). */ if (mask_picture->componentAlpha && PICT_FORMAT_RGB(mask_picture->format)) { if (i915_blend_op[op].src_alpha) { i915_fs_mul(FS_OC, i915_fs_operand(src_reg, W, W, W, W), i915_fs_operand_reg(mask_reg)); } else { i915_fs_mul(FS_OC, i915_fs_operand_reg(src_reg), i915_fs_operand_reg(mask_reg)); } } else { i915_fs_mul(FS_OC, i915_fs_operand_reg(src_reg), i915_fs_operand(mask_reg, W, W, W, W)); } } } FS_END(); }
static void general_composite_rect (pixman_implementation_t *imp, pixman_op_t op, pixman_image_t * src, pixman_image_t * mask, pixman_image_t * dest, int32_t src_x, int32_t src_y, int32_t mask_x, int32_t mask_y, int32_t dest_x, int32_t dest_y, int32_t width, int32_t height) { uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3]; const pixman_format_code_t src_format = src->type == BITS ? src->bits.format : 0; const pixman_format_code_t mask_format = mask && mask->type == BITS ? mask->bits.format : 0; const pixman_format_code_t dest_format = dest->type == BITS ? dest->bits.format : 0; const int src_wide = PIXMAN_FORMAT_IS_WIDE (src_format); const int mask_wide = mask && PIXMAN_FORMAT_IS_WIDE (mask_format); const int dest_wide = PIXMAN_FORMAT_IS_WIDE (dest_format); const int wide = src_wide || mask_wide || dest_wide; const int Bpp = wide ? 8 : 4; uint8_t *scanline_buffer = stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL; pixman_combine_32_func_t compose; store_scanline_t store; source_image_class_t src_class, mask_class; pixman_bool_t component_alpha; uint32_t *bits; int32_t stride; int i; if (width * Bpp > SCANLINE_BUFFER_LENGTH) { scanline_buffer = pixman_malloc_abc (width, 3, Bpp); if (!scanline_buffer) return; } src_buffer = scanline_buffer; mask_buffer = src_buffer + width * Bpp; dest_buffer = mask_buffer + width * Bpp; src_class = _pixman_image_classify (src, src_x, src_y, width, height); mask_class = SOURCE_IMAGE_CLASS_UNKNOWN; if (mask) { mask_class = _pixman_image_classify (mask, src_x, src_y, width, height); } if (op == PIXMAN_OP_CLEAR) fetch_src = NULL; else if (wide) fetch_src = _pixman_image_get_scanline_64; else fetch_src = _pixman_image_get_scanline_32; if (!mask || op == PIXMAN_OP_CLEAR) fetch_mask = NULL; else if (wide) fetch_mask = _pixman_image_get_scanline_64; else fetch_mask = _pixman_image_get_scanline_32; if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC) fetch_dest = NULL; else if (wide) fetch_dest = _pixman_image_get_scanline_64; else fetch_dest = _pixman_image_get_scanline_32; if (wide) store = _pixman_image_store_scanline_64; else store = _pixman_image_store_scanline_32; /* Skip the store step and composite directly into the * destination if the output format of the compose func matches * the destination format. */ if (!wide && !dest->common.alpha_map && !dest->bits.write_func && (op == PIXMAN_OP_ADD || op == PIXMAN_OP_OVER) && (dest->bits.format == PIXMAN_a8r8g8b8 || dest->bits.format == PIXMAN_x8r8g8b8)) { store = NULL; } if (!store) { bits = dest->bits.bits; stride = dest->bits.rowstride; } else { bits = NULL; stride = 0; } component_alpha = fetch_src && fetch_mask && mask && mask->common.type == BITS && mask->common.component_alpha && PIXMAN_FORMAT_RGB (mask->bits.format); if (wide) { if (component_alpha) compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca; else compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64; } else { if (component_alpha) compose = _pixman_implementation_combine_32_ca; else compose = _pixman_implementation_combine_32; } if (!compose) return; if (!fetch_mask) mask_buffer = NULL; for (i = 0; i < height; ++i) { /* fill first half of scanline with source */ if (fetch_src) { if (fetch_mask) { /* fetch mask before source so that fetching of source can be optimized */ fetch_mask (mask, mask_x, mask_y + i, width, (void *)mask_buffer, 0, 0); if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL) fetch_mask = NULL; } if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL) { fetch_src (src, src_x, src_y + i, width, (void *)src_buffer, 0, 0); fetch_src = NULL; } else { fetch_src (src, src_x, src_y + i, width, (void *)src_buffer, (void *)mask_buffer, 0xffffffff); } } else if (fetch_mask) { fetch_mask (mask, mask_x, mask_y + i, width, (void *)mask_buffer, 0, 0); } if (store) { /* fill dest into second half of scanline */ if (fetch_dest) { fetch_dest (dest, dest_x, dest_y + i, width, (void *)dest_buffer, 0, 0); } /* blend */ compose (imp->toplevel, op, (void *)dest_buffer, (void *)src_buffer, (void *)mask_buffer, width); /* write back */ store (&(dest->bits), dest_x, dest_y + i, width, (void *)dest_buffer); } else { /* blend */ compose (imp->toplevel, op, bits + (dest_y + i) * stride + dest_x, (void *)src_buffer, (void *)mask_buffer, width); } } if (scanline_buffer != stack_scanline_buffer) free (scanline_buffer); }
static void general_composite_rect (pixman_implementation_t *imp, pixman_composite_info_t *info) { PIXMAN_COMPOSITE_ARGS (info); uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8]; uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; pixman_iter_t src_iter, mask_iter, dest_iter; pixman_combine_32_func_t compose; pixman_bool_t component_alpha; iter_flags_t narrow, src_iter_flags; int Bpp; int i; if ((src_image->common.flags & FAST_PATH_NARROW_FORMAT) && (!mask_image || mask_image->common.flags & FAST_PATH_NARROW_FORMAT) && (dest_image->common.flags & FAST_PATH_NARROW_FORMAT)) { narrow = ITER_NARROW; Bpp = 4; } else { narrow = 0; Bpp = 8; } if (width * Bpp > SCANLINE_BUFFER_LENGTH) { scanline_buffer = pixman_malloc_abc (width, 3, Bpp); if (!scanline_buffer) return; } src_buffer = scanline_buffer; mask_buffer = src_buffer + width * Bpp; dest_buffer = mask_buffer + width * Bpp; /* src iter */ src_iter_flags = narrow | op_flags[op].src; _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image, src_x, src_y, width, height, src_buffer, src_iter_flags, info->src_flags); /* mask iter */ if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) { /* If it doesn't matter what the source is, then it doesn't matter * what the mask is */ mask_image = NULL; } component_alpha = mask_image && mask_image->common.type == BITS && mask_image->common.component_alpha && PIXMAN_FORMAT_RGB (mask_image->bits.format); _pixman_implementation_src_iter_init ( imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height, mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags); /* dest iter */ _pixman_implementation_dest_iter_init ( imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height, dest_buffer, narrow | op_flags[op].dst, info->dest_flags); compose = _pixman_implementation_lookup_combiner ( imp->toplevel, op, component_alpha, narrow); if (!compose) return; for (i = 0; i < height; ++i) { uint32_t *s, *m, *d; m = mask_iter.get_scanline (&mask_iter, NULL); s = src_iter.get_scanline (&src_iter, m); d = dest_iter.get_scanline (&dest_iter, NULL); compose (imp->toplevel, op, d, s, m, width); dest_iter.write_back (&dest_iter); } if (scanline_buffer != (uint8_t *) stack_scanline_buffer) free (scanline_buffer); }
static void general_composite_rect (pixman_implementation_t *imp, pixman_op_t op, pixman_image_t * src, pixman_image_t * mask, pixman_image_t * dest, int32_t src_x, int32_t src_y, int32_t mask_x, int32_t mask_y, int32_t dest_x, int32_t dest_y, int32_t width, int32_t height) { uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3]; uint8_t *scanline_buffer = stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL; pixman_combine_32_func_t compose; store_scanline_t store; source_image_class_t src_class, mask_class; pixman_bool_t component_alpha; uint32_t *bits; int32_t stride; int narrow, Bpp; int i; narrow = (src->common.flags & FAST_PATH_NARROW_FORMAT) && (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) && (dest->common.flags & FAST_PATH_NARROW_FORMAT); Bpp = narrow ? 4 : 8; if (width * Bpp > SCANLINE_BUFFER_LENGTH) { scanline_buffer = pixman_malloc_abc (width, 3, Bpp); if (!scanline_buffer) return; } src_buffer = scanline_buffer; mask_buffer = src_buffer + width * Bpp; dest_buffer = mask_buffer + width * Bpp; src_class = _pixman_image_classify (src, src_x, src_y, width, height); mask_class = SOURCE_IMAGE_CLASS_UNKNOWN; if (mask) { mask_class = _pixman_image_classify (mask, src_x, src_y, width, height); } if (op == PIXMAN_OP_CLEAR) fetch_src = NULL; else if (narrow) fetch_src = _pixman_image_get_scanline_32; else fetch_src = _pixman_image_get_scanline_64; if (!mask || op == PIXMAN_OP_CLEAR) fetch_mask = NULL; else if (narrow) fetch_mask = _pixman_image_get_scanline_32; else fetch_mask = _pixman_image_get_scanline_64; if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC) fetch_dest = NULL; else if (narrow) fetch_dest = _pixman_image_get_scanline_32; else fetch_dest = _pixman_image_get_scanline_64; if (narrow) store = _pixman_image_store_scanline_32; else store = _pixman_image_store_scanline_64; /* Skip the store step and composite directly into the * destination if the output format of the compose func matches * the destination format. * * If the destination format is a8r8g8b8 then we can always do * this. If it is x8r8g8b8, then we can only do it if the * operator doesn't make use of destination alpha. */ if ((dest->bits.format == PIXMAN_a8r8g8b8) || (dest->bits.format == PIXMAN_x8r8g8b8 && (op == PIXMAN_OP_OVER || op == PIXMAN_OP_ADD || op == PIXMAN_OP_SRC || op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_IN_REVERSE || op == PIXMAN_OP_OUT_REVERSE || op == PIXMAN_OP_DST))) { if (narrow && !dest->common.alpha_map && !dest->bits.write_func) { store = NULL; } } if (!store) { bits = dest->bits.bits; stride = dest->bits.rowstride; } else { bits = NULL; stride = 0; } component_alpha = fetch_src && fetch_mask && mask && mask->common.type == BITS && mask->common.component_alpha && PIXMAN_FORMAT_RGB (mask->bits.format); if (narrow) { if (component_alpha) compose = _pixman_implementation_combine_32_ca; else compose = _pixman_implementation_combine_32; } else { if (component_alpha) compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca; else compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64; } if (!compose) return; if (!fetch_mask) mask_buffer = NULL; for (i = 0; i < height; ++i) { /* fill first half of scanline with source */ if (fetch_src) { if (fetch_mask) { /* fetch mask before source so that fetching of source can be optimized */ fetch_mask (mask, mask_x, mask_y + i, width, (void *)mask_buffer, 0); if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL) fetch_mask = NULL; } if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL) { fetch_src (src, src_x, src_y + i, width, (void *)src_buffer, 0); fetch_src = NULL; } else { fetch_src (src, src_x, src_y + i, width, (void *)src_buffer, (void *)mask_buffer); } } else if (fetch_mask) { fetch_mask (mask, mask_x, mask_y + i, width, (void *)mask_buffer, 0); } if (store) { /* fill dest into second half of scanline */ if (fetch_dest) { fetch_dest (dest, dest_x, dest_y + i, width, (void *)dest_buffer, 0); } /* blend */ compose (imp->toplevel, op, (void *)dest_buffer, (void *)src_buffer, (void *)mask_buffer, width); /* write back */ store (&(dest->bits), dest_x, dest_y + i, width, (void *)dest_buffer); } else { /* blend */ compose (imp->toplevel, op, bits + (dest_y + i) * stride + dest_x, (void *)src_buffer, (void *)mask_buffer, width); } } if (scanline_buffer != stack_scanline_buffer) free (scanline_buffer); }