aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pixman/pixman/pixman-access.c40
-rw-r--r--pixman/pixman/pixman-bits-image.c401
-rw-r--r--pixman/pixman/pixman-fast-path.c9
-rw-r--r--pixman/pixman/pixman-image.c36
-rw-r--r--pixman/pixman/pixman-private.h51
-rw-r--r--pixman/pixman/pixman.c288
-rw-r--r--pixman/test/scaling-crash-test.c193
7 files changed, 655 insertions, 363 deletions
diff --git a/pixman/pixman/pixman-access.c b/pixman/pixman/pixman-access.c
index 33db7fd00..7ca856f3e 100644
--- a/pixman/pixman/pixman-access.c
+++ b/pixman/pixman/pixman-access.c
@@ -2732,7 +2732,7 @@ store_scanline_generic_64 (bits_image_t * image,
*/
pixman_contract (argb8_pixels, (uint64_t *)values, width);
- image->store_scanline_raw_32 (image, x, y, width, argb8_pixels);
+ image->store_scanline_32 (image, x, y, width, argb8_pixels);
free (argb8_pixels);
}
@@ -2753,7 +2753,7 @@ fetch_scanline_generic_64 (pixman_image_t *image,
/* Fetch the pixels into the first half of buffer and then expand them in
* place.
*/
- image->bits.fetch_scanline_raw_32 (image, x, y, width, buffer, NULL);
+ image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL);
format = image->bits.format;
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR ||
@@ -2776,7 +2776,7 @@ fetch_pixel_generic_64 (bits_image_t *image,
int offset,
int line)
{
- uint32_t pixel32 = image->fetch_pixel_raw_32 (image, offset, line);
+ uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line);
uint64_t result;
pixman_format_code_t format;
@@ -2808,7 +2808,7 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image,
int offset,
int line)
{
- uint64_t pixel64 = image->fetch_pixel_raw_64 (image, offset, line);
+ uint64_t pixel64 = image->fetch_pixel_64 (image, offset, line);
uint32_t result;
pixman_contract (&result, &pixel64, 1);
@@ -2819,12 +2819,12 @@ fetch_pixel_generic_lossy_32 (bits_image_t *image,
typedef struct
{
pixman_format_code_t format;
- fetch_scanline_t fetch_scanline_raw_32;
- fetch_scanline_t fetch_scanline_raw_64;
- fetch_pixel_32_t fetch_pixel_raw_32;
- fetch_pixel_64_t fetch_pixel_raw_64;
- store_scanline_t store_scanline_raw_32;
- store_scanline_t store_scanline_raw_64;
+ 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_32;
+ store_scanline_t store_scanline_64;
} format_info_t;
#define FORMAT_INFO(format) \
@@ -2951,12 +2951,12 @@ setup_accessors (bits_image_t *image)
{
if (info->format == image->format)
{
- image->fetch_scanline_raw_32 = info->fetch_scanline_raw_32;
- image->fetch_scanline_raw_64 = info->fetch_scanline_raw_64;
- image->fetch_pixel_raw_32 = info->fetch_pixel_raw_32;
- image->fetch_pixel_raw_64 = info->fetch_pixel_raw_64;
- image->store_scanline_raw_32 = info->store_scanline_raw_32;
- image->store_scanline_raw_64 = info->store_scanline_raw_64;
+ 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_32 = info->store_scanline_32;
+ image->store_scanline_64 = info->store_scanline_64;
return;
}
@@ -2967,13 +2967,13 @@ setup_accessors (bits_image_t *image)
#ifndef PIXMAN_FB_ACCESSORS
void
-_pixman_bits_image_setup_raw_accessors_accessors (bits_image_t *image);
+_pixman_bits_image_setup_accessors_accessors (bits_image_t *image);
void
-_pixman_bits_image_setup_raw_accessors (bits_image_t *image)
+_pixman_bits_image_setup_accessors (bits_image_t *image)
{
if (image->read_func || image->write_func)
- _pixman_bits_image_setup_raw_accessors_accessors (image);
+ _pixman_bits_image_setup_accessors_accessors (image);
else
setup_accessors (image);
}
@@ -2981,7 +2981,7 @@ _pixman_bits_image_setup_raw_accessors (bits_image_t *image)
#else
void
-_pixman_bits_image_setup_raw_accessors_accessors (bits_image_t *image)
+_pixman_bits_image_setup_accessors_accessors (bits_image_t *image)
{
setup_accessors (image);
}
diff --git a/pixman/pixman/pixman-bits-image.c b/pixman/pixman/pixman-bits-image.c
index f8a76a5a3..806c65e7a 100644
--- a/pixman/pixman/pixman-bits-image.c
+++ b/pixman/pixman/pixman-bits-image.c
@@ -36,43 +36,6 @@
#include "pixman-combine32.h"
/* Store functions */
-
-static void
-bits_image_store_scanline_32 (bits_image_t * image,
- int x,
- int y,
- int width,
- const uint32_t *buffer)
-{
- image->store_scanline_raw_32 (image, x, y, width, buffer);
-
- if (image->common.alpha_map)
- {
- x -= image->common.alpha_origin_x;
- y -= image->common.alpha_origin_y;
-
- bits_image_store_scanline_32 (image->common.alpha_map, x, y, width, buffer);
- }
-}
-
-static void
-bits_image_store_scanline_64 (bits_image_t * image,
- int x,
- int y,
- int width,
- const uint32_t *buffer)
-{
- image->store_scanline_raw_64 (image, x, y, width, buffer);
-
- if (image->common.alpha_map)
- {
- x -= image->common.alpha_origin_x;
- y -= image->common.alpha_origin_y;
-
- bits_image_store_scanline_64 (image->common.alpha_map, x, y, width, buffer);
- }
-}
-
void
_pixman_image_store_scanline_32 (bits_image_t * image,
int x,
@@ -81,6 +44,15 @@ _pixman_image_store_scanline_32 (bits_image_t * image,
const uint32_t *buffer)
{
image->store_scanline_32 (image, x, y, width, buffer);
+
+ if (image->common.alpha_map)
+ {
+ x -= image->common.alpha_origin_x;
+ y -= image->common.alpha_origin_y;
+
+ image->common.alpha_map->store_scanline_32 (
+ image->common.alpha_map, x, y, width, buffer);
+ }
}
void
@@ -91,43 +63,22 @@ _pixman_image_store_scanline_64 (bits_image_t * image,
const uint32_t *buffer)
{
image->store_scanline_64 (image, x, y, width, buffer);
-}
-
-/* Fetch functions */
-
-static uint32_t
-bits_image_fetch_pixel_alpha (bits_image_t *image, int x, int y)
-{
- uint32_t pixel;
- uint32_t pixel_a;
-
- pixel = image->fetch_pixel_raw_32 (image, x, y);
- assert (image->common.alpha_map);
-
- x -= image->common.alpha_origin_x;
- y -= image->common.alpha_origin_y;
-
- if (x < 0 || x >= image->common.alpha_map->width ||
- y < 0 || y >= image->common.alpha_map->height)
- {
- pixel_a = 0;
- }
- else
+ if (image->common.alpha_map)
{
- pixel_a = image->common.alpha_map->fetch_pixel_raw_32 (
- image->common.alpha_map, x, y);
- pixel_a = ALPHA_8 (pixel_a);
- }
-
- pixel &= 0x00ffffff;
- pixel |= (pixel_a << 24);
+ x -= image->common.alpha_origin_x;
+ y -= image->common.alpha_origin_y;
- return pixel;
+ image->common.alpha_map->store_scanline_64 (
+ image->common.alpha_map, x, y, width, buffer);
+ }
}
+/* Fetch functions */
+
static force_inline uint32_t
-get_pixel (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
+fetch_pixel_no_alpha (bits_image_t *image,
+ int x, int y, pixman_bool_t check_bounds)
{
if (check_bounds &&
(x < 0 || x >= image->width || y < 0 || y >= image->height))
@@ -138,6 +89,9 @@ get_pixel (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
return image->fetch_pixel_32 (image, x, y);
}
+typedef uint32_t (* get_pixel_t) (bits_image_t *image,
+ int x, int y, pixman_bool_t check_bounds);
+
static force_inline void
repeat (pixman_repeat_t repeat, int size, int *coord)
{
@@ -169,7 +123,8 @@ repeat (pixman_repeat_t repeat, int size, int *coord)
static force_inline uint32_t
bits_image_fetch_pixel_nearest (bits_image_t *image,
pixman_fixed_t x,
- pixman_fixed_t y)
+ pixman_fixed_t y,
+ get_pixel_t get_pixel)
{
int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
@@ -281,7 +236,8 @@ bilinear_interpolation (uint32_t tl, uint32_t tr,
static force_inline uint32_t
bits_image_fetch_pixel_bilinear (bits_image_t *image,
pixman_fixed_t x,
- pixman_fixed_t y)
+ pixman_fixed_t y,
+ get_pixel_t get_pixel)
{
pixman_repeat_t repeat_mode = image->common.repeat;
int width = image->width;
@@ -538,7 +494,8 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
static force_inline uint32_t
bits_image_fetch_pixel_convolution (bits_image_t *image,
pixman_fixed_t x,
- pixman_fixed_t y)
+ pixman_fixed_t y,
+ get_pixel_t get_pixel)
{
pixman_fixed_t *params = image->common.filter_params;
int x_off = (params[0] - pixman_fixed_1) >> 1;
@@ -611,23 +568,24 @@ bits_image_fetch_pixel_convolution (bits_image_t *image,
static force_inline uint32_t
bits_image_fetch_pixel_filtered (bits_image_t *image,
pixman_fixed_t x,
- pixman_fixed_t y)
+ pixman_fixed_t y,
+ get_pixel_t get_pixel)
{
switch (image->common.filter)
{
case PIXMAN_FILTER_NEAREST:
case PIXMAN_FILTER_FAST:
- return bits_image_fetch_pixel_nearest (image, x, y);
+ return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
break;
case PIXMAN_FILTER_BILINEAR:
case PIXMAN_FILTER_GOOD:
case PIXMAN_FILTER_BEST:
- return bits_image_fetch_pixel_bilinear (image, x, y);
+ return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
break;
case PIXMAN_FILTER_CONVOLUTION:
- return bits_image_fetch_pixel_convolution (image, x, y);
+ return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
break;
default:
@@ -638,12 +596,101 @@ bits_image_fetch_pixel_filtered (bits_image_t *image,
}
static void
-bits_image_fetch_transformed (pixman_image_t * image,
- int offset,
- int line,
- int width,
- uint32_t * buffer,
- const uint32_t * mask)
+bits_image_fetch_affine_no_alpha (pixman_image_t * image,
+ int offset,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t * mask)
+{
+ pixman_fixed_t x, y;
+ pixman_fixed_t ux, uy;
+ pixman_vector_t v;
+ int i;
+
+ /* reference point is the center of the pixel */
+ v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
+ v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
+ v.vector[2] = pixman_fixed_1;
+
+ if (image->common.transform)
+ {
+ if (!pixman_transform_point_3d (image->common.transform, &v))
+ return;
+
+ ux = image->common.transform->matrix[0][0];
+ uy = image->common.transform->matrix[1][0];
+ }
+ else
+ {
+ ux = pixman_fixed_1;
+ uy = 0;
+ }
+
+ x = v.vector[0];
+ y = v.vector[1];
+
+ for (i = 0; i < width; ++i)
+ {
+ if (!mask || mask[i])
+ {
+ buffer[i] = bits_image_fetch_pixel_filtered (
+ &image->bits, x, y, fetch_pixel_no_alpha);
+ }
+
+ x += ux;
+ y += uy;
+ }
+}
+
+/* General fetcher */
+static force_inline uint32_t
+fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
+{
+ uint32_t pixel;
+
+ if (check_bounds &&
+ (x < 0 || x >= image->width || y < 0 || y >= image->height))
+ {
+ return 0;
+ }
+
+ pixel = image->fetch_pixel_32 (image, x, y);
+
+ if (image->common.alpha_map)
+ {
+ uint32_t pixel_a;
+
+ x -= image->common.alpha_origin_x;
+ y -= image->common.alpha_origin_y;
+
+ if (x < 0 || x >= image->common.alpha_map->width ||
+ y < 0 || y >= image->common.alpha_map->height)
+ {
+ pixel_a = 0;
+ }
+ else
+ {
+ pixel_a = image->common.alpha_map->fetch_pixel_32 (
+ image->common.alpha_map, x, y);
+
+ pixel_a = ALPHA_8 (pixel_a);
+ }
+
+ pixel &= 0x00ffffff;
+ pixel |= (pixel_a << 24);
+ }
+
+ return pixel;
+}
+
+static void
+bits_image_fetch_general (pixman_image_t * image,
+ int offset,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t * mask)
{
pixman_fixed_t x, y, w;
pixman_fixed_t ux, uy, uw;
@@ -655,8 +702,6 @@ bits_image_fetch_transformed (pixman_image_t * image,
v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
- /* when using convolution filters or PIXMAN_REPEAT_PAD one
- * might get here without a transform */
if (image->common.transform)
{
if (!pixman_transform_point_3d (image->common.transform, &v))
@@ -677,47 +722,30 @@ bits_image_fetch_transformed (pixman_image_t * image,
y = v.vector[1];
w = v.vector[2];
- if (w == pixman_fixed_1 && uw == 0) /* Affine */
+ for (i = 0; i < width; ++i)
{
- for (i = 0; i < width; ++i)
+ pixman_fixed_t x0, y0;
+
+ if (!mask || mask[i])
{
- if (!mask || mask[i])
+ if (w != 0)
{
- buffer[i] =
- bits_image_fetch_pixel_filtered (&image->bits, x, y);
+ x0 = ((pixman_fixed_48_16_t)x << 16) / w;
+ y0 = ((pixman_fixed_48_16_t)y << 16) / w;
}
-
- x += ux;
- y += uy;
- }
- }
- else
- {
- for (i = 0; i < width; ++i)
- {
- if (!mask || mask[i])
+ else
{
- pixman_fixed_t x0, y0;
-
- if (w != 0)
- {
- x0 = ((pixman_fixed_48_16_t)x << 16) / w;
- y0 = ((pixman_fixed_48_16_t)y << 16) / w;
- }
- else
- {
- x0 = 0;
- y0 = 0;
- }
-
- buffer[i] =
- bits_image_fetch_pixel_filtered (&image->bits, x0, y0);
+ x0 = 0;
+ y0 = 0;
}
- x += ux;
- y += uy;
- w += uw;
+ buffer[i] = bits_image_fetch_pixel_filtered (
+ &image->bits, x0, y0, fetch_pixel_general);
}
+
+ x += ux;
+ y += uy;
+ w += uw;
}
}
@@ -732,7 +760,7 @@ bits_image_fetch_solid_32 (pixman_image_t * image,
uint32_t color;
uint32_t *end;
- color = image->bits.fetch_pixel_raw_32 (&image->bits, 0, 0);
+ color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
end = buffer + width;
while (buffer < end)
@@ -751,7 +779,7 @@ bits_image_fetch_solid_64 (pixman_image_t * image,
uint64_t *buffer = (uint64_t *)b;
uint64_t *end;
- color = image->bits.fetch_pixel_raw_64 (&image->bits, 0, 0);
+ color = image->bits.fetch_pixel_64 (&image->bits, 0, 0);
end = buffer + width;
while (buffer < end)
@@ -790,9 +818,9 @@ bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
w = MIN (width, image->width - x);
if (wide)
- image->fetch_scanline_raw_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+ image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
else
- image->fetch_scanline_raw_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+ image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
width -= w;
buffer += w * (wide? 2 : 1);
@@ -828,9 +856,9 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
w = MIN (width, image->width - x);
if (wide)
- image->fetch_scanline_raw_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+ image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
else
- image->fetch_scanline_raw_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
+ image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
buffer += w * (wide? 2 : 1);
x += w;
@@ -878,68 +906,89 @@ bits_image_fetch_untransformed_64 (pixman_image_t * image,
}
}
+typedef struct
+{
+ pixman_format_code_t format;
+ uint32_t flags;
+ fetch_scanline_t fetch_32;
+ fetch_scanline_t fetch_64;
+} fetcher_info_t;
+
+static const fetcher_info_t fetcher_info[] =
+{
+ { PIXMAN_solid,
+ FAST_PATH_NO_ALPHA_MAP,
+ bits_image_fetch_solid_32,
+ bits_image_fetch_solid_64
+ },
+
+ { PIXMAN_any,
+ (FAST_PATH_NO_ALPHA_MAP |
+ FAST_PATH_ID_TRANSFORM |
+ FAST_PATH_NO_CONVOLUTION_FILTER |
+ FAST_PATH_NO_PAD_REPEAT |
+ FAST_PATH_NO_REFLECT_REPEAT),
+ bits_image_fetch_untransformed_32,
+ bits_image_fetch_untransformed_64
+ },
+
+#define FAST_BILINEAR_FLAGS \
+ (FAST_PATH_NO_ALPHA_MAP | \
+ FAST_PATH_NO_ACCESSORS | \
+ FAST_PATH_HAS_TRANSFORM | \
+ FAST_PATH_AFFINE_TRANSFORM | \
+ FAST_PATH_X_UNIT_POSITIVE | \
+ FAST_PATH_Y_UNIT_ZERO | \
+ FAST_PATH_NONE_REPEAT | \
+ FAST_PATH_BILINEAR_FILTER)
+
+ { PIXMAN_a8r8g8b8,
+ FAST_BILINEAR_FLAGS,
+ bits_image_fetch_bilinear_no_repeat_8888,
+ _pixman_image_get_scanline_generic_64
+ },
+
+ { PIXMAN_x8r8g8b8,
+ FAST_BILINEAR_FLAGS,
+ bits_image_fetch_bilinear_no_repeat_8888,
+ _pixman_image_get_scanline_generic_64
+ },
+
+ { PIXMAN_any,
+ (FAST_PATH_NO_ALPHA_MAP |
+ FAST_PATH_HAS_TRANSFORM |
+ FAST_PATH_AFFINE_TRANSFORM),
+ bits_image_fetch_affine_no_alpha,
+ _pixman_image_get_scanline_generic_64
+ },
+
+ { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
+
+ { PIXMAN_null },
+};
+
static void
bits_image_property_changed (pixman_image_t *image)
{
- bits_image_t *bits = (bits_image_t *)image;
+ uint32_t flags = image->common.flags;
+ pixman_format_code_t format = image->common.extended_format_code;
+ const fetcher_info_t *info;
- _pixman_bits_image_setup_raw_accessors (bits);
+ _pixman_bits_image_setup_accessors (&image->bits);
- image->bits.fetch_pixel_32 = image->bits.fetch_pixel_raw_32;
-
- if (bits->common.alpha_map)
+ info = fetcher_info;
+ while (info->format != PIXMAN_null)
{
- image->common.get_scanline_64 =
- _pixman_image_get_scanline_generic_64;
- image->common.get_scanline_32 =
- bits_image_fetch_transformed;
+ if ((info->format == format || info->format == PIXMAN_any) &&
+ (info->flags & flags) == info->flags)
+ {
+ image->common.get_scanline_32 = info->fetch_32;
+ image->common.get_scanline_64 = info->fetch_64;
+ break;
+ }
- image->bits.fetch_pixel_32 = bits_image_fetch_pixel_alpha;
- }
- else if ((bits->common.repeat != PIXMAN_REPEAT_NONE) &&
- bits->width == 1 &&
- bits->height == 1)
- {
- image->common.get_scanline_64 = bits_image_fetch_solid_64;
- image->common.get_scanline_32 = bits_image_fetch_solid_32;
- }
- else if (!bits->common.transform &&
- bits->common.filter != PIXMAN_FILTER_CONVOLUTION &&
- (bits->common.repeat == PIXMAN_REPEAT_NONE ||
- bits->common.repeat == PIXMAN_REPEAT_NORMAL))
- {
- image->common.get_scanline_64 = bits_image_fetch_untransformed_64;
- image->common.get_scanline_32 = bits_image_fetch_untransformed_32;
- }
- else if (bits->common.transform &&
- bits->common.transform->matrix[2][0] == 0 &&
- bits->common.transform->matrix[2][1] == 0 &&
- bits->common.transform->matrix[2][2] == pixman_fixed_1 &&
- bits->common.transform->matrix[0][0] > 0 &&
- bits->common.transform->matrix[1][0] == 0 &&
- !bits->read_func &&
- (bits->common.filter == PIXMAN_FILTER_BILINEAR ||
- bits->common.filter == PIXMAN_FILTER_GOOD ||
- bits->common.filter == PIXMAN_FILTER_BEST) &&
- bits->common.repeat == PIXMAN_REPEAT_NONE &&
- (bits->format == PIXMAN_a8r8g8b8 ||
- bits->format == PIXMAN_x8r8g8b8))
- {
- image->common.get_scanline_64 =
- _pixman_image_get_scanline_generic_64;
- image->common.get_scanline_32 =
- bits_image_fetch_bilinear_no_repeat_8888;
+ info++;
}
- else
- {
- image->common.get_scanline_64 =
- _pixman_image_get_scanline_generic_64;
- image->common.get_scanline_32 =
- bits_image_fetch_transformed;
- }
-
- bits->store_scanline_64 = bits_image_store_scanline_64;
- bits->store_scanline_32 = bits_image_store_scanline_32;
}
static uint32_t *
diff --git a/pixman/pixman/pixman-fast-path.c b/pixman/pixman/pixman-fast-path.c
index cd39980fc..8165db4c7 100644
--- a/pixman/pixman/pixman-fast-path.c
+++ b/pixman/pixman/pixman-fast-path.c
@@ -1873,15 +1873,12 @@ static const pixman_fast_path_t c_fast_paths[] =
FAST_PATH_NO_ACCESSORS | \
FAST_PATH_NO_WIDE_FORMAT)
-#define HAS_NORMAL_REPEAT_FLAGS \
- (FAST_PATH_NO_REFLECT_REPEAT | \
- FAST_PATH_NO_PAD_REPEAT | \
- FAST_PATH_NO_NONE_REPEAT)
-
#define SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \
{ PIXMAN_OP_ ## op, \
PIXMAN_ ## s, \
- SCALED_NEAREST_FLAGS | HAS_NORMAL_REPEAT_FLAGS | FAST_PATH_16BIT_SAFE | FAST_PATH_X_UNIT_POSITIVE, \
+ (SCALED_NEAREST_FLAGS | \
+ FAST_PATH_NORMAL_REPEAT | \
+ FAST_PATH_X_UNIT_POSITIVE), \
PIXMAN_null, 0, \
PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \
fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \
diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c
index 971859318..1cce9273d 100644
--- a/pixman/pixman/pixman-image.c
+++ b/pixman/pixman/pixman-image.c
@@ -297,21 +297,33 @@ compute_image_info (pixman_image_t *image)
/* Transform */
if (!image->common.transform)
{
- flags |= (FAST_PATH_ID_TRANSFORM | FAST_PATH_X_UNIT_POSITIVE);
+ flags |= (FAST_PATH_ID_TRANSFORM |
+ FAST_PATH_X_UNIT_POSITIVE |
+ FAST_PATH_Y_UNIT_ZERO |
+ FAST_PATH_AFFINE_TRANSFORM);
}
else
{
- if (image->common.transform->matrix[0][1] == 0 &&
- image->common.transform->matrix[1][0] == 0 &&
- image->common.transform->matrix[2][0] == 0 &&
- image->common.transform->matrix[2][1] == 0 &&
+ flags |= FAST_PATH_HAS_TRANSFORM;
+
+ if (image->common.transform->matrix[2][0] == 0 &&
+ image->common.transform->matrix[2][1] == 0 &&
image->common.transform->matrix[2][2] == pixman_fixed_1)
{
- flags |= FAST_PATH_SCALE_TRANSFORM;
+ flags |= FAST_PATH_AFFINE_TRANSFORM;
+
+ if (image->common.transform->matrix[0][1] == 0 &&
+ image->common.transform->matrix[1][0] == 0)
+ {
+ flags |= FAST_PATH_SCALE_TRANSFORM;
+ }
}
if (image->common.transform->matrix[0][0] > 0)
flags |= FAST_PATH_X_UNIT_POSITIVE;
+
+ if (image->common.transform->matrix[1][0] == 0)
+ flags |= FAST_PATH_Y_UNIT_ZERO;
}
/* Alpha map */
@@ -326,6 +338,12 @@ compute_image_info (pixman_image_t *image)
flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
break;
+ case PIXMAN_FILTER_BILINEAR:
+ case PIXMAN_FILTER_GOOD:
+ case PIXMAN_FILTER_BEST:
+ flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
+ break;
+
case PIXMAN_FILTER_CONVOLUTION:
break;
@@ -338,15 +356,15 @@ compute_image_info (pixman_image_t *image)
switch (image->common.repeat)
{
case PIXMAN_REPEAT_NONE:
- flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT;
+ flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
break;
case PIXMAN_REPEAT_REFLECT:
- flags |= FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT;
+ flags |= FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
break;
case PIXMAN_REPEAT_PAD:
- flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_NONE_REPEAT;
+ flags |= FAST_PATH_NO_REFLECT_REPEAT | FAST_PATH_NO_NONE_REPEAT | FAST_PATH_NO_NORMAL_REPEAT;
break;
default:
diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h
index 450f7654e..6774b1514 100644
--- a/pixman/pixman/pixman-private.h
+++ b/pixman/pixman/pixman-private.h
@@ -175,24 +175,12 @@ struct bits_image
uint32_t * free_me;
int rowstride; /* in number of uint32_t's */
- /* Fetch a pixel, disregarding alpha maps, transformations etc. */
- fetch_pixel_32_t fetch_pixel_raw_32;
- fetch_pixel_64_t fetch_pixel_raw_64;
-
- /* Fetch a pixel, taking alpha maps into account */
+ fetch_scanline_t fetch_scanline_32;
fetch_pixel_32_t fetch_pixel_32;
- fetch_pixel_64_t fetch_pixel_64;
-
- /* Fetch raw scanlines, with no regard for transformations, alpha maps etc. */
- fetch_scanline_t fetch_scanline_raw_32;
- fetch_scanline_t fetch_scanline_raw_64;
-
- /* Store scanlines with no regard for alpha maps */
- store_scanline_t store_scanline_raw_32;
- store_scanline_t store_scanline_raw_64;
-
- /* Store a scanline, taking alpha maps into account */
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;
/* Used for indirect access to the bits */
@@ -213,9 +201,8 @@ union pixman_image
solid_fill_t solid;
};
-
void
-_pixman_bits_image_setup_raw_accessors (bits_image_t *image);
+_pixman_bits_image_setup_accessors (bits_image_t *image);
void
_pixman_image_get_scanline_generic_64 (pixman_image_t *image,
@@ -577,8 +564,32 @@ _pixman_choose_implementation (void);
#define FAST_PATH_NEEDS_WORKAROUND (1 << 14)
#define FAST_PATH_NO_NONE_REPEAT (1 << 15)
#define FAST_PATH_SAMPLES_COVER_CLIP (1 << 16)
-#define FAST_PATH_16BIT_SAFE (1 << 17)
-#define FAST_PATH_X_UNIT_POSITIVE (1 << 18)
+#define FAST_PATH_X_UNIT_POSITIVE (1 << 17)
+#define FAST_PATH_AFFINE_TRANSFORM (1 << 18)
+#define FAST_PATH_Y_UNIT_ZERO (1 << 19)
+#define FAST_PATH_BILINEAR_FILTER (1 << 20)
+#define FAST_PATH_NO_NORMAL_REPEAT (1 << 21)
+#define FAST_PATH_HAS_TRANSFORM (1 << 22)
+
+#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 | \
+ FAST_PATH_NO_PAD_REPEAT | \
+ FAST_PATH_NO_REFLECT_REPEAT)
+
+#define FAST_PATH_NONE_REPEAT \
+ (FAST_PATH_NO_NORMAL_REPEAT | \
+ FAST_PATH_NO_PAD_REPEAT | \
+ FAST_PATH_NO_REFLECT_REPEAT)
+
+#define FAST_PATH_REFLECT_REPEAT \
+ (FAST_PATH_NO_NONE_REPEAT | \
+ FAST_PATH_NO_NORMAL_REPEAT | \
+ FAST_PATH_NO_PAD_REPEAT)
#define _FAST_PATH_STANDARD_FLAGS \
(FAST_PATH_ID_TRANSFORM | \
diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c
index a27e33b2c..1dbfd83f8 100644
--- a/pixman/pixman/pixman.c
+++ b/pixman/pixman/pixman.c
@@ -488,77 +488,6 @@ walk_region_internal (pixman_implementation_t *imp,
}
}
-#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
-
-static force_inline uint32_t
-compute_src_extents_flags (pixman_image_t *image,
- pixman_box32_t *extents,
- int x,
- int y)
-{
- pixman_box16_t extents16;
- uint32_t flags;
-
- flags = FAST_PATH_COVERS_CLIP;
-
- if (image->common.type != BITS)
- return flags;
-
- if (image->common.repeat == PIXMAN_REPEAT_NONE &&
- (x > extents->x1 || y > extents->y1 ||
- x + image->bits.width < extents->x2 ||
- y + image->bits.height < extents->y2))
- {
- flags &= ~FAST_PATH_COVERS_CLIP;
- }
-
- if (IS_16BIT (extents->x1 - x) &&
- IS_16BIT (extents->y1 - y) &&
- IS_16BIT (extents->x2 - x) &&
- IS_16BIT (extents->y2 - y))
- {
- extents16.x1 = extents->x1 - x;
- extents16.y1 = extents->y1 - y;
- extents16.x2 = extents->x2 - x;
- extents16.y2 = extents->y2 - y;
-
- if (!image->common.transform ||
- pixman_transform_bounds (image->common.transform, &extents16))
- {
- if (extents16.x1 >= 0 && extents16.y1 >= 0 &&
- extents16.x2 <= image->bits.width &&
- extents16.y2 <= image->bits.height)
- {
- flags |= FAST_PATH_SAMPLES_COVER_CLIP;
- }
- }
- }
-
- if (IS_16BIT (extents->x1 - x - 1) &&
- IS_16BIT (extents->y1 - y - 1) &&
- IS_16BIT (extents->x2 - x + 1) &&
- IS_16BIT (extents->y2 - y + 1))
- {
- extents16.x1 = extents->x1 - x - 1;
- extents16.y1 = extents->y1 - y - 1;
- extents16.x2 = extents->x2 - x + 1;
- extents16.y2 = extents->y2 - y + 1;
-
- if (/* src space expanded by one in dest space fits in 16 bit */
- (!image->common.transform ||
- pixman_transform_bounds (image->common.transform, &extents16)) &&
- /* And src image size can be used as 16.16 fixed point */
- image->bits.width < 0x7fff &&
- image->bits.height < 0x7fff)
- {
- /* Then we're "16bit safe" */
- flags |= FAST_PATH_16BIT_SAFE;
- }
- }
-
- return flags;
-}
-
#define N_CACHED_FAST_PATHS 8
typedef struct
@@ -668,6 +597,208 @@ update_cache:
}
}
+static pixman_bool_t
+compute_sample_extents (pixman_transform_t *transform,
+ pixman_box32_t *extents, int x, int y,
+ pixman_fixed_t x_off, pixman_fixed_t y_off,
+ pixman_fixed_t width, pixman_fixed_t height)
+{
+ pixman_fixed_t x1, y1, x2, y2;
+ pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
+
+ /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
+ x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
+ y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
+ x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
+ y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
+
+ if (!transform)
+ {
+ tx1 = (pixman_fixed_48_16_t)x1;
+ ty1 = (pixman_fixed_48_16_t)y1;
+ tx2 = (pixman_fixed_48_16_t)x2;
+ ty2 = (pixman_fixed_48_16_t)y2;
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ pixman_fixed_48_16_t tx, ty;
+ pixman_vector_t v;
+
+ v.vector[0] = (i & 0x01)? x1 : x2;
+ v.vector[1] = (i & 0x02)? y1 : y2;
+ v.vector[2] = pixman_fixed_1;
+
+ if (!pixman_transform_point (transform, &v))
+ return FALSE;
+
+ tx = (pixman_fixed_48_16_t)v.vector[0];
+ ty = (pixman_fixed_48_16_t)v.vector[1];
+
+ if (i == 0)
+ {
+ tx1 = tx;
+ ty1 = ty;
+ tx2 = tx;
+ ty2 = ty;
+ }
+ else
+ {
+ if (tx < tx1)
+ tx1 = tx;
+ if (ty < ty1)
+ ty1 = ty;
+ if (tx > tx2)
+ tx2 = tx;
+ if (ty > ty2)
+ ty2 = ty;
+ }
+ }
+ }
+
+ /* Expand the source area by a tiny bit so account of different rounding that
+ * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
+ * 0.5 so this won't cause the area computed to be overly pessimistic.
+ */
+ tx1 += x_off - 8 * pixman_fixed_e;
+ ty1 += y_off - 8 * pixman_fixed_e;
+ tx2 += x_off + width + 8 * pixman_fixed_e;
+ ty2 += y_off + height + 8 * pixman_fixed_e;
+
+ if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
+ ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
+ tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
+ ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
+ {
+ return FALSE;
+ }
+ else
+ {
+ extents->x1 = pixman_fixed_to_int (tx1);
+ extents->y1 = pixman_fixed_to_int (ty1);
+ extents->x2 = pixman_fixed_to_int (tx2) + 1;
+ extents->y2 = pixman_fixed_to_int (ty2) + 1;
+
+ return TRUE;
+ }
+}
+
+#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
+
+static pixman_bool_t
+analyze_extent (pixman_image_t *image, int x, int y,
+ const pixman_box32_t *extents, uint32_t *flags)
+{
+ pixman_transform_t *transform;
+ pixman_fixed_t *params;
+ pixman_fixed_t x_off, y_off;
+ pixman_fixed_t width, height;
+ pixman_box32_t ex;
+
+ *flags |= FAST_PATH_COVERS_CLIP;
+ if (!image)
+ return TRUE;
+
+ transform = image->common.transform;
+ if (image->common.type == BITS)
+ {
+ /* During repeat mode calculations we might convert the
+ * width/height of an image to fixed 16.16, so we need
+ * them to be smaller than 16 bits.
+ */
+ if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
+ return FALSE;
+
+ if (image->common.repeat == PIXMAN_REPEAT_NONE &&
+ (x > extents->x1 || y > extents->y1 ||
+ x + image->bits.width < extents->x2 ||
+ y + image->bits.height < extents->y2))
+ {
+ (*flags) &= ~FAST_PATH_COVERS_CLIP;
+ }
+ }
+
+ /* Some compositing functions walk one step
+ * outside the destination rectangle, so we
+ * check here that the expanded-by-one source
+ * extents in destination space fits in 16 bits
+ */
+ if (!IS_16BIT (extents->x1 - x - 1) ||
+ !IS_16BIT (extents->y1 - y - 1) ||
+ !IS_16BIT (extents->x2 - x + 1) ||
+ !IS_16BIT (extents->y2 - y + 1))
+ {
+ return FALSE;
+ }
+
+ if (image->common.type == BITS)
+ {
+ switch (image->common.filter)
+ {
+ case PIXMAN_FILTER_CONVOLUTION:
+ params = image->common.filter_params;
+ x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
+ y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
+ width = params[0];
+ height = params[1];
+ break;
+
+ case PIXMAN_FILTER_GOOD:
+ case PIXMAN_FILTER_BEST:
+ case PIXMAN_FILTER_BILINEAR:
+ x_off = - pixman_fixed_1 / 2;
+ y_off = - pixman_fixed_1 / 2;
+ width = pixman_fixed_1;
+ height = pixman_fixed_1;
+ break;
+
+ case PIXMAN_FILTER_FAST:
+ case PIXMAN_FILTER_NEAREST:
+ x_off = - pixman_fixed_e;
+ y_off = - pixman_fixed_e;
+ width = 0;
+ height = 0;
+ break;
+
+ default:
+ return FALSE;
+ }
+ }
+ else
+ {
+ x_off = 0;
+ y_off = 0;
+ width = 0;
+ height = 0;
+ }
+
+ /* Check that the extents expanded by one don't overflow. This ensures that
+ * compositing functions can simply walk the source space using 16.16 variables
+ * without worrying about overflow.
+ */
+ ex.x1 = extents->x1 - 1;
+ ex.y1 = extents->y1 - 1;
+ ex.x2 = extents->x2 + 1;
+ ex.y2 = extents->y2 + 1;
+
+ if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
+ return FALSE;
+
+ /* Check whether the non-expanded, transformed extent is entirely within
+ * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
+ */
+ ex = *extents;
+ if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
+ {
+ if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
+ *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
+ }
+
+ return TRUE;
+}
static void
do_composite (pixman_op_t op,
@@ -737,20 +868,21 @@ do_composite (pixman_op_t op,
}
pixman_region32_init (&region);
-
+
if (!pixman_compute_composite_region32 (
&region, src, mask, dest,
src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
{
goto out;
}
-
+
extents = pixman_region32_extents (&region);
-
- src_flags |= compute_src_extents_flags (src, extents, dest_x - src_x, dest_y - src_y);
- if (mask)
- mask_flags |= compute_src_extents_flags (mask, extents, dest_x - mask_x, dest_y - mask_y);
+ if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
+ goto out;
+
+ if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
+ goto out;
/*
* Check if we can replace our operator by a simpler one
@@ -765,7 +897,7 @@ do_composite (pixman_op_t op,
src_format, src_flags,
mask_format, mask_flags,
dest_format, dest_flags,
- &imp, &func);
+ &imp, &func);
walk_region_internal (imp, op,
src, mask, dest,
diff --git a/pixman/test/scaling-crash-test.c b/pixman/test/scaling-crash-test.c
index 7e8b6d56b..0ce1fece9 100644
--- a/pixman/test/scaling-crash-test.c
+++ b/pixman/test/scaling-crash-test.c
@@ -8,117 +8,202 @@
* We have a source image filled with solid color, set NORMAL or PAD repeat,
* and some transform which results in nearest neighbour scaling.
*
- * The expected result is the destination image filled with this solid
- * color.
+ * The expected result is either that the destination image filled with this solid
+ * color or, if the transformation is such that we can't composite anything at
+ * all, that nothing has changed in the destination.
+ *
+ * The surrounding memory of the source image is a different solid color so that
+ * we are sure to get failures if we access it.
*/
static int
-do_test (int32_t dst_size,
- int32_t src_size,
- int32_t src_offs,
- int32_t scale_factor,
- pixman_repeat_t repeat)
+run_test (int32_t dst_width,
+ int32_t dst_height,
+ int32_t src_width,
+ int32_t src_height,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t scale_x,
+ int32_t scale_y,
+ pixman_filter_t filter,
+ pixman_repeat_t repeat)
{
- int i;
pixman_image_t * src_img;
pixman_image_t * dst_img;
pixman_transform_t transform;
uint32_t * srcbuf;
uint32_t * dstbuf;
+ pixman_box32_t box = { 0, 0, src_width, src_height };
+ pixman_color_t color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc };
+ int result;
+ int i;
- srcbuf = (uint32_t *)malloc (src_size * 4);
- dstbuf = (uint32_t *)malloc (dst_size * 4);
+ static const pixman_fixed_t kernel[] =
+ {
+#define D(f) (pixman_double_to_fixed (f) + 0x0001)
+
+ pixman_int_to_fixed (5),
+ pixman_int_to_fixed (5),
+ D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+ D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+ D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+ D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0),
+ D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0)
+ };
+
+ result = 0;
- /* horizontal test */
- memset (srcbuf, 0xCC, src_size * 4);
- memset (dstbuf, 0x33, dst_size * 4);
+ srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4);
+ dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4);
+
+ memset (srcbuf, 0x88, src_width * src_height * 4);
+ memset (dstbuf, 0x33, dst_width * dst_height * 4);
src_img = pixman_image_create_bits (
- PIXMAN_a8r8g8b8, src_size, 1, srcbuf, src_size * 4);
+ PIXMAN_a8r8g8b8, src_width, src_height,
+ srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4);
+
+ pixman_image_fill_boxes (PIXMAN_OP_SRC, src_img, &color_cc, 1, &box);
+
dst_img = pixman_image_create_bits (
- PIXMAN_a8r8g8b8, dst_size, 1, dstbuf, dst_size * 4);
+ PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4);
- pixman_transform_init_scale (&transform, scale_factor, 65536);
+ pixman_transform_init_scale (&transform, scale_x, scale_y);
pixman_image_set_transform (src_img, &transform);
pixman_image_set_repeat (src_img, repeat);
- pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
+ if (filter == PIXMAN_FILTER_CONVOLUTION)
+ pixman_image_set_filter (src_img, filter, kernel, 27);
+ else
+ pixman_image_set_filter (src_img, filter, NULL, 0);
pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img,
- src_offs, 0, 0, 0, 0, 0, dst_size, 1);
+ src_x, src_y, 0, 0, 0, 0, dst_width, dst_height);
pixman_image_unref (src_img);
pixman_image_unref (dst_img);
- for (i = 0; i < dst_size; i++)
+ for (i = 0; i < dst_width * dst_height; i++)
{
- if (dstbuf[i] != 0xCCCCCCCC)
+ if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333)
{
- free (srcbuf);
- free (dstbuf);
- return 1;
+ result = 1;
+ break;
}
}
- /* vertical test */
- memset (srcbuf, 0xCC, src_size * 4);
- memset (dstbuf, 0x33, dst_size * 4);
+ free (srcbuf);
+ free (dstbuf);
+ return result;
+}
- src_img = pixman_image_create_bits (
- PIXMAN_a8r8g8b8, 1, src_size, srcbuf, 4);
- dst_img = pixman_image_create_bits (
- PIXMAN_a8r8g8b8, 1, dst_size, dstbuf, 4);
+typedef struct info_t info_t;
+struct info_t
+{
+ int value;
+ char name[28];
+};
- pixman_transform_init_scale (&transform, 65536, scale_factor);
- pixman_image_set_transform (src_img, &transform);
- pixman_image_set_repeat (src_img, repeat);
- pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0);
+static const info_t filters[] =
+{
+ { PIXMAN_FILTER_NEAREST, "NEAREST" },
+ { PIXMAN_FILTER_BILINEAR, "BILINEAR" },
+ { PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" },
+};
- pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img,
- 0, src_offs, 0, 0, 0, 0, 1, dst_size);
+static const info_t repeats[] =
+{
+ { PIXMAN_REPEAT_PAD, "PAD" },
+ { PIXMAN_REPEAT_REFLECT, "REFLECT" },
+ { PIXMAN_REPEAT_NORMAL, "NORMAL" }
+};
- pixman_image_unref (src_img);
- pixman_image_unref (dst_img);
+static int
+do_test (int32_t dst_size,
+ int32_t src_size,
+ int32_t src_offs,
+ int32_t scale_factor)
+{
+#define N_ELEMENTS(a) (sizeof (a) / sizeof ((a)[0]))
+ int i, j;
- for (i = 0; i < dst_size; i++)
+ for (i = 0; i < N_ELEMENTS(filters); ++i)
{
- if (dstbuf[i] != 0xCCCCCCCC)
+ for (j = 0; j < N_ELEMENTS (repeats); ++j)
{
- free (srcbuf);
- free (dstbuf);
- return 1;
+ /* horizontal test */
+ if (run_test (dst_size, 1,
+ src_size, 1,
+ src_offs, 0,
+ scale_factor, 65536,
+ filters[i].value,
+ repeats[j].value) != 0)
+ {
+ printf ("Vertical test failed with %s filter and repeat mode %s\n",
+ filters[i].name, repeats[j].name);
+
+ return 1;
+ }
+
+ /* vertical test */
+ if (run_test (1, dst_size,
+ 1, src_size,
+ 0, src_offs,
+ 65536, scale_factor,
+ filters[i].value,
+ repeats[j].value) != 0)
+ {
+ printf ("Vertical test failed with %s filter and repeat mode %s\n",
+ filters[i].name, repeats[j].name);
+
+ return 1;
+ }
}
}
- free (srcbuf);
- free (dstbuf);
return 0;
}
int
main (int argc, char *argv[])
{
+ int i;
+
pixman_disable_out_of_bounds_workaround ();
/* can potentially crash */
assert (do_test (
- 48000, 32767, 1, 65536 * 128, PIXMAN_REPEAT_NORMAL) == 0);
+ 48000, 32767, 1, 65536 * 128) == 0);
/* can potentially get into a deadloop */
assert (do_test (
- 16384, 65536, 32, 32768, PIXMAN_REPEAT_NORMAL) == 0);
+ 16384, 65536, 32, 32768) == 0);
-#if 0
/* can potentially access memory outside source image buffer */
assert (do_test (
- 10, 10, 0, 1, PIXMAN_REPEAT_PAD) == 0);
+ 10, 10, 0, 1) == 0);
assert (do_test (
- 10, 10, 0, 0, PIXMAN_REPEAT_PAD) == 0);
-#endif
+ 10, 10, 0, 0) == 0);
+
+ for (i = 0; i < 100; ++i)
+ {
+ pixman_fixed_t one_seventh =
+ (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (7 << 16);
+
+ assert (do_test (
+ 1, 7, 3, one_seventh + i - 50) == 0);
+ }
+
+ for (i = 0; i < 100; ++i)
+ {
+ pixman_fixed_t scale =
+ (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (32767 << 16);
+
+ assert (do_test (
+ 1, 32767, 16383, scale + i - 50) == 0);
+ }
-#if 0
/* can potentially provide invalid results (out of range matrix stuff) */
assert (do_test (
- 48000, 32767, 16384, 65536 * 128, PIXMAN_REPEAT_NORMAL) == 0);
-#endif
+ 48000, 32767, 16384, 65536 * 128) == 0);
return 0;
}