All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] vga: implement text mode character blink
@ 2026-05-25  8:19 marcandre.lureau
  2026-06-23 10:10 ` Gerd Hoffmann
  2026-06-23 10:54 ` Alex Bennée
  0 siblings, 2 replies; 3+ messages in thread
From: marcandre.lureau @ 2026-05-25  8:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Marc-André Lureau, Gerd Hoffmann

From: Marc-André Lureau <marcandre.lureau@redhat.com>

When bit 3 of the VGA Attribute Mode Control register is set, attribute
bit 7 switches from selecting bright background colors to enabling
character blink.

Implement this by tracking a separate blink phase timer that toggles
every 32 frames (matching real VGA hardware frame counter bit 5 @60hz),
and rendering blinking characters by replacing their foreground with
background during the off phase.

As with cursor, no VMState migration of the fields, as they are
transient display-side states.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/1585
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/display/vga_int.h |  2 ++
 hw/display/vga.c     | 24 +++++++++++++++++++++---
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index 747b5cc6cf8..5664317ecd6 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -130,6 +130,8 @@ typedef struct VGACommonState {
     uint8_t cursor_start, cursor_end;
     bool cursor_visible_phase;
     int64_t cursor_blink_time;
+    bool blink_visible_phase;
+    int64_t blink_time;
     uint32_t cursor_offset;
     const GraphicHwOps *hw_ops;
     bool full_update_text;
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 0ac4bf37310..ea01a889f20 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -45,8 +45,10 @@
 
 bool have_vga = true;
 
-/* 16 state changes per vertical frame @60 Hz */
+/* frame counter bit 4: cursor blink toggles every 16 frames @60 Hz */
 #define VGA_TEXT_CURSOR_PERIOD_MS       (1000 * 2 * 16 / 60)
+/* frame counter bit 5: character blink toggles every 32 frames @60 Hz */
+#define VGA_TEXT_BLINK_PERIOD_MS        (1000 * 2 * 32 / 60)
 
 /* Address mask for non-VESA modes.  */
 #define VGA_VRAM_SIZE                   (256 * KiB)
@@ -1286,6 +1288,13 @@ static void vga_draw_text(VGACommonState *s, int full_update)
         s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
         s->cursor_visible_phase = !s->cursor_visible_phase;
     }
+    if (now >= s->blink_time) {
+        s->blink_time = now + VGA_TEXT_BLINK_PERIOD_MS / 2;
+        s->blink_visible_phase = !s->blink_visible_phase;
+        if (s->ar[VGA_ATC_MODE] & 0x08) {
+            full_update = 1;
+        }
+    }
 
     dest = surface_data(surface);
     linesize = surface_stride(surface);
@@ -1317,8 +1326,17 @@ static void vga_draw_text(VGACommonState *s, int full_update)
 #endif
                 font_ptr = font_base[(cattr >> 3) & 1];
                 font_ptr += 32 * 4 * ch;
-                bgcol = palette[cattr >> 4];
-                fgcol = palette[cattr & 0x0f];
+                if (s->ar[VGA_ATC_MODE] & 0x08) {
+                    bgcol = palette[(cattr >> 4) & 0x07];
+                    if ((cattr & 0x80) && !s->blink_visible_phase) {
+                        fgcol = bgcol;
+                    } else {
+                        fgcol = palette[cattr & 0x0f];
+                    }
+                } else {
+                    bgcol = palette[cattr >> 4];
+                    fgcol = palette[cattr & 0x0f];
+                }
                 if (cw == 16) {
                     vga_draw_glyph16(d1, linesize,
                                      font_ptr, cheight, fgcol, bgcol);
-- 
2.54.0



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] vga: implement text mode character blink
  2026-05-25  8:19 [PATCH] vga: implement text mode character blink marcandre.lureau
@ 2026-06-23 10:10 ` Gerd Hoffmann
  2026-06-23 10:54 ` Alex Bennée
  1 sibling, 0 replies; 3+ messages in thread
From: Gerd Hoffmann @ 2026-06-23 10:10 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: qemu-devel

On Mon, May 25, 2026 at 12:19:44PM +0400, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> When bit 3 of the VGA Attribute Mode Control register is set, attribute
> bit 7 switches from selecting bright background colors to enabling
> character blink.
> 
> Implement this by tracking a separate blink phase timer that toggles
> every 32 frames (matching real VGA hardware frame counter bit 5 @60hz),
> and rendering blinking characters by replacing their foreground with
> background during the off phase.
> 
> As with cursor, no VMState migration of the fields, as they are
> transient display-side states.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/1585
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Acked-by: Gerd Hoffmann <kraxel@redhat.com>

