Grafik & Görüntü
TEKNİK REHBER GRAFİK & GÖRÜNTÜ QT 6 EMBEDDED 2026

Qt 6 Embedded —
EGLFS & QML HMI.

Cross-compile sysroot'tan EGLFS KMS/DRM backend'ine, QML Quick Controls 2 dokunmatik HMI'dan Yocto meta-qt6 entegrasyonuna kadar eksiksiz Qt 6 embedded geliştirme rehberi.

00 Qt 6 embedded platformları

Qt 6, QPA (Qt Platform Abstraction) katmanı üzerinden farklı display backend'lerini destekler. Embedded sistemde doğru platform seçimi, performans ve özellik seti açısından kritiktir.

Platform karşılaştırması

EGLFS (KMS/DRM)
Önerilen modern seçim. DRM/KMS üzerinde EGL/GLES2 ile tam GPU hızlandırması. Wayland veya X11 gerektirmez. QT_QPA_PLATFORM=eglfs ile etkinleştirilir.
linuxfb
Legacy /dev/fb0 backend. GPU hızlandırması yok, saf CPU rendering. Çok düşük bellekli veya GPU sürücüsü olmayan sistemlerde son çare.
wayland
Weston veya başka bir Wayland compositor gerektirir. Pencereli çok uygulama ortamı için tercih edilir. QT_QPA_PLATFORM=wayland.
offscreen
Ekransız render, headless test, screenshot alma için. CI pipeline'larında Qt uygulamalarını test etmekte kullanılır.

Platform seçim kararı

  GPU sürücüsü + DRM/KMS mevcut?
       ↓ Evet
  Tek uygulama kiosk mi?
       ├─ Evet  →  EGLFS (en az overhead)
       └─ Hayır →  Wayland + Qt wayland platform
       ↓ Hayır
  linuxfb (performansı kabul edersen)
    

01 Cross-compile — Qt 6 kaynak derleme ve sysroot

Qt 6 cross-compile için host araçları (qmake, moc, rcc) host'ta, hedef kütüphaneler ise sysroot içinde derlenir. CMake, qt-configure-module yerine birleşik araç olarak kullanılır.

Sysroot hazırlama (RPi4 örneği)

bash — sysroot oluşturma
# Hedef sistemden sysroot kopyala (rsync ile)
rsync -avz --rsync-path="sudo rsync" \
    pi@raspberrypi.local:/usr/include  sysroot/usr/
rsync -avz --rsync-path="sudo rsync" \
    pi@raspberrypi.local:/usr/lib      sysroot/usr/
rsync -avz --rsync-path="sudo rsync" \
    pi@raspberrypi.local:/lib          sysroot/lib/
rsync -avz --rsync-path="sudo rsync" \
    pi@raspberrypi.local:/opt/vc       sysroot/opt/

# Sembolik linkleri düzelt (sysroot'a göreli yapılır)
python3 sysroot-relativelinks.py sysroot

CMake toolchain dosyası

toolchain-rpi4.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(SYSROOT_PATH "/opt/sysroot-rpi4")
set(CMAKE_SYSROOT ${SYSROOT_PATH})
set(CMAKE_FIND_ROOT_PATH ${SYSROOT_PATH})

