From patchwork Fri Sep 19 20:14:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 379 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758313048; bh=Xolh9sPpL4Fhe8SBviksbQ5XaFssdS1gSMuMIRU6Hx8=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=UVfuTxaJ7/fkp/uNrvhqXi8kFJmgl3S6yLcYchUElATNsNnjIt1dYzehHfw6WQBAO ih75rGrnzmbSkW1LvYbHm921e/X+nVClnHDadIP1DH/9JkLZI2ynYFCgz3zlFtuws9 CETPChU2VM1GgKPGw1/9bYpXVDDKMMICHHq2a4YAVpkJvEPc9OQV+wLL+fKyk4wv6E 4UPnPEc5SKI8qe5MLKigfFOoNxPP1QdHvsQNC4D0OulEg62f1tIzS/NgDs+ViAXMkk 6ZBBmru8bRev9HGQ/lIzUA/DvB+z7vPPx+2CnFtV+AeMe4RBB0kSEkPNCbKEgdI2j9 bfDbBbHd2GttA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id F15A767C8E for ; Fri, 19 Sep 2025 14:17:28 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id F9U5qLhCQFtB for ; Fri, 19 Sep 2025 14:17:28 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758313048; bh=Xolh9sPpL4Fhe8SBviksbQ5XaFssdS1gSMuMIRU6Hx8=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=UVfuTxaJ7/fkp/uNrvhqXi8kFJmgl3S6yLcYchUElATNsNnjIt1dYzehHfw6WQBAO ih75rGrnzmbSkW1LvYbHm921e/X+nVClnHDadIP1DH/9JkLZI2ynYFCgz3zlFtuws9 CETPChU2VM1GgKPGw1/9bYpXVDDKMMICHHq2a4YAVpkJvEPc9OQV+wLL+fKyk4wv6E 4UPnPEc5SKI8qe5MLKigfFOoNxPP1QdHvsQNC4D0OulEg62f1tIzS/NgDs+ViAXMkk 6ZBBmru8bRev9HGQ/lIzUA/DvB+z7vPPx+2CnFtV+AeMe4RBB0kSEkPNCbKEgdI2j9 bfDbBbHd2GttA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id E115967C06 for ; Fri, 19 Sep 2025 14:17:28 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758313046; bh=vs2BhE74ejAKiLRXa4UaWVUWDRDQuxK2rcUT9KmWAz8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HVtge+2C+hm0RnQKMB3PUoe4IbYvhIiFSlkXK2lkybZMwSw1ALLD359hIY0rqporv XpAVbft77fsLqmE+f9Q3YzWHLhvSSUU898xLfK4K+7q7ycaXVa1mr8N6k8sK2FLy4L WgqsmeJvMG6U1Ni2Lej4EP/knBnJlUcIHfTgFi1siNm2kBL2YZdg5+iKOBVNdaKW2J zOvn4ZUexumUDVWchkWohWtCRemf/OU/DjSusXV5j6Tfx6VlJWWJqFZP0O6EZXaaiV e5B5G14PYaGLMxnwimV4BP73r9KdGZZ0fpkc3ZHKoy3YuS4Ec5DMTmi2va43HIU+r1 0Hop5glLrJ3xQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 81F4867C0E; Fri, 19 Sep 2025 14:17:26 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 3kpCTTEU45H5; Fri, 19 Sep 2025 14:17:26 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758313044; bh=DE4oZGcFs7eoF+x3UlvSruhE/O8V2PYuwOZdbqCUi/s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VX/yz0zQc5Bja+HY0MmUBH/cWxEQGqzpVsBAvSBoWO/nYv+LngSXgRFBxyrLmKRAJ HL8U3RwOO/ZAs55YXPmRWsEEkW3D0UK3cqT4+K4kem6IndhwNW4eqJQoDD3EOjn8IB cL+um/EKjpfaqGIEPrV8jqNWBeI000BZqKR9VUc/ycy9JFRjJdVdZzuLcr3f5ADJdj om6lGqs/ZW8VY6QnEug/7ApOTbvYp/7fR11gun7EPGv0v8eRzZdVSYECpegSQhGYj/ /BLL7OtqWZo+s2rh8vWOWyOSNdEwLjB+UUveXA00jIHIyDbvzAt0te+sNFoVRQTqWO CpDpWtvaVThYQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id B22EE67B55; Fri, 19 Sep 2025 14:17:23 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Fri, 19 Sep 2025 14:14:44 -0600 Message-ID: <20250919201507.4024144-38-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250919201507.4024144-1-sjg@u-boot.org> References: <20250919201507.4024144-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: ZH6DF477HPXIHOQOUO5W535TWP7MZHXN X-Message-ID-Hash: ZH6DF477HPXIHOQOUO5W535TWP7MZHXN X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 37/42] video: Save overwritten pixels when drawing the cursor List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Save the pixels overwritten by the cursor into the save area. Signed-off-by: Simon Glass --- drivers/video/console_core.c | 63 ++++++++++++++++++++++++++--- drivers/video/vidconsole-uclass.c | 36 +++++++++++++++++ drivers/video/vidconsole_internal.h | 15 ++++++- include/video_console.h | 16 +++++++- 4 files changed, 122 insertions(+), 8 deletions(-) diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c index 4fab5a2605e..3f3efb94ab1 100644 --- a/drivers/video/console_core.c +++ b/drivers/video/console_core.c @@ -190,8 +190,9 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv, bool direction) { - int step, line_step, pbytes, ret; + int step, line_step, pbytes, ret, row; void *line, *dst; + u32 *save_ptr; uint value; ret = check_bpix_support(vid_priv->bpix); @@ -207,20 +208,72 @@ int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv, line_step = vid_priv->line_length; } + /* we should not already have saved data */ + if (curs->saved) { + debug("Trying to show cursor but data is already saved\n"); + return -EINVAL; + } + /* Figure out where to write the cursor in the frame buffer */ line = vid_priv->fb + curs->y * vid_priv->line_length + curs->x * VNBYTES(vid_priv->bpix); + /* save pixels under cursor and draw new cursor in one pass */ value = vid_priv->colour_fg; - - for (int row = 0; row < curs->height; row++) { + save_ptr = curs->save_data; + for (row = 0; row < curs->height; row++) { dst = line; for (int col = 0; col < VIDCONSOLE_CURSOR_WIDTH; col++) - fill_pixel_and_goto_next(&dst, value, pbytes, step); - + *save_ptr++ = swap_pixel_and_goto_next(&dst, value, + pbytes, step); line += line_step; } + curs->saved = true; + + return 0; +} + +int cursor_hide(struct vidconsole_cursor *curs, struct video_priv *vid_priv, + bool direction) +{ + int step, line_step, pbytes, ret; + void *line, *dst; + + ret = check_bpix_support(vid_priv->bpix); + if (ret) + return ret; + + pbytes = VNBYTES(vid_priv->bpix); + if (direction) { + step = -pbytes; + line_step = -vid_priv->line_length; + } else { + step = pbytes; + line_step = vid_priv->line_length; + } + + /* Trying to hide cursor - we should have saved data */ + if (!curs->saved) { + debug("Trying to hide cursor but no data was saved\n"); + return -EINVAL; + } + + /* Figure out where to write the cursor in the frame buffer */ + line = vid_priv->fb + curs->y * vid_priv->line_length + + curs->x * VNBYTES(vid_priv->bpix); + + /* Restore saved pixels */ + u32 *save_ptr = curs->save_data; + dst = line; + for (int row = 0; row < curs->height; row++) { + void *row_dst = dst; + for (int col = 0; col < VIDCONSOLE_CURSOR_WIDTH; col++) + fill_pixel_and_goto_next(&row_dst, *save_ptr++, pbytes, + step); + dst += line_step; + } + curs->saved = false; return 0; } diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 15b62d160cd..3621714c742 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -71,6 +71,9 @@ static int vidconsole_back(struct udevice *dev) return ret; } + /* Hide cursor at old position if it's visible */ + vidconsole_hide_cursor(dev); + priv->xcur_frac -= VID_TO_POS(priv->x_charsize); if (priv->xcur_frac < priv->xstart_frac) { priv->xcur_frac = (priv->cols - 1) * @@ -128,6 +131,9 @@ void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y) { struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + /* Hide cursor at old position if it's visible */ + vidconsole_hide_cursor(dev); + priv->xcur_frac = VID_TO_POS(x); priv->xstart_frac = priv->xcur_frac; priv->ycur = y; @@ -473,6 +479,9 @@ int vidconsole_put_char(struct udevice *dev, char ch) struct vidconsole_priv *priv = dev_get_uclass_priv(dev); int cp, ret; + /* Hide cursor to avoid artifacts */ + vidconsole_hide_cursor(dev); + if (priv->escape) { vidconsole_escape_char(dev, ch); return 0; @@ -752,6 +761,33 @@ int vidconsole_show_cursor(struct udevice *dev) return 0; } +int vidconsole_hide_cursor(struct udevice *dev) +{ + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + struct vidconsole_cursor *curs = &priv->curs; + int ret; + + if (!curs->visible) + return 0; + + /* If the driver stored cursor line and height, use them for drawing */ + if (curs->height) { + struct udevice *vid = dev_get_parent(dev); + struct video_priv *vid_priv = dev_get_uclass_priv(vid); + + ret = cursor_hide(curs, vid_priv, NORMAL_DIRECTION); + if (ret) + return ret; + + /* Update display damage for cursor area */ + video_damage(vid, curs->x, curs->y, VIDCONSOLE_CURSOR_WIDTH, + curs->height); + } + + curs->visible = false; + + return 0; +} #endif /* CONFIG_CURSOR */ int vidconsole_mark_start(struct udevice *dev) diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h index 93f9c7b4e56..241be149ac9 100644 --- a/drivers/video/vidconsole_internal.h +++ b/drivers/video/vidconsole_internal.h @@ -112,7 +112,7 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri struct video_fontdata *fontdata, bool direction); /** - * cursor_show() - Draw a simple vertical cursor + * cursor_show() - Show cursor by saving and drawing pixels * * @curs: cursor information * @vid_priv: video-device info @@ -130,11 +130,22 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri *|---!!we're starting from upper left char corner| *|-----------------------------------------------| * - * Return: 0, if success, or else error code. + * Return: 0 on success, -EINVAL if cursor data already saved */ int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv, bool direction); +/** + * cursor_hide() - Hide cursor by restoring saved pixels + * + * @curs: cursor information + * @vid_priv: video-device info + * @direction: controls cursor orientation (normal or flipped) + * Return: 0 if success, -EINVAL if no cursor data was saved + */ +int cursor_hide(struct vidconsole_cursor *curs, struct video_priv *vid_priv, + bool direction); + /** * console_alloc_cursor() - Allocate cursor save buffer * diff --git a/include/video_console.h b/include/video_console.h index ffe331c5803..9005e9f4442 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -462,6 +462,16 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf); */ int vidconsole_show_cursor(struct udevice *dev); +/** + * vidconsole_hide_cursor() - Hide the cursor + * + * Hides the cursor if it's currently visible + * + * @dev: Console device to use + * Return: 0 if OK, -ve on error + */ +int vidconsole_hide_cursor(struct udevice *dev); + /** * vidconsole_readline_start() - Enable cursor for all video consoles * @@ -485,6 +495,11 @@ static inline int vidconsole_show_cursor(struct udevice *dev) return 0; } +static inline int vidconsole_hide_cursor(struct udevice *dev) +{ + return 0; +} + static inline void vidconsole_readline_start(bool indent) { } @@ -501,7 +516,6 @@ static inline void cli_index_adjust(struct vidconsole_priv *priv, int by) } /** - * vidconsole_push_colour() - Temporarily change the font colour * * @dev: Device to adjust