diff options
author | Toomas Soome <tsoome@me.com> | 2021-02-19 17:33:19 +0200 |
---|---|---|
committer | Toomas Soome <tsoome@me.com> | 2021-03-18 10:05:47 +0200 |
commit | 1b1c4b089b04ffa47f04c2923dc78c7fcafcf964 (patch) | |
tree | 3474ee3c2e4d7381d0c0435ed4a50141a38da3cf /usr/src/boot | |
parent | 5fbc1fe0da7f34cf8155bf7624c94583cc98e47c (diff) | |
download | illumos-gate-1b1c4b089b04ffa47f04c2923dc78c7fcafcf964.tar.gz |
13575 loader: use display pixel density for font autoselection
Reviewed by: Yuri Pankov <yuripv@yuripv.dev>
Approved by: Robert Mustacchi <rm@fingolfin.org>
Diffstat (limited to 'usr/src/boot')
-rw-r--r-- | usr/src/boot/Makefile.version | 2 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.c | 107 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.h | 2 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/efi/loader/framebuffer.c | 2 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/vbe.c | 25 |
5 files changed, 127 insertions, 11 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version index 486e265893..656a8a3d08 100644 --- a/usr/src/boot/Makefile.version +++ b/usr/src/boot/Makefile.version @@ -34,4 +34,4 @@ LOADER_VERSION = 1.1 # Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes. # The version is processed from left to right, the version number can only # be increased. -BOOT_VERSION = $(LOADER_VERSION)-2021.03.12.1 +BOOT_VERSION = $(LOADER_VERSION)-2021.03.16.1 diff --git a/usr/src/boot/sys/boot/common/gfx_fb.c b/usr/src/boot/sys/boot/common/gfx_fb.c index 6331a28ab7..09875a85f1 100644 --- a/usr/src/boot/sys/boot/common/gfx_fb.c +++ b/usr/src/boot/sys/boot/common/gfx_fb.c @@ -1727,6 +1727,113 @@ gfx_fb_putimage(png_t *png, uint32_t ux1, uint32_t uy1, uint32_t ux2, return (0); } +/* Return w^2 + h^2 or 0, if the dimensions are unknown */ +static unsigned +edid_diagonal_squared(void) +{ + unsigned w, h; + + if (edid_info == NULL) + return (0); + + w = edid_info->display.max_horizontal_image_size; + h = edid_info->display.max_vertical_image_size; + + /* If either one is 0, we have aspect ratio, not size */ + if (w == 0 || h == 0) + return (0); + + /* + * some monitors encode the aspect ratio instead of the physical size. + */ + if ((w == 16 && h == 9) || (w == 16 && h == 10) || + (w == 4 && h == 3) || (w == 5 && h == 4)) + return (0); + + /* + * translate cm to inch, note we scale by 100 here. + */ + w = w * 100 / 254; + h = h * 100 / 254; + + /* Return w^2 + h^2 */ + return (w * w + h * h); +} + +/* + * calculate pixels per inch. + */ +static unsigned +gfx_get_ppi(void) +{ + unsigned dp, di; + + di = edid_diagonal_squared(); + if (di == 0) + return (0); + + dp = gfx_fb.framebuffer_common.framebuffer_width * + gfx_fb.framebuffer_common.framebuffer_width + + gfx_fb.framebuffer_common.framebuffer_height * + gfx_fb.framebuffer_common.framebuffer_height; + + return (isqrt(dp / di)); +} + +/* + * Calculate font size from density independent pixels (dp): + * ((16dp * ppi) / 160) * display_factor. + * Here we are using fixed constants: 1dp == 160 ppi and + * display_factor 2. + * + * We are rounding font size up and are searching for font which is + * not smaller than calculated size value. + */ +bitmap_data_t * +gfx_get_font(void) +{ + unsigned ppi, size; + bitmap_data_t *font = NULL; + struct fontlist *fl, *next; + + /* Text mode is not supported here. */ + if (gfx_fb.framebuffer_common.framebuffer_type == + MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT) + return (NULL); + + ppi = gfx_get_ppi(); + if (ppi == 0) + return (NULL); + + /* + * We will search for 16dp font. + * We are using scale up by 10 for roundup. + */ + size = (16 * ppi * 10) / 160; + /* Apply display factor 2. */ + size = roundup(size * 2, 10) / 10; + + STAILQ_FOREACH(fl, &fonts, font_next) { + next = STAILQ_NEXT(fl, font_next); + /* + * If this is last font or, if next font is smaller, + * we have our font. Make sure, it actually is loaded. + */ + if (next == NULL || next->font_data->height < size) { + font = fl->font_data; + if (font->font == NULL || + fl->font_flags == FONT_RELOAD) { + if (fl->font_load != NULL && + fl->font_name != NULL) + font = fl->font_load(fl->font_name); + } + break; + } + } + + return (font); +} + static int load_mapping(int fd, struct font *fp, int n) { diff --git a/usr/src/boot/sys/boot/common/gfx_fb.h b/usr/src/boot/sys/boot/common/gfx_fb.h index 3fb7fcc3af..8d20dcf162 100644 --- a/usr/src/boot/sys/boot/common/gfx_fb.h +++ b/usr/src/boot/sys/boot/common/gfx_fb.h @@ -95,6 +95,8 @@ struct vesa_edid_info { uint8_t checksum; } __packed; +extern struct vesa_edid_info *edid_info; + #define STD_TIMINGS 8 #define DET_TIMINGS 4 diff --git a/usr/src/boot/sys/boot/efi/loader/framebuffer.c b/usr/src/boot/sys/boot/efi/loader/framebuffer.c index 799678b222..bd86ea3e43 100644 --- a/usr/src/boot/sys/boot/efi/loader/framebuffer.c +++ b/usr/src/boot/sys/boot/efi/loader/framebuffer.c @@ -58,7 +58,7 @@ static EFI_HANDLE gop_handle; /* Saved initial GOP mode. */ static uint32_t default_mode = UINT32_MAX; /* Cached EDID. */ -static struct vesa_edid_info *edid_info = NULL; +struct vesa_edid_info *edid_info = NULL; static uint32_t gop_default_mode(void); static int efifb_set_mode(EFI_GRAPHICS_OUTPUT *, uint_t); diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.c b/usr/src/boot/sys/boot/i386/libi386/vbe.c index c48427f5f4..a0514aebec 100644 --- a/usr/src/boot/sys/boot/i386/libi386/vbe.c +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.c @@ -49,6 +49,7 @@ static struct modeinfoblock *vbe_mode = (struct modeinfoblock *)&vbestate.vbe_mode_info; static uint16_t *vbe_mode_list; static size_t vbe_mode_list_size; +struct vesa_edid_info *edid_info = NULL; multiboot_color_t *cmap; /* The default VGA color palette format is 6 bits per primary color. */ int palette_format = 6; @@ -573,34 +574,40 @@ vbe_dump_mode(int modenum, struct modeinfoblock *mi) static bool vbe_get_edid(edid_res_list_t *res) { - struct vesa_edid_info *edid_info; + struct vesa_edid_info *edidp; const uint8_t magic[] = EDID_MAGIC; int ddc_caps; bool ret = false; + if (edid_info != NULL) + return (gfx_get_edid_resolution(edid_info, res)); + ddc_caps = biosvbe_ddc_caps(); if (ddc_caps == 0) { return (ret); } - edid_info = bio_alloc(sizeof (*edid_info)); - if (edid_info == NULL) + edidp = bio_alloc(sizeof (*edidp)); + if (edidp == NULL) return (ret); - memset(edid_info, 0, sizeof (*edid_info)); + memset(edidp, 0, sizeof (*edidp)); - if (VBE_ERROR(biosvbe_ddc_read_edid(0, edid_info))) + if (VBE_ERROR(biosvbe_ddc_read_edid(0, edidp))) goto done; - if (memcmp(edid_info, magic, sizeof (magic)) != 0) + if (memcmp(edidp, magic, sizeof (magic)) != 0) goto done; /* Unknown EDID version. */ - if (edid_info->header.version != 1) + if (edidp->header.version != 1) goto done; - ret = gfx_get_edid_resolution(edid_info, res); + ret = gfx_get_edid_resolution(edidp, res); + edid_info = malloc(sizeof (*edid_info)); + if (edid_info != NULL) + memcpy(edid_info, edidp, sizeof (*edid_info)); done: - bio_free(edid_info, sizeof (*edid_info)); + bio_free(edidp, sizeof (*edidp)); return (ret); } |