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)