11b18d63aSmrg#include <assert.h> 21b18d63aSmrg#include <stdlib.h> 31b18d63aSmrg#include <stdio.h> 41b18d63aSmrg#include <string.h> 59ad247e8Sjmcneill#include "utils.h" 61b18d63aSmrg 71b18d63aSmrg/* 81b18d63aSmrg * We have a source image filled with solid color, set NORMAL or PAD repeat, 91b18d63aSmrg * and some transform which results in nearest neighbour scaling. 101b18d63aSmrg * 111b18d63aSmrg * The expected result is either that the destination image filled with this solid 121b18d63aSmrg * color or, if the transformation is such that we can't composite anything at 131b18d63aSmrg * all, that nothing has changed in the destination. 141b18d63aSmrg * 151b18d63aSmrg * The surrounding memory of the source image is a different solid color so that 161b18d63aSmrg * we are sure to get failures if we access it. 171b18d63aSmrg */ 181b18d63aSmrgstatic int 191b18d63aSmrgrun_test (int32_t dst_width, 201b18d63aSmrg int32_t dst_height, 211b18d63aSmrg int32_t src_width, 221b18d63aSmrg int32_t src_height, 231b18d63aSmrg int32_t src_x, 241b18d63aSmrg int32_t src_y, 251b18d63aSmrg int32_t scale_x, 261b18d63aSmrg int32_t scale_y, 271b18d63aSmrg pixman_filter_t filter, 281b18d63aSmrg pixman_repeat_t repeat) 291b18d63aSmrg{ 301b18d63aSmrg pixman_image_t * src_img; 311b18d63aSmrg pixman_image_t * dst_img; 321b18d63aSmrg pixman_transform_t transform; 331b18d63aSmrg uint32_t * srcbuf; 341b18d63aSmrg uint32_t * dstbuf; 351b18d63aSmrg pixman_color_t color_cc = { 0xcccc, 0xcccc, 0xcccc, 0xcccc }; 369ad247e8Sjmcneill pixman_image_t * solid; 371b18d63aSmrg int result; 381b18d63aSmrg int i; 391b18d63aSmrg 401b18d63aSmrg static const pixman_fixed_t kernel[] = 411b18d63aSmrg { 421b18d63aSmrg#define D(f) (pixman_double_to_fixed (f) + 0x0001) 431b18d63aSmrg 441b18d63aSmrg pixman_int_to_fixed (5), 451b18d63aSmrg pixman_int_to_fixed (5), 461b18d63aSmrg D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 471b18d63aSmrg D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 481b18d63aSmrg D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 491b18d63aSmrg D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), 501b18d63aSmrg D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0), D(1/25.0) 511b18d63aSmrg }; 521b18d63aSmrg 531b18d63aSmrg result = 0; 541b18d63aSmrg 551b18d63aSmrg srcbuf = (uint32_t *)malloc ((src_width + 10) * (src_height + 10) * 4); 561b18d63aSmrg dstbuf = (uint32_t *)malloc (dst_width * dst_height * 4); 571b18d63aSmrg 581b18d63aSmrg memset (srcbuf, 0x88, src_width * src_height * 4); 591b18d63aSmrg memset (dstbuf, 0x33, dst_width * dst_height * 4); 601b18d63aSmrg 611b18d63aSmrg src_img = pixman_image_create_bits ( 621b18d63aSmrg PIXMAN_a8r8g8b8, src_width, src_height, 631b18d63aSmrg srcbuf + (src_width + 10) * 5 + 5, (src_width + 10) * 4); 641b18d63aSmrg 659ad247e8Sjmcneill solid = pixman_image_create_solid_fill (&color_cc); 669ad247e8Sjmcneill pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, src_img, 679ad247e8Sjmcneill 0, 0, 0, 0, 0, 0, src_width, src_height); 689ad247e8Sjmcneill pixman_image_unref (solid); 691b18d63aSmrg 701b18d63aSmrg dst_img = pixman_image_create_bits ( 711b18d63aSmrg PIXMAN_a8r8g8b8, dst_width, dst_height, dstbuf, dst_width * 4); 721b18d63aSmrg 731b18d63aSmrg pixman_transform_init_scale (&transform, scale_x, scale_y); 741b18d63aSmrg pixman_image_set_transform (src_img, &transform); 751b18d63aSmrg pixman_image_set_repeat (src_img, repeat); 761b18d63aSmrg if (filter == PIXMAN_FILTER_CONVOLUTION) 771b18d63aSmrg pixman_image_set_filter (src_img, filter, kernel, 27); 781b18d63aSmrg else 791b18d63aSmrg pixman_image_set_filter (src_img, filter, NULL, 0); 801b18d63aSmrg 811b18d63aSmrg pixman_image_composite (PIXMAN_OP_SRC, src_img, NULL, dst_img, 821b18d63aSmrg src_x, src_y, 0, 0, 0, 0, dst_width, dst_height); 831b18d63aSmrg 841b18d63aSmrg pixman_image_unref (src_img); 851b18d63aSmrg pixman_image_unref (dst_img); 861b18d63aSmrg 871b18d63aSmrg for (i = 0; i < dst_width * dst_height; i++) 881b18d63aSmrg { 891b18d63aSmrg if (dstbuf[i] != 0xCCCCCCCC && dstbuf[i] != 0x33333333) 901b18d63aSmrg { 911b18d63aSmrg result = 1; 921b18d63aSmrg break; 931b18d63aSmrg } 941b18d63aSmrg } 951b18d63aSmrg 961b18d63aSmrg free (srcbuf); 971b18d63aSmrg free (dstbuf); 981b18d63aSmrg return result; 991b18d63aSmrg} 1001b18d63aSmrg 1016ba797d6Smrgtypedef struct filter_info_t filter_info_t; 1026ba797d6Smrgstruct filter_info_t 1031b18d63aSmrg{ 1046ba797d6Smrg pixman_filter_t value; 1051b18d63aSmrg char name[28]; 1061b18d63aSmrg}; 1071b18d63aSmrg 1086ba797d6Smrgstatic const filter_info_t filters[] = 1091b18d63aSmrg{ 1101b18d63aSmrg { PIXMAN_FILTER_NEAREST, "NEAREST" }, 1111b18d63aSmrg { PIXMAN_FILTER_BILINEAR, "BILINEAR" }, 1121b18d63aSmrg { PIXMAN_FILTER_CONVOLUTION, "CONVOLUTION" }, 1131b18d63aSmrg}; 1141b18d63aSmrg 1156ba797d6Smrgtypedef struct repeat_info_t repeat_info_t; 1166ba797d6Smrgstruct repeat_info_t 1176ba797d6Smrg{ 1186ba797d6Smrg pixman_repeat_t value; 1196ba797d6Smrg char name[28]; 1206ba797d6Smrg}; 1216ba797d6Smrg 1226ba797d6Smrg 1236ba797d6Smrgstatic const repeat_info_t repeats[] = 1241b18d63aSmrg{ 1251b18d63aSmrg { PIXMAN_REPEAT_PAD, "PAD" }, 1261b18d63aSmrg { PIXMAN_REPEAT_REFLECT, "REFLECT" }, 1271b18d63aSmrg { PIXMAN_REPEAT_NORMAL, "NORMAL" } 1281b18d63aSmrg}; 1291b18d63aSmrg 1301b18d63aSmrgstatic int 1311b18d63aSmrgdo_test (int32_t dst_size, 1321b18d63aSmrg int32_t src_size, 1331b18d63aSmrg int32_t src_offs, 1341b18d63aSmrg int32_t scale_factor) 1351b18d63aSmrg{ 1361b18d63aSmrg int i, j; 1371b18d63aSmrg 1389ad247e8Sjmcneill for (i = 0; i < ARRAY_LENGTH (filters); ++i) 1391b18d63aSmrg { 1409ad247e8Sjmcneill for (j = 0; j < ARRAY_LENGTH (repeats); ++j) 1411b18d63aSmrg { 1421b18d63aSmrg /* horizontal test */ 1431b18d63aSmrg if (run_test (dst_size, 1, 1441b18d63aSmrg src_size, 1, 1451b18d63aSmrg src_offs, 0, 1461b18d63aSmrg scale_factor, 65536, 1471b18d63aSmrg filters[i].value, 1481b18d63aSmrg repeats[j].value) != 0) 1491b18d63aSmrg { 1501b18d63aSmrg printf ("Vertical test failed with %s filter and repeat mode %s\n", 1511b18d63aSmrg filters[i].name, repeats[j].name); 1521b18d63aSmrg 1531b18d63aSmrg return 1; 1541b18d63aSmrg } 1551b18d63aSmrg 1561b18d63aSmrg /* vertical test */ 1571b18d63aSmrg if (run_test (1, dst_size, 1581b18d63aSmrg 1, src_size, 1591b18d63aSmrg 0, src_offs, 1601b18d63aSmrg 65536, scale_factor, 1611b18d63aSmrg filters[i].value, 1621b18d63aSmrg repeats[j].value) != 0) 1631b18d63aSmrg { 1641b18d63aSmrg printf ("Vertical test failed with %s filter and repeat mode %s\n", 1651b18d63aSmrg filters[i].name, repeats[j].name); 1661b18d63aSmrg 1671b18d63aSmrg return 1; 1681b18d63aSmrg } 1691b18d63aSmrg } 1701b18d63aSmrg } 1711b18d63aSmrg 1721b18d63aSmrg return 0; 1731b18d63aSmrg} 1741b18d63aSmrg 1751b18d63aSmrgint 1761b18d63aSmrgmain (int argc, char *argv[]) 1771b18d63aSmrg{ 1781b18d63aSmrg int i; 1791b18d63aSmrg 1801b18d63aSmrg pixman_disable_out_of_bounds_workaround (); 1811b18d63aSmrg 1821b18d63aSmrg /* can potentially crash */ 1831b18d63aSmrg assert (do_test ( 1841b18d63aSmrg 48000, 32767, 1, 65536 * 128) == 0); 1851b18d63aSmrg 1861b18d63aSmrg /* can potentially get into a deadloop */ 1871b18d63aSmrg assert (do_test ( 1881b18d63aSmrg 16384, 65536, 32, 32768) == 0); 1891b18d63aSmrg 1901b18d63aSmrg /* can potentially access memory outside source image buffer */ 1911b18d63aSmrg assert (do_test ( 1921b18d63aSmrg 10, 10, 0, 1) == 0); 1931b18d63aSmrg assert (do_test ( 1941b18d63aSmrg 10, 10, 0, 0) == 0); 1951b18d63aSmrg 1961b18d63aSmrg for (i = 0; i < 100; ++i) 1971b18d63aSmrg { 1981b18d63aSmrg pixman_fixed_t one_seventh = 1991b18d63aSmrg (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (7 << 16); 2001b18d63aSmrg 2011b18d63aSmrg assert (do_test ( 2021b18d63aSmrg 1, 7, 3, one_seventh + i - 50) == 0); 2031b18d63aSmrg } 2041b18d63aSmrg 2051b18d63aSmrg for (i = 0; i < 100; ++i) 2061b18d63aSmrg { 2071b18d63aSmrg pixman_fixed_t scale = 2081b18d63aSmrg (((pixman_fixed_48_16_t)pixman_fixed_1) << 16) / (32767 << 16); 2091b18d63aSmrg 2101b18d63aSmrg assert (do_test ( 2111b18d63aSmrg 1, 32767, 16383, scale + i - 50) == 0); 2121b18d63aSmrg } 2131b18d63aSmrg 2141b18d63aSmrg /* can potentially provide invalid results (out of range matrix stuff) */ 2151b18d63aSmrg assert (do_test ( 2161b18d63aSmrg 48000, 32767, 16384, 65536 * 128) == 0); 2171b18d63aSmrg 2181b18d63aSmrg return 0; 2191b18d63aSmrg} 220