summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2015-09-24 12:42:51 -0700
committerPatrick Georgi <pgeorgi@google.com>2015-10-27 15:22:16 +0100
commitf86515244a94c81484fa72884698acf322a9130f (patch)
tree8183b0c29da6d00ac77fc45c2333530c762e063c
parentbed16d9706a72921435ad6df7171daf3f008337c (diff)
downloadcoreboot-f86515244a94c81484fa72884698acf322a9130f.tar.xz
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 <pgeorgi@google.com> Original-Commit-Id: 764b383c1763a022728f2b2d9fb90e27c9e32e94 Original-Change-Id: I0ddd184343428904d04d8a76fe18a885529c7d3d Original-Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/302195 Original-Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: http://review.coreboot.org/11926 Tested-by: build bot (Jenkins)
-rw-r--r--payloads/libpayload/drivers/video/graphics.c55
1 files 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));
}