그래픽

Android 그래픽 HAL 아이콘

Android 프레임워크는 그래픽 드라이버의 제조업체 구현과 상호작용하는 다양한 2D 및 3D용 그래픽 렌더링 API를 제공합니다. 따라서 이러한 API가 더 높은 수준에서 어떻게 작동하는지를 제대로 이해하는 것이 중요합니다. 이 페이지에서는 드라이버가 빌드되는 그래픽 하드웨어 추상화 계층(HAL)에 관해 소개합니다. 이 섹션을 계속하려면 다음 용어에 관해 잘 알고 있어야 합니다.

캔버스(일반적인 용어), Canvas(API 요소)
캔버스란 비트맵 또는 Surface 객체에 비교하여 실제 비트의 합성을 처리하는 그리기 표면입니다. Canvas에는 비트맵, 선, 원, 직사각형, 텍스트 등의 표준 컴퓨터 그리기 메서드가 있으며 비트맵 또는 표면에 결합됩니다. 캔버스는 화면에 2D 객체를 그리는 가장 간단하고 쉬운 방법입니다. 기본 클래스는 Canvas입니다.
드로어블
드로어블은 화면의 배경, 제목 또는 다른 부분으로 사용할 수 있는 컴파일된 시각적 리소스입니다. 드로어블은 일반적으로 다른 UI 요소에, 예를 들어 배경 이미지로 로드됩니다. 드로어블은 이벤트를 수신할 수 없지만 기타 상태 및 일정과 같은 다양한 속성을 할당하여 애니메이션 객체나 이미지 라이브러리와 같은 서브클래스를 사용 설정합니다. 대부분의 드로어블 객체는 이미지를 설명하는 XML 또는 비트맵 파일인 드로어블 리소스 파일에서 로드됩니다. 드로어블 리소스는 android.graphics.drawable의 서브클래스로 컴파일됩니다. 드로어블 및 기타 리소스에 관한 자세한 내용은 리소스를 참고하세요.
레이아웃 리소스
레이아웃 리소스는 활동 화면의 레이아웃을 설명하는 XML 파일입니다. 자세한 내용은 레이아웃 리소스를 참고하세요.
9-패치(NinePatch)
9-패치는 기기의 배경 또는 다른 이미지에 사용할 수 있는 크기 조절 가능한 비트맵 리소스입니다. 자세한 내용은 9-패치를 참고하세요.
OpenGL ES
OpenGL ES는 2D 및 3D 그래픽을 렌더링하기 위한 크로스 플랫폼 API입니다. Android는 하드웨어 가속 3D 렌더링을 위한 OpenGL ES 라이브러리를 제공합니다. 2D 렌더링의 경우 캔버스가 더 간편한 옵션입니다. OpenGL ES는 Android 네이티브 개발 키트(NDK)에서 사용할 수 있습니다. android.opengljavax.microedition.khronos.opengles 패키지는 OpenGL ES 기능을 노출합니다.
표면(일반적인 용어), Surface(API 요소)
표면은 화면으로 합성되는 메모리 블록을 나타냅니다. 표면은 그리기를 위한 캔버스를 포함하며 레이어를 그리고 Surface 객체의 크기를 조절할 수 있는 다양한 도우미 메서드를 제공합니다. Surface 클래스를 직접 사용하기보다 SurfaceView 클래스를 사용하세요.
표면 뷰(일반적인 용어), SurfaceView(API 요소)
표면 뷰는 그리기를 위한 Surface 객체를 래핑하고 크기와 형식을 동적으로 지정하는 메서드를 노출하는 View 객체입니다. 표면 뷰는 리소스를 많이 사용하는 작업(예: 게임 또는 카메라 미리보기)의 UI 스레드와 관계없이 그릴 수 있는 방법을 제공하지만 결과적으로 추가 메모리를 사용합니다. 표면 뷰는 캔버스 및 OpenGL ES 그래픽 두 가지 모두를 지원합니다. SurfaceView 객체의 기본 클래스는 SurfaceView입니다.
테마
테마는 텍스트 크기 및 배경 색상 등 여러 가지 속성으로 구성된 집합으로, 다양한 기본 디스플레이 설정을 정의하기 위해 결합됩니다. Android에서는 몇 가지 표준 테마를 제공하는데 이러한 표준 테마는 R.style에 명시되어 있고 이름이 Theme_으로 시작됩니다.
뷰(일반적인 용어), View(API 요소)
뷰는 화면에 직사각형 영역을 그리고 클릭, 키 입력 및 기타 상호작용 이벤트를 처리합니다. 텍스트 상자, 창 등 활동 또는 대화상자 화면에 속하는 대부분의 레이아웃 구성요소의 경우 기본 클래스는 View입니다. View 객체는 상위 객체(ViewGroup 참고)로부터 호출을 받아 스스로를 그리며 원하는 위치 및 크기를 상위 객체에 알립니다. 상위 객체는 이를 고려할 수도 있고 고려하지 않을 수도 있습니다. 자세한 내용은 View를 참고하세요.
뷰 그룹(일반적인 용어), ViewGroup(API 요소)
뷰 그룹은 하위 뷰의 집합을 그룹화합니다. 뷰 그룹은 하위 뷰의 위치와 크기를 결정하며 적절할 때 각 하위 뷰를 호출하여 자신을 그리도록 합니다. 표시되지 않고 레이아웃 전용인 뷰 그룹도 있고, 고유한 UI(예: 스크롤 목록 상자)가 있는 뷰 그룹도 있습니다. 뷰 그룹은 widget 패키지에 포함되지만 ViewGroup 클래스를 확장합니다.
뷰 계층 구조
뷰 계층 구조는 앱의 모든 구성요소에 대한 사용자 인터페이스를 정의하는 뷰와 뷰 그룹 객체가 처리되는 방식입니다. 이 계층 구조는 하나 이상의 하위 뷰나 뷰 그룹을 포함하는 뷰 그룹들로 구성됩니다. Android SDK와 함께 제공되는 Hierarchy Viewer를 사용하면 디버깅 및 최적화를 위한 뷰 계층 구조를 시각적으로 표현할 수 있습니다.
Vulkan
Vulkan은 오버헤드가 낮은 고성능 3D 그래픽용 크로스 플랫폼 API입니다.
위젯
위젯은 양식 요소 및 기타 UI 구성요소(예: 텍스트 상자, 팝업 메뉴)를 렌더링하는 완전하게 구현된 View 서브클래스의 집합 중 하나입니다. 위젯은 완전히 구현되었으므로 자체 측정 및 그리기와 화면 이벤트의 응답을 처리합니다. 위젯은 android.widget 패키지에 속해 있습니다.
창(일반적인 용어), Window(API 요소)
Android 앱에서 창은 일반적인 창의 요소를 지정하는 Window 추상화 클래스에서 파생된 객체로, 이러한 창의 요소로는 창의 모양과 분위기, 타이틀 표시줄 텍스트, 메뉴의 위치와 내용이 있습니다. 대화상자와 활동은 Window 객체를 렌더링하기 위해 Window 클래스 구현을 사용합니다. Window 클래스를 구현하거나 앱에서 창을 사용하지 않아도 됩니다.

