Rotating (efi) framebuffer console
- Reply: Milan Obuch : "Re: Rotating (efi) framebuffer console"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 05 Feb 2022 20:50:41 UTC
Hi,
the screen of my brand new GPD Pocket 3 (tiger lake) laptop is in portrait mode
and reports a resolution of 1200x1920. I have another older device with the same
issue (a GPD Pocket 1).
In 2019 johalun@FreeBSD.org wrote on the freebsd-current about an Lenovo Ideapad
with a portrait mode screen and raised the question if it would be good to support
rotation of the vt_fb console.
Since the new GPD Pocket 3 is a nice device and rather well supported in FreeBSD,
i thought "how hard can it be" (OpenBSD has fb console rotation and Linux has fbcon=rotate..)
The patch (against stable/13, at the end of this mail) works for me(tm):
Whenever the width of a frambuffer device is smaller than it's height; a portrait mode
screen is assumed and the screen is rotated by 90 degrees clockwise.
I write this here for two reasons:
1. give others with similar hardware a chance to avoid the neck-craning issue
and
2. offer to work on something that can be reviewed and merged e.g.
- implement the rest of the transformations (180 degrees, 270 degrees)
- boot-time variable to select behavior
- vt(4) man page update
For 2. i would like to know if vt_fb.c is even the right place to do this.
The framebuffer code in the loader could also get this feature.
best regards
Stefan Grundmann
diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c
index c535d1b753c..19ab5999d89 100644
--- a/sys/dev/vt/hw/fb/vt_fb.c
+++ b/sys/dev/vt/hw/fb/vt_fb.c
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#define FB_FLAG_ROTATE 2147483648
+
static struct vt_driver vt_fb_driver = {
.vd_name = "fb",
.vd_init = vt_fb_init,
@@ -167,7 +169,13 @@ vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color)
info = vd->vd_softc;
c = info->fb_cmap[color];
- o = info->fb_stride * y + x * FBTYPE_GET_BYTESPP(info);
+
+ if (info->fb_flags & FB_FLAG_ROTATE) {
+ o = info->fb_stride * x +
+ (info->fb_width - (y + 1)) * FBTYPE_GET_BYTESPP(info);
+ } else {
+ o = info->fb_stride * y + x * FBTYPE_GET_BYTESPP(info);
+ }
if (info->fb_flags & FB_FLAG_NOWRITE)
return;
@@ -300,7 +308,13 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
/* Skip pixel write, if mask bit not set. */
if (mask != NULL && (mask[byte] & bit) == 0)
continue;
- o = (y + yi) * info->fb_stride + (x + xi) * bpp;
+ if (info->fb_flags & FB_FLAG_ROTATE) {
+ o = (x + xi) * info->fb_stride +
+ (info->fb_width - (y + yi + 1)) * bpp;
+ } else {
+ o = (y + yi) * info->fb_stride + (x + xi) * bpp;
+ }
+
o += vd->vd_transpose;
cc = pattern[byte] & bit ? fgc : bgc;
@@ -464,12 +478,22 @@ vt_fb_init(struct vt_device *vd)
term_color_t c;
info = vd->vd_softc;
- vd->vd_height = MIN(VT_FB_MAX_HEIGHT, info->fb_height);
- margin = (info->fb_height - vd->vd_height) >> 1;
- vd->vd_transpose = margin * info->fb_stride;
- vd->vd_width = MIN(VT_FB_MAX_WIDTH, info->fb_width);
- margin = (info->fb_width - vd->vd_width) >> 1;
- vd->vd_transpose += margin * (info->fb_bpp / NBBY);
+ if (info->fb_height > info->fb_width) { /*assume 90 degrees clockwise rotation*/
+ info->fb_flags |= FB_FLAG_ROTATE;
+ vd->vd_height = MIN(VT_FB_MAX_HEIGHT, info->fb_width);
+ vd->vd_width = MIN(VT_FB_MAX_WIDTH, info->fb_height);
+ margin = (info->fb_height - vd->vd_width) >> 1;
+ vd->vd_transpose = margin * info->fb_stride;
+ margin = (info->fb_width - vd->vd_height) >> 1;
+ vd->vd_transpose += margin * (info->fb_bpp / NBBY);
+ } else {
+ vd->vd_height = MIN(VT_FB_MAX_HEIGHT, info->fb_height);
+ margin = (info->fb_height - vd->vd_height) >> 1;
+ vd->vd_transpose = margin * info->fb_stride;
+ vd->vd_width = MIN(VT_FB_MAX_WIDTH, info->fb_width);
+ margin = (info->fb_width - vd->vd_width) >> 1;
+ vd->vd_transpose += margin * (info->fb_bpp / NBBY);
+ }
vd->vd_video_dev = info->fb_video_dev;
if (info->fb_size == 0)