diff options
Diffstat (limited to 'gfx/cairo/pixman-16-bit-pipeline.patch')
-rw-r--r-- | gfx/cairo/pixman-16-bit-pipeline.patch | 1242 |
1 files changed, 0 insertions, 1242 deletions
diff --git a/gfx/cairo/pixman-16-bit-pipeline.patch b/gfx/cairo/pixman-16-bit-pipeline.patch deleted file mode 100644 index 8a7878ca2..000000000 --- a/gfx/cairo/pixman-16-bit-pipeline.patch +++ /dev/null @@ -1,1242 +0,0 @@ -diff --git a/gfx/cairo/libpixman/src/pixman-access.c b/gfx/cairo/libpixman/src/pixman-access.c ---- a/gfx/cairo/libpixman/src/pixman-access.c -+++ b/gfx/cairo/libpixman/src/pixman-access.c -@@ -933,16 +933,54 @@ store_scanline_x2b10g10r10 (bits_image_t - { - WRITE (image, pixel++, - ((values[i] >> 38) & 0x3ff) | - ((values[i] >> 12) & 0xffc00) | - ((values[i] << 14) & 0x3ff00000)); - } - } - -+static void -+store_scanline_16 (bits_image_t * image, -+ int x, -+ int y, -+ int width, -+ const uint32_t *v) -+{ -+ uint16_t *bits = (uint16_t*)(image->bits + image->rowstride * y); -+ uint16_t *values = (uint16_t *)v; -+ uint16_t *pixel = bits + x; -+ int i; -+ -+ for (i = 0; i < width; ++i) -+ { -+ WRITE (image, pixel++, values[i]); -+ } -+} -+ -+static void -+fetch_scanline_16 (pixman_image_t *image, -+ int x, -+ int y, -+ int width, -+ uint32_t * b, -+ const uint32_t *mask) -+{ -+ const uint16_t *bits = (uint16_t*)(image->bits.bits + y * image->bits.rowstride); -+ const uint16_t *pixel = bits + x; -+ int i; -+ uint16_t *buffer = (uint16_t *)b; -+ -+ for (i = 0; i < width; ++i) -+ { -+ *buffer++ = READ (image, pixel++); -+ } -+} -+ -+ - /* - * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit - * store proc. Despite the type, this function expects a uint64_t buffer. - */ - static void - store_scanline_generic_64 (bits_image_t * image, - int x, - int y, -@@ -1044,32 +1082,47 @@ fetch_pixel_generic_lossy_32 (bits_image - pixman_contract (&result, &pixel64, 1); - - return result; - } - - typedef struct - { - pixman_format_code_t format; -+ fetch_scanline_t fetch_scanline_16; - fetch_scanline_t fetch_scanline_32; - fetch_scanline_t fetch_scanline_64; - fetch_pixel_32_t fetch_pixel_32; - fetch_pixel_64_t fetch_pixel_64; -+ store_scanline_t store_scanline_16; - store_scanline_t store_scanline_32; - store_scanline_t store_scanline_64; - } format_info_t; - - #define FORMAT_INFO(format) \ - { \ - PIXMAN_ ## format, \ -+ NULL, \ - fetch_scanline_ ## format, \ - fetch_scanline_generic_64, \ - fetch_pixel_ ## format, fetch_pixel_generic_64, \ -+ NULL, \ - store_scanline_ ## format, store_scanline_generic_64 \ - } -+#define FORMAT_INFO16(format) \ -+ { \ -+ PIXMAN_ ## format, \ -+ fetch_scanline_16, \ -+ fetch_scanline_ ## format, \ -+ fetch_scanline_generic_64, \ -+ fetch_pixel_ ## format, fetch_pixel_generic_64, \ -+ store_scanline_16, \ -+ store_scanline_ ## format, store_scanline_generic_64 \ -+ } -+ - - static const format_info_t accessors[] = - { - /* 32 bpp formats */ - FORMAT_INFO (a8r8g8b8), - FORMAT_INFO (x8r8g8b8), - FORMAT_INFO (a8b8g8r8), - FORMAT_INFO (x8b8g8r8), -@@ -1079,18 +1132,18 @@ static const format_info_t accessors[] = - FORMAT_INFO (r8g8b8x8), - FORMAT_INFO (x14r6g6b6), - - /* 24bpp formats */ - FORMAT_INFO (r8g8b8), - FORMAT_INFO (b8g8r8), - - /* 16bpp formats */ -- FORMAT_INFO (r5g6b5), -- FORMAT_INFO (b5g6r5), -+ FORMAT_INFO16 (r5g6b5), -+ FORMAT_INFO16 (b5g6r5), - - FORMAT_INFO (a1r5g5b5), - FORMAT_INFO (x1r5g5b5), - FORMAT_INFO (a1b5g5r5), - FORMAT_INFO (x1b5g5r5), - FORMAT_INFO (a4r4g4b4), - FORMAT_INFO (x4r4g4b4), - FORMAT_INFO (a4b4g4r4), -@@ -1132,62 +1185,64 @@ static const format_info_t accessors[] = - - /* 1bpp formats */ - FORMAT_INFO (a1), - FORMAT_INFO (g1), - - /* Wide formats */ - - { PIXMAN_a2r10g10b10, -- NULL, fetch_scanline_a2r10g10b10, -+ NULL, NULL, fetch_scanline_a2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10, - NULL, store_scanline_a2r10g10b10 }, - - { PIXMAN_x2r10g10b10, -- NULL, fetch_scanline_x2r10g10b10, -+ NULL, NULL, fetch_scanline_x2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10, - NULL, store_scanline_x2r10g10b10 }, - - { PIXMAN_a2b10g10r10, -- NULL, fetch_scanline_a2b10g10r10, -+ NULL, NULL, fetch_scanline_a2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10, - NULL, store_scanline_a2b10g10r10 }, - - { PIXMAN_x2b10g10r10, -- NULL, fetch_scanline_x2b10g10r10, -+ NULL, NULL, fetch_scanline_x2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10, - NULL, store_scanline_x2b10g10r10 }, - - /* YUV formats */ - { PIXMAN_yuy2, -- fetch_scanline_yuy2, fetch_scanline_generic_64, -+ NULL, fetch_scanline_yuy2, fetch_scanline_generic_64, - fetch_pixel_yuy2, fetch_pixel_generic_64, - NULL, NULL }, - - { PIXMAN_yv12, -- fetch_scanline_yv12, fetch_scanline_generic_64, -+ NULL, fetch_scanline_yv12, fetch_scanline_generic_64, - fetch_pixel_yv12, fetch_pixel_generic_64, - NULL, NULL }, - - { PIXMAN_null }, - }; - - static void - setup_accessors (bits_image_t *image) - { - const format_info_t *info = accessors; - - while (info->format != PIXMAN_null) - { - if (info->format == image->format) - { -+ image->fetch_scanline_16 = info->fetch_scanline_16; - image->fetch_scanline_32 = info->fetch_scanline_32; - image->fetch_scanline_64 = info->fetch_scanline_64; - image->fetch_pixel_32 = info->fetch_pixel_32; - image->fetch_pixel_64 = info->fetch_pixel_64; -+ image->store_scanline_16 = info->store_scanline_16; - image->store_scanline_32 = info->store_scanline_32; - image->store_scanline_64 = info->store_scanline_64; - - return; - } - - info++; - } -diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c ---- a/gfx/cairo/libpixman/src/pixman-bits-image.c -+++ b/gfx/cairo/libpixman/src/pixman-bits-image.c -@@ -1247,16 +1247,31 @@ src_get_scanline_wide (pixman_iter_t *it - - void - _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) - { - if (iter->flags & ITER_NARROW) - iter->get_scanline = src_get_scanline_narrow; - else - iter->get_scanline = src_get_scanline_wide; -+ -+} -+ -+static uint32_t * -+dest_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask) -+{ -+ pixman_image_t *image = iter->image; -+ int x = iter->x; -+ int y = iter->y; -+ int width = iter->width; -+ uint32_t * buffer = iter->buffer; -+ -+ image->bits.fetch_scanline_16 (image, x, y, width, buffer, mask); -+ -+ return iter->buffer; - } - - static uint32_t * - dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) - { - pixman_image_t *image = iter->image; - int x = iter->x; - int y = iter->y; -@@ -1327,16 +1342,30 @@ dest_get_scanline_wide (pixman_iter_t *i - free (alpha); - } - } - - return iter->buffer; - } - - static void -+dest_write_back_16 (pixman_iter_t *iter) -+{ -+ bits_image_t * image = &iter->image->bits; -+ int x = iter->x; -+ int y = iter->y; -+ int width = iter->width; -+ const uint32_t *buffer = iter->buffer; -+ -+ image->store_scanline_16 (image, x, y, width, buffer); -+ -+ iter->y++; -+} -+ -+static void - dest_write_back_narrow (pixman_iter_t *iter) - { - bits_image_t * image = &iter->image->bits; - int x = iter->x; - int y = iter->y; - int width = iter->width; - const uint32_t *buffer = iter->buffer; - -@@ -1375,28 +1404,41 @@ dest_write_back_wide (pixman_iter_t *ite - } - - iter->y++; - } - - void - _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) - { -- if (iter->flags & ITER_NARROW) -+ if (iter->flags & ITER_16) -+ { -+ if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == -+ (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) -+ { -+ iter->get_scanline = _pixman_iter_get_scanline_noop; -+ } -+ else -+ { -+ iter->get_scanline = dest_get_scanline_16; -+ } -+ iter->write_back = dest_write_back_16; -+ } -+ else if (iter->flags & ITER_NARROW) - { - if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == - (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) - { - iter->get_scanline = _pixman_iter_get_scanline_noop; - } - else - { - iter->get_scanline = dest_get_scanline_narrow; - } -- -+ - iter->write_back = dest_write_back_narrow; - } - else - { - iter->get_scanline = dest_get_scanline_wide; - iter->write_back = dest_write_back_wide; - } - } -diff --git a/gfx/cairo/libpixman/src/pixman-combine16.c b/gfx/cairo/libpixman/src/pixman-combine16.c -new file mode 100644 ---- /dev/null -+++ b/gfx/cairo/libpixman/src/pixman-combine16.c -@@ -0,0 +1,124 @@ -+#ifdef HAVE_CONFIG_H -+#include <config.h> -+#endif -+ -+#include <math.h> -+#include <string.h> -+ -+#include "pixman-private.h" -+ -+#include "pixman-combine32.h" -+ -+static force_inline uint32_t -+combine_mask (const uint32_t src, const uint32_t mask) -+{ -+ uint32_t s, m; -+ -+ m = mask >> A_SHIFT; -+ -+ if (!m) -+ return 0; -+ s = src; -+ -+ UN8x4_MUL_UN8 (s, m); -+ -+ return s; -+} -+ -+static inline uint32_t convert_0565_to_8888(uint16_t color) -+{ -+ return CONVERT_0565_TO_8888(color); -+} -+ -+static inline uint16_t convert_8888_to_0565(uint32_t color) -+{ -+ return CONVERT_8888_TO_0565(color); -+} -+ -+static void -+combine_src_u (pixman_implementation_t *imp, -+ pixman_op_t op, -+ uint32_t * dest, -+ const uint32_t * src, -+ const uint32_t * mask, -+ int width) -+{ -+ int i; -+ -+ if (!mask) -+ memcpy (dest, src, width * sizeof (uint16_t)); -+ else -+ { -+ uint16_t *d = (uint16_t*)dest; -+ uint16_t *src16 = (uint16_t*)src; -+ for (i = 0; i < width; ++i) -+ { -+ if ((*mask & 0xff000000) == 0xff000000) { -+ // it's likely worth special casing -+ // fully opaque because it avoids -+ // the cost of conversion as well the multiplication -+ *(d + i) = *src16; -+ } else { -+ // the mask is still 32bits -+ uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask); -+ *(d + i) = convert_8888_to_0565(s); -+ } -+ mask++; -+ src16++; -+ } -+ } -+ -+} -+ -+static void -+combine_over_u (pixman_implementation_t *imp, -+ pixman_op_t op, -+ uint32_t * dest, -+ const uint32_t * src, -+ const uint32_t * mask, -+ int width) -+{ -+ int i; -+ -+ if (!mask) -+ memcpy (dest, src, width * sizeof (uint16_t)); -+ else -+ { -+ uint16_t *d = (uint16_t*)dest; -+ uint16_t *src16 = (uint16_t*)src; -+ for (i = 0; i < width; ++i) -+ { -+ if ((*mask & 0xff000000) == 0xff000000) { -+ // it's likely worth special casing -+ // fully opaque because it avoids -+ // the cost of conversion as well the multiplication -+ *(d + i) = *src16; -+ } else if ((*mask & 0xff000000) == 0x00000000) { -+ // keep the dest the same -+ } else { -+ // the mask is still 32bits -+ uint32_t s = combine_mask (convert_0565_to_8888(*src16), *mask); -+ uint32_t ia = ALPHA_8 (~s); -+ uint32_t d32 = convert_0565_to_8888(*(d + i)); -+ UN8x4_MUL_UN8_ADD_UN8x4 (d32, ia, s); -+ *(d + i) = convert_8888_to_0565(d32); -+ } -+ mask++; -+ src16++; -+ } -+ } -+ -+} -+ -+ -+void -+_pixman_setup_combiner_functions_16 (pixman_implementation_t *imp) -+{ -+ int i; -+ for (i = 0; i < PIXMAN_N_OPERATORS; i++) { -+ imp->combine_16[i] = NULL; -+ } -+ imp->combine_16[PIXMAN_OP_SRC] = combine_src_u; -+ imp->combine_16[PIXMAN_OP_OVER] = combine_over_u; -+} -+ -diff --git a/gfx/cairo/libpixman/src/pixman-general.c b/gfx/cairo/libpixman/src/pixman-general.c ---- a/gfx/cairo/libpixman/src/pixman-general.c -+++ b/gfx/cairo/libpixman/src/pixman-general.c -@@ -106,46 +106,61 @@ general_composite_rect (pixman_implemen - 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; -+ 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)) -@@ -164,20 +179,20 @@ general_composite_rect (pixman_implemen - - _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); -+ dest_buffer, narrow | op_flags[op].dst | rgb16); - - compose = _pixman_implementation_lookup_combiner ( -- imp->toplevel, op, component_alpha, narrow); -+ imp->toplevel, op, component_alpha, narrow, !!rgb16); - - if (!compose) - return; - - for (i = 0; i < height; ++i) - { - uint32_t *s, *m, *d; - -@@ -234,16 +249,17 @@ general_fill (pixman_implementation_t *i - return FALSE; - } - - pixman_implementation_t * - _pixman_implementation_create_general (void) - { - pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path); - -+ _pixman_setup_combiner_functions_16 (imp); - _pixman_setup_combiner_functions_32 (imp); - _pixman_setup_combiner_functions_64 (imp); - - imp->blt = general_blt; - imp->fill = general_fill; - imp->src_iter_init = general_src_iter_init; - imp->dest_iter_init = general_dest_iter_init; - -diff --git a/gfx/cairo/libpixman/src/pixman-image.c b/gfx/cairo/libpixman/src/pixman-image.c ---- a/gfx/cairo/libpixman/src/pixman-image.c -+++ b/gfx/cairo/libpixman/src/pixman-image.c -@@ -451,16 +451,20 @@ compute_image_info (pixman_image_t *imag - flags |= FAST_PATH_IS_OPAQUE; - } - - if (image->bits.read_func || image->bits.write_func) - flags &= ~FAST_PATH_NO_ACCESSORS; - - if (PIXMAN_FORMAT_IS_WIDE (image->bits.format)) - flags &= ~FAST_PATH_NARROW_FORMAT; -+ -+ if (image->bits.format == PIXMAN_r5g6b5) -+ flags |= FAST_PATH_16_FORMAT; -+ - break; - - case RADIAL: - code = PIXMAN_unknown; - - /* - * As explained in pixman-radial-gradient.c, every point of - * the plane has a valid associated radius (and thus will be -diff --git a/gfx/cairo/libpixman/src/pixman-implementation.c b/gfx/cairo/libpixman/src/pixman-implementation.c ---- a/gfx/cairo/libpixman/src/pixman-implementation.c -+++ b/gfx/cairo/libpixman/src/pixman-implementation.c -@@ -101,45 +101,51 @@ pixman_implementation_t * - imp->fill = delegate_fill; - imp->src_iter_init = delegate_src_iter_init; - imp->dest_iter_init = delegate_dest_iter_init; - - imp->fast_paths = fast_paths; - - for (i = 0; i < PIXMAN_N_OPERATORS; ++i) - { -+ imp->combine_16[i] = NULL; - imp->combine_32[i] = NULL; - imp->combine_64[i] = NULL; - imp->combine_32_ca[i] = NULL; - imp->combine_64_ca[i] = NULL; - } - - return imp; - } - - pixman_combine_32_func_t - _pixman_implementation_lookup_combiner (pixman_implementation_t *imp, - pixman_op_t op, - pixman_bool_t component_alpha, -- pixman_bool_t narrow) -+ pixman_bool_t narrow, -+ pixman_bool_t rgb16) - { - pixman_combine_32_func_t f; - - do - { - pixman_combine_32_func_t (*combiners[]) = - { - (pixman_combine_32_func_t *)imp->combine_64, - (pixman_combine_32_func_t *)imp->combine_64_ca, - imp->combine_32, - imp->combine_32_ca, -+ (pixman_combine_32_func_t *)imp->combine_16, -+ NULL, - }; -- -- f = combiners[component_alpha | (narrow << 1)][op]; -- -+ if (rgb16) { -+ f = combiners[4][op]; -+ } else { -+ f = combiners[component_alpha + (narrow << 1)][op]; -+ } - imp = imp->delegate; - } - while (!f); - - return f; - } - - pixman_bool_t -diff --git a/gfx/cairo/libpixman/src/pixman-linear-gradient.c b/gfx/cairo/libpixman/src/pixman-linear-gradient.c ---- a/gfx/cairo/libpixman/src/pixman-linear-gradient.c -+++ b/gfx/cairo/libpixman/src/pixman-linear-gradient.c -@@ -217,42 +217,185 @@ linear_get_scanline_narrow (pixman_iter_ - } - } - - iter->y++; - - return iter->buffer; - } - -+static uint16_t convert_8888_to_0565(uint32_t color) -+{ -+ return CONVERT_8888_TO_0565(color); -+} -+ -+static uint32_t * -+linear_get_scanline_16 (pixman_iter_t *iter, -+ const uint32_t *mask) -+{ -+ pixman_image_t *image = iter->image; -+ int x = iter->x; -+ int y = iter->y; -+ int width = iter->width; -+ uint16_t * buffer = (uint16_t*)iter->buffer; -+ -+ pixman_vector_t v, unit; -+ pixman_fixed_32_32_t l; -+ pixman_fixed_48_16_t dx, dy; -+ gradient_t *gradient = (gradient_t *)image; -+ linear_gradient_t *linear = (linear_gradient_t *)image; -+ uint16_t *end = buffer + width; -+ pixman_gradient_walker_t walker; -+ -+ _pixman_gradient_walker_init (&walker, gradient, image->common.repeat); -+ -+ /* reference point is the center of the pixel */ -+ v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; -+ v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; -+ v.vector[2] = pixman_fixed_1; -+ -+ if (image->common.transform) -+ { -+ if (!pixman_transform_point_3d (image->common.transform, &v)) -+ return iter->buffer; -+ -+ unit.vector[0] = image->common.transform->matrix[0][0]; -+ unit.vector[1] = image->common.transform->matrix[1][0]; -+ unit.vector[2] = image->common.transform->matrix[2][0]; -+ } -+ else -+ { -+ unit.vector[0] = pixman_fixed_1; -+ unit.vector[1] = 0; -+ unit.vector[2] = 0; -+ } -+ -+ dx = linear->p2.x - linear->p1.x; -+ dy = linear->p2.y - linear->p1.y; -+ -+ l = dx * dx + dy * dy; -+ -+ if (l == 0 || unit.vector[2] == 0) -+ { -+ /* affine transformation only */ -+ pixman_fixed_32_32_t t, next_inc; -+ double inc; -+ -+ if (l == 0 || v.vector[2] == 0) -+ { -+ t = 0; -+ inc = 0; -+ } -+ else -+ { -+ double invden, v2; -+ -+ invden = pixman_fixed_1 * (double) pixman_fixed_1 / -+ (l * (double) v.vector[2]); -+ v2 = v.vector[2] * (1. / pixman_fixed_1); -+ t = ((dx * v.vector[0] + dy * v.vector[1]) - -+ (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden; -+ inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden; -+ } -+ next_inc = 0; -+ -+ if (((pixman_fixed_32_32_t )(inc * width)) == 0) -+ { -+ register uint16_t color; -+ -+ color = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t)); -+ while (buffer < end) -+ *buffer++ = color; -+ } -+ else -+ { -+ int i; -+ -+ i = 0; -+ while (buffer < end) -+ { -+ if (!mask || *mask++) -+ { -+ *buffer = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker, -+ t + next_inc)); -+ } -+ i++; -+ next_inc = inc * i; -+ buffer++; -+ } -+ } -+ } -+ else -+ { -+ /* projective transformation */ -+ double t; -+ -+ t = 0; -+ -+ while (buffer < end) -+ { -+ if (!mask || *mask++) -+ { -+ if (v.vector[2] != 0) -+ { -+ double invden, v2; -+ -+ invden = pixman_fixed_1 * (double) pixman_fixed_1 / -+ (l * (double) v.vector[2]); -+ v2 = v.vector[2] * (1. / pixman_fixed_1); -+ t = ((dx * v.vector[0] + dy * v.vector[1]) - -+ (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden; -+ } -+ -+ *buffer = convert_8888_to_0565(_pixman_gradient_walker_pixel (&walker, t)); -+ } -+ -+ ++buffer; -+ -+ v.vector[0] += unit.vector[0]; -+ v.vector[1] += unit.vector[1]; -+ v.vector[2] += unit.vector[2]; -+ } -+ } -+ -+ iter->y++; -+ -+ return iter->buffer; -+} -+ - static uint32_t * - linear_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) - { - uint32_t *buffer = linear_get_scanline_narrow (iter, NULL); - - pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); - - return buffer; - } - - void - _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) - { - if (linear_gradient_is_horizontal ( - iter->image, iter->x, iter->y, iter->width, iter->height)) - { -- if (iter->flags & ITER_NARROW) -+ if (iter->flags & ITER_16) -+ linear_get_scanline_16 (iter, NULL); -+ else if (iter->flags & ITER_NARROW) - linear_get_scanline_narrow (iter, NULL); - else - linear_get_scanline_wide (iter, NULL); - - iter->get_scanline = _pixman_iter_get_scanline_noop; - } - else - { -- if (iter->flags & ITER_NARROW) -+ if (iter->flags & ITER_16) -+ iter->get_scanline = linear_get_scanline_16; -+ else if (iter->flags & ITER_NARROW) - iter->get_scanline = linear_get_scanline_narrow; - else - iter->get_scanline = linear_get_scanline_wide; - } - } - - PIXMAN_EXPORT pixman_image_t * - pixman_image_create_linear_gradient (pixman_point_fixed_t * p1, -diff --git a/gfx/cairo/libpixman/src/pixman-private.h b/gfx/cairo/libpixman/src/pixman-private.h ---- a/gfx/cairo/libpixman/src/pixman-private.h -+++ b/gfx/cairo/libpixman/src/pixman-private.h -@@ -152,24 +152,28 @@ struct bits_image - int height; - uint32_t * bits; - uint32_t * free_me; - int rowstride; /* in number of uint32_t's */ - - fetch_scanline_t get_scanline_32; - fetch_scanline_t get_scanline_64; - -+ fetch_scanline_t fetch_scanline_16; -+ - fetch_scanline_t fetch_scanline_32; - fetch_pixel_32_t fetch_pixel_32; - store_scanline_t store_scanline_32; - - fetch_scanline_t fetch_scanline_64; - fetch_pixel_64_t fetch_pixel_64; - store_scanline_t store_scanline_64; - -+ store_scanline_t store_scanline_16; -+ - /* Used for indirect access to the bits */ - pixman_read_memory_func_t read_func; - pixman_write_memory_func_t write_func; - }; - - union pixman_image - { - image_type_t type; -@@ -202,17 +206,24 @@ typedef enum - * destination. - * - * When he destination is xRGB, this is useful knowledge, because then - * we can treat it as if it were ARGB, which means in some cases we can - * avoid copying it to a temporary buffer. - */ - ITER_LOCALIZED_ALPHA = (1 << 1), - ITER_IGNORE_ALPHA = (1 << 2), -- ITER_IGNORE_RGB = (1 << 3) -+ ITER_IGNORE_RGB = (1 << 3), -+ -+ /* With the addition of ITER_16 we now have two flags that to represent -+ * 3 pipelines. This means that there can be an invalid state when -+ * both ITER_NARROW and ITER_16 are set. In this case -+ * ITER_16 overrides NARROW and we should use the 16 bit pipeline. -+ * Note: ITER_16 still has a 32 bit mask, which is a bit weird. */ -+ ITER_16 = (1 << 4) - } iter_flags_t; - - struct pixman_iter_t - { - /* These are initialized by _pixman_implementation_{src,dest}_init */ - pixman_image_t * image; - uint32_t * buffer; - int x, y; -@@ -429,16 +440,17 @@ typedef pixman_bool_t (*pixman_fill_func - int x, - int y, - int width, - int height, - uint32_t xor); - typedef void (*pixman_iter_init_func_t) (pixman_implementation_t *imp, - pixman_iter_t *iter); - -+void _pixman_setup_combiner_functions_16 (pixman_implementation_t *imp); - void _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp); - void _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp); - - typedef struct - { - pixman_op_t op; - pixman_format_code_t src_format; - uint32_t src_flags; -@@ -459,32 +471,34 @@ struct pixman_implementation_t - pixman_fill_func_t fill; - pixman_iter_init_func_t src_iter_init; - pixman_iter_init_func_t dest_iter_init; - - pixman_combine_32_func_t combine_32[PIXMAN_N_OPERATORS]; - pixman_combine_32_func_t combine_32_ca[PIXMAN_N_OPERATORS]; - pixman_combine_64_func_t combine_64[PIXMAN_N_OPERATORS]; - pixman_combine_64_func_t combine_64_ca[PIXMAN_N_OPERATORS]; -+ pixman_combine_64_func_t combine_16[PIXMAN_N_OPERATORS]; - }; - - uint32_t - _pixman_image_get_solid (pixman_implementation_t *imp, - pixman_image_t * image, - pixman_format_code_t format); - - pixman_implementation_t * - _pixman_implementation_create (pixman_implementation_t *delegate, - const pixman_fast_path_t *fast_paths); - - pixman_combine_32_func_t - _pixman_implementation_lookup_combiner (pixman_implementation_t *imp, - pixman_op_t op, - pixman_bool_t component_alpha, -- pixman_bool_t wide); -+ pixman_bool_t wide, -+ pixman_bool_t rgb16); - - pixman_bool_t - _pixman_implementation_blt (pixman_implementation_t *imp, - uint32_t * src_bits, - uint32_t * dst_bits, - int src_stride, - int dst_stride, - int src_bpp, -@@ -613,16 +627,17 @@ uint32_t * - #define FAST_PATH_Y_UNIT_ZERO (1 << 18) - #define FAST_PATH_BILINEAR_FILTER (1 << 19) - #define FAST_PATH_ROTATE_90_TRANSFORM (1 << 20) - #define FAST_PATH_ROTATE_180_TRANSFORM (1 << 21) - #define FAST_PATH_ROTATE_270_TRANSFORM (1 << 22) - #define FAST_PATH_SAMPLES_COVER_CLIP_NEAREST (1 << 23) - #define FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR (1 << 24) - #define FAST_PATH_BITS_IMAGE (1 << 25) -+#define FAST_PATH_16_FORMAT (1 << 26) - - #define FAST_PATH_PAD_REPEAT \ - (FAST_PATH_NO_NONE_REPEAT | \ - FAST_PATH_NO_NORMAL_REPEAT | \ - FAST_PATH_NO_REFLECT_REPEAT) - - #define FAST_PATH_NORMAL_REPEAT \ - (FAST_PATH_NO_NONE_REPEAT | \ -diff --git a/gfx/cairo/libpixman/src/pixman-radial-gradient.c b/gfx/cairo/libpixman/src/pixman-radial-gradient.c ---- a/gfx/cairo/libpixman/src/pixman-radial-gradient.c -+++ b/gfx/cairo/libpixman/src/pixman-radial-gradient.c -@@ -395,35 +395,289 @@ radial_get_scanline_narrow (pixman_iter_ - v.vector[2] += unit.vector[2]; - } - } - - iter->y++; - return iter->buffer; - } - -+static uint16_t convert_8888_to_0565(uint32_t color) -+{ -+ return CONVERT_8888_TO_0565(color); -+} -+ -+static uint32_t * -+radial_get_scanline_16 (pixman_iter_t *iter, const uint32_t *mask) -+{ -+ /* -+ * Implementation of radial gradients following the PDF specification. -+ * See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference -+ * Manual (PDF 32000-1:2008 at the time of this writing). -+ * -+ * In the radial gradient problem we are given two circles (c₁,r₁) and -+ * (c₂,r₂) that define the gradient itself. -+ * -+ * Mathematically the gradient can be defined as the family of circles -+ * -+ * ((1-t)·c₁ + t·(c₂), (1-t)·r₁ + t·r₂) -+ * -+ * excluding those circles whose radius would be < 0. When a point -+ * belongs to more than one circle, the one with a bigger t is the only -+ * one that contributes to its color. When a point does not belong -+ * to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0). -+ * Further limitations on the range of values for t are imposed when -+ * the gradient is not repeated, namely t must belong to [0,1]. -+ * -+ * The graphical result is the same as drawing the valid (radius > 0) -+ * circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient -+ * is not repeated) using SOURCE operator composition. -+ * -+ * It looks like a cone pointing towards the viewer if the ending circle -+ * is smaller than the starting one, a cone pointing inside the page if -+ * the starting circle is the smaller one and like a cylinder if they -+ * have the same radius. -+ * -+ * What we actually do is, given the point whose color we are interested -+ * in, compute the t values for that point, solving for t in: -+ * -+ * length((1-t)·c₁ + t·(c₂) - p) = (1-t)·r₁ + t·r₂ -+ * -+ * Let's rewrite it in a simpler way, by defining some auxiliary -+ * variables: -+ * -+ * cd = c₂ - c₁ -+ * pd = p - c₁ -+ * dr = r₂ - r₁ -+ * length(t·cd - pd) = r₁ + t·dr -+ * -+ * which actually means -+ * -+ * hypot(t·cdx - pdx, t·cdy - pdy) = r₁ + t·dr -+ * -+ * or -+ * -+ * ⎷((t·cdx - pdx)² + (t·cdy - pdy)²) = r₁ + t·dr. -+ * -+ * If we impose (as stated earlier) that r₁ + t·dr >= 0, it becomes: -+ * -+ * (t·cdx - pdx)² + (t·cdy - pdy)² = (r₁ + t·dr)² -+ * -+ * where we can actually expand the squares and solve for t: -+ * -+ * t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² = -+ * = r₁² + 2·r₁·t·dr + t²·dr² -+ * -+ * (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r₁·dr)t + -+ * (pdx² + pdy² - r₁²) = 0 -+ * -+ * A = cdx² + cdy² - dr² -+ * B = pdx·cdx + pdy·cdy + r₁·dr -+ * C = pdx² + pdy² - r₁² -+ * At² - 2Bt + C = 0 -+ * -+ * The solutions (unless the equation degenerates because of A = 0) are: -+ * -+ * t = (B ± ⎷(B² - A·C)) / A -+ * -+ * The solution we are going to prefer is the bigger one, unless the -+ * radius associated to it is negative (or it falls outside the valid t -+ * range). -+ * -+ * Additional observations (useful for optimizations): -+ * A does not depend on p -+ * -+ * A < 0 <=> one of the two circles completely contains the other one -+ * <=> for every p, the radiuses associated with the two t solutions -+ * have opposite sign -+ */ -+ pixman_image_t *image = iter->image; -+ int x = iter->x; -+ int y = iter->y; -+ int width = iter->width; -+ uint16_t *buffer = iter->buffer; -+ -+ gradient_t *gradient = (gradient_t *)image; -+ radial_gradient_t *radial = (radial_gradient_t *)image; -+ uint16_t *end = buffer + width; -+ pixman_gradient_walker_t walker; -+ pixman_vector_t v, unit; -+ -+ /* reference point is the center of the pixel */ -+ v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2; -+ v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2; -+ v.vector[2] = pixman_fixed_1; -+ -+ _pixman_gradient_walker_init (&walker, gradient, image->common.repeat); -+ -+ if (image->common.transform) -+ { -+ if (!pixman_transform_point_3d (image->common.transform, &v)) -+ return iter->buffer; -+ -+ unit.vector[0] = image->common.transform->matrix[0][0]; -+ unit.vector[1] = image->common.transform->matrix[1][0]; -+ unit.vector[2] = image->common.transform->matrix[2][0]; -+ } -+ else -+ { -+ unit.vector[0] = pixman_fixed_1; -+ unit.vector[1] = 0; -+ unit.vector[2] = 0; -+ } -+ -+ if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1) -+ { -+ /* -+ * Given: -+ * -+ * t = (B ± ⎷(B² - A·C)) / A -+ * -+ * where -+ * -+ * A = cdx² + cdy² - dr² -+ * B = pdx·cdx + pdy·cdy + r₁·dr -+ * C = pdx² + pdy² - r₁² -+ * det = B² - A·C -+ * -+ * Since we have an affine transformation, we know that (pdx, pdy) -+ * increase linearly with each pixel, -+ * -+ * pdx = pdx₀ + n·ux, -+ * pdy = pdy₀ + n·uy, -+ * -+ * we can then express B, C and det through multiple differentiation. -+ */ -+ pixman_fixed_32_32_t b, db, c, dc, ddc; -+ -+ /* warning: this computation may overflow */ -+ v.vector[0] -= radial->c1.x; -+ v.vector[1] -= radial->c1.y; -+ -+ /* -+ * B and C are computed and updated exactly. -+ * If fdot was used instead of dot, in the worst case it would -+ * lose 11 bits of precision in each of the multiplication and -+ * summing up would zero out all the bit that were preserved, -+ * thus making the result 0 instead of the correct one. -+ * This would mean a worst case of unbound relative error or -+ * about 2^10 absolute error -+ */ -+ b = dot (v.vector[0], v.vector[1], radial->c1.radius, -+ radial->delta.x, radial->delta.y, radial->delta.radius); -+ db = dot (unit.vector[0], unit.vector[1], 0, -+ radial->delta.x, radial->delta.y, 0); -+ -+ c = dot (v.vector[0], v.vector[1], -+ -((pixman_fixed_48_16_t) radial->c1.radius), -+ v.vector[0], v.vector[1], radial->c1.radius); -+ dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0], -+ 2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1], -+ 0, -+ unit.vector[0], unit.vector[1], 0); -+ ddc = 2 * dot (unit.vector[0], unit.vector[1], 0, -+ unit.vector[0], unit.vector[1], 0); -+ -+ while (buffer < end) -+ { -+ if (!mask || *mask++) -+ { -+ *buffer = convert_8888_to_0565( -+ radial_compute_color (radial->a, b, c, -+ radial->inva, -+ radial->delta.radius, -+ radial->mindr, -+ &walker, -+ image->common.repeat)); -+ } -+ -+ b += db; -+ c += dc; -+ dc += ddc; -+ ++buffer; -+ } -+ } -+ else -+ { -+ /* projective */ -+ /* Warning: -+ * error propagation guarantees are much looser than in the affine case -+ */ -+ while (buffer < end) -+ { -+ if (!mask || *mask++) -+ { -+ if (v.vector[2] != 0) -+ { -+ double pdx, pdy, invv2, b, c; -+ -+ invv2 = 1. * pixman_fixed_1 / v.vector[2]; -+ -+ pdx = v.vector[0] * invv2 - radial->c1.x; -+ /* / pixman_fixed_1 */ -+ -+ pdy = v.vector[1] * invv2 - radial->c1.y; -+ /* / pixman_fixed_1 */ -+ -+ b = fdot (pdx, pdy, radial->c1.radius, -+ radial->delta.x, radial->delta.y, -+ radial->delta.radius); -+ /* / pixman_fixed_1 / pixman_fixed_1 */ -+ -+ c = fdot (pdx, pdy, -radial->c1.radius, -+ pdx, pdy, radial->c1.radius); -+ /* / pixman_fixed_1 / pixman_fixed_1 */ -+ -+ *buffer = convert_8888_to_0565 ( -+ radial_compute_color (radial->a, b, c, -+ radial->inva, -+ radial->delta.radius, -+ radial->mindr, -+ &walker, -+ image->common.repeat)); -+ } -+ else -+ { -+ *buffer = 0; -+ } -+ } -+ -+ ++buffer; -+ -+ v.vector[0] += unit.vector[0]; -+ v.vector[1] += unit.vector[1]; -+ v.vector[2] += unit.vector[2]; -+ } -+ } -+ -+ iter->y++; -+ return iter->buffer; -+} - static uint32_t * - radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) - { - uint32_t *buffer = radial_get_scanline_narrow (iter, NULL); - - pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); - - return buffer; - } - - void - _pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) - { -- if (iter->flags & ITER_NARROW) -+ if (iter->flags & ITER_16) -+ iter->get_scanline = radial_get_scanline_16; -+ else if (iter->flags & ITER_NARROW) - iter->get_scanline = radial_get_scanline_narrow; - else - iter->get_scanline = radial_get_scanline_wide; - } - -+ - PIXMAN_EXPORT pixman_image_t * - pixman_image_create_radial_gradient (pixman_point_fixed_t * inner, - pixman_point_fixed_t * outer, - pixman_fixed_t inner_radius, - pixman_fixed_t outer_radius, - const pixman_gradient_stop_t *stops, - int n_stops) - { |