앱 개발자는 세 가지 방식, 즉 캔버스, OpenGL ES 또는 Vulkan을 통해 화면에 이미지를 그립니다.

Android 그래픽 구성요소

개발자가 어떤 렌더링 API를 사용하든 모든 것이 표면으로 렌더링됩니다. 표면은 흔히 SurfaceFlinger에 의해 소비되는 버퍼 큐의 생산자 측을 나타냅니다. Android 플랫폼에 생성되는 모든 창은 표면에 의해 지원됩니다. 렌더링되어 표시되는 모든 표면은 SurfaceFlinger에 의해 디스플레이에 합성됩니다.

아래 다이어그램은 주요 구성요소가 함께 작동하는 방식을 보여줍니다.

이미지 렌더링 구성요소

그림 1. 표면이 렌더링되는 방식

아래에 주요 구성요소가 설명되어 있습니다.

이미지 스트림 생산자

이미지 스트림 생산자는 소비를 위한 그래픽 버퍼를 생성하는 모든 요소일 수 있으며, OpenGL ES, 캔버스 2D, 미디어 서버 동영상 디코더 등을 예로 들 수 있습니다.

이미지 스트림 소비자

이미지 스트림의 가장 일반적인 소비자는 SurfaceFlinger입니다. 이 시스템 서비스는 현재 표시된 표면을 소비하며, 창 관리자가 제공한 정보를 사용하여 표면을 디스플레이에 합성합니다. SurfaceFlinger는 디스플레이의 콘텐츠를 수정할 수 있는 유일한 서비스입니다. SurfaceFlinger는 OpenGL 및 하드웨어 컴포저를 사용하여 표면 그룹을 구성합니다.

카메라 미리보기 이미지 스트림을 소비하는 카메라 앱과 같은 다른 OpenGL ES 앱도 이미지 스트림을 소비할 수 있습니다. GL이 아닌 앱도 소비자가 될 수 있습니다(예: ImageReader 클래스).

하드웨어 컴포저

디스플레이 하위 시스템을 위한 하드웨어 추상화입니다. SurfaceFlinger는 특정 합성 작업을 하드웨어 컴포저에 위임하여 OpenGL 및 GPU의 작업을 오프로드할 수 있습니다. SurfaceFlinger는 또 다른 OpenGL ES 클라이언트의 역할을 담당할 뿐입니다. 예를 들어 SurfaceFlinger는 한두 개의 버퍼를 세 번째 버퍼로 합성할 때 OpenGL ES를 사용합니다. 그러면 GPU가 모든 계산을 수행하는 것보다 낮은 전력으로 합성을 진행할 수 있습니다.

