summaryrefslogtreecommitdiff
path: root/usr/src/boot
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2021-02-19 17:33:19 +0200
committerToomas Soome <tsoome@me.com>2021-03-18 10:05:47 +0200
commit1b1c4b089b04ffa47f04c2923dc78c7fcafcf964 (patch)
tree3474ee3c2e4d7381d0c0435ed4a50141a38da3cf /usr/src/boot
parent5fbc1fe0da7f34cf8155bf7624c94583cc98e47c (diff)
downloadillumos-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.version2
-rw-r--r--usr/src/boot/sys/boot/common/gfx_fb.c107
-rw-r--r--usr/src/boot/sys/boot/common/gfx_fb.h2
-rw-r--r--usr/src/boot/sys/boot/efi/loader/framebuffer.c2
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/vbe.c25
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);
}