Поверхность и держатель поверхности

Объекты 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, работают непосредственно с поверхностью.