Внедрить аппаратный композитор HAL

Аппаратный компоновщик (HWC) HAL объединяет слои, полученные от SurfaceFlinger, уменьшая объем композиции OpenGL ES (GLES) и графического процессора.

HWC абстрагирует объекты, такие как наложения и 2D-блитеры, на составные поверхности и взаимодействует со специализированным оборудованием для композиции окон с составными окнами. Используйте HWC для объединения окон вместо объединения SurfaceFlinger с графическим процессором. Большинство графических процессоров не оптимизированы для композиции, и когда графический процессор компонует слои из SurfaceFlinger, приложения не могут использовать графический процессор для собственного рендеринга.

Реализации HWC должны поддерживать:

  • Минимум четыре наложения:
    • Статус бар
    • Системная панель
    • Приложение
    • Обои/фон
  • Слои, размер которых больше экрана (например, обои).
  • Одновременное предварительно умноженное альфа-смешение на пиксель и альфа-смешение на плоскости.
  • Аппаратный путь для защищенного воспроизведения видео
  • Порядок упаковки RGBA, форматы YUV, свойства мозаики, поворота и шага.

Для реализации HWC:

  1. Внедрите неработающий HWC и отправьте всю работу по составлению в GLES.
  2. Реализуйте алгоритм для постепенного делегирования композиции HWC. Например, делегируйте только первые три или четыре поверхности накладному оборудованию HWC.
  3. Оптимизируйте HWC. Это может включать в себя:
    • Выбор поверхностей, максимально снимающих нагрузку с графического процессора, и отправка их в HWC.
    • Определение того, обновляется ли экран. Если это не так, делегируйте композицию GLES, а не HWC, чтобы сэкономить электроэнергию. Когда экран снова обновится, продолжайте выгружать композицию в HWC.
    • Подготовка к распространенным случаям использования, таким как:
      • Главный экран, который включает строку состояния, системную панель, окно приложения и живые обои.
      • Полноэкранные игры в портретном и ландшафтном режиме
      • Полноэкранное видео со скрытыми субтитрами и контролем воспроизведения.
      • Защищенное воспроизведение видео
      • Многооконный режим с разделенным экраном

Примитивы HWC

HWC предоставляет два примитива, слои и дисплеи , для представления работы композиции и ее взаимодействия с аппаратным обеспечением дисплея. HWC также обеспечивает контроль над VSYNC и обратный вызов SurfaceFlinger для уведомления его о возникновении события VSYNC.

HIDL-интерфейс

Android 8.0 и более поздних версий использует интерфейс HIDL под названием Composer HAL для связывания IPC между 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 ссылаются на имена lowCamelCase, которые не существуют в интерфейсе как именованные поля. Почти каждая функция загружается путем запроса указателя на функцию с помощью 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 через обратный вызов горячего подключения. Виртуальные дисплеи создаются с помощью SurfaceFlinger, вызывающего createVirtualDisplay() для запроса дисплея. Если HWC поддерживает композицию виртуального дисплея, он возвращает дескриптор. Затем SurfaceFlinger делегирует композицию дисплеев HWC. Если HWC не поддерживает композицию виртуального дисплея, SurfaceFlinger создает дескриптор и объединяет дисплей.

Операции композиции отображения

Один раз для VSYNC SurfaceFlinger просыпается, если у него есть новый контент для объединения. Этим новым контентом могут быть новые буферы изображений из приложений или изменение свойств одного или нескольких слоев. Когда SurfaceFlinger пробуждает его:

  1. Обрабатывает транзакции, если они есть.
  2. Фиксирует новые графические буферы, если они есть.
  3. Выполняет новую композицию, если шаг 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 не участвует в составлении композиции.
  • СМЕШАННОЕ — графический процессор объединяет некоторые слои в кадровый буфер, а HWC объединяет кадровый буфер и оставшиеся слои, записывая непосредственно в выходной буфер.
  • HWC — HWC объединяет все слои и записывает непосредственно в выходной буфер.

Выходной формат

Форматы вывода буфера виртуального дисплея зависят от его режима:

  • Режим GLES — драйвер EGL устанавливает формат выходного буфера в dequeueBuffer() , обычно RGBA_8888 . Потребитель должен иметь возможность принять формат вывода, установленный драйвером, иначе буфер не сможет быть прочитан.
  • Режимы MIXED и HWC . Если потребителю требуется доступ к ЦП, он устанавливает формат. В противном случае используется формат IMPLEMENTATION_DEFINED , и Gralloc устанавливает лучший формат на основе флагов использования. Например, Gralloc устанавливает формат YCbCr, если потребителем является видеокодер, и HWC может эффективно записать этот формат.

Заборы синхронизации

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

Например, когда приложение отправляет буфер, создаваемый на графическом процессоре, оно также отправляет объект ограничения синхронизации. Этот забор сигнализирует, когда графический процессор завершил запись в буфер.

HWC требует, чтобы графический процессор завершил запись буферов, прежде чем буферы будут отображены. Ограждения синхронизации передаются через графический конвейер с буферами и сигнализируют о записи буферов. Перед отображением буфера HWC проверяет, подал ли сигнал барьер синхронизации, и если да, то отображает буфер.

Дополнительную информацию о границах синхронизации см. в разделе «Интеграция с Hardware Composer» .