<디스플레이 출력에 대한 이야기>
디스플레이 패널은 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의 개념과 컨셉을 간단하게나마 알고 넘어가는것이 좋다.
일단 DRM은 DRI를 구성하는 컴포넌트 중 하나라고 생각하고 다음 설명으로 넘어가도 큰 무리가 없을것이다.
Direct Rendering Infrastructure(DRI)
DRI는 X Window 시스템 환경에서 그래픽 하드웨어를 직접 접근하기 위한 framework이다. DRI는 X 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 컴포넌트 구성 모듈
<DRM>
DRM은 FBDEV(fb드라이버)를 대체하는 디스플레이 컨트롤 드라이버이자 GPU접근을 가능케 하는 리눅스 커널의 서브 시스템이다. (DRM드라이버를 사용하여 디스플레이컨트롤과 GPU컨트롤을 함께 제어 할 수 있다.)
리눅스 커널의 서브 시스템인 DRM(Direct Rendering Manager)은 GPU를 접근할 수 있는 Display H/W IP(통칭하여 그래픽 하드웨어, X86 desktop PC에서의 Video cards)를 제어하기 위한 커널 드라이버라고 할 수 있다.
커널의 DRM드라이버는 크게 다음과 같은 기능의 User API를 제공 하고 있다.
다음은 이해를 돕기 위한 DRM드라이버에 대한 추가 설명이다
Kernel Mode Setting(KMS)
Graphics Execution Manager (GEM)
DRM security
일반적으로 wayland와 같은 display server 프로세스는 프로그램을 시작 할 때 master 프로세스가 되기 위해 SET_MASTER ioctl을 통해 DRM-Master상태를 얻어 전체 그래픽 세션에 대한 권한을 갖을 수 있으며, DROP_MASTER를 이용하여 master권한을 해제 할 수 있다. master권한이 없는 프로세스가 제한된 ioctl을 호출 할 경우 error가 반환될 것이다. DRM-Master권한을 갖지 못한 나머지 프로세스들은 DRM-Auth를 통해 일부 제한된 ioctl을 호출할 수 있는 권한을 얻을 수 있다
DRM DMA engine
DRM 인터페이스(지원 범위)
<DRM 아키텍쳐>
DRM은 “DRM core”, “DRM driver” 두 부분으로 구성된다. DRM core는 DRM의 기본 framework으로서 공통적인 API를 제공하며 DRM driver는 사용중인 특정 하드웨어 를 위해 API를 확장해서 사용할 수 있다. 특정 H/W를 위해 확장된 DRM과 함께 libdrm또한 libdrm-driver를 확장하여 사용할 수 있다. (AP/GPU vendor에 의해 확장 됨)
아래는 리눅스 커널에서 DRM드라이버의 디렉토리 구조이다.
라즈베리파이는 Broadcom사의 VC4를 이용하여 H/W aceleration을 enable한다
<DRM device model>
DRM의 KMS는 디스플레이 컨트롤러의 출력 파이프라인을 추상 하드웨어 블록으로 모델링하고 관리한다.
CRTC
스캔아웃 엔진을 나타내며 현재 스캔아웃 버퍼에 있는 픽셀 데이터를 읽고 비디오모드 타이밍 신호를 생성한다
사용 가능한 CRTC의 수는 하드웨어가 동시에 처리 할 수 있는 독립 출력 장치의 수를 결정 하므로 디스플레이 장치 당 하나 이상의 CRTC가 필요하다
Connectors
디스플레이 컨트롤러가 스캔 아웃 작업(CRTC에 의한)에서 비디오 신호를 전송하여 표시 할 위치를 나타낸다
일반적으로 출력장치(모니터, 패널)가 있는 하드웨어의 물리적 커넥터(VGA, DVI, HDMI)를 나타내며
연결상태, EDID데이터, DPMS상태 또는 지원되는 비디오 모드와 같은 현재 물리적으로 연결 된 출력 장치의 정보도 커넥터에 의해 관리된다
Encoders
디스플레이 컨트롤러는 커넥터에 적합한 포맷을 사용하여 CRTC로부터 비디오 모드 타이밍 신호를 인코딩 해야 한다. 인코더는 이러한 인코딩 중 하나를 수행 할 수 있는 하드웨어 블록을 나타낸다. 디지털 출력을 위한 인코딩의 예로 TMDS 및 LVDS 있음. 아날로그 출력일 경우 일반적으로 특정 DAC블록이 사용 된다. 커넥터는 한 번에 한 인코더의 신호만 수신 가능하다.
모든 CRTC가 모든 사용 가능한 인코더에 연결되는 것은 아니며 CRTC- 인코더 - 커넥터의 가능한 조합을 제한하는 추가 물리적 제한이있을 수 있다
Planes
plane은 하드웨어 블록이 아니라 스캔아웃 엔진(CRTC)이 공급되는 버퍼가 있는 메모리 개체이다(한개의 이미지 레이어)
프레임 버퍼를 보유하고있는 plane을 primary plane이라고 부르며 CRTC가 비디오 모드(display resolution, pixel size, pixel format, refresh rate )를 결정하는 소스이기 때문에 각 CRTC에는 연결된 하나의 plane이 반드시 있어야한다.
디스플레이 컨트롤러가 하드웨어 커서 오버레이를 지원하거나 추가 하드웨어 오버레이에서 스캔하여 출력 장치로 전송 된 최종 이미지를 혼합 할 수있는 경우 CRTC는 커서 플레인과 연관 될 수 있다
위 그림은 FBDEV와 DRM이 최종 display를 위한 device종단까지 연결되는 과정을 보여주고 있다. 기존 FBDEV는 graphic memory를 바로 화면에 출력하였지만 DRM은 scaling, rotate, composit등 다양한 기능을 지원하기 위해 CRTC와 Encoder, Connector블락을 포함하고있다
FBDEV와 DRM
|
기능 |
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 |
최근 AP는 Display 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(그래픽 메모리 관리를 위한 메니져)을 포함하고 있다. GEM은 user application에서의 유연한 buffer allocation과 read/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)을 위한 목적으로 확장 되었다. 위 그림과 같이 DRM은 video card에(Embedded인 경우 display H/W IP + GPU) 대한 멀티 application의 동시 접근을 가능케 한다
출처: https://en.wikipedia.org/wiki/Direct_Rendering_Manager
위 그림은 어플리케이션이 DRM을 이용하여 video card를 사용하는 과정을 간단히 나타내고 있다.
libdrm은 Kernel의 DRM드라이버를 사용하기 위한 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)을 수행 한다
'Wayland in Embedded linux > 1. Linux graphic system and DRM' 카테고리의 다른 글
3. libdrm을 사용하여 DRM 사용하는 어플리케이션 예제 (0) | 2017.06.11 |
---|---|
1. DRM driver & panel output (0) | 2017.06.08 |
2. libdrm없이 kernel의 DRM드라이버를 바로 사용하는 어플리케이션 예제 (0) | 2017.05.29 |