Wayland in Embedded linux/1. Linux graphic system and DRM

1. 임베디드 linux 그래픽 시스템과 DRM

Onionfra 2017. 5. 26. 11:20

<디스플레이 출력에 대한 이야기>


디스플레이 패널은 CPU/GPU가 준비해 놓은 버퍼를 특정 주기마다 출력한다(AP를 사용하는 임베디드에서는 디스플레이 컨트롤러 H/W IP가 이역할을 담당한다). 이 출력되는 구간을 Vertical Blank(일반적인 패널에서 좌측 위 끝에서 우측아래 끝까지 그려지는 구간)라고 하며 이 주기가 패널의 fps를 결정 하게 된다. 또한 tearing을 방지하기 위해 이 구간 동안 AP의 디스플레이 컨트롤러 IP가 frame buffer에 접근하지 않도록 구현되어 있다.(Vsync, sync/fence 활용)

*tearing: framebuffer가 패널로 출력 되고 있는도중 CPU가 frambuffer 영역을 갱신하여 패널 화면에 다음 frame이 섞여 출력되어 화면이 깨져보이는 현상

 

예를 들어 60fps인 경우 초당 60장의 frame(16.6ms 마다 한장)이 출력되며 이런 fps는 AP의 디스플레이 컨트롤러 H/W IP의 성능에 따라 결정된다. 이 Vertical Blank(VBLANK)구간이 끝나면 디스플레이 H/W IP는 VSYNC 이벤트를 발생시켜 커널 디스플레이 드라이버가 이 동기화를 제어 할 수 있는 기준을 제공 해 준다.

*최근 디스플레이 스택 메커니즘은 디스플레이 드라이버와 패널의 동기화 뿐만 아니라 framebuffer를 그리는 Application단까지 동기화 체인을 구성하여 보다 매끄러운 화면 동작을 구현하고 있다. 안드로이드 같은경우 sync-fence(butter project)를 통하여 이를 구현하였고 wayland도 이와 비슷한 메커니즘이 적용되어 있다.

 

<DRI>


DRM은 원래 X86시스템에서 DRI의 일부분으로 사용되어지고 있었다. 임베디드 시스템에서는 DRI전체를 사용하고 있지는 않지만 시스템에서의 DRM의 포지션과 역할을 이해하기위해서는 DRI의 개념과 컨셉을 간단하게나마 알고 넘어가는것이 좋다.

일단 DRMDRI를 구성하는 컴포넌트 중 하나라고 생각하고 다음 설명으로 넘어가도 큰 무리가 없을것이다.


Direct Rendering Infrastructure(DRI)

DRIX Window 시스템 환경에서 그래픽 하드웨어를 직접 접근하기 위한 framework이다. DRIX server의 변경과 여러가지의 클라이언트 라이브러리, 그리고 커널의 DRM(Direct Rendering Manager)를 포함 한다. DRI 사용의 가장 중요한 목표는 Mesa(Opengl을 지원하는 공개소스)를 위한 H/W 가속을 지원하는 빠른 OpenGL 프로그램을 만들기 위함이다. (GPU H/W를 이용하는 빠른 가속을 User space 또는 어플리케이션에 지원하기 위해)


많은 3D 가속 드라이버가(3DFX, AMD, Intel, Matrox) DRI 스펙으로 구현 되었다.


DRI는 크게 다음 3개의 컴포넌트를 포함한다.

- X server

- The direct rendering client

- Kernel-level device driver(DRM)



DRI 컴포넌트 구성 모듈

-XFree86 extensions:
-GLXExtension
-GLcoreExtension
-DriExtension
-libGL
-libGLDriver
-MesaDriver
-DRM
-DRMTemplates

참조: https://dri.freedesktop.org/wiki/

* 이 블로그에서 설명하려고 하는 Wayland의 비교대상으로 지칭되는 디스플레이 서버(컴포지터, 윈도우 매니져)가 나의 무지로 X Server, X window, Xorg.. 등 여러가지로 지칭되고 있다. 사실 대부분 임베디드 리눅스 개발자로서 시간을 보내서 user영역 그래픽 시스템에 대해서는 아직 많이 모른다. 검색 중에 알게 된 다음 블로그에서 내가 모르는 많은것을 설명하고 있다. http://webos21.blog.me/191170199



