Skip to content

wlroots: add RGA hardware scaling for direct scanout on Rockchip#2365

Draft
aenertia wants to merge 1 commit intoROCKNIX:nextfrom
aenertia:wlroots-freergascaling
Draft

wlroots: add RGA hardware scaling for direct scanout on Rockchip#2365
aenertia wants to merge 1 commit intoROCKNIX:nextfrom
aenertia:wlroots-freergascaling

Conversation

@aenertia
Copy link
Contributor

@aenertia aenertia commented Mar 1, 2026

Use the Rockchip RGA 2D engine to scale fullscreen client buffers to output resolution when the DRM plane cannot handle the mismatch natively. This enables direct scanout for emulators rendering at native console resolutions (320x240, 480x272, 640x480) on larger displays (720p/1080p HDMI), bypassing GLES2 compositing entirely.

The RGA is auto-detected at runtime via librga. On non-Rockchip hardware or when librga is absent, no RGA code compiles or executes. All code paths are gated behind WLR_HAS_RGA and fall through to the existing GLES2 compositor on failure.

Targets: RK3566 (RGA2), RK3326 (RGA2 with DT overlay). No effect on SM8250, SM8550, SDM845, S922X, H700, RK3399, RK3588.

This has had minimal testing on 353p and rgb30 as well as a custom build on rk3326 for xf40h.

Good results depending on how the core/emu is setup and the panel size, but hard to gauge how much of a perf improvement it nets (if any), but doesn't seem to cause any issues.

@aenertia
Copy link
Contributor Author

aenertia commented Mar 1, 2026

I kept the patch duplicated in both tree's as it's entirely possible the two targets may need to diverge and there wasn't a cleaner way of adding it without adding case statment to a global package. Let me know if there is a better way to handle this.

@aenertia
Copy link
Contributor Author

aenertia commented Mar 1, 2026

This likewise still needs rga dts to be enabled ; not such a problem on rk3566 but for a bunch of the 3326's that needs to be added to a custom dts or overlay for a specific target device.

+ wlr_files += files('render/rga_accel.c')
+ message('RGA hardware scaling: enabled')
+else
+ message('RGA hardware scaling: disabled (librga not found)')
Copy link
Contributor

Choose a reason for hiding this comment

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

Please raise an error here to prevent silent degradation

case ${DEVICE} in
RK3566|RK3588|RK3326)
PKG_DEPENDS_TARGET+=" librga"
;;
Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose patch is the same for both 3326 and 3566.
To avoid duplicate files please use PKG_PATCH_DIRS+=" rockchip-rga" in this case clause

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right — the patches are currently identical. I'll consolidate into a shared rockchip-rga patch directory and update the package.mk to use:

case ${DEVICE} in
RK3566|RK3326)
PKG_PATCH_DIRS+=" rockchip-rga"
;;
esac

This removes the duplication while keeping the device gating. I'd originally separated them anticipating divergence between the two RGA implementations but that hasn't materialized and can be split later if
needed.

+ bool available;
+};
+
+static int drm_format_to_rk(uint32_t drm_fourcc) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this conversion looks weird and inconsistent:

  • ARGB -> BGRA
  • RGB -> RGB

Please:

  • describe how did you check different pixel formats
  • remove the ones you cannot check

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The ARGB→BGRA vs RGB→RGB mapping reflects how RGA's internal format enumeration differs from DRM/GBM codes. The RGA appears to use its own RK_FORMAT_* enum where the channel ordering is defined differently from DRM_FORMAT_*. The conversion table maps between these two namespaces — it's not swapping channels, it's translating format identifiers.

That said, I'll document which format pairs have been validated on hardware and gate the untested ones behind a compile-time flag so they don't silently produce garbled output. The core path
(XRGB8888/ARGB8888 which covers 95%+ of emulator output) was tested. The other ones are primarily so hantro/hwdec surfaces work; and I didn't test them but they follow the same mapping logic.

@aenertia
Copy link
Contributor Author

aenertia commented Mar 3, 2026

Since we are not going to pretend this will ever go upstream it's probably worthwhile setting an environment check to allow forcing RGA scaling off, within wlroots - rather than having to mask the device at OS level to achieve the same. Thoughts?

I'll do a review later on tonight on this and update with requested changes.

@aenertia
Copy link
Contributor Author

aenertia commented Mar 3, 2026

Since we are not going to pretend this will ever go upstream it's probably worthwhile setting an environment check to allow forcing RGA scaling off, within wlroots - rather than having to mask the device at OS level to achieve the same. Thoughts?

I'll do a review later on tonight on this and update with requested changes.

I'll add WLR_RGA_DISABLE=1 environment check at init so it can be toggled without rebuilding. This gives an escape hatch if a specific device or emulator has issues.

@aenertia aenertia force-pushed the wlroots-freergascaling branch from e6b8c12 to 1e8a220 Compare March 3, 2026 09:36
@aenertia
Copy link
Contributor Author

aenertia commented Mar 3, 2026

@aenertia
Copy link
Contributor Author

aenertia commented Mar 4, 2026

I think for this to be useful it will need a launch option added; it should be possible to force RGA for any core/screen by 'faking' the output size to be bigger/smaller. Retroarch cores seem to do this properly but dolphin sizes it's output to the screen regardless of it's sub-surface resolution - which still goes via the GPU/CPU scaling path. But if the emulators were run in a fake output workspace matched to the internal resolution size then this should 'just work' for everything

Use Rockchip RGA 2D engine to scale fullscreen client buffers for
direct scanout, enabling emulators rendering at native resolutions
(320x240, 480x272, 640x480) on larger displays while bypassing
GLES2 compositing entirely.

RGA is auto-detected via librga at runtime. Non-Rockchip hardware
is unaffected — code gated behind WLR_HAS_RGA compile flag.
Can be disabled at runtime via WLR_RGA_DISABLE=1 environment var.

Targets: RK3566 (RGA2), RK3326 (RGA2 with DT overlay).
No impact on SM8250, SM8550, SDM845, S922X, H700, RK3399, RK3588.

Patches consolidated into shared rockchip-rga directory to avoid
duplication between device trees.

DRM-to-RGA format mapping documented: the apparent ARGB->BGRA swap
is a namespace translation between DRM packed-pixel and RGA byte-order
conventions, not a channel reorder. Primary path (XRGB8888/ARGB8888)
validated on hardware.
@aenertia aenertia force-pushed the wlroots-freergascaling branch from 1e8a220 to 4348c08 Compare March 4, 2026 18:51
@aenertia aenertia marked this pull request as draft March 4, 2026 19:29
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.

2 participants