On Sun, 2 Nov 2025, Chad Jablonski wrote:
> Convert 1bpp monochrome images to 32bpp ARGB given a foreground and
> background color. This also supports most significant and least
> significant bit ordering.
>
> This is useful for host data transfers of glyphs when drawing text in X.
>
> Signed-off-by: Chad Jablonski <chad@jablonski.xyz>
> ---
> hw/display/ati_2d.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
> index 15cf29a061..181bf634f0 100644
> --- a/hw/display/ati_2d.c
> +++ b/hw/display/ati_2d.c
> @@ -45,6 +45,28 @@ static int ati_bpp_from_datatype(ATIVGAState *s)
> }
>
> #define DEFAULT_CNTL (s->regs.dp_gui_master_cntl & GMC_DST_PITCH_OFFSET_CNTL)
> +/* Convert 1bpp monochrome data to 32bpp ARGB using color expansion */
> +static void expand_colors(uint8_t *color_dst, const uint8_t *mono_src,
> + uint32_t width, uint32_t height,
> + uint32_t fg_color, uint32_t bg_color,
> + bool lsb_to_msb)
> +{
> + uint32_t byte, color;
> + uint8_t *pixel;
> + int i, j, bit;
> + /* Rows are 32-bit aligned */
> + int bytes_per_row = ((width + 31) / 32) * 4;
I think there's some QEMU_ALIGN macro for that maybe in qemu/osdep.h?
> +
> + for (i = 0; i < height; i++) {
> + for (j = 0; j < width; j++) {
> + byte = mono_src[i * bytes_per_row + (j / 8)];
> + bit = lsb_to_msb ? 7 - (j % 8) : j % 8;
> + color = (byte >> bit) & 0x1 ? fg_color : bg_color;
> + pixel = &color_dst[(i * width + j) * 4];
> + memcpy(pixel, &color, sizeof(color));
Since it's just writing a 32 bit value maybe cast and = would be faster
than calling memcpy for this.
Regards,
BALATON Zoltan
> + }
> + }
> +}
>
> void ati_2d_blt(ATIVGAState *s)
> {
>