Аппаратный компоновщик (HWC) HAL компонует слои, полученные от SurfaceFlinger, уменьшая объем работы OpenGL ES (GLES) и графического процессора.
HWC абстрагирует объекты, такие как наложения и 2D-блитеры, для создания композитных поверхностей и взаимодействует со специализированным оборудованием для компоновки окон для создания композитных окон. Используйте HWC для создания композитных окон вместо того, чтобы использовать SurfaceFlinger для композитинга с графическим процессором. Большинство графических процессоров не оптимизированы для композиции, и когда графический процессор компонует слои из SurfaceFlinger, приложения не могут использовать графический процессор для собственного рендеринга.
Реализации HWC должны поддерживать:
- По крайней мере четыре наложения:
- Строка состояния
- Системная панель
- Приложение
- Обои/фон
- Слои, размер которых больше размера дисплея (например, обои)
- Одновременное предварительно умноженное попиксельное альфа-смешивание и поплоскостное альфа-смешивание
- Аппаратный путь для защищенного воспроизведения видео
- Порядок упаковки RGBA, форматы YUV, а также свойства тайлинга, свизлинга и шага
Для внедрения HWC:
- Реализовать неоперационный HWC и отправить все работы по составлению в GLES.
- Реализуйте алгоритм для поэтапного делегирования композиции HWC. Например, делегируйте только первые три или четыре поверхности аппаратному обеспечению наложения HWC.
- Оптимизируйте HWC. Это может включать в себя:
- Выбор поверхностей, максимально снимающих нагрузку с графического процессора, и передача их на HWC.
- Проверка обновления экрана. Если нет, делегируйте компоновку GLES вместо HWC для экономии энергии. Когда экран снова обновится, продолжайте передавать компоновку HWC.
- Подготовка к распространенным случаям использования, таким как:
- Главный экран, включающий строку состояния, системную панель, окно приложения и живые обои.
- Полноэкранные игры в портретном и альбомном режиме
- Полноэкранное видео со скрытыми субтитрами и управлением воспроизведением
- Защищенное воспроизведение видео
- Разделенный экран многооконный режим
Примитивы HWC
HWC предоставляет два примитива: слои и дисплеи , для представления работы композиции и её взаимодействия с оборудованием дисплея. HWC также обеспечивает управление вертикальной синхронизацией (VSync) и обратный вызов SurfaceFlinger для уведомления о событии вертикальной синхронизации (VSync).
HIDL-интерфейс
В Android 8.0 и более поздних версиях используется HIDL -интерфейс Composer HAL для межпроцессного взаимодействия между HWC и SurfaceFlinger. Composer HAL заменяет устаревший интерфейс hwcomposer2.h
. Если поставщики предоставляют реализацию HWC в Composer HAL, Composer HAL напрямую принимает вызовы HIDL от SurfaceFlinger. Если поставщики предоставляют устаревшую реализацию HWC, Composer HAL загружает указатели на функции из hwcomposer2.h
, перенаправляя вызовы HIDL в вызовы указателей на функции.
HWC предоставляет функции для определения свойств конкретного дисплея, переключения между различными конфигурациями дисплея (например, разрешением 4k или 1080p) и цветовыми режимами (например, собственный цвет или настоящий sRGB), а также для включения, выключения дисплея или перевода его в режим пониженного энергопотребления, если поддерживается.
Указатели на функции
Если поставщики реализуют Composer HAL напрямую, SurfaceFlinger вызывает его функции через HIDL IPC. Например, для создания слоя SurfaceFlinger вызывает createLayer()
в Composer HAL.
Если поставщики реализуют интерфейс hwcomposer2.h
, Composer HAL вызывает указатели на функции hwcomposer2.h
. В комментариях hwcomposer2.h
функции интерфейса HWC обозначаются именами в стиле lowerCamelCase, которые не существуют в интерфейсе как именованные поля. Практически каждая функция загружается путём запроса указателя на функцию с помощью getFunction
, предоставляемой hwc2_device_t
. Например, функция createLayer
— это указатель на функцию типа HWC2_PFN_CREATE_LAYER
, который возвращается при передаче перечисляемого значения HWC2_FUNCTION_CREATE_LAYER
в getFunction
.
Подробную документацию по функциям Composer HAL и функциям передачи функций HWC см. в файле composer
. Подробную документацию по указателям функций HWC см. в файле hwcomposer2.h
.
Маркеры слоев и отображения
Управление слоями и дисплеями осуществляется с помощью маркеров, генерируемых HWC. Эти маркеры непрозрачны для SurfaceFlinger.
Когда SurfaceFlinger создаёт новый слой, он вызывает createLayer
, который возвращает тип Layer
для прямых реализаций или hwc2_layer_t
для сквозных реализаций. Когда SurfaceFlinger изменяет свойство этого слоя, SurfaceFlinger передаёт значение hwc2_layer_t
в соответствующую функцию модификации вместе с любой другой информацией, необходимой для внесения изменений. Тип hwc2_layer_t
достаточно большой, чтобы содержать как указатель, так и индекс.
Физические дисплеи создаются путём горячего подключения. При горячем подключении физического дисплея HWC создаёт дескриптор и передаёт его в SurfaceFlinger через обратный вызов горячего подключения. Виртуальные дисплеи создаются с помощью вызова метода createVirtualDisplay()
для запроса дисплея SurfaceFlinger. Если HWC поддерживает композицию виртуальных дисплеев, он возвращает дескриптор. Затем SurfaceFlinger делегирует композицию дисплеев HWC. Если HWC не поддерживает композицию виртуальных дисплеев, SurfaceFlinger создаёт дескриптор и выполняет композицию дисплея.
Операции композиции отображения
SurfaceFlinger выходит из спящего режима один раз за вертикальную синхронизацию, если у него есть новый контент для компоновки. Этот новый контент может представлять собой новые буферы изображений из приложений или изменение свойств одного или нескольких слоёв. Когда SurfaceFlinger выходит из спящего режима:
- Обрабатывает транзакции, если таковые имеются.
- Фиксирует новые графические буферы, если они есть.
- Выполняет новую композицию, если шаг 1 или 2 привел к изменению отображаемого содержимого.
Для выполнения новой композиции SurfaceFlinger создаёт и уничтожает слои или изменяет их состояние, если применимо. Он также обновляет слои, используя такие вызовы, как setLayerBuffer
или setLayerColor
. После обновления всех слоёв SurfaceFlinger вызывает validateDisplay
, который сообщает HWC о необходимости проверить состояние слоёв и определить, как будет выполняться композиция. По умолчанию SurfaceFlinger пытается настроить каждый слой таким образом, чтобы он был составлен HWC; хотя в некоторых случаях SurfaceFlinger выполняет композицию с использованием резервного графического процессора.
После вызова validateDisplay
SurfaceFlinger вызывает getChangedCompositionTypes
, чтобы проверить, требуется ли HWC изменить какие-либо типы композиции слоёв перед выполнением композиции. Чтобы принять изменения, SurfaceFlinger вызывает acceptDisplayChanges
.
Если какие-либо слои отмечены для композиции SurfaceFlinger, SurfaceFlinger компонует их в целевой буфер. Затем SurfaceFlinger вызывает setClientTarget
, чтобы передать буфер дисплею, чтобы его можно было отобразить на экране или затем скомпоновать со слоями, не отмеченными для композиции SurfaceFlinger. Если ни один слой не отмечен для композиции SurfaceFlinger, SurfaceFlinger пропускает этап компоновки.
Наконец, SurfaceFlinger вызывает presentDisplay
, чтобы сообщить HWC о необходимости завершить процесс композиции и отобразить конечный результат.
Несколько дисплеев
Android 10 поддерживает несколько физических дисплеев. При разработке реализации HWC для Android 7.0 и более поздних версий существуют некоторые ограничения, отсутствующие в определении HWC:
- Предполагается, что имеется ровно один внутренний дисплей. Именно этот дисплей отображается при первом горячем подключении во время загрузки. После горячего подключения внутренний дисплей невозможно отключить.
- Помимо внутреннего дисплея, в процессе нормальной работы устройства может быть подключено любое количество внешних дисплеев. Платформа предполагает, что все подключаемые дисплеи после первого внутреннего дисплея являются внешними, поэтому при добавлении дополнительных внутренних дисплеев они ошибочно классифицируются как
Display.TYPE_HDMI
вместоDisplay.TYPE_BUILT_IN
.
Хотя описанные выше операции SurfaceFlinger выполняются для каждого дисплея, они выполняются последовательно для всех активных дисплеев, даже если обновляется содержимое только одного дисплея.
Например, если обновляется внешний дисплей, последовательность следующая:
// In Android 9 and lower: // Update state for internal display // Update state for external display validateDisplay(<internal display>) validateDisplay(<external display>) presentDisplay(<internal display>) presentDisplay(<external display>) // In Android 10 and higher: // Update state for internal display // Update state for external display validateInternal(<internal display>) presentInternal(<internal display>) validateExternal(<external display>) presentExternal(<external display>)
Виртуальная композиция дисплея
Композиция виртуального дисплея аналогична композиции внешнего дисплея. Разница между композицией виртуального дисплея и композицией физического дисплея заключается в том, что виртуальные дисплеи отправляют выходные данные в буфер Gralloc, а не на экран. Аппаратный компоновщик (HWC) записывает выходные данные в буфер, обеспечивает границу завершения и отправляет буфер потребителю (например, видеокодеру, графическому процессору, центральному процессору и т. д.). Виртуальные дисплеи могут использовать 2D/блиттер или оверлеи, если конвейер дисплея записывает данные в память.
Режимы
Каждый кадр находится в одном из трех режимов после того, как SurfaceFlinger вызывает метод validateDisplay()
HWC:
- GLES — графический процессор компонует все слои, записывая данные непосредственно в выходной буфер. HWC в компоновке не участвует.
- СМЕШАННЫЙ — GPU объединяет некоторые слои в буфер кадра, а HWC объединяет буфер кадра и оставшиеся слои, записывая их непосредственно в выходной буфер.
- HWC — HWC объединяет все слои и записывает их непосредственно в выходной буфер.
Формат вывода
Форматы вывода буфера виртуального дисплея зависят от их режима:
- Режим GLES — драйвер EGL устанавливает формат выходного буфера в
dequeueBuffer()
, обычноRGBA_8888
. Потребитель должен иметь возможность принять выходной формат, установленный драйвером, иначе буфер не будет прочитан. - Режимы MIXED и HWC — если потребителю требуется доступ к процессору, формат задаёт потребитель. В противном случае используется формат
IMPLEMENTATION_DEFINED
, и Gralloc выбирает оптимальный формат на основе флагов использования. Например, Gralloc задаёт формат YCbCr, если потребитель является видеокодером, и HWC может эффективно записывать этот формат.
Синхронизационные ограждения
Синхронизирующие барьеры (заборы синхронизации) — важнейший аспект графической системы Android. Они позволяют процессору выполнять работу независимо от параллельной работы графического процессора, блокируя её только при наличии реальной зависимости.
Например, когда приложение отправляет буфер, создаваемый графическим процессором, оно также отправляет объект синхронизационного барьера. Этот барьер сигнализирует о завершении графическим процессором записи в буфер.
HWC требует, чтобы графический процессор завершил запись буферов до их отображения. Синхронизирующие барьеры передаются через графический конвейер вместе с буферами и сигнализируют о записи буферов. Перед отображением буфера HWC проверяет, подал ли сигнал синхрозащита, и если подал, отображает буфер.
Дополнительную информацию о синхронных ограждениях см. в разделе Интеграция Hardware Composer .