* [PATCH v2 1/5] vt: Add cursor-size helpers
2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
2026-09-15 12:40 ` sashiko-bot
2026-09-23 12:57 ` Greg KH
2026-09-15 12:29 ` [PATCH v2 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
` (3 subsequent siblings)
4 siblings, 2 replies; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 UTC (permalink / raw)
To: deller, gregkh, jirislaby, simona
Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
Thomas Zimmermann
Cursors in the VT subsystem are blocks within a character cell that are
filled with the foreground color. The new helpers vc_cursor_start() and
vc_cursor_end() return the scanlines in which the cursor block starts rsp.
ends. This is compatible with VGA hardware
In terms of cursor design, the new cursor-size helpers follow established
styles in fbcon. The only exception is in underline cursors for fonts with
a size larger than 10. The underlining dash is now one pixel closer to
the font-glyph data, so that the cursor looks less detached. This follows
the style used by vgacon.
Similar code in vgacon and fbcon ignores the cursor's default size stored
in vt.cur_default. The consoles default to full-block cursors, while vt
defaults to underline cursors. The new helper fall back to cur_default and
then underline cursors; in this order.
v2:
- export non-font interface for vgacon
- avoid interference from concurrent user space (Sashiko)
- fix function docs (Sashiko)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
drivers/tty/vt/vt.c | 93 ++++++++++++++++++++++++++++++++++
include/linux/console_struct.h | 7 +++
2 files changed, 100 insertions(+)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 57edf37495a8..5d2583cd6e79 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -71,6 +71,7 @@
* by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
*/
+#include <linux/compiler.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched/signal.h>
@@ -264,6 +265,98 @@ unsigned int vc_font_size(const struct vc_font *font)
}
EXPORT_SYMBOL_GPL(vc_font_size);
+/*
+ * Cursors
+ */
+
+/**
+ * vc_cursor_start - Calculates the cursor's first scanline within a character cell
+ * @cell_height: The overall height of the character cell
+ * @cursor_size: The size constant of cursor pattern
+ *
+ * The parameter @cell_height is the height of the character cell as
+ * displayed by the console. The argument given in @cursor_size is one
+ * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
+ * For unknown values, the helper draws the default cursor or an underline
+ * dash.
+ *
+ * Returns:
+ * The index of the cursor's first scanline within the character cell
+ */
+unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size)
+{
+ const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
+
+retry:
+ switch (cursor_size) {
+ case CUR_NONE:
+ return cell_height;
+ case CUR_UNDERLINE:
+ if (cell_height < 10)
+ return cell_height - 1;
+ else
+ return cell_height - 3;
+ case CUR_LOWER_THIRD:
+ return cell_height - cell_height / 3;
+ case CUR_LOWER_HALF:
+ return cell_height - cell_height / 2;
+ case CUR_TWO_THIRDS:
+ return cell_height - (cell_height * 2) / 3;
+ case CUR_BLOCK:
+ return 0;
+ default:
+ pr_warn_once("Unknown cursor %u\n", cursor_size);
+ if (cursor_size != cursor_default_size)
+ cursor_size = cursor_default_size;
+ else
+ cursor_size = CUR_UNDERLINE;
+ goto retry;
+ }
+}
+EXPORT_SYMBOL_GPL(vc_cursor_start);
+
+/**
+ * vc_cursor_end - Calculates the first scanline after the cursor within a character cell
+ * @cell_height: The overall height of the character cell
+ * @cursor_size: The size constant of cursor pattern
+ *
+ * The parameter @cell_height is the height of the character cell as
+ * displayed by the console. The argument given in @cursor_size is one
+ * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
+ * For unknown values, the helper draws the default cursor or an underline
+ * dash.
+ *
+ * Returns:
+ * The index of the first scanline after the cursor within the character cell
+ */
+unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size)
+{
+ const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
+
+retry:
+ switch (cursor_size) {
+ case CUR_UNDERLINE:
+ if (cell_height < 10)
+ return cell_height;
+ else
+ return cell_height - 1;
+ case CUR_NONE:
+ case CUR_LOWER_THIRD:
+ case CUR_LOWER_HALF:
+ case CUR_TWO_THIRDS:
+ case CUR_BLOCK:
+ return cell_height;
+ default:
+ pr_warn_once("Unknown cursor %u\n", cursor_size);
+ if (cursor_size != cursor_default_size)
+ cursor_size = cursor_default_size;
+ else
+ cursor_size = CUR_UNDERLINE;
+ goto retry;
+ }
+}
+EXPORT_SYMBOL_GPL(vc_cursor_end);
+
/*
* /sys/class/tty/tty0/
*
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index fe915afdece5..1d37c7898ea0 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -204,6 +204,10 @@ struct vc {
extern struct vc vc_cons [MAX_NR_CONSOLES];
extern void vc_SAK(struct work_struct *work);
+/*
+ * Cursors
+ */
+
#define CUR_MAKE(size, change, set) ((size) | ((change) << 8) | \
((set) << 16))
#define CUR_SIZE(c) ((c) & 0x00000f)
@@ -222,6 +226,9 @@ extern void vc_SAK(struct work_struct *work);
#define CUR_CHANGE(c) ((c) & 0x00ff00)
#define CUR_SET(c) (((c) & 0xff0000) >> 8)
+unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size);
+unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size);
+
bool con_is_visible(const struct vc_data *vc);
#endif /* _LINUX_CONSOLE_STRUCT_H */
--
2.55.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v2 1/5] vt: Add cursor-size helpers
2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
@ 2026-09-15 12:40 ` sashiko-bot
2026-09-23 12:57 ` Greg KH
1 sibling, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-15 12:40 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: dri-devel, linux-serial
> Cursors in the VT subsystem are blocks within a character cell that are
> filled with the foreground color. The new helpers vc_cursor_start() and
> vc_cursor_end() return the scanlines in which the cursor block starts rsp.
> ends. This is compatible with VGA hardware
>
> In terms of cursor design, the new cursor-size helpers follow established
> styles in fbcon. The only exception is in underline cursors for fonts with
> a size larger than 10. The underlining dash is now one pixel closer to
> the font-glyph data, so that the cursor looks less detached. This follows
> the style used by vgacon.
>
> Similar code in vgacon and fbcon ignores the cursor's default size stored
> in vt.cur_default. The consoles default to full-block cursors, while vt
> defaults to underline cursors. The new helper fall back to cur_default and
> then underline cursors; in this order.
>
> v2:
> - export non-font interface for vgacon
> - avoid interference from concurrent user space (Sashiko)
> - fix function docs (Sashiko)
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260915123304.1027277-1-tzimmermann@suse.de?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 1/5] vt: Add cursor-size helpers
2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
2026-09-15 12:40 ` sashiko-bot
@ 2026-09-23 12:57 ` Greg KH
2026-09-23 13:30 ` Thomas Zimmermann
1 sibling, 1 reply; 13+ messages in thread
From: Greg KH @ 2026-09-23 12:57 UTC (permalink / raw)
To: Thomas Zimmermann
Cc: deller, jirislaby, simona, linux-fbdev, dri-devel, linux-serial,
sashiko-reviews
On Tue, Sep 15, 2026 at 02:29:12PM +0200, Thomas Zimmermann wrote:
> Cursors in the VT subsystem are blocks within a character cell that are
> filled with the foreground color. The new helpers vc_cursor_start() and
> vc_cursor_end() return the scanlines in which the cursor block starts rsp.
> ends. This is compatible with VGA hardware
>
> In terms of cursor design, the new cursor-size helpers follow established
> styles in fbcon. The only exception is in underline cursors for fonts with
> a size larger than 10. The underlining dash is now one pixel closer to
> the font-glyph data, so that the cursor looks less detached. This follows
> the style used by vgacon.
>
> Similar code in vgacon and fbcon ignores the cursor's default size stored
> in vt.cur_default. The consoles default to full-block cursors, while vt
> defaults to underline cursors. The new helper fall back to cur_default and
> then underline cursors; in this order.
>
> v2:
> - export non-font interface for vgacon
> - avoid interference from concurrent user space (Sashiko)
> - fix function docs (Sashiko)
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> Reviewed-by: Helge Deller <deller@gmx.de>
> ---
> drivers/tty/vt/vt.c | 93 ++++++++++++++++++++++++++++++++++
> include/linux/console_struct.h | 7 +++
> 2 files changed, 100 insertions(+)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 57edf37495a8..5d2583cd6e79 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -71,6 +71,7 @@
> * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
> */
>
> +#include <linux/compiler.h>
> #include <linux/module.h>
> #include <linux/types.h>
> #include <linux/sched/signal.h>
> @@ -264,6 +265,98 @@ unsigned int vc_font_size(const struct vc_font *font)
> }
> EXPORT_SYMBOL_GPL(vc_font_size);
>
> +/*
> + * Cursors
> + */
> +
> +/**
> + * vc_cursor_start - Calculates the cursor's first scanline within a character cell
> + * @cell_height: The overall height of the character cell
> + * @cursor_size: The size constant of cursor pattern
> + *
> + * The parameter @cell_height is the height of the character cell as
> + * displayed by the console. The argument given in @cursor_size is one
> + * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
> + * For unknown values, the helper draws the default cursor or an underline
> + * dash.
> + *
> + * Returns:
> + * The index of the cursor's first scanline within the character cell
> + */
> +unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size)
> +{
> + const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
> +
> +retry:
> + switch (cursor_size) {
> + case CUR_NONE:
> + return cell_height;
> + case CUR_UNDERLINE:
> + if (cell_height < 10)
> + return cell_height - 1;
> + else
> + return cell_height - 3;
> + case CUR_LOWER_THIRD:
> + return cell_height - cell_height / 3;
> + case CUR_LOWER_HALF:
> + return cell_height - cell_height / 2;
> + case CUR_TWO_THIRDS:
> + return cell_height - (cell_height * 2) / 3;
> + case CUR_BLOCK:
> + return 0;
> + default:
> + pr_warn_once("Unknown cursor %u\n", cursor_size);
Can userspace trigger this? If not, who can?
> + if (cursor_size != cursor_default_size)
> + cursor_size = cursor_default_size;
> + else
> + cursor_size = CUR_UNDERLINE;
Why underline as a default?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 1/5] vt: Add cursor-size helpers
2026-09-23 12:57 ` Greg KH
@ 2026-09-23 13:30 ` Thomas Zimmermann
0 siblings, 0 replies; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-23 13:30 UTC (permalink / raw)
To: Greg KH
Cc: deller, jirislaby, simona, linux-fbdev, dri-devel, linux-serial,
sashiko-reviews
Hi
Am 23.09.26 um 14:57 schrieb Greg KH:
[...]
>> + * Returns:
>> + * The index of the cursor's first scanline within the character cell
>> + */
>> +unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size)
>> +{
>> + const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
>> +
>> +retry:
>> + switch (cursor_size) {
>> + case CUR_NONE:
>> + return cell_height;
>> + case CUR_UNDERLINE:
>> + if (cell_height < 10)
>> + return cell_height - 1;
>> + else
>> + return cell_height - 3;
>> + case CUR_LOWER_THIRD:
>> + return cell_height - cell_height / 3;
>> + case CUR_LOWER_HALF:
>> + return cell_height - cell_height / 2;
>> + case CUR_TWO_THIRDS:
>> + return cell_height - (cell_height * 2) / 3;
>> + case CUR_BLOCK:
>> + return 0;
>> + default:
>> + pr_warn_once("Unknown cursor %u\n", cursor_size);
> Can userspace trigger this? If not, who can?
Yes. There's the "vt.cur_default" parameter on the kernel's command line
[1], and apparently there's some escape sequence. [2] The cursor size
is the lowest 4 bits of that value, while
[1] https://elixir.bootlin.com/linux/v7.2.6/source/drivers/tty/vt/vt.c#L167
[2] https://elixir.bootlin.com/linux/v7.2.6/source/drivers/tty/vt/vt.c#L2523
Apart from that, I just noticed that this switch should certainly handle
CUR_DEF without printing a warning.
>
>> + if (cursor_size != cursor_default_size)
>> + cursor_size = cursor_default_size;
>> + else
>> + cursor_size = CUR_UNDERLINE;
> Why underline as a default?
This has been the default all along. It is the default value of the
cur_default parameter and picked up by vt when starting up a console.
[3] VGA BIOSes tend to default to underline as well AFAICT. Only the old
cursor code in fbcon falls back to full-size blocks if nothing else
works. Using underline harmonizes behavior across components.
[3] https://elixir.bootlin.com/linux/v7.2.6/source/drivers/tty/vt/vt.c#L2297
Best regards
Thomas
>
> thanks,
>
> greg k-h
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri, (HRB 36809, AG Nürnberg)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 2/5] vgacon: Remove trailing whitespaces
2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
2026-09-15 12:35 ` sashiko-bot
2026-09-15 12:29 ` [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 UTC (permalink / raw)
To: deller, gregkh, jirislaby, simona
Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
Thomas Zimmermann
Fix coding style.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
drivers/video/console/vgacon.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 37bd18730fe0..536e7fe4d142 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -881,14 +881,14 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
/* First, the Sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
/* CPU writes only to map 2 */
- vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
+ vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
/* Sequential addressing */
- vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
+ vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
/* Clear synchronous reset */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
/* Now, the graphics controller, select map 2 */
- vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
+ vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
/* disable odd-even addressing */
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
/* map start at A000:0000 */
@@ -930,7 +930,7 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
raw_spin_lock_irq(&vga_lock);
/* First, the sequencer, Synchronous reset */
- vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
+ vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
/* CPU writes to maps 0 and 1 */
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
/* odd-even addressing */
@@ -959,7 +959,7 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
/* Wilton (1987) mentions the following; I don't know what
it means, but it works, and it appears necessary */
inb_p(video_port_status);
- vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
+ vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
clear_attribs = true;
}
raw_spin_unlock_irq(&vga_lock);
--
2.55.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}()
2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
2026-09-15 12:29 ` [PATCH v2 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
2026-09-15 12:39 ` sashiko-bot
2026-09-15 12:29 ` [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
2026-09-15 12:29 ` [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 UTC (permalink / raw)
To: deller, gregkh, jirislaby, simona
Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
Thomas Zimmermann
Replace vgacon's custom cursor metrics with the shared helpers
vc_cursor_start() and vc_font_cursor_end(). Note that the _end()
function returns the index of the scanline below the cursor, while
VGA hardware expects the cursor's final scanline. Hence vgacon
subtracts 1 from the end value.
The cursor shapes remain mostly unchanged, except that non-underline
cursors now also use the glyph's top-most and bottom-most scanline.
This follows the style used by fbcon.
v2:
- restore use of vc_cell_height (Sashiko)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
drivers/video/console/vgacon.c | 33 +++++----------------------------
1 file changed, 5 insertions(+), 28 deletions(-)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 536e7fe4d142..b1408bb5e265 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -506,6 +506,7 @@ static void vgacon_set_cursor_size(int from, int to)
static void vgacon_cursor(struct vc_data *c, bool enable)
{
unsigned int c_height;
+ unsigned int c_size;
if (c->vc_mode != KD_TEXT)
return;
@@ -513,10 +514,11 @@ static void vgacon_cursor(struct vc_data *c, bool enable)
vgacon_restore_screen(c);
c_height = c->vc_cell_height;
+ c_size = CUR_SIZE(c->vc_cursor_type);
write_vga(14, (c->vc_pos - vga_vram_base) / 2);
- if (!enable) {
+ if (!enable || c_size == CUR_NONE) {
if (vga_video_type >= VIDEO_TYPE_VGAC)
vgacon_set_cursor_size(31, 30);
else
@@ -524,33 +526,8 @@ static void vgacon_cursor(struct vc_data *c, bool enable)
return;
}
- switch (CUR_SIZE(c->vc_cursor_type)) {
- case CUR_UNDERLINE:
- vgacon_set_cursor_size(c_height - (c_height < 10 ? 2 : 3),
- c_height - (c_height < 10 ? 1 : 2));
- break;
- case CUR_TWO_THIRDS:
- vgacon_set_cursor_size(c_height / 3,
- c_height - (c_height < 10 ? 1 : 2));
- break;
- case CUR_LOWER_THIRD:
- vgacon_set_cursor_size(c_height * 2 / 3,
- c_height - (c_height < 10 ? 1 : 2));
- break;
- case CUR_LOWER_HALF:
- vgacon_set_cursor_size(c_height / 2,
- c_height - (c_height < 10 ? 1 : 2));
- break;
- case CUR_NONE:
- if (vga_video_type >= VIDEO_TYPE_VGAC)
- vgacon_set_cursor_size(31, 30);
- else
- vgacon_set_cursor_size(31, 31);
- break;
- default:
- vgacon_set_cursor_size(1, c_height);
- break;
- }
+ vgacon_set_cursor_size(vc_cursor_start(c_height, c_size),
+ vc_cursor_end(c_height, c_size) - 1);
}
static void vgacon_doresize(struct vc_data *c,
--
2.55.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper
2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
` (2 preceding siblings ...)
2026-09-15 12:29 ` [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
2026-09-15 12:40 ` sashiko-bot
2026-09-15 12:29 ` [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 UTC (permalink / raw)
To: deller, gregkh, jirislaby, simona
Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
Thomas Zimmermann
The new helper font_glyph_cursor() fills a glyph with a cursor pattern.
As with the font_glyph_rotate_*() helpers, the caller has to provide the
output memory.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
include/linux/font.h | 4 +++
lib/fonts/Makefile | 3 ++-
lib/fonts/font_cursor.c | 56 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+), 1 deletion(-)
create mode 100644 lib/fonts/font_cursor.c
diff --git a/include/linux/font.h b/include/linux/font.h
index 5e1cf9830084..be1a26ff8ae9 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -109,6 +109,10 @@ const unsigned char *font_data_glyph_buf(font_data_t *fd,
bool font_data_is_equal(font_data_t *lhs, font_data_t *rhs);
int font_data_export(font_data_t *fd, struct console_font *font, unsigned int vpitch);
+/* font_cursor.c */
+void font_glyph_cursor(unsigned int width, unsigned int height,
+ unsigned int from, unsigned int to, unsigned char *out);
+
/* font_rotate.c */
void font_glyph_rotate_90(const unsigned char *glyph, unsigned int width, unsigned int height,
unsigned char *out);
diff --git a/lib/fonts/Makefile b/lib/fonts/Makefile
index 7202a70a56ef..bc08bf8ea3f8 100644
--- a/lib/fonts/Makefile
+++ b/lib/fonts/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# Font handling
-font-y := fonts.o
+font-y := fonts.o \
+ font_cursor.o
font-$(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION) += font_rotate.o
# Built-in fonts; sorted by Family-Size in ascending order
diff --git a/lib/fonts/font_cursor.c b/lib/fonts/font_cursor.c
new file mode 100644
index 000000000000..7f4d587669aa
--- /dev/null
+++ b/lib/fonts/font_cursor.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <linux/string.h>
+
+#include "font.h"
+
+/**
+ * font_glyph_cursor - Create a cursor glyph
+ * @width: The glyph width in bits per scanline
+ * @height: The number of scanlines in the glyph
+ * @start: The first scanline of the cursor block
+ * @end: The first scanline after the cursor block
+ * @out: The cursor-glyph bitmap
+ *
+ * The parameters @width and @height refer to the glyph size. The caller
+ * has to provide the output buffer @out of sufficient size to hold the
+ * cursor glyph. The arguments in @start and @end describe the number of
+ * scanlines occupied by the cursor block; counting from the top of the
+ * glyph. The helper fills these scanlines with a pattern and clears the
+ * remaining scanlines.
+ */
+void font_glyph_cursor(unsigned int width, unsigned int height,
+ unsigned int start, unsigned int end, unsigned char *out)
+{
+ unsigned int pitch = font_glyph_pitch(width);
+ const unsigned char *out_end = out + height * pitch;
+ unsigned int size;
+
+ if (WARN_ON_ONCE(start > height))
+ start = height;
+ if (WARN_ON_ONCE(end > height))
+ end = height;
+
+ if (end < start)
+ end = start;
+
+ /* clear scanlines before cursor block */
+ size = start * pitch;
+ memset(out, 0x00, size);
+ out += size;
+
+ /* set cursor block */
+ size = (end - start) * pitch;
+ memset(out, 0xff, size);
+ out += size;
+
+ /* clear scanlines below cursor block */
+ size = (height - end) * pitch;
+ memset(out, 0x00, size);
+ out += size;
+
+ WARN_ON_ONCE(out != out_end);
+}
+EXPORT_SYMBOL_GPL(font_glyph_cursor);
--
2.55.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph()
2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
` (3 preceding siblings ...)
2026-09-15 12:29 ` [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
2026-09-15 12:41 ` sashiko-bot
4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 UTC (permalink / raw)
To: deller, gregkh, jirislaby, simona
Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
Thomas Zimmermann
The kernel's font library provides font_glyph_cursor() to create cursor
glyphs. Replace fbcon's fbcon_fill_cursor_mask() with a new helper that
uses font_glyph_cursor().
The cursor shapes remain mostly unchanged. The only exception is in
underline cursors for fonts with a size larger than 10. The underlining
dash is now one pixel closer to the font-glyph data, so that the cursor
looks less detached. This follows the style used by vgacon.
v2:
- adapt to new VT interface
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
drivers/video/fbdev/core/bitblit.c | 3 +-
drivers/video/fbdev/core/fbcon.c | 45 +++++++---------------------
drivers/video/fbdev/core/fbcon.h | 2 +-
drivers/video/fbdev/core/fbcon_ccw.c | 3 +-
drivers/video/fbdev/core/fbcon_cw.c | 3 +-
drivers/video/fbdev/core/fbcon_ud.c | 3 +-
6 files changed, 16 insertions(+), 43 deletions(-)
diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
index 39f44258d793..03b3b18e1fe9 100644
--- a/drivers/video/fbdev/core/bitblit.c
+++ b/drivers/video/fbdev/core/bitblit.c
@@ -334,11 +334,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
vc->vc_cursor_type != par->p->cursor_shape ||
par->cursor_state.mask == NULL ||
par->cursor_reset) {
- unsigned char *mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
+ unsigned char *mask = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
if (!mask)
return;
- fbcon_fill_cursor_mask(par, vc, mask);
kfree(par->cursor_state.mask);
par->cursor_state.mask = (const char *)mask;
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 615fa596b7cc..8581b7a9b3b7 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -444,44 +444,21 @@ static void fbcon_del_cursor_work(struct fb_info *info)
cancel_delayed_work_sync(&par->cursor_work);
}
-void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask)
+unsigned char *fbcon_cursor_glyph(const struct vc_font *font, unsigned int cursor_type)
{
- static const unsigned int pattern = 0xffffffff;
- unsigned int pitch = vc_font_pitch(&vc->vc_font);
- unsigned int cur_height, size;
+ unsigned int height = font->height;
+ unsigned int cursor_size = CUR_SIZE(cursor_type);
+ unsigned char *glyph;
- switch (CUR_SIZE(vc->vc_cursor_type)) {
- case CUR_NONE:
- cur_height = 0;
- break;
- case CUR_UNDERLINE:
- if (vc->vc_font.height < 10)
- cur_height = 1;
- else
- cur_height = 2;
- break;
- case CUR_LOWER_THIRD:
- cur_height = vc->vc_font.height / 3;
- break;
- case CUR_LOWER_HALF:
- cur_height = vc->vc_font.height / 2;
- break;
- case CUR_TWO_THIRDS:
- cur_height = (vc->vc_font.height * 2) / 3;
- break;
- case CUR_BLOCK:
- default:
- cur_height = vc->vc_font.height;
- break;
- }
+ glyph = kmalloc_array(height, vc_font_pitch(font), GFP_ATOMIC);
+ if (!glyph)
+ return NULL;
- size = (vc->vc_font.height - cur_height) * pitch;
- while (size--)
- *mask++ = (unsigned char)~pattern;
+ font_glyph_cursor(font->width, height,
+ vc_cursor_start(height, cursor_size),
+ vc_cursor_end(height, cursor_size), glyph);
- size = cur_height * pitch;
- while (size--)
- *mask++ = (unsigned char)pattern;
+ return glyph;
}
#ifndef MODULE
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 407d207b14f1..054cf66b15fa 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -202,7 +202,7 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
extern void fbcon_set_bitops_ur(struct fbcon_par *par);
extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
-void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask);
+unsigned char *fbcon_cursor_glyph(const struct vc_font *font, unsigned int cursor_type);
#define FBCON_ATTRIBUTE_UNDERLINE 1
#define FBCON_ATTRIBUTE_REVERSE 2
diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
index 33f02d579e02..9a9839631cc5 100644
--- a/drivers/video/fbdev/core/fbcon_ccw.c
+++ b/drivers/video/fbdev/core/fbcon_ccw.c
@@ -298,10 +298,9 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
par->cursor_reset) {
unsigned char *tmp, *mask;
- tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC);
+ tmp = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
if (!tmp)
return;
- fbcon_fill_cursor_mask(par, vc, tmp);
mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC);
if (!mask) {
diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
index bde820967eb9..4cb20337cf79 100644
--- a/drivers/video/fbdev/core/fbcon_cw.c
+++ b/drivers/video/fbdev/core/fbcon_cw.c
@@ -281,10 +281,9 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
par->cursor_reset) {
unsigned char *tmp, *mask;
- tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC);
+ tmp = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
if (!tmp)
return;
- fbcon_fill_cursor_mask(par, vc, tmp);
mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC);
if (!mask) {
diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
index eaf08999e249..ac22b9846b79 100644
--- a/drivers/video/fbdev/core/fbcon_ud.c
+++ b/drivers/video/fbdev/core/fbcon_ud.c
@@ -328,10 +328,9 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
par->cursor_reset) {
unsigned char *tmp, *mask;
- tmp = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
+ tmp = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
if (!tmp)
return;
- fbcon_fill_cursor_mask(par, vc, tmp);
mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
if (!mask) {
--
2.55.0
^ permalink raw reply related [flat|nested] 13+ messages in thread