[Concept,13/22] video: Export a function to draw a BMP with transparency

Message ID 20251003165525.440173-14-sjg@u-boot.org
State New
Headers
Series video: Enhancements to support a pointer |

Commit Message

Simon Glass Oct. 3, 2025, 4:55 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Provide a new BMP function which can draw a bitmap while regarding a
chosen colour as transparent.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/video_bmp.c |  6 ++++
 include/video.h           | 16 ++++++++++
 test/dm/video.c           | 62 ++++++++++++++++++++++++++++++++-------
 3 files changed, 74 insertions(+), 10 deletions(-)
  

Patch

diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index ebdf73e25a9..43aa45f0efe 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -507,3 +507,9 @@  int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
 {
 	return draw_bmp(dev, bmp_image, x, y, align, false, 0);
 }
+
+int video_bmp_displaya(struct udevice *dev, ulong bmp_image, int x, int y,
+		       bool align, bool alpha, u32 acolour)
+{
+	return draw_bmp(dev, bmp_image, x, y, align, alpha, acolour);
+}
diff --git a/include/video.h b/include/video.h
index 9d9a725d30d..1ad5868e2f6 100644
--- a/include/video.h
+++ b/include/video.h
@@ -383,6 +383,22 @@  void video_bmp_get_info(const void *bmp_image, ulong *widthp, ulong *heightp,
 int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
 		      bool align);
 
+/**
+ * video_bmp_displaya() - Display a BMP image with alpha transparency
+ *
+ * @dev:	Device to use
+ * @bmp_image:	Address of BMP image
+ * @x:		X position to draw image
+ * @y:		Y position to draw image
+ * @align:	true to adjust the coordinates to centre the image (see
+ *		video_bmp_display() for details)
+ * @alpha:	true to enable alpha transparency
+ * @acolour:	Color to treat as transparent (RGB888 format: 0xRRGGBB)
+ * Return: 0 if OK, -ve on error
+ */
+int video_bmp_displaya(struct udevice *dev, ulong bmp_image, int x, int y,
+		       bool align, bool alpha, u32 acolour);
+
 /**
  * video_get_xsize() - Get the width of the display in pixels
  *
diff --git a/test/dm/video.c b/test/dm/video.c
index a802228b790..3defa184b14 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -667,15 +667,25 @@  static int dm_test_video_comp_bmp8(struct unit_test_state *uts)
 }
 DM_TEST(dm_test_video_comp_bmp8, UTF_SCAN_PDATA | UTF_SCAN_FDT);
 
-/* Test drawing the riscos pointer */
-static int dm_test_video_bmp_alpha(struct unit_test_state *uts)
+/**
+ * check_bmp_alpha() - Test drawing the riscos pointer with transparency
+ *
+ * Draws the riscos pointer BMP in various positions with and without
+ * transparency to verify alpha blending works correctly
+ *
+ * @uts: Test state
+ * @dev: Video device
+ * @first: Expected compression after first pointer draw
+ * @second: Expected compression after second pointer draw
+ * @trans: Expected compression after drawing with transparency
+ * Return: 0 if OK, -ve on error
+ */
+static int check_bmp_alpha(struct unit_test_state *uts, struct udevice *dev,
+			   int first, int second, int trans)
 {
-	struct video_priv *priv;
-	struct udevice *dev;
+	struct video_priv *priv = dev_get_uclass_priv(dev);
 	ulong addr;
 
-	ut_assertok(video_get_nologo(uts, &dev));
-	priv = dev_get_uclass_priv(dev);
 	addr = map_to_sysmem(video_image_getptr(riscos_arrow));
 
 	/* Draw a black rectangle first */
@@ -684,17 +694,49 @@  static int dm_test_video_bmp_alpha(struct unit_test_state *uts)
 
 	/* Draw the pointer on top of the black rectangle */
 	ut_assertok(video_bmp_display(dev, addr, 110, 110, false));
-	ut_asserteq(174, video_compress_fb(uts, dev, false));
+	ut_asserteq(first, video_compress_fb(uts, dev, false));
 	ut_assertok(video_check_copy_fb(uts, dev));
 
-	/* Draw the pointer on top of the black rectangle */
+	/* Draw the pointer on top of the white background */
 	ut_assertok(video_bmp_display(dev, addr, 350, 110, false));
-	ut_asserteq(249, video_compress_fb(uts, dev, false));
+	ut_asserteq(second, video_compress_fb(uts, dev, false));
+
+	/* Draw the pointer with white (0xffffff) as transparent */
+	ut_assertok(video_bmp_displaya(dev, addr, 110, 160, false, true,
+				       0xffffff));
+	ut_assertok(video_bmp_displaya(dev, addr, 350, 160, false, true,
+				       0xffffff));
+	ut_asserteq(trans, video_compress_fb(uts, dev, false));
 	ut_assertok(video_check_copy_fb(uts, dev));
 
 	return 0;
 }
-DM_TEST(dm_test_video_bmp_alpha, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
+/* Test drawing the riscos pointer on a 16bpp display */
+static int dm_test_video_bmp_alpha16(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(video_get_nologo(uts, &dev));
+	ut_assertok(check_bmp_alpha(uts, dev, 174, 249, 358));
+
+	return 0;
+}
+DM_TEST(dm_test_video_bmp_alpha16, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
+/* Test drawing the riscos pointer on 32bpp display */
+static int dm_test_video_bmp_alpha32(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
+	ut_assertnonnull(dev);
+	ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
+	ut_assertok(check_bmp_alpha(uts, dev, 641, 710, 869));
+
+	return 0;
+}
+DM_TEST(dm_test_video_bmp_alpha32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
 
 /* Test TrueType console */
 static int dm_test_video_truetype(struct unit_test_state *uts)