Skip to content

Conversation

@kbader94
Copy link
Owner

This patch series introduces framebuffer rotation support in GRUB,
intended for mobile, embedded, vertical-display systems, and weirdos
like me who have a primary screen in portrait orientation. It adds a
GRUB_FB_ROTATION configuration variable, which applies rotation
transforms to all framebuffer drawing operations (blit, fill, scroll,
etc.) when rendering to the primary framebuffer target.

This functionality has been requested and discussed previously:


How it works:

GRUB's graphical subsystem performs drawing operations on two types of
rendering targets: the framebuffer (the visible screen), and off-screen
buffers used for intermediate rendering (e.g., text composition).

Graphical operations, such as 'blit', 'fill', etc, are issued with a grub_video_fbblit_info
parameter, which contains image data, along with a
grub_video_mode_info structure describing the drawing context.
This patch series extends grub_video_mode_info with the following fields:

  • rotation: the current rotation mode (0, 90, 180, 270 degrees)
  • original_width, original_height: the logical dimensions prior to rotation

The rotation variable from config is applied only to the framebuffer target.
Off-screen render targets explicitly set rotation = GRUB_VIDEO_ROTATE_NONE to
prevent interference with text layout and other logical rendering.

Coordinate transformations are handled via new helper functions:
trans_x, trans_y, and grub_video_transform_rectangle. These are
applied throughout GRUB’s drawing pipeline (blit, fill, scroll,
dirty) so that output appears correctly rotated in the final framebuffer.


Patch summary:

[PATCH 1/3] video_fb: Support 2D dirty regions for partial updates

GRUB previously tracked only vertical (Y-span) dirty regions,
causing entire pixel rows to be refreshed when even a small region
changed.

This patch introduces 2D rectangle-based tracking for screen updates,
allowing minimal partial updates and simplifying future work applying
rotation transformations to framebuffer drawing operations. 

- Modifies `video_fb.c` to track (x, y, width, height) dirty rectangles
- Updates `doublebuf_*_update_screen()` to use the new region tracking
- Updates the `dirty` function signature to accept `x` and `width`

This patch is required to be applied first.

[PATCH 2/3] video_fb: Implement framebuffer rotation transforms

Adds rotation-aware rendering to the framebuffer pipeline.

- Introduces `rotation`, `original_width`, and `original_height`
  to `grub_video_mode_info`
- Updates all framebuffer operations (`blit`, `fill`, `scroll`, `dirty`)
  to apply rotation transforms
- Off-screen render targets explicitly set `rotation = NONE`

Key implementation points:

- `grub_video_fb_create_render_target_from_pointer()` assumes the
  target is the framebuffer and sets the configured rotation
- `grub_video_fb_create_render_target()` is used for off-screen
  render targets and always disables rotation

TODO:

- `grub_video_fb_dispatch_blit` falls back to unoptimized blitters
  when rotation is enabled. Optimized blitters currently do not
  support transformed coordinates.

[PATCH 3/3] mkconfig: Add GRUB_FB_ROTATION configuration option

Adds scripting and config support for setting framebuffer rotation
via the GRUB config.

- `util/grub-mkconfig.in`: exports `GRUB_FB_ROTATION`
- `util/grub.d/00_header.in`: evaluates the env var and sets rotation
- `util/grub.d/10_linux.in`: passes the rotation setting to Linux when
  `GRUB_GFXPAYLOAD_LINUX=keep` is used

Supported values:
  - Degrees: `90`, `180`, `270`
  - Aliases: `right`, `inverted`, `left`

Known limitations:

  • When rotation is enabled, grub_video_fb_dispatch_blit() bypasses
    optimized blitters and uses a slower fallback. Optimized blitters do
    not yet support rotated coordinate systems.

Tested on:

  • Ubuntu 22.04 EFI, Intel i13500 (physical hardware)
  • Lubuntu 24.04 BIOS, QEMU VM
  • GRUB standalone (BIOS, via QEMU)

Changelog:

v2:
- Reformat echo statements in 00_header.in for readability
- Improve inline documentation and comment clarity
- Additional testing

@kbader94 kbader94 force-pushed the fb_rot_rebased branch 4 times, most recently from 084d282 to 02522af Compare June 13, 2025 01:14
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: grub_video_fb_dispatch_blit falls back to unoptimized blitters
when rotation is enabled. Optimized blitters currently do not
support transformed coordinates.

kbader94 added 3 commits June 13, 2025 08:50
    Adds config support for setting framebuffer rotation
    via the GRUB config.

    - `util/grub-mkconfig.in`: exports `GRUB_FB_ROTATION`
    - `util/grub.d/00_header.in`: evaluates the env var and sets rotation
    - `util/grub.d/10_linux.in`: passes the rotation setting to Linux when
      `GRUB_GFXPAYLOAD_LINUX=keep` is used

    Supported values:
      - Degrees: `90`, `180`, `270`
      - Aliases: `right`, `inverted`, `left`

Signed-off-by: Kyle Bader <kyle.bader94@gmail.com>
    GRUB previously tracked only vertical (Y-span) dirty regions,
    causing entire pixel rows to be refreshed when even a small region
    changed.

    This patch introduces 2D rectangle-based tracking for screen updates,
    allowing minimal partial updates and simplifying future work applying
    rotation transformations to framebuffer drawing operations.

    - Modifies `video_fb.c` to track (x, y, width, height) dirty rectangles
    - Updates `doublebuf_*_update_screen()` to use the new region tracking
    - Updates the `dirty` function signature to accept `x` and `width`

    This patch is required to be applied first before other patches
    in the Frambuffer Rotation patch series.

Signed-off-by: Kyle Bader <kyle.bader94@gmail.com>
    Adds rotation-aware rendering to framebuffer drawing operations.

    - Introduces `rotation`, `original_width`, and `original_height`
      to `grub_video_mode_info`
    - Updates all framebuffer operations (`blit`, `fill`, `scroll`, `dirty`)
      to apply rotation transforms

    Key implementation points:

    - `grub_video_fb_create_render_target_from_pointer()` assumes the
      target is the framebuffer and sets the configured rotation
    - `grub_video_fb_create_render_target()` is used for off-screen
      render targets and always disables rotation
    - Off-screen render targets explicitly set `rotation = NONE`

    TODO:

    - `grub_video_fb_dispatch_blit' Uses unoptimized default(slow) blitter when rotation
    env_var is provided. Optimized blitters currently do not support transformed coordinates.

Signed-off-by: Kyle Bader <kyle.bader94@gmail.com>
@SteveZMTstudios
Copy link

This should be considered to add. Many devices use mystery display module and this problem also troubled this community almost 12 years (from the first thread from arch forum).

@kbader94
Copy link
Owner Author

kbader94 commented Oct 4, 2025

@SteveZMTstudios I plan on resubmitting this feature to the GRUB mailing list after the next release, since GRUB is currently in a code freeze for this part of the release cycle. That's a tentative submission in November, and then hopefully it might be included in the next GRUB release. Thanks for your interest!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants