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

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

Слои

Слой — важнейшая единица композиции. Слой — это комбинация поверхности и экземпляра 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 , чтобы запечатлеть процесс включения дисплея, а затем воспроизвести его покадрово.