Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105850654
D28849.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D28849.diff
View Options
diff --git a/stand/common/gfx_fb.h b/stand/common/gfx_fb.h
--- a/stand/common/gfx_fb.h
+++ b/stand/common/gfx_fb.h
@@ -109,6 +109,8 @@
uint8_t checksum;
} __packed;
+extern struct vesa_edid_info *edid_info;
+
#define STD_TIMINGS 8
#define DET_TIMINGS 4
diff --git a/stand/common/gfx_fb.c b/stand/common/gfx_fb.c
--- a/stand/common/gfx_fb.c
+++ b/stand/common/gfx_fb.c
@@ -1863,6 +1863,113 @@
}
}
+/* 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 @@
}
}
+ if (font == NULL)
+ font = gfx_get_font();
+
if (font != NULL) {
*rows = height / font->vfbd_height;
*cols = width / font->vfbd_width;
diff --git a/stand/efi/libefi/efi_console.c b/stand/efi/libefi/efi_console.c
--- a/stand/efi/libefi/efi_console.c
+++ b/stand/efi/libefi/efi_console.c
@@ -952,13 +952,24 @@
/*
* setup_font() can adjust terminal size.
- * Note, we do use UEFI terminal dimensions first,
- * this is because the font selection will attempt
- * to achieve at least this terminal dimension and
- * we do not end up with too small font.
+ * We can see two kind of bad happening.
+ * We either can get too small console font - requested
+ * terminal size is large, display resolution is
+ * large, and we get very small font.
+ * Or, we can get too large font - requested
+ * terminal size is small and this will cause large
+ * font to be selected.
+ * Now, the setup_font() is updated to consider
+ * display density and this should give us mostly
+ * acceptable font. However, the catch is, not all
+ * display devices will give us display density.
+ * Still, we do hope, external monitors do - this is
+ * where the display size will matter the most.
+ * And for laptop screens, we should still get good
+ * results by requesting 80x25 terminal.
*/
- gfx_state.tg_tp.tp_row = rows;
- gfx_state.tg_tp.tp_col = cols;
+ gfx_state.tg_tp.tp_row = 25;
+ gfx_state.tg_tp.tp_col = 80;
setup_font(&gfx_state, fb_height, fb_width);
rows = gfx_state.tg_tp.tp_row;
cols = gfx_state.tg_tp.tp_col;
diff --git a/stand/efi/loader/framebuffer.c b/stand/efi/loader/framebuffer.c
--- a/stand/efi/loader/framebuffer.c
+++ b/stand/efi/loader/framebuffer.c
@@ -38,6 +38,8 @@
#include <efilib.h>
#include <efiuga.h>
#include <efipciio.h>
+#include <Protocol/EdidActive.h>
+#include <Protocol/EdidDiscovered.h>
#include <machine/metadata.h>
#include "bootstrap.h"
@@ -47,6 +49,12 @@
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
static EFI_GUID pciio_guid = EFI_PCI_IO_PROTOCOL_GUID;
static EFI_GUID uga_guid = EFI_UGA_DRAW_PROTOCOL_GUID;
+static EFI_GUID active_edid_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID;
+static EFI_GUID discovered_edid_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID;
+static EFI_HANDLE gop_handle;
+
+/* Cached EDID. */
+struct vesa_edid_info *edid_info = NULL;
static EFI_GRAPHICS_OUTPUT *gop;
static EFI_UGA_DRAW_PROTOCOL *uga;
@@ -467,10 +475,71 @@
return (0);
}
+/*
+ * Fetch EDID info. Caller must free the buffer.
+ */
+static struct vesa_edid_info *
+efifb_gop_get_edid(EFI_HANDLE h)
+{
+ const uint8_t magic[] = EDID_MAGIC;
+ EFI_EDID_ACTIVE_PROTOCOL *edid;
+ struct vesa_edid_info *edid_infop;
+ EFI_GUID *guid;
+ EFI_STATUS status;
+ size_t size;
+
+ guid = &active_edid_guid;
+ status = BS->OpenProtocol(h, guid, (void **)&edid, IH, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (status != EFI_SUCCESS ||
+ edid->SizeOfEdid == 0) {
+ guid = &discovered_edid_guid;
+ status = BS->OpenProtocol(h, guid, (void **)&edid, IH, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (status != EFI_SUCCESS ||
+ edid->SizeOfEdid == 0)
+ return (NULL);
+ }
+
+ size = MAX(sizeof(*edid_infop), edid->SizeOfEdid);
+
+ edid_infop = calloc(1, size);
+ if (edid_infop == NULL)
+ return (NULL);
+
+ memcpy(edid_infop, edid->Edid, edid->SizeOfEdid);
+
+ /* Validate EDID */
+ if (memcmp(edid_infop, magic, sizeof (magic)) != 0)
+ goto error;
+
+ if (edid_infop->header.version != 1)
+ goto error;
+
+ return (edid_infop);
+error:
+ free(edid_infop);
+ return (NULL);
+}
+
+static bool
+efifb_get_edid(edid_res_list_t *res)
+{
+ bool rv = false;
+
+ if (edid_info == NULL)
+ edid_info = efifb_gop_get_edid(gop_handle);
+
+ if (edid_info != NULL)
+ rv = gfx_get_edid_resolution(edid_info, res);
+
+ return (rv);
+}
+
int
efi_find_framebuffer(teken_gfx_t *gfx_state)
{
- EFI_HANDLE h, *hlist;
+ EFI_HANDLE *hlist;
UINTN nhandles, i, hsize;
struct efi_fb efifb;
EFI_STATUS status;
@@ -498,23 +567,25 @@
/*
* Search for ConOut protocol, if not found, use first handle.
*/
- h = *hlist;
+ gop_handle = *hlist;
for (i = 0; i < nhandles; i++) {
void *dummy = NULL;
status = OpenProtocolByHandle(hlist[i], &conout_guid, &dummy);
if (status == EFI_SUCCESS) {
- h = hlist[i];
+ gop_handle = hlist[i];
break;
}
}
- status = OpenProtocolByHandle(h, &gop_guid, (void **)&gop);
+ status = OpenProtocolByHandle(gop_handle, &gop_guid, (void **)&gop);
free(hlist);
if (status == EFI_SUCCESS) {
gfx_state->tg_fb_type = FB_GOP;
gfx_state->tg_private = gop;
+ if (edid_info == NULL)
+ edid_info = efifb_gop_get_edid(gop_handle);
} else {
status = BS->LocateProtocol(&uga_guid, NULL, (VOID **)&uga);
if (status == EFI_SUCCESS) {
@@ -767,9 +838,25 @@
} else if (strcmp(argv[1], "off") == 0) {
(void) cons_update_mode(false);
} else if (strcmp(argv[1], "get") == 0) {
+ edid_res_list_t res;
+
if (argc != 2)
goto usage;
+ TAILQ_INIT(&res);
efifb_from_gop(&efifb, gop->Mode, gop->Mode->Info);
+ if (efifb_get_edid(&res)) {
+ struct resolution *rp;
+
+ printf("EDID");
+ while ((rp = TAILQ_FIRST(&res)) != NULL) {
+ printf(" %dx%d", rp->width, rp->height);
+ TAILQ_REMOVE(&res, rp, next);
+ free(rp);
+ }
+ printf("\n");
+ } else {
+ printf("no EDID information\n");
+ }
print_efifb(gop->Mode->Mode, &efifb, 1);
printf("\n");
} else if (!strcmp(argv[1], "list")) {
@@ -778,6 +865,7 @@
if (argc != 2)
goto usage;
+
pager_open();
for (mode = 0; mode < gop->Mode->MaxMode; mode++) {
status = gop->QueryMode(gop, mode, &infosz, &info);
diff --git a/stand/i386/libi386/vbe.c b/stand/i386/libi386/vbe.c
--- a/stand/i386/libi386/vbe.c
+++ b/stand/i386/libi386/vbe.c
@@ -51,6 +51,7 @@
static uint16_t *vbe_mode_list;
static size_t vbe_mode_list_size;
+struct vesa_edid_info *edid_info = NULL;
/* The default VGA color palette format is 6 bits per primary color. */
int palette_format = 6;
@@ -836,34 +837,40 @@
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);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 22, 3:56 PM (4 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15556252
Default Alt Text
D28849.diff (10 KB)
Attached To
Mode
D28849: loader: use display pixel density for font autoselection
Attached
Detach File
Event Timeline
Log In to Comment