В этой статье (перевод [1]) рассматриваются графические стеки операционных систем Linux - какие технологии используются для создания GUI-приложений, как они взаимодействуют с системой и друг с другом. Начнем с низкого уровня, и также рассмотрим высокоуровневый инструментарий создания GUI-интерфейса.
[Linux и его ядро]
Здесь имя "Linux" просто обозначает ядро операционной системы (Linux kernel). Т. е. подразумевается не полная операционная система, которая содержит из коробки весь набор приложений, а скорее ядро, вокруг которого все построено. Ядро служит интерфейсом между реальным оборудованием и рабочими процессами.
Если мы скомпилируем и установим ядро Linux kernel на машине вместе со вспомогательными инструментами и утилитами, то мы можем получить очень примитивную графику через настройку режима ядра (Kernel Mode Setting) в виртуальном терминале, но не сложную графику, такую как окна программ, визуальные эффекты, и изображения с красивыми градиентами. Чтобы работать в Linux со сложной графикой, понадобится полный графический стек, включая драйверы графики, обертки API-вызовов графики, система окон, компоновщик (compositor) и многое другое.
Таким образом, в большинстве операционных систем, основанных на Linux, таких как Ubuntu, Debian и openSUSE, графический стек уже упакован в их дистрибутивы. Поэтому у нас есть доступ к графическому окружению из коробки. Однако на некоторых операционных системах, таких как Arch, LFS, Gentoo или Alpine, нам нужно вручную сконфигурировать стек, чтобы получить доступ к графическим функциям.
Подводя итог: в Linux нет традиционного GUI или встроенной стандартизированной библиотеки, через которую мы могли бы разработать GUI-программы. Тем не менее у нас есть доступ к множеству сторонних библиотек, наборов инструментария GUI, драйверов и пакетов, через которые мы можем получить доступ к графической системе.
[Graphics API]
Graphics API отвечает за трансляцию определенного набора инструкций, наподобие рисования треугольника, в более специфичный код, который может выполнить процессор графики (GPU). Таким образом graphics API это описание, как код разработчика может общаться с GPU.
Существует несколько популярных API, таких как OpenGL, OpenGL ES, Metal, Direct3D и Vulkan. Однако большинство графических стеков интенсивно используют библиотеку OpenGL, потому что она бесплатна и кроссплатформенна.
OpenGL API. OpenGL означает "Open Graphics Library". Это набор спецификаций, связанных исключительно с аппаратным ускорением рендеринга 2D и 3D графики, независимо от платформы. Традиционный язык OpenGL - язык C, однако есть привязки и для других языков, таких как Java, Golang и Rust.
Если быть точным, OpenGL не совсем библиотека, потому что каждый поставщик должен реализовать спецификацию для создания библиотеки OpenGL. Таким образом, на дистрибутивах Linux двоичный файл библиотеки libGL.so будет отличаться для разных вендоров. Дополнительно существуют несколько реализаций спецификации OpenGL, включая проприетарные сторонние (third-party) и открытые (open-source) решения.
Mesa. Mesa это open-source реализация OpenGL API и Vulkan. Она использует драйверы видеокарты для транслирования своего API в форму, специфичную для аппаратуры видеокарты. Дополнительно Mesa поддерживает архитектуру Gallium3D для построения 3D-драйверов графики, которые позволяют реализовать портируемость для всех основных операционных систем.
Современные серверы экрана и оконные менеджеры наподобие X.Org и Wayland используют OpenGL внутри себя, так что вся графика проходит через Mesa.
GLES. GLES обозначает OpenGL Embedded System. Это профиль OpenGL, предназначенный для встраиваемых устройств (embedded devices), таких как телефоны Android и iPhone.
GLX и WGL. Как упоминалось выше, библиотека OpenGL занимается только рисованием 2D и 3D графики, и у неё нет концепции управления окнами. По этой причине нужен какой-то способ привязки сцены OpenGL к окну приложения. GLX является расширением X Window System, которое предоставляет интерфейс между сценой OpenGL и X Window System.
Подобно GLX, WGL это интерфейс для OpenGL и традиционная система окон Microsoft Windows.
EGL и GLUT. EGL это платформонезависимое API, предоставляющее интерфейс для OpenGL и традиционной системе окон операционной системы. Это API не зависит от GLX или WGL, но вместо этого полагается на то, что вендоры реализуют его спецификацию.
В отличие от EGL, GLUT работает оберткой вокруг GLX и WGL, позволяя нам писать портируемые графические приложения.
fglrx и Catalyst. Catalyst это драйвер Xorg OpenGL от AMD, который известен под именем fglrx. Это проприетарный драйвер для X.Org, и в нем есть собственная реализация спецификации OpenGL.
[DRM и DRI]
И OpenGL, и window system реализуют части ПО, которые относятся к рисованию объектов на экране. Таким образом, они генерируют набор специфических для видеокарты инструкций, которые ядро Linux обрабатывает через Direct Rendering Manager (DRM).
На Linux для этого у нас есть библиотека libdrm, которая упрощает доступ к DRM на операционной системе. DRM использует набор традиционных системных вызовов ioctl для выделения памяти под графические объекты и данные для команд и текстур. Система ioctl это специальный тип системных вызовов, которые обрабатывают специфические для устройства операции ввода и вывода. В нашем случае операции ввода и вывода происходят с видеокартой.
Так что когда мы запускаем графическое приложение, оно загружает драйвер OpenGL - например Mesa. Драйвер в свою очередь загружает libdrm, которая разрешает прямое общение с ядром через ioctl. Так продолжается, пока работает графическое приложение. Однако нам нужен способ, с помощью которого window system, такая как X Server, узнает о событиях окна, чтобы выполнить синхронизацию и обновление графического интерфейса. Этот процесс синхронизации известен как Direct Rendering Infrastructure (DRI).
KMS. Графические приложения хорошо работают, когда у нас есть работающий X Server, или compositor. Как насчет графики, которая работает помимо X Server, наподобие виртуального терминала или заставки загрузки (splash screen)? Здесь вводится в действие подсистема Kernel Mode Settings (KMS).
KMS это подсистема в ядре Linux и libdrm, которая позволяет напрямую конфигурировать реальное оборудование через ioctls. По этой причине нам не нужно полагаться на X Server. Однако следует иметь в виду, что KMS очень низкоуровневая подсистема, и она должна использоваться только в том случае, когда не могут быть запущены графический сервер или compositor.
[X Window System]
X Window System это open-source система поддержки окон приложений, используемая в большинстве дистрибутивов Linux. Она работает по принципу архитектуры клиент-сервер, которая обеспечивает прозрачный для сетевого обмена способ взаимодействия с окнами, и по этой причине может с успехом использоваться в удаленных окружениях.
X Window System не только представляет фундаментальный фреймворк для GUI-окружений, но также поддерживает обработку событий и визуальные эффекты.
X11. Поскольку X Window System основана на архитектуре клиент-сервер, она не требует, чтобы клиент и сервер работали на одной и той же машине. Поэтому нам нужен протокол, который переносит сообщения между клиентом и сервером. Протокол X11 как раз отвечает за доставку таких сообщений. Когда клиент и сервер работают на одной и той же машине, обмен сообщениями осуществляется через сокеты Юникс (UNIX sockets).
Кроме того, протокол X11 является расширяемым. Так что в него можно просто добавить новые функции без создания нового протокола и нарушения работы существующих клиентов. Одно из наиболее полезных расширений - XRender, который добавляет поддержку технологии сглаживания при рисовании (anti-aliased drawings).
Xlib и XCB. X Library, или Xlib, это реализация на стороне клиента X Window System. Эта библиотека, в свою очередь, используется графическим инструментарием наподобие GTK+ и QT, чтобы создавать графический фронтэнд для программных приложений.
XCB, или X C-language Binding также реализация на стороне клиента X Window System. Однако она более низкоуровневая, чем Xlib, и части Xlib используют XCB для некоторых функций.
X.Org Server. X.Org это реализация X Window System на стороне сервера. Это наиболее часто используемый сервер экрана на системах семейства Unix. X.Org Server обычно запускается менеджером экрана (display manager) или вручную из виртуального терминала.
[Cairo]
Cairo это библиотека для рисования, которая имеет дело только с векторной графикой. В ней реализован практически тот же API, что и в HTML5 < canvas>. Дополнительно Cairo поддерживает рисование поверхностей (surfaces) X11 через Xlib backend.
Хотя мы можем использовать Cairo напрямую, однако она главным образом используется в инструментарии рисования наподобие GTK+. Она также поддерживает генерацию изображений через OpenGL.
Pixman. И X-сервер, и Cairo каждый имеет свою собственную реализацию для манипуляции пикселями, в результате получается раздутый код. Чтобы решить эту проблему, был разработан Pixman. Это Pixman общая библиотека для X server и Cairo, которая предоставляет алгоритмы растеризации, поддержку градиентов и другие функции.
[Compositor]
Compositor эта программа, которая представляет внутренний (off-screen) буфер для каждого окна на экране. Этот буфер также известен как Composite Overlay Window или COW, и им манипулирует compositor. Таким образом, compositor может применить дополнительную стилизацию, такую как тени, прозрачность и градиенты. Но это не все, также может предоставляться вертикальная синхронизация и помощь в решении проблемы плавного перетаскивания окон (tear-free experience).
Каждый кадр работающего окна проходит через compositor. Compositor захватывает матрицу точек окна из X server, и рисует её на OpenGL сцене.
[Wayland]
Хотя X все еще остается функциональным и стабильным, у него все же есть некоторые проблемы. Во-первых, он его дизайн небезопасен, поскольку использует прозрачный сетевой обмен данными. Таким образом, полезная нагрузка трафика может подвергнуться сниффингу. Во-вторых, его очень старая подсистема окон слишком сильно полагается на расширения, и части его функционала были портированы в ядро Linux.
Wayland это новая замена для X. Wayland не полагается на архитектуру клиент-сервер. Так, вместо того, чтобы полагаться на сервер, он работает как window manager или compositor для графических приложений, чтобы обрабатывать событий через evdev и отображать окна тот же самый стек. Протокол Wayland также основа на сокетах UNIX.
Wayland-клиент запрашивает буфер у приложения compositor, и рисует в нем с помощью OpenGL, Cairo, или любого другого модуля для рендеринга. Compositor может легко манипулировать буфером для создания визуальных эффектов перед передачей его клиенту. Таким образом compositor работает как сервер и компоновщик.
XWayland. XWayland предоставляет X Server, который работает под Wayland. Поэтому это пакет совместимости для X-приложений при их переводе под Wayland. Однако он добавляет дополнительный слой между X-клиентом и X-сервером, поскольку сообщения передаются через Wayland compositor.
[GUI тулкиты]
GUI toolkit или GUI-библиотека содержит функционал, необходимый для создания графических интерфейсов и таких элементов, как виджеты, сцены и обработчики событий. Некоторые GUI toolkit-ы представляют собой полнофункциональные фреймворки, предоставляющие виджеты, инструменты для визуального дизайна GUI и среду разработки.
Библиотека GUI toolkit обычно это обертка вокруг низкоуровневой библиотеки, такой как Xlib или XCB. Таким образом, она упрощает для нас разработку графических приложений с дополнительной стилизацией и расширенным поведением.
Кроме того, многие зрелые GUI toolkit-ы обладают продуманным дизайном. Другими словами, в них реализован свои собственные языки разметки, системы событий и машины состояний. Машина состояний отвечает за обслуживание сложных программ, которые носят реактивный характер.
Существует несколько GUI-тулкитов, каждый из них со своей областью применения. Наиболее популярны сегодня GTK+, Qt, wxWidgets, FLTK и imgui.
GTK+. GTK+ или GIMP Toolkit это тулкит для операционных систем линейки Unix, которые используют X Window System и Wayland. В этих системах имеется стабильный GUI-тулкит для сборки кроссплатформенных и современных GUI-приложений. Некоторые самые популярные GUI-программы разработаны с помощью GTK, включая GIMP, Mozilla Firefox, GNOME Desktop Environment, Inkscape и Pidgin.
В GTK toolkit встроены также подсистемы бэкэндов, такие как GDI для Windows и Quartz для macOS, так что мы можем разрабатывать программы и для других платформ. Кроме того, существуют независимые проекты, которые предоставляют дополнительные программы для упрощения разработки GTK-программ. Один из таких проектов Glade. Glade предоставляет графический интерфейс для упрощения разработки фронтэнда программы. Некоторые проекты наподобие Firefox имеют свой собственный адаптированный форк GTK.
Хотя GTK toolkit изначально был рассчитан на язык C, в нем также есть привязки для других языков, такие как GTKmm для C++, PyGObject для Python и gotk3 для Golang.
Qt. Это широко известный кроссплатформенный фреймворк разработки, который предоставляет библиотеку виджетов и полный набор дополнительного функционала. В отличие от GTK, в Qt есть свой собственный инструмент разработки, который называется QtDesigner, и интегрированная среда программирования, которая называется QtCreator.
Дополнительно Qt имеет собственную реализацию сетей, web-сокетов, мультимедийных функций, SQL, XML и web engine. Программы Qt довольно легко портируются между платформами с минимальной модификацией исходного кода. Таким образом, этот тулкит является подходящим выбором для встраиваемых систем и десктопов.
Фреймворк Qt досконально реализован на языке C++. Однако также есть привязки для других языков. В Qt реализован собственный язык разметки QML (Qt markup language), который синтаксически подобен CSS. По этой причине QML мощное средство для гибкой настройки виджетов под любой вкус.
Некоторые популярные приложения написанные на Qt: Autodesk Maya, Autodesk 3ds Max, Crytek CryEngine, DaVinci Resolve и K Desktop Environment (KDE).
[Роль OpenGL]
Из всего вышесказанного можно сделать вывод, что нет официального нативного инструментария или библиотеки GUI, которая является серебряной пулей для разработки GUI-приложения под Linux. Каждый модуль в графическом стеке служит уникальной цели.
По большей части все графические стеки проводят свои операции через OpenGL. Поэтому можно с уверенностью сказать, что можно разрабатывать свое автономное приложение исключительно на основе OpenGL. Так что OpenGL можно считать неким нативным инструментом для разработки графических приложений на Linux.
В качестве примера можно привести Blender, который является кроссплатформенным инструментом для 3D-моделирования и анимации. Blender не полагается на другие тулкиты GUI и низкоуровневые приложения клиента, но в нем реализована собственная библиотека виджетов, полностью основанная на OpenGL.
[Ссылки]
1. GUI Under Linux site:baeldung.com. 2. ncurses site:wikipedia.org. |