BufferQueue и Gralloc

Класс BufferQueue соединяет компоненты, генерирующие буферы графических данных ( производители ), с компонентами, принимающими данные для отображения или дальнейшей обработки ( потребители ). Почти все, что перемещает буферы графических данных по системе, зависит от BufferQueue.

Распределитель памяти Gralloc выполняет выделение буферов и реализован через два интерфейса HIDL, специфичных для производителя (см. hardware/interfaces/graphics/allocator/ и hardware/interfaces/graphics/mapper/ ). Функция allocate() принимает ожидаемые аргументы (ширина, высота, формат в пикселях), а также набор флагов использования.

Производители и потребители BufferQueue

Потребители создают и владеют структурой данных BufferQueue и могут существовать в других процессах, чем их производители. Когда производителю нужен буфер, он запрашивает свободный буфер у BufferQueue, вызывая dequeueBuffer() , указывая ширину, высоту, формат пикселей и флаги использования буферов. Затем производитель заполняет буфер и возвращает буфер в очередь, вызывая queueBuffer() . Затем потребитель получает буфер с помощью acquireBuffer() и использует содержимое буфера. Когда потребитель завершает работу, он возвращает буфер в очередь, вызывая releaseBuffer() . Платформа синхронизации управляет тем, как буферы перемещаются по графическому конвейеру Android.

Некоторые характеристики BufferQueue, такие как максимальное количество буферов, которые она может содержать, определяются совместно производителем и потребителем. Однако BufferQueue выделяет буферы по мере необходимости. Буферы сохраняются до тех пор, пока не изменятся характеристики; например, если производитель запрашивает буферы другого размера, старые буферы освобождаются, а новые буферы выделяются по запросу.

Содержимое буфера никогда не копируется BufferQueue, поскольку перемещение такого большого количества данных неэффективно. Вместо этого буферы всегда передаются дескриптором.

Отслеживание BufferQueue с помощью Systrace

Чтобы понять, как перемещаются графические буферы, используйте Systrace — инструмент, записывающий активность устройства за короткий период времени. Графический код системного уровня хорошо инструментирован, как и большая часть соответствующего кода фреймворка приложения.

Чтобы использовать Systrace, включите теги gfx , view и sched . Объекты BufferQueue отображаются в трассировке. В качестве примера, если вы берете трассировку во время работы Grafika Play video (SurfaceView) , строка, помеченная как SurfaceView , сообщает вам, сколько буферов стояло в очереди в любой момент времени.

Значение увеличивается, пока приложение активно, что запускает визуализацию кадров декодером MediaCodec. Значение уменьшается, пока SurfaceFlinger работает и потребляет буферы. При показе видео со скоростью 30 кадров в секунду значение очереди изменяется от 0 до 1, поскольку отображение с частотой 60 кадров в секунду может не отставать от источника. SurfaceFlinger просыпается только тогда, когда нужно выполнить работу, а не 60 раз в секунду. Система пытается избежать работы и отключает VSYNC, если ничего не обновляет экран.

Если вы переключитесь на воспроизведение видео Grafika (TextureView) и захватите новую трассировку, вы увидите строку с надписью com.android.grafika / com.android.grafika.PlayMovieActivity . Это основной уровень пользовательского интерфейса, который является еще одним BufferQueue. Поскольку TextureView отрисовывается в слое пользовательского интерфейса, а не в отдельном слое, здесь отображаются все обновления, управляемые видео.

Граллок

Распределитель Gralloc HAL hardware/libhardware/include/hardware/gralloc.h выполняет выделение буфера с помощью флагов использования. Флаги использования включают такие атрибуты, как:

  • Как часто к памяти будет обращаться программное обеспечение (ЦП)
  • Как часто к памяти будет обращаться аппаратное обеспечение (GPU)
  • Будет ли память использоваться как текстура OpenGL ES (GLES)
  • Будет ли память использоваться видеокодером

Например, если формат буфера производителя указывает RGBA_8888 пикселей, а производитель указывает, что доступ к буферу будет осуществляться из программного обеспечения (это означает, что приложение будет обращаться к пикселям на ЦП), Gralloc создает буфер с 4 байтами на пиксель в порядке RGBA. Если вместо этого производитель указывает, что доступ к его буферу будет осуществляться только с аппаратного обеспечения и как к текстуре GLES, Gralloc может делать все, что пожелает драйвер GLES, например, порядок BGRA, нелинейные swizzled макеты и альтернативные цветовые форматы. Разрешение аппаратному обеспечению использовать его предпочтительный формат может повысить производительность.

Некоторые значения нельзя комбинировать на определенных платформах. Например, для флага кодировщика видео могут потребоваться пиксели YUV, поэтому добавление доступа к программному обеспечению и указание RGBA_8888 не удастся.

Дескриптор, возвращаемый Gralloc, может передаваться между процессами через Binder.

Защищенные буферы

Флаг использования GRALLOC_USAGE_PROTECTED позволяет отображать графический буфер только через аппаратно защищенный путь. Эти плоскости наложения являются единственным способом отображения содержимого DRM (буферы, защищенные DRM, недоступны для SurfaceFlinger или драйвера OpenGL ES).

Видео с защитой DRM может быть представлено только на плоскости наложения. Видеопроигрыватели, поддерживающие защищенное содержимое, должны быть реализованы с помощью SurfaceView. Программное обеспечение, работающее на незащищенном оборудовании, не может читать или записывать буфер; аппаратно защищенные пути должны отображаться в оверлее Hardware Composer (то есть защищенные видео исчезают с экрана, если Hardware Composer переключается на композицию OpenGL ES).

Дополнительные сведения о защищенном содержимом см. в разделе DRM .