<DRM>


DRMFBDEV(fb드라이버)대체하는 디스플레이 컨트롤 드라이버이자 GPU접근을 가능케 하는 리눅스 커널의 서브 시스템이다. (DRM드라이버를 사용하여 디스플레이컨트롤과 GPU컨트롤을 함께 제어 할 수 있다.)

리눅스 커널의 서브 시스템인 DRM(Direct Rendering Manager)GPU를 접근할 수 있는 Display H/W IP(통칭하여 그래픽 하드웨어, X86 desktop PC에서의 Video cards)를 제어하기 위한 커널 드라이버라고 할 수 있다.


커널의 DRM드라이버는 크게 다음과 같은 기능의 User API를 제공 하고 있다.

GPU Access API: User-space에서 GPUaccess(3D rendering, video decoding)하기 위한 API
DRM Security: master로 지정된 1개의 프로세스에 의해서만 호출 되도 제한하는 기능을 제공하는 API
KMS(Kernel Mode Setting) API: 디스플레이 설정(resolution, refresh rate)을 위한 API
GEM(Graphics Execution Manager) API: 그래픽 메모리(allocation, free, synchronization ) 관리를 위한 API


다음은 이해를 돕기 위한 DRM드라이버에 대한 추가 설명이다

DRMdirect h/w accessDRI 클라이언트에세 제공하는 커널 모듈이다.
DRMh/w lock를 이용한 graphics h/w에 대한 동기화된 액세스를 제공한다
DRM은 그래픽 하드웨어에 액세스 하기 위한 DRI보안 정책을 적용한다
DRM은 일반적인 DMA 엔진을 제공한다
DRM은 확장 가능하다


<DRM의 구성 요소>


Kernel Mode Setting(KMS)

kernel에서 그래픽 하드웨어 출력에 대한 설정/변경 을 담당한다.(resolutions, color depths, memory layouts and refresh rate)
과거에 그래픽하드웨어 출력에 대한 설정은 X server의 역할 이었다.
User spaceX servermode-setting 수행하면서 발생했던 slow user switching, flickering이슈를 해결 할 수 있었다
KMS를 사용하게 됨으로서 많은 작업을 단순화 할 수 있고 보안을 향상 시킬 수 있었다.
커널과 X server에서 중복하여 존재하던 mode-setting 코드가 시스템에서 제거 될 수 있었다.(오직 커널에서만 존재)
커널 부팅시에 mode-setting이 가능해 졌다.

Graphics Execution Manager (GEM)

GEMGPU의 메모리를 할당하고 해제 한다.
GEMi915 그래픽 드라이버를 위한 비디오 메모리 매니저를 제공하기 위해 intel 엔지니어에 의해 개발되었다
GEM을 통해 user space 프로그램은 gpu의 비디오 메모리에 있는 메모리 객체를 create, handle, destroy할 수 있다
user space 프로그램이 비디오 메모리를 필요로 할 경우 GEM API를 사용하여 DRM driver에세 할당을 요청하면 된다.
GEM APIbufferpopulate하고 필요하지 않을 때 release하는 동작을 제공한다.

GEM 은 동일한 DRM device를 사용하는 두개 이상의 user space 프로그램이 GEM개체를 공유할 수 있게 한다.


DRM security

DRMioctlsmaster로 지정된 1개의 프로세스에 의해서만 호출하도록 제한된다.
일반적으로 wayland와 같은 display server 프로세스는 프로그램을 시작 할 때 master 프로세스가 되기 위해 SET_MASTER ioctl을 통해 DRM-Master상태를 얻어 전체 그래픽 세션에 대한 권한을 갖을 수 있으며, DROP_MASTER를 이용하여 master권한을 해제 할 수 있다. master권한이 없는 프로세스가 제한된 ioctl을 호출 할 경우 error가 반환될 것이다. DRM-Master권한을 갖지 못한 나머지 프로세스들은 DRM-Auth 통해  일부 제한된 ioctl을 호출할 수 있는 권한을 얻을 수 있다