하드웨어 컴포저 HAL은 나머지 절반의 작업을 수행하며, 모든 Android 그래픽 렌더링의 중심점이 됩니다. 하드웨어 컴포저는 이벤트를 지원해야 하며, 여기에는 VSYNC 및 plug-and-playHDMI 지원용 핫플러그가 포함됩니다.

Gralloc

그래픽 메모리 할당자(Gralloc)는 이미지 생산자가 요청한 메모리를 할당하는 데 필요합니다. 자세한 내용은 Gralloc HAL을 참고하세요.

데이터 흐름

아래 다이어그램에는 Android 그래픽 파이프라인이 묘사되어 있습니다.

그래픽 데이터 흐름

그림 2. Android를 통한 그래픽 데이터 흐름

왼쪽에 있는 객체는 그래픽 버퍼를 생성하는 렌더기입니다(예: 홈 화면, 상태 표시줄 및 시스템 UI). SurfaceFlinger는 합성자이며, 하드웨어 컴포저는 구성자입니다.

BufferQueue

BufferQueue는 Android 그래픽 구성요소들을 연결시키는 역할을 합니다. BufferQueue는 생산자에서 소비자로 이어지는 버퍼의 끊임없는 순환을 중재하는 큐 쌍입니다. 생산자가 버퍼를 전달하면 SurfaceFlinger는 모든 요소를 디스플레이에 합성해야 합니다.

BufferQueue 통신 프로세스는 아래 다이어그램을 참고하세요.

BufferQueue 통신 프로세스

그림 3. BufferQueue 통신 프로세스

BufferQueue에는 이미지 스트림 생산자와 이미지 스트림 소비자를 함께 연결하는 로직이 포함되어 있습니다. 이미지 생산자의 예로는 카메라 HAL 또는 OpenGL ES 게임에 의해 생성된 카메라 미리보기가 있습니다. 이미지 소비자의 예로는 SurfaceFlinger 또는 OpenGL ES 스트림을 표시하는 또 다른 앱(예: 카메라 뷰파인더를 표시하는 카메라 앱)이 있습니다.

BufferQueue는 버퍼 풀을 큐와 결합하고 바인더 IPC를 사용하여 프로세스 간에 버퍼를 전달하는 데이터 구조입니다. 그래픽 버퍼를 생성하려는 대상에게 전달하는 요소 또는 생산자 인터페이스는 IGraphicBufferProducer(SurfaceTexture의 일부)입니다. BufferQueue는 특히 표면에 렌더링하고 GL 소비자와 함께 소비하는 데 주로 사용됩니다.

BufferQueue는 다음과 같이 세 가지 모드로 작동할 수 있습니다.

동기식 모드 - BufferQueue는 기본적으로 동기식 모드에서 작동합니다. 이 모드에서는 생산자로부터 들어오는 모든 버퍼가 소비자에서 나가게 됩니다. 이 모드에서는 버퍼가 삭제되지 않습니다. 생산자가 너무 빠르고 소모되는 속도보다 빨리 버퍼를 생성하는 경우 차단하고 여유 버퍼를 기다립니다.

비차단 모드 - 이러한 경우에 BufferQueue는 버퍼를 기다리는 대신 오류를 생성하는 비차단 모드에서 작동할 수도 있습니다. 이 모드에서도 버퍼는 삭제되지 않습니다. 이 모드는 애플리케이션 소프트웨어에서 발생할 수 있는 교착 상태를 방지하는 데 유용합니다. 교착 상태는 애플리케이션 소프트웨어에서 그래픽 프레임워크의 복잡한 종속 항목을 이해하지 못하기 때문에 발생할 수 있습니다.

삭제 모드 - 마지막으로, 오류를 생성하거나 기다리는 대신 기존 버퍼를 삭제하도록 BufferQueue를 구성할 수도 있습니다. 예를 들어 최대한 빨리 텍스처 뷰 및 그림에 대한 GL 렌더링을 수행하는 경우에는 버퍼를 드롭해야 합니다.

이러한 대부분의 작업을 수행하기 위해 SurfaceFlinger는 그저 또 다른 OpenGL ES 클라이언트로 기능합니다. 예를 들어 SurfaceFlinger는 한두 개의 버퍼를 세 번째 버퍼로 합성할 때 OpenGL ES를 사용합니다.

하드웨어 컴포저 HAL은 나머지 절반의 작업을 수행합니다. 이 HAL은 모든 Android 그래픽 렌더링에서 중심점 역할을 합니다.