SDV Media: Displays verwalten

SDV Media stellt OEM-Anwendungen mit der Linux DRM API verfügbare Displays zur Verfügung.

Interaktion zwischen DRM-Komponenten

  • Ein Framebuffer ist eine Quelle für Pixeldaten, die von einem extern zugewiesenen Speicherpuffer unterstützt wird.

  • Eine Ebene ist eine Bildquelle, die von CRTC verwendet wird. Sie ist mit einem Framebuffer verknüpft und kann eine zugeschnittene Ansicht des Framebuffers darstellen.

  • CRTC steht für eine allgemeine Displaypipeline. Sie kann mehrere Ebenen kombinieren, um die endgültige Videoausgabe zu erstellen, und die Ausgabe an mehrere Encoder senden.

  • Der Encoder konvertiert die Videoausgabe von CRTC in ein Format, das für einen bestimmten Connector geeignet ist.

  • Der Connector steht für einen verfügbaren Display-Connector. Beispiel: ein HDMI-Anschluss.

Eine ausführlichere Beschreibung finden Sie hier:

API-Oberfläche

SDV Media bietet die Linux DRM-Schnittstellen. Sie können zwar direkt mit dem ioctl-Systemaufruf verwendet werden, für die Anwendungsentwicklung wird jedoch eine Userspace-Hilfsbibliothek empfohlen. Beispiel:

  • drm-rs -Crate für Rust (empfohlen)
  • libdrm für C/C++. Die drm-kms Manpage bietet einen umfassenden Überblick über die APIs und ihre Verwendung.

Rendering auf einem einzelnen Display einrichten

  1. Öffnen Sie ein DRM-Gerät (/dev/dri/card*) und verwenden Sie die Linux DRM APIs (z.B. über libdrm) für den zugehörigen Dateideskriptor, um das Display und den Modus auszuwählen.

    Normalerweise stellt das Hostsystem nur ein einzelnes virtuelles GPU-Gerät zur Verfügung, das als /dev/dri/card0 angezeigt wird.

  2. Weisen Sie mit der Linux DRM API Vorder- und Hintergrundpuffer zu.

    Wir empfehlen, minigbm's gbm_bo_create() zu verwenden und den DMA-BUF-Dateideskriptor mit gbm_bo_get_fd() abzurufen.

  3. Erstellen Sie GL-Framebuffer, die von den zugewiesenen Puffern unterstützt werden.

    1. Erstellen Sie mit eglCreateImageKHR und EGL_LINUX_DMA_BUF_EXT (aus EGL_EXT_image_dma_buf_import Erweiterung) ein EGLImage aus dem DRM-Puffer.

    2. Erstellen Sie eine GL-Textur und legen Sie mit glEGLImageTargetTexture2DOES (aus GL_OES_EGL_image Erweiterung) den Speicher der Textur auf das EGLImage aus dem vorherigen Schritt fest.

    3. Erstellen Sie einen GL-Framebuffer und legen Sie mit glFramebufferTexture2D die unterstützende Textur auf die im vorherigen Schritt erstellte Textur fest.

  4. So rendern Sie einen Frame:

    1. Binden Sie einen der erstellten GL-Framebuffer.

    2. Zeichnen Sie einen Frame mit den üblichen GLES APIs.

    3. Zeigen Sie den Frame auf einem Display an: Senden Sie mit der Linux DRM API (drmModeAtomicCommit()) ein DRM_MODE_PAGE_FLIP_EVENT mit dem DMA-BUF-Dateideskriptor, der vom gebundenen GL-Framebuffer verwendet wird.

Videoausgabe aus mehreren Ebenen zusammensetzen

Für die hardwarebeschleunigte mehrschichtige (mehrere Ebenen) Komposition muss das Hostsystem jede Ebene als separaten DRM-Connector (virtuelles Display) zur Verfügung stellen und sie dem richtigen Hardwarestandort bzw. der richtigen Pipeline zuordnen.

Weitere Informationen finden Sie unter Rendering auf mehreren Displays einrichten.

Rendering auf mehreren Displays einrichten

  1. Öffnen Sie das DRM-Gerät /dev/dri/card* wie im Ablauf für ein einzelnes Display.

  2. Listen Sie die verfügbaren Display-Connectors auf.

    Jedes Display wird als separater DRM-Connector des DRM-Geräts zur Verfügung gestellt.

  3. Für jeden Display-Connector:

    1. Wählen Sie eine CRTC aus, die mit dem Connector kompatibel ist. Jeder Connector hat eine Liste der verfügbaren Encoder und jeder Encoder gibt an, mit welchen CRTCs er verwendet werden kann. Es ist immer mindestens eine kompatible CRTC vorhanden.

      1. Wählen Sie eine Ebene aus, die mit der CRTC kompatibel ist.

      2. Erstellen Sie DRM-Framebuffer, die von GPU-Puffern unterstützt werden. Dieser Vorgang ist derselbe wie bei der Variante mit einem einzelnen Display.

      3. Verbinden Sie Ebene, CRTC und Connector und legen Sie den Videomodus auf der CRTC fest.

        Sie können den Modus mehrerer Displays gleichzeitig festlegen, indem Sie die Atomic API verwenden, um die folgenden DRM-Attribute für jeden Connector, jede CRTC und jede Ebene festzulegen.

    Vollständige Liste der erforderlichen Attribute:

    Ziel Attribut Typ Beschreibung
    Connector CRTC_ID CRTC-ID ID der CRTC, die dem Connector zugewiesen werden soll
    CRTC MODE_ID Blob-ID ID eines Attribut-Blobs, das mit drmModeCreatePropertyBlob erstellt wurde und die drmModeModeInfo-Struktur des ausgewählten Videomodus enthält
    CRTC ACTIVE bool true, um die CRTC als aktiv zu markieren
    Ebene FB_ID Framebuffer-ID ID des DRM-Framebuffers, der auf dem Display angezeigt werden soll
    Ebene SRC_X Pixel X-Koordinate des Quellbildrechtecks des Framebuffers
    Ebene SRC_Y Pixel Y-Koordinate des Quellbildrechtecks des Framebuffers
    Ebene SRC_W 16.16-Festpunkt Breite des Quellbildrechtecks des Framebuffers (Pixel um 16 Bit nach links verschoben)
    Ebene SRC_H 16.16-Festpunkt Höhe des Quellbildrechtecks des Framebuffers (Pixel um 16 Bit nach links verschoben)
    Ebene CRTC_X Pixel X-Koordinate des Zielbildrechtecks der CRTC
    Ebene CRTC_Y Pixel Y-Koordinate des Zielbildrechtecks der CRTC
    Ebene CRTC_W Pixel Breite des Zielbildrechtecks der CRTC
    Ebene CRTC_H Pixel Höhe des Zielbildrechtecks der CRTC
  4. Geben Sie die Rendering-Schleife ein:

    1. Warten Sie auf das Seitenwechselereignis auf einer CRTC, bevor Sie den nächsten Frame rendern.

    2. Rendern Sie einen Frame und zeigen Sie ihn auf dem Display an, indem Sie einen Seitenwechsel für die angegebene CRTC und den angegebenen Framebuffer planen.