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 <yupingso@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/45235
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
Yu-Ping Wu 2020-09-10 13:31:13 +08:00 committed by Shelley Chen
parent 5d1a328e88
commit 541f2f74a3
1 changed files with 13 additions and 14 deletions

View File

@ -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 * Initialize the sample array for this line, and also
* left of S0 there are no corresponding input pixels so just * the equals counter, which counts how many of the latest
* copy the S0 values over. * pixels were exactly equal.
*
* 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.
*/ */
int equals = S0 * SSZ; int equals = 0;
uint8_t last_equal = ypix[0][0]; uint8_t last_equal = ypix[0][0];
for (sx = 0; sx < SSZ; sx++) {
for (sy = 0; sy < SSZ; sy++) { for (sy = 0; sy < SSZ; sy++) {
for (sx = S0; sx < SSZ; sx++) { if (sx - S0 >= dim_org->width) {
if (sx >= dim_org->width) {
sample[sx][sy] = sample[sx - 1][sy]; sample[sx][sy] = sample[sx - 1][sy];
equals++; equals++;
continue; 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, if (pal_to_rgb(i, pal, header->colors_used,
&sample[sx][sy])) &sample[sx][sy]))
goto bitmap_error; goto bitmap_error;
@ -886,8 +887,6 @@ static int draw_bitmap_v3(const struct vector *top_left,
equals = 1; equals = 1;
} }
} }
for (sx = S0 - 1; sx >= 0; sx--)
sample[sx][sy] = sample[S0][sy];
} }
ix = 0; ix = 0;