레이어 및 디스플레이

레이어 및 디스플레이는 합성 작업, 그리고 디스플레이 하드웨어와의 상호작용을 나타내는 2개의 프리미티브입니다.

레이어

레이어는 가장 중요한 합성 단위입니다. 레이어는 노출 영역SurfaceControl의 인스턴스 조합입니다. 각 레이어에는 해당 레이어가 다른 레이어와 상호작용하는 방식을 정의하는 속성 집합이 있습니다. 레이어 속성은 아래 표에 설명되어 있습니다.

속성 설명
위치 디스플레이에 레이어가 표시되는 위치를 정의합니다. 레이어 가장자리의 위치, 그리고 다른 레이어에 상대적인 Z 순서(다른 레이어의 앞이나 뒤에 위치해야 하는지 여부) 등의 정보를 포함합니다.
콘텐츠 레이어에 표시된 콘텐츠가 위치 속성에서 정의한 경계 내에 어떻게 표시되어야 하는지를 정의합니다. 자르기(콘텐츠의 일부를 확장하여 레이어 경계를 채움) 및 변환(회전되었거나 뒤집힌 콘텐츠를 표시) 등의 정보를 포함합니다.
구성 레이어를 어떻게 다른 레이어와 합성해야 하는지 정의합니다. 혼합 모드, 그리고 알파 합성의 전체 레이어 알파 값 등의 정보를 포함합니다.
최적화 레이어를 올바르게 합성하는 데 꼭 필요하지는 않지만 HWC(Hardware Composer) 기기에서 합성 수행 방식을 최적화하는 데 사용할 수 있는 정보를 제공합니다. 레이어의 표시 영역, 그리고 이전 프레임 이후에 업데이트된 레이어의 부분 등에 대한 정보를 포함합니다.

디스플레이

디스플레이 역시 중요한 합성 단위입니다. 시스템은 여러 개의 디스플레이를 보유할 수 있으며 디스플레이는 일반 시스템 작업 도중에 추가 또는 삭제 가능합니다. 디스플레이는 HWC 또는 프레임워크의 요청 시에 추가/삭제됩니다. HWC 기기는 외부 디스플레이가 연결되거나 기기에서 연결 해제될 때 디스플레이를 추가 또는 삭제하도록 요청하며 이를 핫플러깅이라고 부릅니다. 클라이언트는 가상 디스플레이를 요청합니다. 가상 플레이의 콘텐츠는 실제 디스플레이 대신 오프스크린 버퍼에 렌더링됩니다.

가상 디스플레이

SurfaceFlinger는 내부 디스플레이(스마트폰 또는 태블릿에 내장됨), 외부 디스플레이(HDMI를 통해 연결된 TV 등), 그리고 시스템 내에서 합성된 출력을 제공하는 하나 이상의 가상 디스플레이를 지원합니다. 가상 디스플레이는 화면을 녹화하거나 네트워크를 통해 화면을 전송하는 데 사용할 수 있습니다. 가상 디스플레이에 대해 생성된 프레임은 BufferQueue에 작성됩니다.

가상 디스플레이는 기본 디스플레이(레이어 스택)와 같은 레이어 집합을 공유하거나 자체 집합을 소유할 수 있습니다. 가상 디스플레이에는 VSYNC가 없으므로 내부 디스플레이의 VSYNC가 모든 디스플레이의 합성을 트리거합니다.

가상 디스플레이를 지원하는 HWC 구현에서는 가상 디스플레이를 OpenGL ES(GLES), HWC 또는 GLES 및 HWC 둘 다와 합성할 수 있습니다. 지원하지 않는 구현에서는 가상 디스플레이가 항상 GLES를 사용하여 합성됩니다.

우수사례: screenrecord

screenrecord 명령어는 사용자가 화면에 표시되는 모든 콘텐츠를 디스크에 .mp4 파일로 녹화할 수 있게 해줍니다. 이를 구현하기 위해 시스템은 SurfaceFlinger에서 합성된 프레임을 수신하여 동영상 인코더에 작성한 다음 인코딩된 동영상 데이터를 파일에 작성합니다. 동영상 코덱은 별도의 프로세스(mediaserver)에 의해 관리되므로 대규모 그래픽 버퍼가 시스템 주변에서 움직여야 합니다. 보다 높은 수준의 구현을 위해 60fps 동영상을 전체 해상도로 녹화하는 것을 목표로 합니다. 이를 효율적으로 달성하기 위한 핵심은 BufferQueue입니다.

MediaCodec 클래스는 앱이 데이터를 버퍼의 원시 바이트나 노출 영역을 통해 제공할 수 있게 해줍니다. screenrecord가 동영상 인코더 액세스를 요청하면 mediaserver 프로세스는 BufferQueue를 생성하고 자체적으로 소비자 측에 연결한 다음 생산자 측을 다시 screenrecord에 노출 영역으로 전송합니다.

그러면 screenrecord 유틸리티는 기본 디스플레이를 미러링(같은 레이어를 전부 보유)하는 가상 디스플레이를 생성하도록 SurfaceFlinger에 요청하고, mediaserver 프로세스에서 가져온 노출 영역에 출력을 전송하도록 지시합니다. 이 경우 SurfaceFlinger는 버퍼의 소비자가 아닌 생산자입니다.

구성이 완료되면 screenrecord는 인코딩된 데이터가 표시될 때 트리거됩니다. 앱이 그려지는 동안 버퍼는 SurfaceFlinger로 전송되며 SurfaceFlinger는 이를 하나의 버퍼로 합성한 후 mediaserver 프로세스의 동영상 인코더로 직접 전송합니다. 전체 프레임은 screenrecord 프로세스에 의해 절대 확인되지 않습니다. 내부적으로는 자체적으로 버퍼를 이동하고 핸들별로 데이터를 전달하여 오버헤드를 최소화하는 방식이 mediaserver 프로세스에 있습니다.

우수사례: 보조 디스플레이 시뮬레이션

WindowManager는 SurfaceFlinger에 SurfaceFlinger가 BufferQueue 소비자로 기능하는 표시 레이어를 생성하도록 요청할 수 있습니다. 또한 SurfaceFlinger가 BufferQueue 생산자로 기능하는 가상 디스플레이를 생성하도록 SurfaceFlinger에 요청할 수도 있습니다.

가상 디스플레이를 표시 레이어에 연결하면 합성된 화면이 표시되는 창의 위치에 폐쇄 루프가 생성됩니다. 이 창은 이제 합성된 출력의 일부이므로 다음 새로고침 시 창 내의 합성된 이미지에 창 콘텐츠도 표시됩니다. 실제 과정을 보려면 설정에서 개발자 옵션을 사용 설정하고 보조 디스플레이 시뮬레이션을 선택한 후 창을 사용 설정하세요. 보조 디스플레이가 작동하는 모습을 보려면 screenrecord를 사용하여 디스플레이 사용 설정 작업을 캡처하고 이를 프레임별로 재생하세요.