Слои и дисплеи — это два примитива, которые представляют собой работу композиции и взаимодействие с аппаратным обеспечением дисплея.
Слои
Слой — самая важная единица композиции. Слой — это комбинация поверхности и экземпляра SurfaceControl
. Каждый слой имеет набор свойств, которые определяют, как он взаимодействует с другими слоями. Свойства слоя описаны в следующей таблице:
Свойство | Описание |
---|---|
Позиционный | Определяет, где слой отображается на дисплее. Включает информацию, такую как положение краев слоя и его Z-порядок относительно других слоев (должен ли он находиться перед другими слоями или позади них). |
Содержание | Определяет, как содержимое, отображаемое на слое, должно быть представлено в пределах, определенных позиционными свойствами. Включает такую информацию, как обрезка (для расширения части содержимого для заполнения границ слоя) и преобразование (для отображения повернутого или перевернутого содержимого). |
Состав | Определяет, как слой должен быть скомпонован с другими слоями. Включает информацию, такую как режим смешивания и альфа-значение для всего слоя для альфа-композиции . |
Оптимизация | Предоставляет информацию, которая не является строго необходимой для правильного составления слоя, но может использоваться устройством Hardware Composer (HWC) для оптимизации выполнения композиции. Включает такую информацию, как видимая область слоя и какая часть слоя была обновлена с момента предыдущего кадра. |
Дисплеи
Дисплей — еще одна важная единица композиции. Система может иметь несколько дисплеев, и дисплеи могут добавляться или удаляться во время обычных операций системы. Дисплеи добавляются или удаляются по запросу HWC или по запросу фреймворка. Устройство HWC запрашивает добавление или удаление дисплеев при подключении или отключении внешнего дисплея от устройства, что называется горячим подключением . Клиенты запрашивают виртуальные дисплеи , содержимое которых отображается во внеэкранном буфере, а не на физическом дисплее.
Виртуальные дисплеи
SurfaceFlinger поддерживает внутренний дисплей (встроенный в телефон или планшет), внешние дисплеи (например, телевизор, подключенный через HDMI) и один или несколько виртуальных дисплеев, которые делают композитный вывод доступным в системе. Виртуальные дисплеи можно использовать для записи экрана или отправки экрана по сети. Кадры, сгенерированные для виртуального дисплея, записываются в BufferQueue.
Виртуальные дисплеи могут совместно использовать тот же набор слоев, что и основной дисплей (стек слоев), или иметь свой собственный набор. Для виртуального дисплея нет VSync, поэтому VSync для внутреннего дисплея запускает композицию для всех дисплеев.
В реализациях HWC, которые их поддерживают, виртуальные дисплеи могут быть составлены с OpenGL ES (GLES), HWC или обоими GLES и HWC. В реализациях, которые не поддерживают, виртуальные дисплеи всегда составлены с использованием GLES.
Пример: запись экрана
Команда screenrecord
позволяет пользователю записывать все, что появляется на экране, в виде файла MP4 на диске. Для реализации этого система получает составные кадры от SurfaceFlinger, записывает их в видеокодер, а затем записывает закодированные видеоданные в файл. Видеокодеки управляются отдельным процессом ( mediaserver
), поэтому большие графические буферы должны перемещаться по системе. Чтобы сделать это более сложным, цель состоит в том, чтобы записывать видео 60 кадров в секунду в полном разрешении. Ключ к эффективной работе — BufferQueue.
Класс MediaCodec
позволяет приложению предоставлять данные в виде сырых байтов в буферах или через поверхность. Когда screenrecord
запрашивает доступ к видеокодеру, процесс mediaserver
создает BufferQueue, подключается к стороне потребителя, а затем передает сторону производителя обратно в screenrecord
как поверхность.
Затем утилита screenrecord
просит SurfaceFlinger создать виртуальный дисплей, который является зеркалом основного дисплея (то есть имеет все те же слои), и направляет его на отправку вывода на поверхность, полученного от процесса mediaserver
. В этом случае SurfaceFlinger является производителем буферов, а не потребителем.
После завершения настройки screenrecord
срабатывает при появлении закодированных данных. По мере отрисовки приложений их буферы передаются в SurfaceFlinger, который объединяет их в один буфер, отправляемый непосредственно видеокодеру в процессе mediaserver
. Полные кадры никогда не видны процессу screenrecord
. Внутри процесса mediaserver
есть свой собственный способ перемещения буферов, который также передает данные по дескриптору, минимизируя накладные расходы.
Пример: моделирование вторичных дисплеев
WindowManager может попросить SurfaceFlinger создать видимый слой, для которого SurfaceFlinger выступает в качестве потребителя BufferQueue. Также можно попросить SurfaceFlinger создать виртуальный дисплей, для которого SurfaceFlinger выступает в качестве производителя BufferQueue.
Если вы подключаете виртуальный дисплей к видимому слою, создается замкнутый контур, в котором составной экран отображается в окне. Теперь это окно является частью составного вывода, поэтому при следующем обновлении составное изображение внутри окна также показывает содержимое окна. Чтобы увидеть это в действии, включите параметры разработчика в настройках , выберите Имитировать вторичные дисплеи и включите окно. Чтобы увидеть вторичные дисплеи в действии, используйте screenrecord
, чтобы записать процесс включения дисплея, а затем воспроизвести его покадрово.