From patchwork Fri Sep 19 20:14:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 363 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=1758312999; bh=YCE/y4iXP+/iSRQgmkw3Gi2b1wmn51YpKHBVAVkHNTk=; 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=M1NeULrN9Thi4rrFy54HDM1Ux4S+0KDsrXmrkWEniMRAANV1G5MtlZIcsJpQwyle7 70t5bS+8sBf3JJiC4il7D5oywJysNteT2vBppr/IUomBKyFitX+ArxB9C8RftR1moo SxPmvd01wfHP4t231W0Nl8RExgAssRFz13dePLzK85mIAw+fyjOa18yLG3n3wy1BkH YbXKNd0N96sBiS03ZvbQ1hTg0Q7pttBhqz4m+zTz3t9mOsHggZQVis7Ty1KJSK1X63 FvmytO6W3fBoqIEEwcCuL/0L4EbyYKJOQ5sTrXS+CNs2PcRmpWDpsJvYygpYX/8/Bd TeQQG+e6BgDaw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8305867C5B for ; Fri, 19 Sep 2025 14:16:39 -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 Xc970FDAHGLB for ; Fri, 19 Sep 2025 14:16:39 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758312997; bh=YCE/y4iXP+/iSRQgmkw3Gi2b1wmn51YpKHBVAVkHNTk=; 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=rTdN+bx3uORtJgc8NR3Rs6tZ5WO1Yv8z9AFqUs2WlsKyfhLoBu13lnVvdpTBwJmPC BMf7QfLNktVbWDIc4MA/f7MLtJhlAINMuBDPzn6V9vZyNj4WnD+yptH1QKhxlreeVp qDYE3AxZavfZSI/AeCGOcaBX5hnWvLtq2NpSTYjcI7tta7ji7JivWh0k4x14EyQAPW 4W4ySZ+79yqr2b94irAIl4eUlSVO4jootCnDXJ7ZyayLL12GHL+P8HoS0UJTdke8sT 4rns6e/aH6zcc5HBzxLolNl5S3krj4RjfCOeUvkA+pRwnyFJyS9KDg6cudJLjjCcZP kq/Gii6z1xU1A== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 774F167BB6 for ; Fri, 19 Sep 2025 14:16:37 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758312994; bh=MGvCbHctLq4RgU+JLHOdBXkvEZmwDPfSeU1nweP+kcQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mbNt63jpaBvPwA8eLCwcZOpV8JAntWJykeyJJK5HFdQGH4P8kfESRAZEXkVBeZtsK IcyDALQg+KpRkgK5EZ7H+l2p+076+aeKkhfzpjTCRMf6HR0QFiMF0SA4HyclAffuZY pKJ0G94MXxUf3zthXcwI9AZF9vyLNXzFoJmk6yTtvBxqlkT3/5+mIIaeRS/3a5Z/bD EoDRkggboUMpECUkQxKdOgiTstyTGzTodbtz4tihGe7UyPisvDxiti8FEzGiUs/paH P8qH3vqL+ireIzPthEpW9P2z5x8Ilz0b+hp6CSz/W3/FfmDu/pfq3He+Ftm6tchNyF mKGCgHoMBa5uw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 5D3F167B3B; Fri, 19 Sep 2025 14:16:34 -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 5mDoGvjxjhCs; Fri, 19 Sep 2025 14:16:34 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758312992; bh=zVzCdpym2G1+1NmPS+eaMKlYbB7TxUFha5wdTn9JgVE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZYE5s2R+s4/f2N1WLInMa8rBhG6m4glMTUyfSq9CPX75FczCv0KzC9rdi77cZbokB yeVwTJpKlKODfyu1R/8PEI1RPcBWETVq7dDmSUWavpiCbjXR0w/CPKYoU1Lks05Etr 6mnEz9iUcoJV1i93Up231GNqLU5f8UpaYg8CiPLow6j80OgidEiXFd5ASPo8jSJ+28 M/2n4mmptHHU2w9a3ed2rNzcFrWeigczSecvslAgQeef4tU/KP7LvDtyex2FLYfTDk 9HU2vAa2PKmYq+fva+kgmFqiSPSRh9KM19J6177zM2iPqAZxzZ1pu8WnUQ2jmnQXkt udxifD2h1B2Qg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 84F4D67A99; Fri, 19 Sep 2025 14:16:32 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Fri, 19 Sep 2025 14:14:28 -0600 Message-ID: <20250919201507.4024144-22-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: 4NBQNKJVN263ACCDQWNLQTOYVFWYF6JK X-Message-ID-Hash: 4NBQNKJVN263ACCDQWNLQTOYVFWYF6JK 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 21/42] video: Move cursor drawing into the uclass 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 Rather than having the truetype driver draw the cursor, make it just return the information needed to draw the cursor. This will make it possible for the normal console to support a cursor too. Add a check for the cursor being entirely within the framebuffer. Signed-off-by: Simon Glass --- drivers/video/console_core.c | 14 +++++--- drivers/video/console_normal.c | 18 ++++++---- drivers/video/console_truetype.c | 42 ++++++++++-------------- drivers/video/vidconsole-uclass.c | 51 +++++++++++++++++++++++++---- drivers/video/vidconsole_internal.h | 14 +++++--- include/video_console.h | 29 +++++++++++++--- 6 files changed, 119 insertions(+), 49 deletions(-) diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c index 575d0bfe2b8..6db42e63ea9 100644 --- a/drivers/video/console_core.c +++ b/drivers/video/console_core.c @@ -160,12 +160,12 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri return ret; } -int cursor_show(void *line, struct video_priv *vid_priv, uint height, +int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv, bool direction) { int step, line_step, pbytes, ret; + void *line, *dst; uint value; - void *dst; ret = check_bpix_support(vid_priv->bpix); if (ret) @@ -180,16 +180,22 @@ int cursor_show(void *line, struct video_priv *vid_priv, uint height, line_step = vid_priv->line_length; } + /* 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); + value = vid_priv->colour_fg; - for (int row = 0; row < height; row++) { + for (int 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); + line += line_step; } - return ret; + return 0; } int console_probe(struct udevice *dev) diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index 315d3daa5ce..ad7eb4661a4 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -75,17 +75,18 @@ int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) return console_fixed_putc_xy(dev, x_frac, y, cp, priv->fontdata); } -static int __maybe_unused console_set_cursor_visible(struct udevice *dev, - bool visible, uint x, - uint y, uint index) +static __maybe_unused int console_get_cursor_info(struct udevice *dev, + bool visible, uint x, uint y, + uint index) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid); struct console_simple_priv *priv = dev_get_priv(dev); struct video_fontdata *fontdata = priv->fontdata; + struct vidconsole_cursor *curs = &vc_priv->curs; int pbytes = VNBYTES(vid_priv->bpix); - void *start; + void *start, *line; /* for now, this is not used outside expo */ if (!IS_ENABLED(CONFIG_EXPO)) @@ -98,7 +99,12 @@ static int __maybe_unused console_set_cursor_visible(struct udevice *dev, x -= 1; start = vid_priv->fb + y * vid_priv->line_length + x * pbytes; - cursor_show(start, vid_priv, vc_priv->y_charsize, NORMAL_DIRECTION); + line = start; + + /* Store line pointer and height in cursor struct */ + curs->x = x; + curs->y = y; + curs->height = vc_priv->y_charsize; return 0; } @@ -116,7 +122,7 @@ struct vidconsole_ops console_ops = { .get_font = console_simple_get_font, .select_font = console_simple_select_font, #ifdef CONFIG_CURSOR - .set_cursor_visible = console_set_cursor_visible, + .get_cursor_info = console_get_cursor_info, #endif }; diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index eedc285903b..eee4ea2e2a9 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -993,33 +993,30 @@ static int truetype_entry_restore(struct udevice *dev, struct abuf *buf) return 0; } -static int truetype_set_cursor_visible(struct udevice *dev, bool visible, - uint x, uint y, uint index) +static int truetype_get_cursor_info(struct udevice *dev, bool visible, + uint x, uint y, uint index) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); - struct udevice *vid = dev->parent; - struct video_priv *vid_priv = dev_get_uclass_priv(vid); struct console_tt_priv *priv = dev_get_priv(dev); - void *line; + struct vidconsole_cursor *curs = &vc_priv->curs; uint height; if (xpl_phase() <= PHASE_SPL) return -ENOSYS; - if (!visible) - return 0; - /* * figure out where to place the cursor. This driver ignores the * passed-in values, since an entry_restore() must have been done before * calling this function. */ - if (index < priv->pos_ptr) - x = VID_TO_PIXEL(priv->pos[index].xpos_frac); - else - x = VID_TO_PIXEL(vc_priv->xcur_frac); - - y = vc_priv->ycur; + if (visible) { + index = priv->pos_ptr; + if (index < priv->pos_ptr) + x = VID_TO_PIXEL(priv->pos[index].xpos_frac); + else + x = VID_TO_PIXEL(vc_priv->xcur_frac); + y = vc_priv->ycur; + } /* Get font height from current font type */ if (priv->cur_fontdata) @@ -1027,16 +1024,13 @@ static int truetype_set_cursor_visible(struct udevice *dev, bool visible, else height = priv->cur_met->font_size; - /* Figure out where to write the cursor in the frame buffer */ - line = vid_priv->fb + y * vid_priv->line_length + - x * VNBYTES(vid_priv->bpix); - - /* Use the shared cursor drawing function */ - cursor_show(line, vid_priv, height, NORMAL_DIRECTION); + /* Store line pointer and height in cursor struct */ + curs->x = x; + curs->y = y; + curs->index = index; + curs->height = height; - video_damage(dev->parent, x, y, VIDCONSOLE_CURSOR_WIDTH, height); - - return video_sync(vid, true); + return 0; } const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep) @@ -1101,7 +1095,7 @@ struct vidconsole_ops console_truetype_ops = { .nominal = truetype_nominal, .entry_save = truetype_entry_save, .entry_restore = truetype_entry_restore, - .set_cursor_visible = truetype_set_cursor_visible + .get_cursor_info = truetype_get_cursor_info, }; U_BOOT_DRIVER(vidconsole_truetype) = { diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 46fd355c05f..479793bc227 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -17,6 +17,7 @@ #include #include #include +#include "vidconsole_internal.h" #include /* Bitmap font for code page 437 */ #include @@ -702,21 +703,59 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf) } #ifdef CONFIG_CURSOR -int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, - uint x, uint y, uint index) +int vidconsole_show_cursor(struct udevice *dev, uint x, uint y, uint index) { + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); struct vidconsole_ops *ops = vidconsole_get_ops(dev); + struct vidconsole_cursor *curs = &priv->curs; int ret; - if (ops->set_cursor_visible) { - ret = ops->set_cursor_visible(dev, visible, x, y, index); - if (ret != -ENOSYS) + /* find out where the cursor should be drawn */ + if (ops->get_cursor_info) { + ret = ops->get_cursor_info(dev, true, x, y, index); + if (ret && ret != -ENOSYS) + return ret; + } + + /* 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); + + /* + * avoid drawing off the display - we assume that the driver + * ensures that curs->y < vid_priv->ysize + */ + curs->height = min(curs->height, vid_priv->ysize - curs->y); + + ret = cursor_show(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); + } + + priv->curs.visible = true; + + return 0; +} + +int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, + uint x, uint y, uint index) +{ + if (visible) { + int ret; + + ret = vidconsole_show_cursor(dev, x, y, index); + if (ret) return ret; } return 0; } -#endif +#endif /* CONFIG_CURSOR */ void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, enum colour_idx bg, struct vidconsole_colour *old) diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h index 0654a8f98e6..c008b9cf7d3 100644 --- a/drivers/video/vidconsole_internal.h +++ b/drivers/video/vidconsole_internal.h @@ -9,6 +9,10 @@ #include #include +struct udevice; +struct vidconsole_cursor; +struct video_priv; + #define FLIPPED_DIRECTION 1 #define NORMAL_DIRECTION 0 @@ -98,10 +102,10 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri /** * cursor_show() - Draw a simple vertical cursor * - * @line: pointer to framebuffer buffer: upper left cursor corner - * @vid_priv: driver private data - * @height: height of the cursor in pixels - * @param direction controls cursor orientation. Can be normal or flipped. + * @curs: cursor information + * @vid_priv: video-device info + * @direction: controls cursor orientation (normal or flipped) + * * When normal: When flipped: *|-----------------------------------------------| *| * | line stepping | @@ -116,7 +120,7 @@ int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_pri * * Return: 0, if success, or else error code. */ -int cursor_show(void *line, struct video_priv *vid_priv, uint height, +int cursor_show(struct vidconsole_cursor *curs, struct video_priv *vid_priv, bool direction); /** diff --git a/include/video_console.h b/include/video_console.h index ba34bb8e19f..d86cac42110 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -330,9 +330,9 @@ struct vidconsole_ops { int (*entry_restore)(struct udevice *dev, struct abuf *buf); /** - * set_cursor_visible() - Show or hide the cursor + * get_cursor_info() - Get cursor position info * - * Shows or hides a cursor at the current position + * Calculates and stores cursor position information * * @dev: Console device to use * @visible: true to show the cursor, false to hide it @@ -341,8 +341,8 @@ struct vidconsole_ops { * @index: Character position (0 = at start) * Return: 0 if OK, -ve on error */ - int (*set_cursor_visible)(struct udevice *dev, bool visible, - uint x, uint y, uint index); + int (*get_cursor_info)(struct udevice *dev, bool visible, + uint x, uint y, uint index); }; /* Get a pointer to the driver operations for a video console device */ @@ -430,6 +430,21 @@ int vidconsole_entry_save(struct udevice *dev, struct abuf *buf); int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf); #ifdef CONFIG_CURSOR +/** + * vidconsole_show_cursor() - Show the cursor + * + * Shows a cursor at the specified position. The position is passed in, but for + * the truetype console it is not actually used, since it tracks where the + * cursor must go. + * + * @dev: Console device to use + * @x: X position in pixels + * @y: Y position in pixels + * @index: Character position (0 = at start) + * Return: 0 if OK, -ve on error + */ +int vidconsole_show_cursor(struct udevice *dev, uint x, uint y, uint index); + /** * vidconsole_set_cursor_visible() - Show or hide the cursor * @@ -445,6 +460,12 @@ int vidconsole_entry_restore(struct udevice *dev, struct abuf *buf); int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, uint x, uint y, uint index); #else +static inline int vidconsole_show_cursor(struct udevice *dev, uint x, uint y, + uint index) +{ + return 0; +} + static inline int vidconsole_set_cursor_visible(struct udevice *dev, bool visible, uint x, uint y, uint index)