Объекты Surface позволяют приложениям визуализировать изображения для отображения на экранах. Интерфейсы SurfaceHolder позволяют приложениям редактировать и управлять поверхностями.
Поверхность
Поверхность — это интерфейс, позволяющий производителю обмениваться буферами с потребителем.
Поверхности отображения обычно используют очереди BufferQueues, настроенные на тройную буферизацию. Буферы выделяются по требованию, поэтому, если производитель генерирует буферы достаточно медленно, например, с частотой 30 кадров/с на дисплее с частотой 60 кадров/с, в очереди может быть всего два выделенных буфера. Выделение буферов по требованию помогает минимизировать потребление памяти. Сводку по буферам, связанным с каждым слоем, можно увидеть в выходных данных dumpsys SurfaceFlinger
.
Большинство клиентов выполняют рендеринг на поверхности с помощью OpenGL ES или Vulkan . Однако некоторые клиенты выполняют рендеринг на поверхности с помощью холста.
Рендеринг холста
Библиотека Skia Graphics предоставляет реализацию холста. Если вы хотите нарисовать прямоугольник, вы вызываете API Canvas, который соответствующим образом устанавливает байты в буфере. Чтобы предотвратить одновременное обновление буфера двумя клиентами или запись в него во время отображения, заблокируйте доступ к буферу. Для работы с блокировками холста используйте следующие команды:
-
lockCanvas()
блокирует буфер для рендеринга на ЦП и возвращает Canvas, который можно использовать для рисования. -
unlockCanvasAndPost()
разблокирует буфер и отправляет его компоновщику. -
lockHardwareCanvas()
блокирует буфер для рендеринга на графическом процессоре и возвращает холст, который можно использовать для рисования.
При первом запросе буфера из BufferQueue производитель выделяет буфер и инициализирует его нулем. Инициализация необходима для предотвращения непреднамеренного обмена данными между процессами. Однако при повторном использовании буфера его предыдущее содержимое сохраняется. Если многократно вызывать lockCanvas()
и unlockCanvasAndPost()
без отрисовки, производитель циклически переключается между ранее отрисованными кадрами.
Код блокировки/разблокировки поверхности сохраняет ссылку на ранее отрисованный буфер. Если при блокировке поверхности указать «грязную» область, она скопирует неизменённые пиксели из предыдущего буфера. Обычно буфером управляют SurfaceFlinger или HWC; но поскольку требуется только чтение из буфера, ждать монопольного доступа не нужно.
SurfaceHolder
SurfaceHolder — это интерфейс, который система использует для совместного использования поверхностей с приложениями. Некоторым клиентам, работающим с поверхностями, необходим SurfaceHolder, поскольку API для получения и установки параметров поверхностей реализованы через SurfaceHolder. SurfaceView содержит SurfaceHolder.
Большинство компонентов, взаимодействующих с представлением, используют SurfaceHolder. Некоторые другие API, например, MediaCodec, работают непосредственно с поверхностью.