Surface и SurfaceHolder

Объекты Surface позволяют приложениям создавать изображения для показа на экранах. Интерфейсы SurfaceHolder позволяют приложениям редактировать поверхности и управлять ими.

Поверхность

Поверхность – это интерфейс, с помощью которого производитель обменивается буферами с потребителем.

Поверхности дисплея обычно используют BufferQueues, настроенные для тройной буферизации. Буферы выделяются по запросу, поэтому, если производитель создает буферы достаточно медленно, например с частотой 30 кадров в секунду на дисплее с частотой 60 кадров в секунду, в очереди может быть только два выделенных буфера. Выделение буферов по запросу помогает минимизировать потребление памяти. Сводку по буферам, связанным с каждым слоем, можно посмотреть в выходных данных dumpsys SurfaceFlinger.

Большинство клиентов выполняют рендеринг на поверхности с помощью OpenGL ES или Vulkan. Однако некоторые клиенты отрисовывают контент на поверхностях с помощью элемента canvas.

Отрисовка холста

Реализация холста обеспечивается графической библиотекой Skia. Если вы хотите нарисовать прямоугольник, вы вызываете Canvas API, который устанавливает байты в буфере соответствующим образом. Чтобы буфер не обновлялся двумя клиентами одновременно и не записывался во время отображения, заблокируйте буфер для доступа к нему. Для работы с блокировкой макета используйте следующие команды:

  • lockCanvas() блокирует буфер для отрисовки на ЦП и возвращает объект Canvas для рисования.
  • unlockCanvasAndPost() разблокирует буфер и отправляет его в компоновщик.
  • lockHardwareCanvas() блокирует буфер для рендеринга на графическом процессоре и возвращает холст для рисования.

Когда производитель впервые запрашивает буфер из BufferQueue, буфер выделяется и инициализируется нулем. Инициализация необходима, чтобы избежать случайной передачи данных между процессами. Однако если вы используете буфер повторно, его предыдущее содержимое сохраняется. Если вы несколько раз вызываете методы lockCanvas() и unlockCanvasAndPost(), не рисуя ничего, производитель переключается между ранее отрисованными кадрами.

Код блокировки/разблокировки поверхности сохраняет ссылку на ранее отрисованный буфер. Если при блокировке поверхности указать область, которая не должна обновляться, то пиксели из нее будут скопированы из предыдущего буфера. Обычно буфер обрабатывается SurfaceFlinger или HWC, но поскольку вам нужно только читать из буфера, нет необходимости ждать эксклюзивного доступа.

SurfaceHolder

SurfaceHolder – это интерфейс, который система использует, чтобы передавать приложениям право собственности на поверхности. Некоторым клиентам, работающим с поверхностями, требуется SurfaceHolder, поскольку API для получения и установки параметров поверхности реализованы через SurfaceHolder. SurfaceView содержит SurfaceHolder.

Большинство компонентов, взаимодействующих с представлением, используют SurfaceHolder. Некоторые другие API, например MediaCodec, работают с самой поверхностью.