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

HAL-интерфейс Hardware Composer (HWC) компонует слои, полученные от 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. Например, для создания слоя SurfaceFlinger вызывает createLayer() в Composer HAL.

Если поставщики реализуют интерфейс hwcomposer2.h , Composer HAL вызывает указатели на функции hwcomposer2.h . В комментариях hwcomposer2.h функции интерфейса HWC упоминаются с помощью имен в нижнем регистре (lowerCamelCase), которые не существуют в интерфейсе в качестве именованных полей. Практически каждая функция загружается путем запроса указателя на функцию с помощью getFunction предоставляемой типом hwc2_device_t . Например, функция createLayer представляет собой указатель на функцию типа HWC2_PFN_CREATE_LAYER , который возвращается, когда в getFunction передается перечисляемое значение HWC2_FUNCTION_CREATE_LAYER .

Подробную документацию по функциям 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 создает дескриптор и компонует дисплей.

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

При каждом включении 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/blitter или наложения, если конвейер отображения записывает данные в память.

Режимы

После вызова метода HWC validateDisplay() SurfaceFlinger каждый кадр находится в одном из трех режимов:

  • GLES — Графический процессор выполняет компоновку всех слоев, записывая данные непосредственно в выходной буфер. HWC не участвует в компоновке.
  • СМЕШАННЫЙ РЕЖИМ — Графический процессор объединяет некоторые слои в буфер кадров, а HWC объединяет буфер кадров и оставшиеся слои, записывая данные непосредственно в выходной буфер.
  • HWC — HWC объединяет все слои и записывает данные непосредственно в выходной буфер.

Формат вывода

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

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

Ограждения синхронизации

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

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

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

Для получения дополнительной информации о синхронизационных барьерах см. раздел «Интеграция с аппаратным Composer» .