aboutsummaryrefslogtreecommitdiff
path: root/stand/common
diff options
context:
space:
mode:
authorToomas Soome <tsoome@FreeBSD.org>2021-02-20 08:51:28 +0000
committerToomas Soome <tsoome@FreeBSD.org>2021-02-27 09:26:02 +0000
commitbecaac3972f1fde4e3c44516399468ba5ca65c9b (patch)
tree124942a742ecd89c75f58de230945b723540d175 /stand/common
parentc01da939b0998f8de068a23c9016c377e761255e (diff)
downloadsrc-becaac3972f1fde4e3c44516399468ba5ca65c9b.tar.gz
src-becaac3972f1fde4e3c44516399468ba5ca65c9b.zip
loader: use display pixel density for font autoselection
Calculate font size from 16 density independent pixels (dp) by using: size = 16 * ppi/160 * display_factor We are specifying font size 16dp, and assuming 1dp = 160ppi. Also apply scaling factor 2 (display_factor). MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D28849
Diffstat (limited to 'stand/common')
-rw-r--r--stand/common/gfx_fb.c110
-rw-r--r--stand/common/gfx_fb.h2
2 files changed, 112 insertions, 0 deletions
diff --git a/stand/common/gfx_fb.c b/stand/common/gfx_fb.c
index 02a0a3d2be22..77cf1d39854f 100644
--- a/stand/common/gfx_fb.c
+++ b/stand/common/gfx_fb.c
@@ -1863,6 +1863,113 @@ reset_font_flags(void)
}
}
+/* 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_state.tg_fb.fb_width *
+ gfx_state.tg_fb.fb_width +
+ gfx_state.tg_fb.fb_height *
+ gfx_state.tg_fb.fb_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.
+ */
+static vt_font_bitmap_data_t *
+gfx_get_font(void)
+{
+ unsigned ppi, size;
+ vt_font_bitmap_data_t *font = NULL;
+ struct fontlist *fl, *next;
+
+ /* Text mode is not supported here. */
+ if (gfx_state.tg_fb_type == FB_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->vfbd_height < size) {
+ font = fl->font_data;
+ if (font->vfbd_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 vt_font_bitmap_data_t *
set_font(teken_unit_t *rows, teken_unit_t *cols, teken_unit_t h, teken_unit_t w)
{
@@ -1887,6 +1994,9 @@ set_font(teken_unit_t *rows, teken_unit_t *cols, teken_unit_t h, teken_unit_t w)
}
}
+ if (font == NULL)
+ font = gfx_get_font();
+
if (font != NULL) {
*rows = height / font->vfbd_height;
*cols = width / font->vfbd_width;
diff --git a/stand/common/gfx_fb.h b/stand/common/gfx_fb.h
index 04076a2c6d38..ac63d7939cef 100644
--- a/stand/common/gfx_fb.h
+++ b/stand/common/gfx_fb.h
@@ -109,6 +109,8 @@ struct vesa_edid_info {
uint8_t checksum;
} __packed;
+extern struct vesa_edid_info *edid_info;
+
#define STD_TIMINGS 8
#define DET_TIMINGS 4