2025-03-04 6:04 AM
When trying to rotate the display on an STM32MP157C board from landscape (800x480) to portrait (480x800) mode, I'm experiencing issues. Using the /sys/class/graphics/fb0/rotate interface doesn't actually rotate the display, and using Qt's EGLFS with rotation settings results in only half the screen being rotated properly.
This changes the value but doesn't affect display.
Using EGLFS KMS config with rotation:
QString configPath = "/tmp/eglfs_kms.json";
QFile configFile(configPath);
if (configFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
configFile.write("{\n"
" \"device\": \"/dev/dri/card0\",\n"
" \"outputs\": [\n"
" {\n"
" \"name\": \"DPI-1\",\n"
" \"mode\": \"480x800\",\n"
" \"transform\": \"rotate-90\"\n"
" }\n"
" ]\n"
"}\n");
configFile.close();
qputenv("QT_QPA_EGLFS_KMS_CONFIG", configPath.toUtf8());
}
This partially works (screen reports correct orientation) but only half the screen is correctly rotated.
3.QML-based rotation:
Item {
width: parent.height
height: parent.width
anchors.centerIn: parent
rotation: 90
transformOrigin: Item.Center
// Content goes here
}
This somewhat works , but i dont this this is a proper solution
4.Setting various environment variables:
QT_QPA_EGLFS_ROTATION=90
QSG_RENDER_LOOP=basic
5.I tried different variations of the EGLFS configuration, including:
{
"device": "/dev/dri/card0",
"hwcursor": false,
"outputs": [
{
"name": "DPI-1",
"mode": "800x480",
"transform": "rotate-90"
}
]
}
And:
{
"device": "/dev/dri/card0",
"hwcursor": false,
"gbm": true,
"outputs": [
{
"name": "DPI-1",
"format": "xrgb8888",
"rotation": 90
}
]
}
6.Checked the device tree, which shows:
display-controller@5a001000 {
compatible = "st,stm32-ltdc";
reg = <0x5a001000 0x400>;
interrupts = <0x00 0x58 0x04 0x00 0x59 0x04>;
clocks = <0x0e 0xa7>;
clock-names = "lcd";
resets = <0x0e 0xc00>;
status = "okay";
/* No rotation property here */
}
7.Used modetest to inspect DRM properties:
The output shows mode support for 800x480 but no explicit rotation property.
From my debugging logs, when using the EGLFS configuration, Qt correctly reports the screen orientation as portrait:
=== SCREEN INFORMATION ===
Screen size: QSize(480, 800)
Physical size (mm): QSizeF(86, 154)
Platform: "eglfs"
Orientation: Qt::PortraitOrientation
However, visually, only half the screen appears correctly rotated. The debug logs show that the EGLFS configuration is being loaded correctly:
qt.qpa.eglfs.kms: Loading KMS setup from "/tmp/eglfs_kms.json"
qt.qpa.eglfs.kms: Adding QPlatformScreen 0x816d0 ( "UNKNOWN1" ) to QPA with geometry QRect(0,0 480x800)
When examining the available planes with modetest, I see:
qt.qpa.eglfs.kms: Loading KMS setup from "/tmp/eglfs_kms.json"
qt.qpa.eglfs.kms: Adding QPlatformScreen 0x816d0 ( "UNKNOWN1" ) to QPA with geometry QRect(0,0 480x800)
Currently, I'm using a QML-based rotation approach, but it causes performance issues with animations and effects. I'm looking for a proper hardware-accelerated rotation solution that works with the STM32 LTDC controller.
How can I get proper full-screen rotation with the STM32 LTDC controller? Is there a specific driver setting or Qt configuration I'm missing? Are there known limitations with this hardware?
Solved! Go to Solution.
2025-06-08 1:18 PM - edited 2025-06-08 1:20 PM
#ifndef SCREENORIENTATIONHANDLER_H
#define SCREENORIENTATIONHANDLER_H
#include <QObject>
#include <QQuickWindow>
/**
* @brief The ScreenOrientationHandler class allows dynamic rotation handling
* for QML content on embedded STM32 platforms using the LTDC display controller.
*/
class ScreenOrientationHandler : public QObject
{
Q_OBJECT
Q_PROPERTY(int screenRotation READ screenRotation WRITE setScreenRotation NOTIFY screenRotationChanged)
public:
explicit ScreenOrientationHandler(QObject *parent = nullptr);
int screenRotation() const { return m_rotation; }
void setScreenRotation(int rotation);
// Should be called from main.cpp after QGuiApplication is created
Q_INVOKABLE void initialize();
// Attach to a specific QQuickWindow to manage its rotation
Q_INVOKABLE void attachToWindow(QQuickWindow *window);
signals:
void screenRotationChanged();
private slots:
void handleFocusWindowChanged(QWindow *window);
private:
void applyRotation();
int m_rotation = 0;
QQuickWindow *m_window = nullptr;
};
#endif // SCREENORIENTATIONHANDLER_H
#include "ScreenOrientationHandler.h"
#include <QGuiApplication>
#include <QScreen>
#include <QQuickItem>
ScreenOrientationHandler::ScreenOrientationHandler(QObject *parent)
: QObject(parent)
{
}
void ScreenOrientationHandler::setScreenRotation(int rotation)
{
rotation = rotation % 360;
if (rotation < 0) rotation += 360;
if (m_rotation != rotation) {
m_rotation = rotation;
applyRotation();
emit screenRotationChanged();
}
}
void ScreenOrientationHandler::initialize()
{
applyRotation();
if (QGuiApplication *app = qobject_cast<QGuiApplication*>(QGuiApplication::instance())) {
connect(app, &QGuiApplication::focusWindowChanged,
this, &ScreenOrientationHandler::handleFocusWindowChanged);
}
}
void ScreenOrientationHandler::handleFocusWindowChanged(QWindow *window)
{
if (auto *qWindow = qobject_cast<QQuickWindow *>(window)) {
attachToWindow(qWindow);
}
}
void ScreenOrientationHandler::attachToWindow(QQuickWindow *window)
{
if (m_window != window) {
m_window = window;
if (m_window) {
applyRotation();
connect(m_window, &QQuickWindow::widthChanged, this, &ScreenOrientationHandler::applyRotation);
connect(m_window, &QQuickWindow::heightChanged, this, &ScreenOrientationHandler::applyRotation);
}
}
}
void ScreenOrientationHandler::applyRotation()
{
if (!m_window) return;
QQuickItem *rootItem = m_window->contentItem();
if (!rootItem) return;
rootItem->setProperty("rotation", m_rotation);
if (m_rotation == 90 || m_rotation == 270) {
rootItem->setProperty("clip", true); // Prevent rendering artifacts
rootItem->setWidth(m_window->height());
rootItem->setHeight(m_window->width());
rootItem->setX((m_window->width() - m_window->height()) / 2);
rootItem->setY((m_window->height() - m_window->width()) / 2);
} else {
rootItem->setWidth(m_window->width());
rootItem->setHeight(m_window->height());
rootItem->setX(0);
rootItem->setY(0);
}
}
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickWindow>
#include <QCursor>
#include "ScreenOrientationHandler.h" // renamed handler for clarity
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// Hide mouse cursor (optional)
QGuiApplication app(argc, argv);
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
// Setup rotation
ScreenOrientationHandler orientationHandler;
orientationHandler.setScreenRotation(90); // Portrait mode
// QML engine setup
QQmlApplicationEngine engine;
const QUrl mainQmlUrl(QStringLiteral("qrc:/qml/main.qml"));
// Attach rotation handler to the QML window once it's created
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app,
[mainQmlUrl, &orientationHandler](QObject *obj, const QUrl &objUrl)
{
if (!obj && objUrl == mainQmlUrl)
QCoreApplication::exit(-1);
if (auto *win = qobject_cast<QQuickWindow *>(obj))
orientationHandler.attachToWindow(win);
}, Qt::QueuedConnection);
engine.load(mainQmlUrl);
return app.exec();
}
Here is the full implementation with how to use it in main.c
From here you just define you windows in designer 480x800 for example and you can design properly and run properly in portrait mode for embeded devices.
IF you have any suggestions or improvements of this code please share your thoughts , because from what i saw a lot of people have this problem.
#QT PORTATI MODE QML
2025-03-05 1:01 AM - edited 2025-03-05 1:02 AM
Hello @lepot ,
On STM32MP15X, LTDC has no rotation option that can be done in HW.
From my previous tests, I think the best balance between rendering and performances using QML was to have a global container (QML Rect or Item) under the QML main Window applying the rotation.
I put you an example of an old demo I had on this platform (main.qml):
ApplicationWindow {
id: base
width: _windowWidth
height: _windowHeight
visible: true
Item {
anchors.centerIn: base.contentItem
width: _portrait ? base.height : base.width
height: _portrait ? base.width : base.height
rotation: _portrait ? 90 : 0
<.... app ....>
}
}
I hope it will help you go forward.
Kind regards,
Erwan.
2025-05-27 3:49 AM
I'm trying this on Qt 6.9. Rotating the whole application this way seems to work, however any Popup based QML items (Menu, ComboBox drop down, ...) are not rotated, because they are parented to the window overlay.
You need to rotate the overlay as well:
Overlay.overlay.rotation: _portrait ? 90 : 0
2025-06-08 1:10 PM
@Erwan SZYMANSKI , @wincak Thank you for you suggestons , it worked , soon i will provide the whole implementation , where ytou could choose different rotations , and it is only defined once in the main.c
2025-06-08 1:18 PM - edited 2025-06-08 1:20 PM
#ifndef SCREENORIENTATIONHANDLER_H
#define SCREENORIENTATIONHANDLER_H
#include <QObject>
#include <QQuickWindow>
/**
* @brief The ScreenOrientationHandler class allows dynamic rotation handling
* for QML content on embedded STM32 platforms using the LTDC display controller.
*/
class ScreenOrientationHandler : public QObject
{
Q_OBJECT
Q_PROPERTY(int screenRotation READ screenRotation WRITE setScreenRotation NOTIFY screenRotationChanged)
public:
explicit ScreenOrientationHandler(QObject *parent = nullptr);
int screenRotation() const { return m_rotation; }
void setScreenRotation(int rotation);
// Should be called from main.cpp after QGuiApplication is created
Q_INVOKABLE void initialize();
// Attach to a specific QQuickWindow to manage its rotation
Q_INVOKABLE void attachToWindow(QQuickWindow *window);
signals:
void screenRotationChanged();
private slots:
void handleFocusWindowChanged(QWindow *window);
private:
void applyRotation();
int m_rotation = 0;
QQuickWindow *m_window = nullptr;
};
#endif // SCREENORIENTATIONHANDLER_H
#include "ScreenOrientationHandler.h"
#include <QGuiApplication>
#include <QScreen>
#include <QQuickItem>
ScreenOrientationHandler::ScreenOrientationHandler(QObject *parent)
: QObject(parent)
{
}
void ScreenOrientationHandler::setScreenRotation(int rotation)
{
rotation = rotation % 360;
if (rotation < 0) rotation += 360;
if (m_rotation != rotation) {
m_rotation = rotation;
applyRotation();
emit screenRotationChanged();
}
}
void ScreenOrientationHandler::initialize()
{
applyRotation();
if (QGuiApplication *app = qobject_cast<QGuiApplication*>(QGuiApplication::instance())) {
connect(app, &QGuiApplication::focusWindowChanged,
this, &ScreenOrientationHandler::handleFocusWindowChanged);
}
}
void ScreenOrientationHandler::handleFocusWindowChanged(QWindow *window)
{
if (auto *qWindow = qobject_cast<QQuickWindow *>(window)) {
attachToWindow(qWindow);
}
}
void ScreenOrientationHandler::attachToWindow(QQuickWindow *window)
{
if (m_window != window) {
m_window = window;
if (m_window) {
applyRotation();
connect(m_window, &QQuickWindow::widthChanged, this, &ScreenOrientationHandler::applyRotation);
connect(m_window, &QQuickWindow::heightChanged, this, &ScreenOrientationHandler::applyRotation);
}
}
}
void ScreenOrientationHandler::applyRotation()
{
if (!m_window) return;
QQuickItem *rootItem = m_window->contentItem();
if (!rootItem) return;
rootItem->setProperty("rotation", m_rotation);
if (m_rotation == 90 || m_rotation == 270) {
rootItem->setProperty("clip", true); // Prevent rendering artifacts
rootItem->setWidth(m_window->height());
rootItem->setHeight(m_window->width());
rootItem->setX((m_window->width() - m_window->height()) / 2);
rootItem->setY((m_window->height() - m_window->width()) / 2);
} else {
rootItem->setWidth(m_window->width());
rootItem->setHeight(m_window->height());
rootItem->setX(0);
rootItem->setY(0);
}
}
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickWindow>
#include <QCursor>
#include "ScreenOrientationHandler.h" // renamed handler for clarity
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// Hide mouse cursor (optional)
QGuiApplication app(argc, argv);
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
// Setup rotation
ScreenOrientationHandler orientationHandler;
orientationHandler.setScreenRotation(90); // Portrait mode
// QML engine setup
QQmlApplicationEngine engine;
const QUrl mainQmlUrl(QStringLiteral("qrc:/qml/main.qml"));
// Attach rotation handler to the QML window once it's created
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app,
[mainQmlUrl, &orientationHandler](QObject *obj, const QUrl &objUrl)
{
if (!obj && objUrl == mainQmlUrl)
QCoreApplication::exit(-1);
if (auto *win = qobject_cast<QQuickWindow *>(obj))
orientationHandler.attachToWindow(win);
}, Qt::QueuedConnection);
engine.load(mainQmlUrl);
return app.exec();
}
Here is the full implementation with how to use it in main.c
From here you just define you windows in designer 480x800 for example and you can design properly and run properly in portrait mode for embeded devices.
IF you have any suggestions or improvements of this code please share your thoughts , because from what i saw a lot of people have this problem.
#QT PORTATI MODE QML