SDV Media: gestire i display

SDV Media espone i display disponibili alle app OEM con l'API Linux DRM.

Interazione tra i componenti DRM

Figura 1. Interazione tra i componenti DRM.

  • Un framebuffer è un'origine di dati dei pixel, supportata da un buffer di memoria allocato esternamente.

  • Un piano è un'origine immagine utilizzata da CRTC. È associato a un framebuffer e può rappresentare una visualizzazione ritagliata del framebuffer.

  • CRTC rappresenta una pipeline di visualizzazione complessiva. Può combinare più piani per creare l'output video finale e inviarlo a più codificatori.

  • Un encoder converte l'output video da CRTC in un formato adatto a un connettore specifico.

  • Un connettore rappresenta un connettore del display disponibile. Ad esempio, una porta HDMI.

Per una descrizione più dettagliata, consulta:

Piattaforma API

SDV Media fornisce le interfacce DRM di Linux. Sebbene possano essere utilizzate direttamente utilizzando la chiamata di sistema ioctl, per lo sviluppo di applicazioni è consigliabile utilizzare una libreria helper userspace. Ad esempio:

Configurare il rendering su un singolo display

  1. Apri un dispositivo DRM (/dev/dri/card*) e utilizza le API DRM di Linux, ad esempio tramite libdrm, sul relativo descrittore del file per selezionare il display e la relativa modalità.

    In genere, il sistema host espone un solo dispositivo GPU virtuale, che viene visualizzato come /dev/dri/card0.

  2. Alloca buffer anteriori e posteriori con l'API DRM di Linux.

    Ti consigliamo di utilizzare minigbm gbm_bo_create() e ottenere il descrittore del file DMA-BUF con gbm_bo_get_fd().

  3. Crea frame buffer GL supportati dai buffer allocati.

    1. Crea un EGLImage dal buffer DRM con eglCreateImageKHR con EGL_LINUX_DMA_BUF_EXT (dall'estensione EGL_EXT_image_dma_buf_import).

    2. Crea una texture GL e utilizza glEGLImageTargetTexture2DOES (dall'estensione GL_OES_EGL_image) per impostare l'archiviazione della texture su EGLImage del passaggio precedente.

    3. Crea un framebuffer GL e utilizza glFramebufferTexture2D per impostare la relativa texture di supporto su quella creata nel passaggio precedente.

  4. Per eseguire il rendering di un frame:

    1. Associa uno dei framebuffer GL creati.

    2. Disegna un frame con le solite API GLES.

    3. Visualizza il frame su uno schermo: utilizza l'API Linux DRM (drmModeAtomicCommit()) per inviare un DRM_MODE_PAGE_FLIP_EVENT con il descrittore di file DMA-BUF utilizzato dal framebuffer GL associato.

Comporre l'output video da più livelli

Per la composizione multilivello (multipiano) con accelerazione hardware, ci affidiamo al sistema host che espone ogni livello come connettore DRM separato (display virtuale) e li mappa alla pipeline / posizione hardware corretta.

Per maggiori dettagli, consulta Configurare il rendering su più display.

Configurare il rendering su più display

  1. Apri il dispositivo DRM /dev/dri/card* come nel flusso a un solo display.

  2. Elenca i connettori di visualizzazione disponibili.

    Ogni display viene esposto come connettore DRM separato del dispositivo DRM.

  3. Per ogni connettore del display:

    1. Seleziona un CRTC compatibile con il connettore. Ogni connettore ha un elenco di codificatori disponibili e ogni codificatore indica con quali CRTC può essere utilizzato. Esiste sempre almeno un CRTC compatibile.

      1. Seleziona un piano compatibile con il CRTC.

      2. Crea frame buffer DRM supportati dai buffer GPU. Questa procedura è identica a quella per la variante a un solo display.

      3. Collega il piano, il CRTC e il connettore e imposta la modalità video sul CRTC.

        È possibile impostare la modalità di più display contemporaneamente utilizzando l'API atomica per impostare le seguenti proprietà DRM per ogni connettore, CRTC e set di piani.

    L'elenco completo delle proprietà necessarie:

    Target ProprietàTipoDescrizione
    ConnettoreCRTC_IDID CRTCID del CRTC da assegnare al connettore
    CRTCMODE_IDID blob ID di un blob di proprietà creato utilizzando drmModeCreatePropertyBlob, contenente lo struct drmModeModeInfo della modalità video selezionata
    CRTCACTIVEBooleanotrue per contrassegnare il CRTC come attivo
    AereoFB_IDID framebufferID del framebuffer DRM da visualizzare sullo schermo
    AereoSRC_XPixelCoordinata X del rettangolo dell'immagine di origine del framebuffer
    AereoSRC_YPixelCoordinata Y del rettangolo dell'immagine di origine del framebuffer
    AereoSRC_W16.16 fixed pointLarghezza del rettangolo dell'immagine di origine del framebuffer (pixel spostati a sinistra di 16 bit)
    AereoSRC_H16.16 fixed pointAltezza del rettangolo dell'immagine di origine del framebuffer (pixel spostati a sinistra di 16 bit)
    AereoCRTC_XPixelCoordinata X del rettangolo dell'immagine di destinazione CRTC
    AereoCRTC_YPixelCoordinata Y del rettangolo dell'immagine di destinazione CRTC
    AereoCRTC_WPixelLarghezza del rettangolo dell'immagine di destinazione CRTC
    AereoCRTC_HPixelAltezza del rettangolo dell'immagine di destinazione CRTC
  4. Inserisci il ciclo di rendering:

    1. Attendi l'evento di cambio pagina su un CRTC prima di eseguire il rendering del frame successivo.

    2. Esegui il rendering di un frame e visualizzalo sullo schermo pianificando un cambio di pagina per CRTC e framebuffer specifici.