52cf0a800d
tested by ajacoutot@, krw@ and on a bulk ports build by landry@.
210 lines
5.2 KiB
C
210 lines
5.2 KiB
C
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "pixman.h"
|
|
|
|
/*
|
|
* 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 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
|
|
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)
|
|
{
|
|
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;
|
|
|
|
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;
|
|
|
|
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_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_width, dst_height, dstbuf, dst_width * 4);
|
|
|
|
pixman_transform_init_scale (&transform, scale_x, scale_y);
|
|
pixman_image_set_transform (src_img, &transform);
|
|
pixman_image_set_repeat (src_img, repeat);
|
|
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_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_width * dst_height; i++)
|
|
{
|
|
if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333)
|
|
{
|
|
result = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
free (srcbuf);
|
|
free (dstbuf);
|
|
return result;
|
|
}
|
|
|
|
typedef struct info_t info_t;
|
|
struct info_t
|
|
{
|
|
int value;
|
|
char name[28];
|
|
};
|
|
|
|
static const info_t filters[] =
|
|
{
|
|
{ PIXMAN_FILTER_NEAREST, "NEAREST" },
|
|
{ PIXMAN_FILTER_BILINEAR, "BILINEAR" },
|
|
{ PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" },
|
|
};
|
|
|
|
static const info_t repeats[] =
|
|
{
|
|
{ PIXMAN_REPEAT_PAD, "PAD" },
|
|
{ PIXMAN_REPEAT_REFLECT, "REFLECT" },
|
|
{ PIXMAN_REPEAT_NORMAL, "NORMAL" }
|
|
};
|
|
|
|
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 < N_ELEMENTS(filters); ++i)
|
|
{
|
|
for (j = 0; j < N_ELEMENTS (repeats); ++j)
|
|
{
|
|
/* 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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) == 0);
|
|
|
|
/* can potentially get into a deadloop */
|
|
assert (do_test (
|
|
16384, 65536, 32, 32768) == 0);
|
|
|
|
/* can potentially access memory outside source image buffer */
|
|
assert (do_test (
|
|
10, 10, 0, 1) == 0);
|
|
assert (do_test (
|
|
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);
|
|
}
|
|
|
|
/* can potentially provide invalid results (out of range matrix stuff) */
|
|
assert (do_test (
|
|
48000, 32767, 16384, 65536 * 128) == 0);
|
|
|
|
return 0;
|
|
}
|