set(CMAKE_C_COMPILER   aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# Qt host araçları
set(QT_HOST_PATH /opt/qt6-host)
set(QT_HOST_PATH_CMAKE_DIR /opt/qt6-host/lib/cmake)

Qt 6 host araçları derleme

bash — Qt 6 host build
# Qt 6 kaynak indir
git clone --branch v6.7.2 --depth 1 \
    https://code.qt.io/qt/qt5.git qt6
cd qt6 && perl init-repository

# Host araçları derle (hedef için gerekli)
mkdir build-host && cd build-host
cmake ../qt6 \
    -DCMAKE_INSTALL_PREFIX=/opt/qt6-host \
    -DQT_BUILD_EXAMPLES=OFF \
    -DQT_BUILD_TESTS=OFF
cmake --build . --parallel $(nproc)
cmake --install .

# Cross-compile için Qt 6
mkdir build-rpi4 && cd build-rpi4
cmake ../qt6 \
    -DCMAKE_TOOLCHAIN_FILE=../toolchain-rpi4.cmake \
    -DCMAKE_INSTALL_PREFIX=/opt/qt6-rpi4 \
    -DQT_HOST_PATH=/opt/qt6-host \
    -DFEATURE_eglfs=ON \
    -DFEATURE_linuxfb=ON \
    -DFEATURE_wayland=OFF \
    -DQT_BUILD_EXAMPLES=OFF
cmake --build . --parallel $(nproc)
cmake --install .

02 EGLFS yapılandırması — KMS JSON, cursor, vsync

EGLFS, DRM/KMS connector ve modunu JSON dosyası aracılığıyla yapılandırır. Çözünürlük, yönlendirme, cursor ve VSync bu dosyada belirlenir.

Ortam değişkenleri

QT_QPA_PLATFORM
eglfs olarak ayarla. Alternatif: eglfs:fb=1 ile belirli fb cihazı.
QT_QPA_EGLFS_KMS_CONFIG
JSON konfigürasyon dosyasının yolu. Connector, mod, rotation ayarları burada.
QT_QPA_EGLFS_WIDTH/HEIGHT
Ekran boyutunu mm cinsinden zorla. DPI hesabı için kullanılır.
QT_QPA_EGLFS_HIDECURSOR
1 ile fare imlecini gizle — dokunmatik kiosk için.
QT_QPA_EGLFS_FORCEVSYNC
1 ile VSync zorla — tear-free render için.

KMS JSON konfigürasyon dosyası

/etc/qt-kms.json
{
    "device": "/dev/dri/card0",
    "hwcursor": false,
    "pbuffers": true,
    "outputs": [
        {
            "name": "HDMI-A-1",
            "mode": "1920x1080",
            "refresh": 60,
            "rotation": 0,
            "virtualIndex": 0
        },
        {
            "name": "DSI-1",
            "mode": "1024x600",
            "refresh": 60,
            "rotation": 90,
            "virtualIndex": 1
        }
    ]
}

Uygulama başlatma scripti

bash — EGLFS başlatma
export QT_QPA_PLATFORM=eglfs
export QT_QPA_EGLFS_KMS_CONFIG=/etc/qt-kms.json
export QT_QPA_EGLFS_HIDECURSOR=1
export QT_QPA_EGLFS_FORCEVSYNC=1
export QT_QPA_FONTDIR=/usr/share/fonts/truetype
export QT_SCALE_FACTOR=1.5    # DPI ölçekleme

./my-qt6-hmi

03 QML ile HMI — Quick Controls 2, font, image cache

Qt Quick Controls 2 (QQC2), embedded için optimize edilmiş hafif kontrol seti sunar. Özel tema ve FreeType font rendering ile tutarlı görünüm sağlanır.

Minimal QML uygulaması

main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

ApplicationWindow {
    id: root
    visible: true
    width: 1024; height: 600
    title: "HMI Panel"
    color: "#1a1a2e"

    ColumnLayout {
        anchors.centerIn: parent
        spacing: 20

        Text {
            text: "Motor Sıcaklığı"
            font.pixelSize: 32
            font.family: "Roboto"
            color: "#e0e0e0"
            Layout.alignment: Qt.AlignHCenter
        }

        Text {
            id: tempDisplay
            text: motorMonitor.temperature + " °C"
            font.pixelSize: 72
            font.bold: true
            color: motorMonitor.temperature > 80 ? "#ff4444" : "#44ff88"
            Layout.alignment: Qt.AlignHCenter
        }

        ProgressBar {
            value: motorMonitor.temperature / 120
            Layout.fillWidth: true
            Layout.preferredHeight: 24
        }

        Button {
            text: "Resetle"
            Layout.alignment: Qt.AlignHCenter
            onClicked: motorMonitor.reset()
        }
    }
}

Embedded için QQC2 tema

main.cpp — stil ayarı
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    // Embedded için "Basic" stil — en hafif
    // Alternatifler: "Material", "Universal", "Fusion"
    QQuickStyle::setStyle("Basic");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

Font rendering ve image cache

bash — font ve cache ayarları
# FreeType ile anti-aliased font
export QT_QPA_FONTDIR=/usr/share/fonts/truetype/roboto

# Texture atlas boyutu (VRAM yönetimi)
export QSG_ATLAS_WIDTH=2048
export QSG_ATLAS_HEIGHT=2048

# Image cache boyutu (MB) — düşük bellek için azalt
export QML_DISK_CACHE_PATH=/tmp/qml-cache
export QT_QUICK_CONTROLS_CONF=/etc/qtquickcontrols2.conf

04 Touch input — evdev, libinput, kalibrasyon

Qt 6 EGLFS, dokunmatik ekranı evdev veya libinput backend'i üzerinden alır. Ekran koordinatlarını uygulama koordinatlarına eşlemek için kalibrasyon gerekebilir.

Ortam değişkenleri

QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS
evdev backend için kalibrasyon matrisi ve cihaz yolu. Örnek: rotate=180:invertx:invertz.
QT_QPA_GENERIC_PLUGINS
Ek plugin yükle. evdevtouch:/dev/input/event1 ile belirli cihazı zorla.
QT_QPA_LIBINPUT_DEVICE_RULE
libinput backend ile belirli cihazları dahil et/çıkar.

Dokunmatik kalibrasyon

bash — touch kalibrasyon
# Dokunma noktasını izle
evtest /dev/input/event1

# libinput ile cihaz listesi
libinput list-devices

# Qt evdev kalibrasyon parametreleri (weston.ini formatından farklı)
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=\
    /dev/input/event1:rotate=0

# 90 derece döndürülmüş ekran
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=\
    /dev/input/event1:rotate=90

# Yanlış eksen: X/Y eksenlerini değiştir
export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=\
    /dev/input/event1:swapxy:invertx

QML'de çoklu dokunma

QML — MultiPointTouchArea
Rectangle {
    width: 800; height: 480

    MultiPointTouchArea {
        anchors.fill: parent
        minimumTouchPoints: 1
        maximumTouchPoints: 5

        onTouchUpdated: (touchPoints) => {
            touchPoints.forEach(tp => {
                console.log("Parmak", tp.pointId,
                    ":", tp.x.toFixed(0), tp.y.toFixed(0))
            })
        }
    }

    // Pinch/zoom örneği
    PinchArea {
        anchors.fill: parent
        onPinchUpdated: (pinch) => {
            console.log("Scale:", pinch.scale.toFixed(2))
        }
    }
}

05 Qt + OpenGL ES — QOpenGLWidget, GLSL shader

Qt 6 ile doğrudan OpenGL ES çağrıları yapılabilir. QOpenGLWidget widget içine GLES2 render gömer; QQuickView ise QML sahnesini GLES2 ile hızlandırır.

QOpenGLWidget ile özel render

C++ — QOpenGLWidget subclass
#include <QOpenGLWidget>
#include <QOpenGLFunctions_ES2>
#include <QOpenGLShaderProgram>

class GlWidget : public QOpenGLWidget,
                 protected QOpenGLFunctions_ES2
{
    Q_OBJECT
    QOpenGLShaderProgram *prog = nullptr;

protected:
    void initializeGL() override {
        initializeOpenGLFunctions();
        prog = new QOpenGLShaderProgram(this);
        prog->addShaderFromSourceCode(QOpenGLShader::Vertex,
            "attribute vec2 pos;\n"
            "void main() { gl_Position = vec4(pos, 0.0, 1.0); }\n");
        prog->addShaderFromSourceCode(QOpenGLShader::Fragment,
            "precision mediump float;\n"
            "uniform vec4 color;\n"
            "void main() { gl_FragColor = color; }\n");
        prog->link();
    }

    void paintGL() override {
        glClearColor(0.1f, 0.1f, 0.15f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        prog->bind();
        prog->setUniformValue("color", QVector4D(0.2f, 0.8f, 0.4f, 1.0f));

        GLfloat verts[] = { 0.0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f };
        prog->enableAttributeArray("pos");
        prog->setAttributeArray("pos", GL_FLOAT, verts, 2);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        prog->release();
    }

    void resizeGL(int w, int h) override {
        glViewport(0, 0, w, h);
    }
};

GPU hızlandırmalı QML animasyon

QML — shader animasyon
import QtQuick 2.15

Rectangle {
    width: 400; height: 400

    // GPU'da çalışan özel shader efekti
    layer.enabled: true
    layer.effect: ShaderEffect {
        property real time: 0.0

        NumberAnimation on time {
            from: 0; to: 6.28; duration: 3000
            loops: Animation.Infinite
        }

        fragmentShader: "
            varying highp vec2 qt_TexCoord0;
            uniform sampler2D source;
            uniform highp float time;
            void main() {
                highp vec2 uv = qt_TexCoord0;
                uv.x += 0.01 * sin(uv.y * 20.0 + time);
                gl_FragColor = texture2D(source, uv);
            }
        "
    }

    Image { source: "panel_bg.png"; anchors.fill: parent }
}

06 Yocto meta-qt6 — qt6-base, qt6-declarative, IVI

Yocto Project'te Qt 6 için meta-qt6 katmanı gereklidir. Qt IVI (In-Vehicle Infotainment) ek katmanı otomotiv HMI için servis altyapısı sağlar.

meta-qt6 kurulumu

bash — katman ekleme
# meta-qt6 kaynak
git clone https://code.qt.io/yocto/meta-qt6.git \
    -b 6.7 sources/meta-qt6

# bblayers.conf'a ekle
bitbake-layers add-layer sources/meta-qt6

# local.conf'ta Qt özellikleri etkinleştir
DISTRO_FEATURES:append = " opengl eglfs"
QT6_EGLFS_INTEGRATION = "kms"

IMAGE_INSTALL — Qt 6 paketleri

recipes-core/images/qt6-hmi-image.bb
require recipes-core/images/core-image-minimal.bb

IMAGE_INSTALL:append = " \
    qt6-base            \
    qt6-declarative     \
    qt6-quickcontrols2  \
    qt6-multimedia      \
    qt6-svg             \
    qt6-virtualkeyboard \
    fontconfig          \
    ttf-roboto          \
    my-hmi-application  \
"

# QML önbelleği için tmp dizini
IMAGE_INSTALL:append = " qml-cache-pregeneration"

Qt IVI (In-Vehicle Infotainment)

QML — Qt IVI servis örneği
import QtIvi 1.0
import QtIvi.Media 1.0

Item {
    MediaPlayer {
        id: player

        onPlaybackStateChanged: {
            if (playbackState === MediaPlayer.PlayingState)
                console.log("Çalıyor:", currentTrack.title)
        }
    }

    ClimateControl {
        id: climate
        Component.onCompleted: {
            console.log("Kabin sıcaklığı:",
                targetTemperature.value, "°C")
        }
    }
}

07 Performans optimizasyonu — QML profiler, render loop

Embedded sistemlerde Qt uygulaması yavaş çalışıyorsa QML profiler ile darboğazı bul, render loop seçimini optimize et ve delegate caching ile bellek kullanımını azalt.

QML profiler

bash — profiler başlatma
# Uygulamayı profiler modunda başlat
QML_PROFILER=1 ./my-hmi-app &

# Qt Creator'da Analyze → QML Profiler → Attach
# veya komut satırından:
qmlprofiler -attach localhost my-hmi-app

# FPS sayacını HUD olarak göster
QSG_RENDER_TIMING=1 ./my-hmi-app
export QSG_VISUALIZE=overdraw    # overdraw analizi
export QSG_VISUALIZE=batches     # render batch analizi

Render loop seçimi

basic
Tek thread: UI ve render aynı thread'de. Basit uygulamalar için yeterli, düşük gecikme.
threaded
Ayrı render thread. UI thread bloke olsa bile animasyonlar devam eder. GPU sürücüsü destekliyorsa önerilen.
windows
Her pencere için ayrı OpenGL context. Çok ekran veya çok pencere senaryolarında.
bash — render loop
# Threaded render loop (önerilen)
export QSG_RENDER_LOOP=threaded

# GPU sürücüsü threaded desteklemiyorsa
export QSG_RENDER_LOOP=basic

# Mevcut loop'u öğren
QSG_INFO=1 ./my-hmi-app 2>&1 | grep "render loop"

Delegate caching ve texture atlas

QML — ListView delegate optimize
ListView {
    model: sensorModel
    cacheBuffer: 200    // piksel cinsinden önbellek alanı

    delegate: Rectangle {
        // layer.enabled = true → GPU texture cache
        layer.enabled: true
        layer.smooth: true

        width: ListView.view.width
        height: 60

        Text {
            text: model.name + ": " + model.value
            font.pixelSize: 20
            anchors.centerIn: parent
        }
    }
}

08 Pratik

Üç gerçek senaryo: i.MX8 LVDS ekranda Qt 6 dashboard, NXP eIQ ile Qt + ML inference ve Yocto image build akışı.

i.MX8 LVDS ekranda Qt 6 dashboard

bash — i.MX8 deploy
# i.MX8 için cross-compile
export QT_QPA_PLATFORM=eglfs
export QT_QPA_EGLFS_KMS_CONFIG=/etc/qt-kms-imx8.json

# qt-kms-imx8.json
cat > /etc/qt-kms-imx8.json <<'EOF'
{
    "device": "/dev/dri/card1",
    "outputs": [{
        "name": "LVDS-1",
        "mode": "1024x768",
        "refresh": 60
    }]
}
EOF

# GPU sürücüsü: Vivante GC7000 (NXP proprietary)
# Yocto'da: PREFERRED_PROVIDER_virtual/mesa = "imx-gpu-viv"

./dashboard-app

NXP eIQ ile Qt + ML inference

C++ — TFLite inference + Qt görüntüleme
#include <QQuickImageProvider>
#include <tensorflow/lite/interpreter.h>
#include <tensorflow/lite/model.h>

class InferenceProvider : public QQuickImageProvider {
public:
    InferenceProvider() : QQuickImageProvider(QImage) {
        // TFLite modelini yükle
        model_ = tflite::FlatBufferModel::BuildFromFile(
            "/usr/share/models/mobilenet_v2.tflite");
        tflite::InterpreterBuilder(*model_, resolver_)
            (&interpreter_);
        interpreter_->AllocateTensors();
    }

    QImage requestImage(const QString &id,
                        QSize *, const QSize &) override
    {
        // Kamera frame'ini al, inference yap, sonucu overlay et
        QImage frame = captureFrame();
        runInference(frame);
        drawBoundingBoxes(frame);
        return frame;
    }
private:
    std::unique_ptr<tflite::FlatBufferModel> model_;
    tflite::ops::builtin::BuiltinOpResolver resolver_;
    std::unique_ptr<tflite::Interpreter>    interpreter_;
};

Yocto Qt 6 image build — tam akış

bash — Yocto build
# Katmanları hazırla
source oe-init-build-env build-imx8

bitbake-layers add-layer ../sources/meta-qt6
bitbake-layers add-layer ../sources/meta-imx
bitbake-layers add-layer ../sources/meta-imx/meta-bsp

# local.conf
echo 'MACHINE = "imx8mq-evk"' >> conf/local.conf
echo 'DISTRO = "fsl-imx-wayland"' >> conf/local.conf
echo 'IMAGE_INSTALL:append = " qt6-base qt6-declarative my-hmi"' \
    >> conf/local.conf

# Build
bitbake core-image-qt6-hmi

# SD kart imajını yaz
bzcat tmp/deploy/images/imx8mq-evk/*.wic.bz2 \
    | dd of=/dev/sdX bs=4M status=progress