[coreboot-gerrit] New patch to review for coreboot: cbgfx: use bilinear interpolation to scale bitmap

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Fri Oct 16 16:46:28 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/11926

-gerrit

commit 0d7e6320a22e92aff9cc958d30a7ee7c78e99574
Author: Daisuke Nojiri <dnojiri at chromium.org>
Date:   Thu Sep 24 12:42:51 2015 -0700

    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 at google.com>
    Original-Commit-Id: 764b383c1763a022728f2b2d9fb90e27c9e32e94
    Original-Change-Id: I0ddd184343428904d04d8a76fe18a885529c7d3d
    Original-Signed-off-by: Daisuke Nojiri <dnojiri at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/302195
    Original-Reviewed-by: Randall Spangler <rspangler at chromium.org>
---
 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 c261473..da06267 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));
 		}



More information about the coreboot-gerrit mailing list