diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c index 632a283de9..b9a93a03e2 100644 --- a/payloads/libpayload/drivers/video/graphics.c +++ b/payloads/libpayload/drivers/video/graphics.c @@ -715,19 +715,20 @@ static fpmath_t lanczos_weight(fpmath_t in, int off) * * So (off - S0) - (in - floor(in)) is the distance from the sample * pixel to S0 minus the distance from S0 to the output pixel, aka - * the distance from the sample pixel to the output pixel. + * the distance from the sample pixel to the output pixel. (Note that + * this calculation using fpfloor() is only valid if |in| is not + * negative, which is always the case for our current code.) */ fpmath_t x = fpisub(off - S0, fpsubi(in, fpfloor(in))); - if (fpequals(x, fp(0))) - return fp(1); - /* x * 2 / a can save some instructions if a == 2 */ fpmath_t x2a = x; if (LNCZ_A != 2) x2a = fpmul(x, fpfrac(2, LNCZ_A)); fpmath_t x_times_pi = fpmul(x, fppi()); + if (fpequals(x_times_pi, fp(0))) + return fp(1); /* * Rather than using sinr(pi*x), we leverage the "one-based" sine diff --git a/payloads/libpayload/tests/drivers/Makefile.mk b/payloads/libpayload/tests/drivers/Makefile.mk index 7705473ef7..8d668c2e42 100644 --- a/payloads/libpayload/tests/drivers/Makefile.mk +++ b/payloads/libpayload/tests/drivers/Makefile.mk @@ -1,6 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only -tests-y += speaker-test +tests-y += graphics-test speaker-test + +graphics-test-srcs += tests/drivers/graphics-test.c +graphics-test-srcs += libc/fpmath.c speaker-test-srcs += tests/drivers/speaker-test.c speaker-test-mocks += inb diff --git a/payloads/libpayload/tests/drivers/graphics-test.c b/payloads/libpayload/tests/drivers/graphics-test.c new file mode 100644 index 0000000000..6e4d9b3528 --- /dev/null +++ b/payloads/libpayload/tests/drivers/graphics-test.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "../drivers/video/graphics.c" + +#include +#include + +static void test_lanczos(void **state) +{ + /* This makes sure the `x` in lanczos_weight() becomes very small. This + test is mostly here to prove we won't end up dividing by zero. */ + fpmath_t x = lanczos_weight(fpisub(1, fpfrac(1, 1 << 30)), S0 + 1); + assert_true(fpequals(x, fp(1))); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_lanczos), + }; + + return lp_run_group_tests(tests, NULL, NULL); +}