take care,
  Gerd



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] vga: implement text mode character blink
  2026-05-25  8:19 [PATCH] vga: implement text mode character blink marcandre.lureau
  2026-06-23 10:10 ` Gerd Hoffmann
@ 2026-06-23 10:54 ` Alex Bennée
  1 sibling, 0 replies; 3+ messages in thread
From: Alex Bennée @ 2026-06-23 10:54 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: qemu-devel, Gerd Hoffmann

marcandre.lureau@redhat.com writes:

> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> When bit 3 of the VGA Attribute Mode Control register is set, attribute
> bit 7 switches from selecting bright background colors to enabling
> character blink.
>
> Implement this by tracking a separate blink phase timer that toggles
> every 32 frames (matching real VGA hardware frame counter bit 5 @60hz),
> and rendering blinking characters by replacing their foreground with
> background during the off phase.
>
> As with cursor, no VMState migration of the fields, as they are
> transient display-side states.
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/1585

I don't think this resolves all of 1585 because I think its asking for
the other text mode features as well.

> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hw/display/vga_int.h |  2 ++
>  hw/display/vga.c     | 24 +++++++++++++++++++++---
>  2 files changed, 23 insertions(+), 3 deletions(-)
>
> diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
> index 747b5cc6cf8..5664317ecd6 100644
> --- a/hw/display/vga_int.h
> +++ b/hw/display/vga_int.h
> @@ -130,6 +130,8 @@ typedef struct VGACommonState {
>      uint8_t cursor_start, cursor_end;
>      bool cursor_visible_phase;
>      int64_t cursor_blink_time;
> +    bool blink_visible_phase;
> +    int64_t blink_time;
>      uint32_t cursor_offset;
>      const GraphicHwOps *hw_ops;
>      bool full_update_text;
> diff --git a/hw/display/vga.c b/hw/display/vga.c
> index 0ac4bf37310..ea01a889f20 100644
> --- a/hw/display/vga.c
> +++ b/hw/display/vga.c
> @@ -45,8 +45,10 @@
>  
>  bool have_vga = true;
>  
> -/* 16 state changes per vertical frame @60 Hz */
> +/* frame counter bit 4: cursor blink toggles every 16 frames @60 Hz */
>  #define VGA_TEXT_CURSOR_PERIOD_MS       (1000 * 2 * 16 / 60)
> +/* frame counter bit 5: character blink toggles every 32 frames @60 Hz */
> +#define VGA_TEXT_BLINK_PERIOD_MS        (1000 * 2 * 32 / 60)
>  
>  /* Address mask for non-VESA modes.  */
>  #define VGA_VRAM_SIZE                   (256 * KiB)
> @@ -1286,6 +1288,13 @@ static void vga_draw_text(VGACommonState *s, int full_update)
>          s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
>          s->cursor_visible_phase = !s->cursor_visible_phase;
>      }
> +    if (now >= s->blink_time) {
> +        s->blink_time = now + VGA_TEXT_BLINK_PERIOD_MS / 2;
> +        s->blink_visible_phase = !s->blink_visible_phase;
> +        if (s->ar[VGA_ATC_MODE] & 0x08) {
> +            full_update = 1;
> +        }
> +    }

You should update the comment above vga_draw_text and remove "flashing"
as unimplemented.

>  
>      dest = surface_data(surface);
>      linesize = surface_stride(surface);
> @@ -1317,8 +1326,17 @@ static void vga_draw_text(VGACommonState *s, int full_update)
>  #endif
>                  font_ptr = font_base[(cattr >> 3) & 1];
>                  font_ptr += 32 * 4 * ch;
> -                bgcol = palette[cattr >> 4];
> -                fgcol = palette[cattr & 0x0f];
> +                if (s->ar[VGA_ATC_MODE] & 0x08) {
> +                    bgcol = palette[(cattr >> 4) & 0x07];
> +                    if ((cattr & 0x80) && !s->blink_visible_phase) {
> +                        fgcol = bgcol;
> +                    } else {
> +                        fgcol = palette[cattr & 0x0f];
> +                    }
> +                } else {
> +                    bgcol = palette[cattr >> 4];
> +                    fgcol = palette[cattr & 0x0f];
> +                }
>                  if (cw == 16) {
>                      vga_draw_glyph16(d1, linesize,
>                                       font_ptr, cheight, fgcol, bgcol);

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-06-23 10:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-25  8:19 [PATCH] vga: implement text mode character blink marcandre.lureau
2026-06-23 10:10 ` Gerd Hoffmann
2026-06-23 10:54 ` Alex Bennée

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.