From 541f2f74a37db36a8e35800950fd02adb0443d88 Mon Sep 17 00:00:00 2001 From: Yu-Ping Wu Date: Thu, 10 Sep 2020 13:31:13 +0800 Subject: libpayload: cbgfx: Fix 'equals' counter for Lanczos resampling The current initialization of the 'equals' counter is incorrect, so that when 'equals >= SSZ * SSZ', the pixels in the sample array might not be all the same, leading to a wrong pixel value being set in the framebuffer. The 'equals' counter stores the number of latest pixels that were exactly equal. Within the for loop of 'ox', the sample array is updated in a column-based order, and the 'equals' counter is updated accordingly. However, the 'equals' counter is initialized in a row-based order, which causes it to be set too large than it should be. Consider the example where sample[sx][sy] are initially: [X X X A A A] // sy = 0 [X X X B B B] [X X X B B B] [X X X B B B] [X X X B B B] [X X X B B B] // sy = SSZ Then, the correct implementation will initialize 'equals' to be 15, with last_equal being B. Suppose all of the remaining pixels are B. Then, at the end of the 'while (fpfloor(ixfp) > ix)' loop when ix = 4, or equivalently after 4 more columns of sample are updated, 'equals' will be 15 + 6 * 4 = 39, which is greater than SSZ * SSZ = 36, but we can see there are still 2 A's in the sample: [B B B B A A] [B B B B B B] [B B B B B B] [B B B B B B] [B B B B B B] [B B B B B B] Therefore, we must also initialize the 'equals' counter in a column-based order. BUG=b:167739127 TEST=emerge-puff libpayload TEST=Character 'k' is rendered correctly on puff BRANCH=zork Change-Id: Ibc91ad1af85adcf093eff40797cd54f32f57111d Signed-off-by: Yu-Ping Wu Reviewed-on: https://review.coreboot.org/c/coreboot/+/45235 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- payloads/libpayload/drivers/video/graphics.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'payloads') diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c index 2bf5e19d88..563f2961c7 100644 --- a/payloads/libpayload/drivers/video/graphics.c +++ b/payloads/libpayload/drivers/video/graphics.c @@ -858,24 +858,25 @@ static int draw_bitmap_v3(const struct vector *top_left, } /* - * Initialize the sample array for this line. For pixels to the - * left of S0 there are no corresponding input pixels so just - * copy the S0 values over. - * - * Also initialize the equals counter, which counts how many of - * the latest pixels were exactly equal. We know the columns - * left of S0 must be equal to S0, so start with that number. + * Initialize the sample array for this line, and also + * the equals counter, which counts how many of the latest + * pixels were exactly equal. */ - int equals = S0 * SSZ; + int equals = 0; uint8_t last_equal = ypix[0][0]; - for (sy = 0; sy < SSZ; sy++) { - for (sx = S0; sx < SSZ; sx++) { - if (sx >= dim_org->width) { + for (sx = 0; sx < SSZ; sx++) { + for (sy = 0; sy < SSZ; sy++) { + if (sx - S0 >= dim_org->width) { sample[sx][sy] = sample[sx - 1][sy]; equals++; continue; } - uint8_t i = ypix[sy][sx - S0]; + /* + * For pixels to the left of S0 there are no + * corresponding input pixels so just use + * ypix[sy][0]. + */ + uint8_t i = ypix[sy][MAX(0, sx - S0)]; if (pal_to_rgb(i, pal, header->colors_used, &sample[sx][sy])) goto bitmap_error; @@ -886,8 +887,6 @@ static int draw_bitmap_v3(const struct vector *top_left, equals = 1; } } - for (sx = S0 - 1; sx >= 0; sx--) - sample[sx][sy] = sample[S0][sy]; } ix = 0; -- cgit v1.2.3