Класс 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, если экран не обновляется.
Если вы переключитесь на видео Play (TextureView) Grafika и захватите новую трассировку, вы увидите строку с меткой 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, нелинейные свизлированные макеты и альтернативные цветовые форматы. Разрешение оборудованию использовать его предпочтительный формат может повысить производительность.
Некоторые значения не могут быть объединены на определенных платформах. Например, флаг видеокодера может потребовать пиксели YUV, поэтому добавление программного доступа и указание RGBA_8888
не удается.
Дескриптор, возвращаемый Gralloc, может передаваться между процессами через Binder.
Защищенные буферы
Флаг использования Gralloc GRALLOC_USAGE_PROTECTED
позволяет отображать графический буфер только через аппаратно защищенный путь. Эти плоскости наложения являются единственным способом отображения содержимого DRM (буферы с защитой DRM не могут быть доступны SurfaceFlinger или драйверу OpenGL ES).
Видео с защитой DRM может быть представлено только на плоскости наложения. Видеоплееры, поддерживающие защищенный контент, должны быть реализованы с помощью SurfaceView. Программное обеспечение, работающее на незащищенном оборудовании, не может считывать или записывать буфер; пути с аппаратной защитой должны отображаться на наложении Hardware Composer (то есть защищенные видео исчезают с дисплея, если Hardware Composer переключается на композицию OpenGL ES).
Подробную информацию о защищенном контенте см. в разделе DRM .