BufferQueue 및 Gralloc

BufferQueue 클래스는 그래픽 데이터의 버퍼를 생성하는 구성요소(생산자)를 디스플레이 또는 추가 처리를 위한 데이터를 허용하는 구성요소(소비자)에 연결합니다. 시스템을 통해 그래픽 데이터 버퍼를 이동하는 대부분의 요소는 BufferQueue에 의존합니다.

Gralloc 메모리 할당자는 버퍼 할당을 실행하며 2개의 공급업체별 HIDL 인터페이스(hardware/interfaces/graphics/allocator/hardware/interfaces/graphics/mapper/ 참고)를 통해 구현됩니다. allocate() 함수는 예상 인수(너비, 높이, 픽셀 형식)와 사용 플래그 집합을 취합니다.

BufferQueue 생산자 및 소비자

소비자는 BufferQueue 데이터 구조를 생성 및 소유하며 생산자보다 다양한 프로세스에 존재할 수 있습니다. 버퍼가 필요한 생산자는 dequeueBuffer()를 호출하여 BufferQueue에서 프리 버퍼를 요청하는 방식으로 버퍼의 너비, 높이, 픽셀 형식과 사용 플래그를 지정합니다. 이어서 생산자는 queueBuffer()를 호출하여 버퍼를 채우고 버퍼를 대기열에 반환합니다. 다음으로 소비자는 acquireBuffer()로 버퍼를 획득하고 버퍼 콘텐츠를 활용합니다. 이를 완료한 소비자는 releaseBuffer()를 호출하여 버퍼를 대기열에 반환합니다. sync 프레임워크는 버퍼가 Android 그래픽 파이프라인을 통해 이동하는 방식을 제어합니다.

보유 가능한 최대 버퍼 수와 같은 BufferQueue의 일부 특성은 생산자 및 소비자 조합에 의해 결정됩니다. 하지만 BufferQueue는 필요에 따라 버퍼를 할당합니다. 버퍼는 특성이 변경되지 않는 이상 유지됩니다. 예를 들어 생산자가 다른 크기의 버퍼를 요청하면 기존 버퍼가 해제되고 요청에 따라 새 버퍼가 할당됩니다.

이렇게 많은 데이터를 이동하는 것은 비효율적이므로 BufferQueue가 버퍼 콘텐츠를 복사하는 경우는 없습니다. 대신 버퍼는 항상 핸들에 의해 전달됩니다.

Systrace로 BufferQueue 추적

그래픽 버퍼가 이동하는 방식을 이해하려면 Systrace를 사용하세요. 이 도구는 단기간에 걸친 기기 활동을 기록합니다. 시스템 수준의 그래픽 코드는 대부분의 관련 앱 프레임워크 코드처럼 제대로 계측화됩니다.

Systrace를 사용하려면 gfx, viewsched 태그를 사용 설정하세요. BufferQueue 개체는 트레이스에 표시됩니다. 한 예로 Grafika's Play 동영상(SurfaceView)이 실행되는 동안 트레이스를 취하면 SurfaceView로 라벨이 지정된 행에서 대기열에 등록된 버퍼의 수를 언제든지 알려줍니다.

앱이 활성화된 동안에는 값이 증분되며, 그러면 MediaCodec 디코더가 프레임을 렌더링하기 시작합니다. SurfaceFlinger가 작동하고 버퍼를 소비하는 동안에는 값이 감소합니다. 60fps까지는 디스플레이가 소스와 속도를 맞출 수 있으므로 30fps로 동영상을 표시할 경우 대기열 값은 0부터 1까지 다양합니다. SurfaceFlinger는 초당 60회가 아니라 완료해야 하는 작업이 있는 경우에만 절전 모드가 해제됩니다. 화면에서 업데이트되는 내용이 없으면 시스템은 작업을 회피하고 VSYNC를 사용 중지합니다.

Grafika's Play 동영상(TextureView)으로 전환하고 새 트레이스를 가져오면 com.android.grafika / com.android.grafika.PlayMovieActivity로 라벨이 지정된 행이 표시됩니다. 이는 또 다른 BufferQueue인 기본 UI 레이어입니다. TextureView는 별도의 계층 대신 UI 계층으로 렌더링되므로 모든 동영상 기반 업데이트가 여기에 표시됩니다.

Gralloc

Gralloc 할당자 HAL hardware/libhardware/include/hardware/gralloc.h는 사용 플래그를 통해 버퍼 할당을 실행합니다. 사용 플래그에는 다음과 같은 속성이 포함됩니다.

  • 소프트웨어에서 메모리가 액세스되는 빈도(CPU)
  • 하드웨어에서 메모리가 액세스되는 빈도(GPU)
  • 메모리가 OpenGL ES(GLES) 텍스처로 사용될지 여부
  • 메모리가 동영상 인코더에 의해 사용될지 여부

예를 들어 생산자의 버퍼 형식이 RGBA_8888 픽셀을 지정하고 생산자는 버퍼가 소프트웨어에서 액세스된다고 나타내는 경우(앱이 CPU의 픽셀과 접촉), Gralloc은 R-G-B-A 순서대로 픽셀당 4바이트의 버퍼를 생성합니다. 대신 버퍼가 하드웨어에서 GLES 텍스처로만 액세스된다고 생산자가 명시한 경우 Gralloc은 GLES 드라이버에서 원하는 모든 작업(예: BGRA 순서 지정, 비선형 혼합 레이아웃, 대체 색상 형식)을 실행할 수 있습니다. 하드웨어에서 기본 형식을 사용하도록 허용하면 성능이 개선될 수 있습니다.

일부 값은 특정 플랫폼에서 결합할 수 없습니다. 예를 들어 동영상 인코더 플래그에는 YUV 픽셀이 필요할 수 있으므로 소프트웨어 액세스를 추가하고 RGBA_8888을 지정하는 데 실패합니다.

Gralloc에 의해 반환된 핸들은 바인더를 통해 프로세스 간에 전달할 수 있습니다.

보호된 버퍼

Gralloc 사용 플래그 GRALLOC_USAGE_PROTECTED는 그래픽 버퍼를 하드웨어로 보호된 경로를 통해서만 표시할 수 있게 해줍니다. 이러한 오버레이 평면은 DRM 콘텐츠를 표시할 수 있는 유일한 방법입니다(DRM으로 보호된 버퍼는 SurfaceFlinger 또는 OpenGL ES 드라이버에서 액세스할 수 없음).

DRM으로 보호된 동영상은 오버레이 평면에만 표시할 수 있습니다. 보호된 콘텐츠를 지원하는 동영상 플레이어는 SurfaceView로 구현해야 합니다. 보호되지 않는 하드웨어에서 실행되는 소프트웨어는 버퍼를 읽거나 쓸 수 없습니다. 하드웨어로 보호된 경로는 Hardware Composer 오버레이에 표시되어야 합니다(즉, Hardware Composer가 OpenGL ES 구성으로 전환되면 보호된 동영상이 디스플레이에서 사라짐).

보호된 콘텐츠에 관한 자세한 내용은 DRM을 참조하세요.