DRM DMA engine

서버는 할당 된 버퍼를 지정할 수 있다
클라이언트는 DRM API를 사용하여 지정된 버퍼를 가상 주소 공간에 매핑한다
클라이언트는 DRM으로부터 이런 버퍼중 일부를 예약한다
버퍼를 명령으로 채운다
DRM이 그래픽 하드웨어에 버퍼를 보내도록 요청한다.
DRM은 각 OpenGL GLX컨텍스트에 대한 DMA버퍼 규를 관리한다.
DRM은 각 DMA버퍼 요청의 간단한 스케쥴링을 수행한다.


DRM 인터페이스(지원 범위)

Memory mapping
Context management
DMA operations
AGP management
vblank control
fence management
memory management
output management


<DRM 아키텍쳐>


DRM 디바이스 파일:  /dev/dri/cardX
DRM kernel 모듈: /kernel/drivers/gpu/drm directory
GPU h/w마다 DRM을 위한 커널 모듈이 존재하며 DRM을 지원하기 위한 코드가 구현되어 있다


DRM“DRM core”, “DRM driver” 두 부분으로 구성된다. DRM coreDRM의 기본 framework으로서 공통적인 API를 제공하며 DRM driver는 사용중인 특정 하드웨어 를 위해 API를 확장해서 사용할 수 있다. 특정 H/W를 위해 확장된 DRM과 함께 libdrm또한 libdrm-driver를 확장하여 사용할 수 있다. (AP/GPU vendor에 의해 확장 됨)


아래는 리눅스 커널에서 DRM드라이버의 디렉토리 구조이다.

라즈베리파이는 Broadcom사의 VC4를 이용하여 H/W aceleration을 enable한다




<DRM device model>


DRMKMS디스플레이 컨트롤러의 출력 파이프라인을 추상 하드웨어 블록으로 모델링하고 관리한다.


CRTC

스캔아웃 엔진을 나타내며 현재 스캔아웃 버퍼에 있는 픽셀 데이터를 읽고 비디오모드 타이밍 신호를 생성한다

사용 가능한 CRTC의 수는 하드웨어가 동시에 처리 할 수 있는 독립 출력 장치의 수를 결정 하므로 디스플레이 장치 당 하나 이상의 CRTC가 필요하다

Connectors

디스플레이 컨트롤러가 스캔 아웃 작업(CRTC에 의한)에서 비디오 신호를 전송하여 표시 할 위치를 나타낸다

일반적으로 출력장치(모니터, 패널)가 있는 하드웨어의 물리적 커넥터(VGA, DVI, HDMI)를 나타내며

연결상태, EDID데이터, DPMS상태 또는 지원되는 비디오 모드와 같은 현재 물리적으로 연결 된 출력 장치의 정보도 커넥터에 의해 관리된다

Encoders

디스플레이 컨트롤러는 커넥터에 적합한 포맷을 사용하여 CRTC로부터 비디오 모드 타이밍 신호를 인코딩 해야 한다인코더는 이러한 인코딩 중 하나를 수행 할 수 있는 하드웨어 블록을 나타낸다. 디지털 출력을 위한 인코딩의 예로 TMDS LVDS 있음. 아날로그 출력일 경우 일반적으로 특정 DAC블록이 사용 된다. 커넥터는 한 번에 한 인코더의 신호만 수신 가능하다.

모든 CRTC가 모든 사용 가능한 인코더에 연결되는 것은 아니며 CRTC- 인코더 - 커넥터의 가능한 조합을 제한하는 추가 물리적 제한이있을있다

Planes

plane은 하드웨어 블록이 아니라 스캔아웃 엔진(CRTC)이 공급되는 버퍼가 있는 메모리 개체이다(한개의 이미지 레이어)

프레임 버퍼를 보유하고있는 planeprimary plane이라고 부르며 CRTC가 비디오 모드(display resolution, pixel size, pixel format, refresh rate )결정하는 소스이기 때문에 각 CRTC에는 연결된 하나의 plane이 반드시 있어야한다.

