Слои и дисплеи

Слои и дисплеи — это два основных элемента, представляющих собой элементы композиции и взаимодействия с аппаратным обеспечением дисплея.

Слои

Слой — это важнейшая единица композиции. Слой представляет собой комбинацию поверхности и экземпляра SurfaceControl . Каждый слой имеет набор свойств, определяющих его взаимодействие с другими слоями. Свойства слоя описаны в следующей таблице:

Свойство Описание
Позиционный Определяет положение слоя на экране. Включает такую ​​информацию, как положение ребер слоя и его Z-порядок относительно других слоев (должен ли он находиться перед другими слоями или за ними).
Содержание Определяет, как содержимое слоя отображается в пределах границ, заданных позиционными свойствами. Это включает в себя обрезку (для расширения содержимого до размеров слоя) и трансформацию (для отображения повернутого или отраженного содержимого).
Композиция Определяет способ компоновки слоя с другими слоями. Включает такую ​​информацию, как режим наложения и значение альфа-канала для всего слоя при альфа-композиции .
Оптимизация Предоставляет информацию, которая не является строго необходимой для правильного компоновочного процесса слоя, но которую устройство Hardware Composer (HWC) может использовать для оптимизации производительности компоновки. Сюда входит видимая область слоя и часть, обновленная с момента предыдущего кадра.

Дисплеи

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

Устройство HWC запрашивает добавление или удаление дисплеев при подключении или отключении внешнего дисплея от устройства, что называется «горячим подключением» . Клиенты запрашивают виртуальные дисплеи , содержимое которых отображается в буфере за пределами экрана, а не на физическом дисплее.

Виртуальные дисплеи

SurfaceFlinger поддерживает внутренний дисплей (встроенный в телефон или планшет), внешние дисплеи (например, телевизор, подключенный через HDMI) и один или несколько виртуальных дисплеев, обеспечивающих композитный вывод изображения внутри системы. Виртуальные дисплеи можно использовать для записи экрана или передачи изображения по сети. Кадры, созданные для виртуального дисплея, записываются в BufferQueue.

Виртуальные дисплеи могут использовать тот же набор слоев, что и основной дисплей (стек слоев), или иметь свой собственный набор. Для виртуального дисплея отсутствует функция VSync, поэтому включение VSync для внутреннего дисплея запускает композицию для всех дисплеев.

В реализациях HWC, поддерживающих виртуальные дисплеи, их можно комбинировать с OpenGL ES (GLES), HWC или с обоими протоколами одновременно. В реализациях, не поддерживающих эту технологию, виртуальные дисплеи всегда комбинируются с использованием GLES.

Пример из практики: запись экрана

Команда screenrecord позволяет пользователю записывать все, что отображается на экране, в файл MP4 на диск. Для этого система получает скомпонованные кадры от SurfaceFlinger, записывает их в видеокодер, а затем записывает закодированные видеоданные в файл. Видеокодеки управляются отдельным процессом ( mediaserver ), поэтому большие графические буферы должны перемещаться по системе. Чтобы усложнить задачу, цель состоит в записи видео с частотой 60 кадров в секунду в полном разрешении. Ключ к эффективной работе — BufferQueue.

Класс MediaCodec позволяет приложению предоставлять данные в виде необработанных байтов в буферах или через интерфейс. Когда screenrecord запрашивает доступ к видеокодеру, процесс mediaserver создает BufferQueue, подключается к стороне потребителя, а затем передает сторону производителя обратно в screenrecord в виде интерфейса.

Затем утилита screenrecord запрашивает у SurfaceFlinger создание виртуального дисплея, который дублирует основной дисплей (то есть, имеет все те же слои), и направляет его на отправку на поверхность выходных данных, полученных от процесса mediaserver . В этом случае SurfaceFlinger является производителем буферов, а не их потребителем.

После завершения настройки screenrecord запускается, когда появляются закодированные данные. По мере отрисовки приложения их буферы передаются в SurfaceFlinger, который объединяет их в один буфер, отправляемый непосредственно видеокодеру в процессе mediaserver . Полные кадры никогда не видны процессу screenrecord . Внутри процесса mediaserver используется собственный способ перемещения буферов, который также передает данные по дескриптору, минимизируя накладные расходы.

Пример из практики: моделирование дополнительных дисплеев

Менеджер окон может запросить у SurfaceFlinger создание видимого слоя, для которого SurfaceFlinger будет выступать в качестве потребителя BufferQueue. Также можно запросить у SurfaceFlinger создание виртуального дисплея, для которого SurfaceFlinger будет выступать в качестве производителя BufferQueue.

Если подключить виртуальный дисплей к видимому слою, создаётся замкнутый цикл, в котором скомпонованный экран отображается в окне. Это окно теперь является частью скомпонованного вывода, поэтому при следующем обновлении скомпонованное изображение внутри окна также будет отображать содержимое окна. Чтобы увидеть это в действии, включите параметры разработчика в настройках , выберите «Имитировать дополнительные дисплеи» и включите окно. Чтобы увидеть работу дополнительных дисплеев, используйте screenrecord , чтобы запечатлеть момент включения дисплея, а затем воспроизведите его покадрово.