From f86515244a94c81484fa72884698acf322a9130f Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Thu, 24 Sep 2015 12:42:51 -0700 Subject: cbgfx: use bilinear interpolation to scale bitmap This change replaces the current scaling algorithm (nearest neighbor) used for bitmap rendering with the bilinear interpolation, which has much better reproduction. BUG=none BRANCH=tot TEST=Tested on Samus Change-Id: I02520883debb7db40ffc19d4480244e0acabc818 Signed-off-by: Patrick Georgi Original-Commit-Id: 764b383c1763a022728f2b2d9fb90e27c9e32e94 Original-Change-Id: I0ddd184343428904d04d8a76fe18a885529c7d3d Original-Signed-off-by: Daisuke Nojiri Original-Reviewed-on: https://chromium-review.googlesource.com/302195 Original-Reviewed-by: Randall Spangler Reviewed-on: http://review.coreboot.org/11926 Tested-by: build bot (Jenkins) --- payloads/libpayload/drivers/video/graphics.c | 55 ++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c index c26147333f..da06267aa9 100644 --- a/payloads/libpayload/drivers/video/graphics.c +++ b/payloads/libpayload/drivers/video/graphics.c @@ -243,11 +243,20 @@ static int check_bound(const struct vector *image, return within_box(&p, &bound) < 0; } +static uint32_t bli(uint32_t q00, uint32_t q10, uint32_t q01, uint32_t q11, + struct fraction *tx, struct fraction *ty) +{ + uint32_t r0 = (tx->nume * q10 + (tx->deno - tx->nume) * q00) / tx->deno; + uint32_t r1 = (tx->nume * q11 + (tx->deno - tx->nume) * q01) / tx->deno; + uint32_t p = (ty->nume * r1 + (ty->deno - ty->nume) * r0) / ty->deno; + return p; +} + static int draw_bitmap_v3(const struct vector *top_left, const struct scale *scale, const struct vector *image, const struct bitmap_header_v3 *header, - const struct bitmap_palette_element_v3 *palette, + const struct bitmap_palette_element_v3 *pal, const uint8_t *pixel_array) { const int bpp = header->bits_per_pixel; @@ -292,26 +301,50 @@ static int draw_bitmap_v3(const struct vector *top_left, dir = -1; } /* - * Plot pixels scaled by the nearest neighbor interpolation. We scan + * Plot pixels scaled by the bilinear interpolation. We scan * over the image on canvas (using d) and find the corresponding pixel * in the bitmap data (using s). */ - struct vector s, d; + struct vector s0, s1, d; + struct fraction tx, ty; for (d.y = 0; d.y < image->height; d.y++, p.y += dir) { - s.y = d.y * scale->y.deno / scale->y.nume; - const uint8_t *data = pixel_array + s.y * y_stride; + s0.y = d.y * scale->y.deno / scale->y.nume; + s1.y = s0.y; + if (s0.y + 1 < ABS(header->height)) + s1.y++; + ty.deno = scale->y.nume; + ty.nume = (d.y * scale->y.deno) % scale->y.nume; + const uint8_t *data0 = pixel_array + s0.y * y_stride; + const uint8_t *data1 = pixel_array + s1.y * y_stride; p.x = top_left->x; for (d.x = 0; d.x < image->width; d.x++, p.x++) { - s.x = d.x * scale->x.deno / scale->x.nume; - uint8_t index = data[s.x]; - if (index >= header->colors_used) { + s0.x = d.x * scale->x.deno / scale->x.nume; + s1.x = s0.x; + if (s1.x + 1 < header->width) + s1.x++; + tx.deno = scale->x.nume; + tx.nume = (d.x * scale->x.deno) % scale->x.nume; + uint8_t c00 = data0[s0.x]; + uint8_t c10 = data0[s1.x]; + uint8_t c01 = data1[s0.x]; + uint8_t c11 = data1[s1.x]; + if (c00 >= header->colors_used + || c10 >= header->colors_used + || c01 >= header->colors_used + || c11 >= header->colors_used) { LOG("Color index exceeds palette boundary\n"); return CBGFX_ERROR_BITMAP_DATA; } const struct rgb_color rgb = { - .red = palette[index].red, - .green = palette[index].green, - .blue = palette[index].blue, + .red = bli(pal[c00].red, pal[c10].red, + pal[c01].red, pal[c11].red, + &tx, &ty), + .green = bli(pal[c00].green, pal[c10].green, + pal[c01].green, pal[c11].green, + &tx, &ty), + .blue = bli(pal[c00].blue, pal[c10].blue, + pal[c01].blue, pal[c11].blue, + &tx, &ty), }; set_pixel(&p, calculate_color(&rgb)); } -- cgit v1.2.3