디스플레이 컨트롤러가 하드웨어 커서 오버레이를 지원하거나 추가 하드웨어 오버레이에서 스캔하여 출력 장치로 전송 된 최종 이미지를 혼합 수있는 경우 CRTC는 커서 플레인과 연관 될 수 있다


위 그림은 FBDEVDRM이 최종 display를 위한 device종단까지 연결되는 과정을 보여주고 있다. 기존 FBDEV graphic memory 바로 화면에 출력하였지만 DRMscaling, rotate, composit등 다양한 기능을 지원하기 위해 CRTCEncoder, Connector블락을 포함하고있다


FBDEVDRM

아래 표와 같이 DRM은 최근 그래픽 시스템의 복잡한 요구사항을 만족시키기 위해 FBDEV에 비해 많은 기능을 지원한다

 

기능

FB

DRM

메모리

Dynamic Allocation

X

O

Multiple Buffers

Panning

O

Import

X

dmabuf

Export

mmap

dmabuf mmap

변환

Overlays

X

O

Rotation

X

O

Scaling

X

O

Cropping/Panning

O

O


최근 APDisplay controller H/W IP에서 분리되어 존재하고 있던 rotation, scaling등을 위한 H/W IP를 통합 시키고 있다.
이와 함께 DRM드라이버는 Display controller H/W IP기반에 display, overlay, rotation, scaling, cropping, CSC등의 기능을 하나로 통합하여 user application쉽게 사용할 수 있는 간단한 사용 path 제공한다(기존 FB드라이버가 framebuffer에서 DMA로 바로 출력만 하는 기능을 갖고 있다). 또한 디스플레이에 고해상도가 필요해지고 복잡한 디스플레이 사용 시나리오에 대한 지원을 가능케 하기위해 DRM GEM(그래픽 메모리 관리를 위한 메니져)을 포함하고 있다. GEMuser application에서의 유연한 buffer allocationread/write를 지원한다.


출처: https://en.wikipedia.org/wiki/Direct_Rendering_Manager

과거 FBDEV에서는 멀티 어플리케이션이 하나뿐인 GPU사용을 위해 비디오 메모리를 사용하고 free하는 작업을 진행 했어야 했다이 작업이 멀티 어플리케이션에 의해 다중으로 수행되면 GPU를 사용함에 있어 충돌하는 상황이 발생할 수 밖에 없었다DRM은 이러한 상황을 중간에서 관리하여 멀티 어플리케이션이 충돌없이 GPU를 사용할 수 있게 해준다.

초창기 DRM은 다중 프로그램이 GPU를 충돌없이 사용하게 하는 중재자 역할의 목적으로만 만들어 졌으나, 이후에 user가 Framebuffer를 관리하거나 mode setting(KMS), memory sharing, memory 동기화(GEM)을 위한 목적으로 확장 되었다위 그림과 같이 DRMvideo card(Embedded인 경우 display H/W IP + GPU) 대한 멀티 application의 동시 접근을 가능케 한다


출처: https://en.wikipedia.org/wiki/Direct_Rendering_Manager

위 그림은 어플리케이션이 DRM을 이용하여 video card를 사용하는 과정을 간단히 나타내고 있다.

libdrmKernelDRM드라이버를 사용하기 위한 user space 라이브러리(wrapper) 이다. libdrm을 사용하면 커널 인터페이스가

사용자 공간에 직접 노출되는 것을 피할 수 있을 뿐만 아니라 프로그램간에 코드를 재사용하고 공유할 수 있는 이점이 있다. 또한

예제에서 libdrm을 사용하는 것과 사용하지 않을 때를 설명 할 것이다.


출처: https://en.wikipedia.org/wiki/Direct_Rendering_Manager

위 그림은 어플리케이션이 DRM을 이용하여 video card를 사용하는 과정을 좀더 자세히 나타내고 있다.

어플리케이션은 libdrm라이브러리를 사용하여 ioctl을 통해 커널의 DRM드라이버에 명령을 내린다.

DRM드라이버는 GEM을 이용하여 메모리 버퍼를 관리를 하며 KMS를 이용하여 framebuffer

mode setting(screen resolution, color depth, refresh rate)을 수행 한다