Что такое иксы в linux
Что такое иксы в linux
И последнее, о чем следует знать, — это о текстовом (консольном) и графическом режимах работы. Ибо непонимание их отличий является источником множества недоразумений, связанных, например, с поддержкой видеокарт, различием клавиатурных раскладок в консоли и в Иксах, и так далее.
Так вот, Linux изначально предназначался для работы в текстовом режиме. В коем и поддерживает все видеокарты, соответствующие стандарту VESA — то есть все, изготовленные человечеством за последние полтора десятка лет. Правда, в ядре его есть и поддержка собственно графического режима — через так называемый линейный кадровый буфер(frame buffer). Однако программ, использующих такой режим, очень немного.
Основным же способом вывода графики в Linux является оконная система X (X Window System) или, в просторечии, Иксы. Это — не часть Linux’а, а именно самостоятельная система, предназначенная для работы поверх любых Unix-подобных операционок (и не только их). Тем не менее, она стандартно входит во все дистрибутивы Linux общего назначения, за исключением специализированных (например, сугубо серверных). И часто устанавливается по умолчанию.
Установить Иксы мало — их нужно еще и должным образом настроить. В понятие это входит определение видеокарты, характеристик монитора, мыши, установка экранного разрешения, и так далее. С большинством вопросов, касающихся распознавания «железа», успешно справляются инсталляторы юзерофильных дистрибутивов, и соответствующие параметры устанавливаются автоматически (хотя тут часто допустимы и ручные коррективы). А вот доведение до конца локализации предоставляется пользователю: он может указать желаемую клавиатурную раскладку (например, русскую), ее вариант (в современных условиях обычно winkeys — для Windows-маркированных клавиатур), переключатель с латиницы на кириллицу, и так далее.
В некоторых дистрибутивах (Gentoo, Archlinux) автоматическая настройка Иксов при первичной инсталляции не предусмотрена. В этом случае пользователю придется выполнить ее самому. Впрочем, современные средства автоконфигурирования в Иксах делают этот процесс не очень сложным, хотя и требующим ручной доводки (в отношении экранных шрифтов и клавиатурных раскладок).
Однако и настройкой Иксов дело не заканчивается. Так как сама по себе оконная система X не способна выполнить никакие пользовательские задачи. Для этого она требует специальной программы — менеджера окон или интегрированной рабочей среды (так называемого пользовательского десктопа). Выбор таковых развитые инсталляторы также предоставляют пользователю.
И, наконец, последнее. Традиционный способ авторизации в Linux — задание логина и пароля в текстовом режиме. После чего Иксы можно (и обычно — нужно) запустить вручную специальной командой. Однако возможна и автоматическая загрузка Иксов при старте системы — и сейчас в юзерофильных дистрибутивах именно это, как правило, и практикуется. В этом случае авторизация происходит посредством специальной программы — десктоп-менеджера. Который, помимо всего прочего, позволяет обычно выбрать менеджер окон или интегрированную среду.
Что придет на замену X Window System?
Одним из знаменательных Linux событий прошлого года стал выход 25-й Федоры с графическим окружением Gnome 3.22 на базе дисплейного сервера Wayland, который призван заменить X Window System. Но зачем вообще после стольких лет возникла такая необходимость?
В последнее время экипаж МКС пересел с Windows на Linux.
— Хьюстон, у нас проблемы. Нас сносит на Юпитер.
— Вы что, опять возились с xorg.conf?
— Да. Хьюстон, за три последних дня у нас почему-то выросли бороды.
Далее, речь о том, почему Linux необходима новая графическая среда, хотя бы в 2017 г, а отдельным постом я расскажу про Wayland и Mir.
Номенклатура X
Я уверен, что вы уже прочитали статью Хабрапост про графический стек Linux, а также страницу на Вики и теперь можете уверенно двигаться дальше. Ну, а если пока оставили в закладках, позвольте вкратце напомнить.
Графическая подсистема X.Org Server состоит из двух частей.
Еще немного тезауруса о технологиях, благодаря которым современное графическое окружение Linux держит свою марку.
Mesa — Реализация OpenGL, OpenCL и Vulkan API для Linux и Unix, включающая в себя как программные библиотеки, так и набор драйверов видеокарт. Mesa имеет и умеет много чего, но в основном это открытая реализация OpenGL API, для трансляции которого в исполнительные команды используются программные:
lvmpipe — может и быстрый,
и аппаратные бэкенды с помощью открытых драйверов intel, radeon и noveau.
Всемогущий X
Программирование на X — это как чтение французских философов, после этого начинаешь задаваться вопросом: что я на самом деле знаю?
Томас Турман.
Кому на сегодняшний день позарез нужны иксы? В Android телефонах, телевизорах, планшетах X Windows System не используется, Хромбуки тоже как-то без них обходятся. Значит речь идет только о Linux / Unix рабочих станциях, в основном по той причине, что тулкиты GTK+ и QT, долгое время не могли обходиться без X.
В этом году X11 исполняется 30 лет. Секрет живучести X Window System в следующих принципах, сформулированных в 1996 г.
Сочетание этих принципов позволило X11 быть невероятно гибким и масштабируемым решением для столь разных графических оболочек Unix в течении долгого времени. Особенное место занимает последний — обеспечить механизм, для того, чтобы X-клиент смог реализовать все свои затеи. Обратной стороной такой всеядности и живучести стало невероятное нагромождение устаревших стандартов, методов и технологий. Можно вспомнить сервер шрифтов вместе с XLFD или движок для отрисовки многоугольников и разноцветных полос.
Изначально X был государством в государстве и подменял собой множество функции ядра ОС:
X.Org и принуждение к миру
Некоторое время всех все устраивало, программисты ваяли стильные приложения, примерно такие.
Затем внезапно устройства стали более быстрыми, мощными и сложными: несколько GPU, мониторов, разношерстые устройства ввода. Рендеринг также стал более сложным, появился OpenGL. X Window system стала обрастать расширениями, однако ядро протокола по политическим мотивам осталось нетронутым. На все недостатки находились обходные пути, и пошло и поехало… BIOS видеокарты, порты I/O, подсистема питания. И всем этим хозяйством X управлял из рук вон плохо, превратившись в ОС внутри ОС, причем достаточно паршивую ОС.
Стало понятно, что иксы нужно менять, но в этот момент начались дрязги и пляски вокруг лицензии xfree86. После того, как страсти по лицензиям утихли, произошло размежевание иксовых разработчиков и основная их масса выбрала X.Org со свободной лицензией GPL. Работа снова закипела.
Какие-же функции остались за X сервером после всех этих трансформаций? В принципе не так уж много. По сути основная работа иксов состоит в том, чтобы посредничать между X-клиентом и WM — оконным менеджером. Клиентская программа рисует фрейм, X сервер передает данные WM, который рендерит кадр, определяет местоположение окна и передает обратно серверу, который показывает готовый результат. Основную работу сейчас делает именно WM, и напрашивается вопрос. А что случится, если мы уберем посредника? Ответ — Wayland.
Точно так-же при обновлении содержимого экрана иксы не при делах. Приложение рисует что-то, данные через DRI попадают в область off-screen buffer памяти видеокарты. Приложение затем оповещает сервер о том, что буфер изменился, а X-сервер передает это сообщение WM, и тот через DRI рисует новую картинку.
Помимо этого остаются архитектурные ограничения, которые невозможно обойти, не ломая совместимость с древними Motif приложениями. Да-да, не смейтесь, несколько лет назад я сам с такими работал и даже сопровождал. К таким ограничениям относится ужасный IPC, полный захват устройств ввода, в результате чего скринсейвер не запускается при открытом меню, кнопки управления звуком блокированы скринсейвером и pop-up сообщениями. Дерганое изображение, неравномерная отрисовка, артефакты обновления, это все никуда не денется, как бы ни старались иксовые программисты, а они стараются все меньше и все больше перестраиваются на Wayland. Ах, да и еще имманентное состояние гонки.
Состояние гонки
В силу своей асинхронности X11 предрасположен создавать состояние гонки между событиями X-клиента или между быстрым и мертвым тормознутым X-клиентом. Возьмем простейший случай: пользователь щелчком левой кнопки мыши вызывает меню приложения, затем отпускает кнопку и приложение при наведения курсора выполняет определенное действие. Покажем последовательность событий на диаграмме Фейнмана.
На диаграмме видно, что произойдет, если пользователь отпустит левую клавишу раньше события 4. Если натренированный на действие пользователь заранее переместился на место предполагаемого пункта меню до того момента, пока там возникло новое окно, то тогда произойдет состояние гонки mouse ahead. Событие ButtonRelease придется на еще не занятую новым окном область экрана. Это вполне вероятно на удаленных X-сессиях по медленной сети.
Промежуточные итоги
Тридцать лет тому назад Unix сервера и рабочие станции благодаря X Window System получили унифицированную графическую среду, что было довольно прогрессивным и важным шагом для ИТ индустрии. Кто сейчас восхищается давнишними конкурентами — Sun NeWS, Amiga, или ругает их? Тогда иксы обошли их во за счет кросс-платформенности, возможности запускать приложения поверх TCP/IP, что было сравнимо с http доступом для веб приложений сегодня.
Вместе с тем создатели иксов явно где-то перемудрили. Принцип обеспечения механизмов, но не политики впоследствии сыграл злую шутку с экосистемой X и она обросла всем тем, чем обросла. За десятилетия ландшафт компьютеров, устройств и ПО радикально изменился, а X Window System проникла на лаптопы и даже смартфоны Нокиа. До сих пор разработчикам вполне удавалось держать проект на плаву, благодаря миграции значительной части функционала в ядро. Этот ресурс уже тоже исчерпан, и в силу вступил неумолимый закон убывающей отдачи. Наконец-то есть возможность начать с чистого листа, догнать и перегнать тренд, вместо того, чтобы плестись за ним. Я также связываю с этим давно обещанный прорыв Linux на десктопы. Закономерность или случайность, но Linux имеет полное доминирование на устройствах, где нет X сервера.
Немного обо всем и все о немногом, или практический опыт системного администратора.
Пн | Вт | Ср | Чт | Пт | Сб | Вс |
---|---|---|---|---|---|---|
« Янв | Март » | |||||
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
Графическая подсистема в Linux называется X Window System. Разрабатывалась она изначально как модель клиент/сервер, поэтому и состоит из двух частей: сервера и клиента. В роли сервера выступает процесс X-server, а в роли клиентов графические приложения. Клиент и сервер общаются между собой по правилам описанным в X-протоколе. Собственно сам X-сервер и состоит из двух больших частей: это набор драйверов для работы с устройствами ввода-вывода и X-протокол для работы с приложениями.
Сейчас важно понять, что с устройствами ввода (клавиатурой, мышью и другими) и устройствами вывода (видеоадаптеры, мониторы и прочие) взаимодействует именно X-сервер, а не приложения. Мы не будет углубляться в подробности X-протокола и тонкости взаимодействия всех компонентов. Отметим себе, что X-сервер взаимодействует с приложениями при помощи механизма unix-сокетов и internet-сокетов. Возможность взаимодействия через internet-сокеты позволяет X-серверу и клиенту работать в связке находясь на разных компьютерах объединенных в сеть.
Попробуем выполнить несколько практических упражнений, которые помогут разобраться с основами взаимодействия X-сервера и приложений. Как правило на рабочей станции уже запущен один экземпляр X-сервера. Запустим еще один экземпляр командой (команда должна запускаться от имени суперпользователя):
В результате на одной из виртуальных консолей будет запущен экземпляр X-сервера. На этой консоли вы увидите черный (либо серый) экран с крестиком вместо указателя мыши. Теперь перейдите на свободную консоль и наберите команду:
Перейдите на консоль в которой запущен X-сервер. Вы должны увидеть в левом верхнем углу аналоговые часы. Программа xclock в данном примере является клиентом для X-сервера. С помощью ключа -display мы указали программе с каким X-сервером ей нужно взаимодействовать, то есть какой X-сервер выведет на устройство вывода (монитор) изображение программы xclock.
Вернемся к нашим часам на втором экземпляре X-сервера. Вы видите что у программы нет привычной окантовки окна с кнопками свернуть, развернуть, закрыть. Дело в том, что их рисует не X-сервер, а другой процесс, который называется менеджер окон. Менеджер окон также занимается масштабированием и перемещением изображения программ. Такое разделение функций также повышает гибкость всей графической подсистемы X Window. Так как вы можете выбирать какой менеджер окон использовать для прорисовки рамок приложений.
Чтобы на нашем втором экземпляре X-сервера запустить менеджер окон по умолчанию выполните команду x-window-manager –display=0:1 и снова вернитесь на консоль где запущен второй X-сервер. Теперь вы видите вокруг часов привычную рамку и верхнюю полоску окна с тремя привычными кнопками. Окно можно масштабировать и перемещать по экрану, используя “мышь”, а также закрыть его нажав на привычный “крестик”.
Как уже было сказано, X-сервер работает с устройствами ввода/вывода информации. Основной конфигурационный файл в котором хранятся настройки X-сервера называется /etc/X11/xorg.conf. Хотя во многих современных настольных дистрибутивах этот файл пустой, так как за настройку оборудования отвечает другая подсистема, тем не менее X-сервер продолжает читать конфигурацию из этого файла. Рассмотрим этот файл, так как возможны ситуации когда параметры ваших устройств ввода/вывода будут автоматически определяться некорректно и тогда ручная правка файла /etc/X11/xorg.conf может помочь решить проблему.
Файл /etc/X11/xorg.conf разбит на секции при помощи ключевых слов section и end section. Рассмотрим наиболее важные секции.
В секции “ServerFlags” указываются опции с которыми запускается X-сервер:
В секции “Files” указываются пути к файлам которые могут понадобиться в работе X-сервера. Например, здесь указываются путь к шрифтам X-сервера. Причем путь может указывать на другой компьютер в сети на котором установлен XFS (X Font Server):
В секции “Modules” указываются модули, которые будут подгружаться во время загрузки X-сервера:
Секция “InputDevice“. Таких секций может быть несколько и отличаются они уникальным идентификатором (Identifier). Одна секция “Input Device” отвечает за одно устройство ввода. То есть в настольных компьютерах есть как минимум две такие секции: одна для описания клавиатуры, и одна для описания манипулятора “мышь”.
Section «InputDevice»
Identifier «Generic Keyboard»
Driver «kbd»
Option «CoreKeyboard»
Option «XkbRules» «xorg»
Option «XkbModel» «pc104»
Option «XkbLayout» «us»
EndSection
Section «InputDevice»
Identifier «Configured Mouse»
Driver «mouse»
Option «CorePointer»
Option «Device» «/dev/input/mice»
Option «Protocol» «ImPS/2»
Option «Emulate3Buttons» «true»
EndSection
Небольшое замечание к секции “InputDevice” для клавиатуры. Именно в этой секции определяются раскладки клавиатуры для графического окружения. Обращаю на это ваше внимание, так как для алфавитно-цифрового режима (виртуальные консоли, например) раскладку поддерживает драйвер терминала встроенный в ядро.
Если у вас есть манипулятор “мышь” с более чем тремя кнопками и дополнительные кнопки не работают, то реакцию на эти дополнительные кнопки можно определить в секции “InputDevice” для этого устройства. Например, параметр Option “ZAxisMapping” “4 5″ отвечает за прокрутку колесика “мышки”. Если числа 4 и 5 поменять местами, то прокрутка будет реализована в обратном направлении.
Секции “Device“, “Monitor” и “Screen” являются секциями, которые отвечают за устройства вывода информации. В секции “Device” прописана информация о видеоадаптере и драйверах для него, в секции “Monitor” описаны характеристики монитора, а в секции “Screen” характеристики экрана (разрешение и прочие). Количество этих секций в зависимости от конфигурации может быть разное, но как минимум каждая из них присутствует в единичном экземпляре в файле xorg.conf.
Section «Device»
Identifier «Intel Corporation 82815 CGC [Chipset Graphics Controller]»
Driver «i810»
BusID «PCI:0:2:0»
EndSection
Section «Screen»
Identifier «Default Screen»
Device «Intel Corporation 82815 CGC [Chipset Graphics Controller]»
Monitor «Универсальный монитор»
DefaultDepth 24
SubSection «Display»
Depth 16
Modes «1280×1024» «1024×768» «800×600»
EndSubSection
SubSection «Display»
Depth 24
Modes «1280×1024» «1024×768» «800×600»
EndSubSection
Для этого в секции “Monitor” необходимо прописать один или несколько параметров modeline. Рассмотрим для примера следующую строку:
Числа 768 771 777 806 означают ту же информацию только для вертикального разрешения. Если вы не совсем поняли, что значат эти параметры не расстраивайтесь. В любом случае вам не нужно вычислять их вручную, так как они должны быть указаны в документации к вашему монитору. И ваша задача просто найти эти параметры и правильно прописать их в строке modeline.
-vsync, -hsync или могут быть +vsync, +hsync, обозначают тип синхроимпульса. Эти параметры также берутся из документации к монитору.
Хотя такое ручное добавление параметров уже редкость, тем не менее еще может иметь место, и поэтому будьте осторожны в установке этих параметров, так как неправильная их установка может привести даже к выходу монитора из строя.
При решении проблем с запуском X-сервера, много информации можно почерпнуть из файла /var/log/Xorg.0.log, в котором можно увидеть все сообщения о процессе запуска X-сервера.
Давайте теперь более подробно поговорим о дисплей менеджерах (Display managers) или менеджерах экрана.
Термином графическая оболочка очень часто называют как оконные менеджеры (WindowMaker, IceWM, Blackbox, JWM и другие), так и полнофункциональные графические оболочки (GNOME, KDE, XFCE и другие).
Конфигурационные файлы дисплей менеджера xdm, расположены в каталоге /etc/X11/xdm/. Поле успешной регистрации пользователя в системе с помощью xdm, будет выполнятся скрипт Xsession, расположенный в /etc/X11/xdm/. Из этого скрипта будет выполнен запуск скрипта /etc/X11/Xsession, который продолжит загрузку графической подсистемы.
Конфигурационные файлы для дисплей менеджера gdm расположены в каталоге /etc/gdm/, а для kdm в каталоге /etc/kde4/kdm (для четвертой версии KDE).
Если вы работаете в алфавитно-цифровом режиме, то для перехода в графический режим достаточно выполнить команду startx. В результате будет запущен графическая среда по умолчанию. Дисплей менеджер в процессе выполнения скрипта startx, не запускается, так как пользователь уже аутентифицировался в системе при помощи программы getty
Графический стек Linux
(оригинал — Jasper St. Pierre, разработчик GNOME Shell, взято отсюда)
Это обзорная статья о составных частях графического стека Linux и том, как они уживаются вместе. Изначально я написал её для себя после разговоров об этом стеке с Оуэном Тейлором, Рэем Строудом и Эдэмом Джексоном (Owen Taylor — мэйнтейнер Gnome Shell; Ray Strode — мэйнтейнер большого количества десктопных пакетов сообщества RedHat; Adam Jackson — разработчик графического стека Gnome Shell и интеграции с XOrg; прим. переводчика).
Я постоянно дёргал их, снова и снова расспрашивал о всяких мелочах, а потом эти мелочи благополучно забывал. В конце концов, я задал им вопрос — а нет ли какого-нибудь обзорного документа, уткнувшись в который я бы избавил ребят от своего назойливого внимания? Не получив утвердительного ответа я решил написать эту статью, которая по завершению была вычитана Эдэмом Джексоном и Дэвидом Эйрли. Они оба работают над этим стеком.
Я хочу вас предупредить, дорогие читатели — такое устройство большой части графического стека Linux, каким оно показано в этой статье, справедливо для открытых драйверов. Это означает, что внутри проприетарных драйверов от AMD или nVidia всё может быть немного не так. Или не совсем так. Или вообще не так. У них могут быть как свои собственные реализации OpenGL, так и скопированная реализация Mesa. Я буду описывать тот стек, который реализуется в открытых драйверах “radeon”, “noveau” и драйверах фирмы Intel.
Если у вас есть какие-нибудь вопросы, или вам кажется, что какие-то детали недостаточно ясны (ну или я очень-очень заблуждаюсь либо как-то путано пишу) — вы, пожалуйста, не стесняйтесь писать об этом в комментариях.
Для начала я прямо тут кратко распишу все компоненты стека. Ну, для того, чтобы вы в общих чертах в них ориентировались по ходу дальнейшего описания.
В общем, если быть точным, в зависимости от выбранного вами типа отрисовки есть два разных сценария развития событий внутри стека:
Трёхмерная отрисовка с помощью OpenGL
Двухмерная отрисовка с помощью cairo
Ну, и для того, чтобы получить нарисованное на экране, Xorg сам с помощью KMS и драйверов видеокарты подготавливает кадровый буфер.
X Window System, X11, Xlib, Xorg
X11 напрямую не относится к графической системе — в него включена система доставки сообщений, описание свойств окон и многое другое. Кроме того, поверх X11 реализована куча вещей, вообще не имеющих отношение к графике (например, буфер обмена и поддержка “drag-and-drop”). Я пишу о X11 тут только для общего понимания его места внутри X Window System. Надеюсь, когда-нибудь получится написать отдельный пост об X Window System, X11 и их странной архитектуре.
Я стараюсь быть максимально аккуратным в именованиях. Если я пишу «X-сервер», то я говорю про абстрактный сервер X — это может быть Xorg, может быть реализация сервера X от Apple, а может быть и Kdrive. Без разницы. Если же я пишу “X11” или “X Window System”, то это значит, что я имею в виду архитектуру протокола и системы в целом. Ну а если я пишу “Xorg” — то это про детали реализации Xorg, самого распространённого X-сервера и ни в коей мере не про детали реализации каких-либо других X-серверов. Если вы встретите просто “X” — это опечатка или косяк.
X11 (сам протокол) разрабатывался с целью быть расширяемым (т.е. с возможностью добавления новых фич без создания принципиально нового протокола и без потери обратной совместимости со старыми клиентами). Для примера, xeyes и oclock выглядят, скажем так, «нестандартно», из-за Shape Extension, которое позволяет использовать окна непрямоугольной формы. Если вам не очень понятно, с помощью какой магии эта функциональность появляется из ниоткуда, то вот ответ: магия тут ни при чём. Поддержка расширения должна быть добавлена на обеих сторонах — и у клиента, и у сервера. В базовой спецификации протокола есть специальный функционал для получения клиентами информации от сервера о доступных расширениях. С помощью этого функционала клиенты могут решать, что использовать, а что — нет.
В архитектуру X11 была заложена возможность быть прозрачным для сетевой среды. Проще говоря, мы не можем полагаться на то, что клиентская и серверная части (X-сервер и X-клиент) находятся на одной машине, поэтому общение между ними должно быть реализовано посредством сети. На самом деле, современные среды рабочего стола в обычной конфигурации так не работают, потому что, кроме X11 в интерпроцессном взаимодействии участвуют, например, всякие DBus. Работа же по сетевому соединению достаточно интенсивна и порождает большое количество трафика. Когда клиентская и серверная часть X Window System находятся на одной машине, вместо общения посредством сетевого соединения они общаются через UNIX-сокет и это здорово снижает нагрузку на ядро.
К X Window System и ряду его расширений мы вернёмся чуть-чуть позже.
Cairo
Сairo может рисовать на поверхностях X11 через специальный Xlib-бэкенд.
В GTK+2 вплоть до версии 2.8 cairo использовался как опциональный компонент. В настоящее время для GTK+3 cairo считается обязательным.
Расширение XRender
Для поддержки отрисовки примитивов с антиалиасингом в протоколе X11 есть специальное расширение, XRender (базовые операции рисования протокола X11 не используют антиалиасинг). Кроме отрисовки примитивов с антиалиасингом, это расширение позволяет использовать градиенты, матричные трансформации и т.д.
Изначально обоснованием ввода в протокол такого расширения была апелляция к тому, что у драйверов могут быть особые, аппаратно ускоренные способы этой отрисовки, которые и будет использовать XRender.
К сожалению, практика показала, что программная растеризация (в силу достаточно неочевидных причин) ничуть не уступает в скорости аппаратной. Ну да ладно.
XRender работает с выравненными трапециями — четырёхугольниками с, возможно, непараллельными левой и правой сторонами. Карл Уорт и Кейт Пэккард разработали для отрисовки этих примитивов достаточно быстрый программный метод. У выравненных трапеций есть ещё один плюс — трапеции легко представимы в виде двух треугольников. Это упрощает их отрисовку с помощью железа. У cairo есть замечательная утилита show-traps, которая демонстрирует то, как происходит рассечение примитивов, передаваемых ей на отрисовку, на трапеции.
Простой пример из красной окружности. Окружность разбивается на два набора трапеций — один для контура и один для заливки. Поскольку реализация show-traps малоинформативно показывает этот процесс, я поправил исходники утилиты для того, чтобы каждая трапеция красилась своим собственным цветом. Вот пример набора трапеций для отрисовки чёрного контура.
pixman
И X-сервер, и cairo нуждаются в работе с пикселями. Ранее Cairo и Xorg по-разному реализовывали работу с растеризацией, попиксельным доступом к разнообразным буферам (ARGB32, BGR24, RGB565), градиентами, матрицами и всем остальным. Теперь же и cairo и X-сервер делают всё это через относительно низкоуровневую библиотеку pixman. Несмотря на то, что pixman — это разделяемая библиотека, у неё нет ни публичного API, ни определённого API для операций отрисовки. Строго говоря, у неё вообще нет API — это просто хранилище кода для дедупликации его между ранее упомянутыми двумя компонентами.
OpenGL, mesa, gallium
А это самая весёлая часть — современное аппаратное ускорение отрисовки. Я полагаю, что все и так знают, что такое OpenGL. Это не библиотека, это даже не конкретный набор исходников для сборки libGL.so. У каждого производителя своя собственная libGL.so, так или иначе совместимая со спецификацией OpenGL.
Например, nVidia предоставляет свою реализацию OpenGL и собственную libGL.so, которая реализуется по-разному для тех же Windows или OS X.
Если вы используете открытые драйверы, то реализация вашей libGL.so, скорее всего, основана на mesa. Mesa — это большая куча всего, но основная и самая известная часть этой кучи — открытая реализация OpenGL. Внутри самой mesa за OpenGL API используются различные бэкенды для трансляции API в исполнительные команды. Существует три программных бэкенда:
Кроме программных бэкендов mesa поддерживает аппаратные:
На самом деле, gallium — это набор компонентов, поверх которых можно достаточно просто построить драйвер. Смысл в том, что драйвер состоит из:
К сожалению, разработчики Intel не используют gallium. Мои коллеги говорят, что это из-за нежелания разработчиков драйверов Intel иметь какие-либо прослойки между mesa и своим драйвером.
Немного сокращений
Дальше будут встречаться сокращения, для которых мне бы не хотелось выделять отдельный большой абзац по ходу повествования. Поэтому я просто перечислю их тут. Многие из них имеют лишь историческую ценность, но, тем не менее, я про них напишу. Дабы вы были в курсе.
Драйверы Xorg, DRM, DRI
Чуть раньше я писал, что Xorg может производить аппаратно-ускоренную отрисовку. Добавлю, что это реализовано не через трансляцию команд рисования X11 в вызовы API OpenGL. Тогда как Xorg работает с железом, если драйверы железа работают в недрах mesa, а Xorg на mesa не завязан?
Ответ прост. Ведь как оно? Mesa отвечает за реализацию OpenGL, Xorg отвечает за реализацию отрисовки команд X11, и они оба должны рисовать на железе с помощью специфичных для конкретного железа команд. В своё время в архитектуры Xorg и mesa был введён разделяемый компонент, который и загружает эти команды в ядро — так называемый “Direct Rendering Manager” («менеджер прямой отрисовки») или DRM.
Libdrm использует набор оригинальных закрытых ioctl’ей ядра для выделения ресурсов графического ускорителя и предоставления ему команд с текстурами. Общий интерфейс из этих ioctl’ей бывает (в общем-то, предсказуемо) двух видов:
Между ними нет значимых различий. Они оба делают одно и то же, просто чуть-чуть различаются в реализации. Исторически GEM был представлен компанией Intel, в качестве простой альтернативы TTM. Через некоторое время GEM разросся и «простота» стала такой же, как у TTM. Такие дела.
К чему всё это? К тому, что, например, когда вы запускаете утилиту типа glxgears, она загружает mesa. Mesa загружает libdrm. Libdrm общается с драйвером ядра, используя GEM/TTM. Да, glxgears напрямую работает с ядром для того, чтобы показать вам несколько крутящихся шестерёнок, таким образом напоминая о том, что это бенчмаркинговая утилита.
Если вы выполните в консоли команду (подставив lib32/lib64 в зависимости от архитектуры):
то увидите, что там лежат аппаратно-зависимые драйверы. Для тех случаев, когда функциональности, заложенной в GEM/TTM недостаточно, драйверы mesa и X-сервера предоставляют ещё более закрытый набор ещё более закрытых ioctl’ей для общения с ядром, которые, собственно, и находится в этих аппаратно-зависимых драйверах. Сам libdrm эти драйверы не загружает.
X-серверу необходимо знать, что же вообще происходит с графической подсистемой для того, чтобы реализовывать синхронизацию. Эта методология синхронизации (например, между запущенным вами glxgears, ядром и X-сервером) называется DRI или, более правильно, DRI2. DRI расшифровывается, как “Direct Rendering Infrastructure” («инфраструктура прямой отрисовки»). Вообще, под DRI понимают две вещи:
Поскольку мы придерживаемся строгой терминологии, а DRI1 выглядит глупо, мы будем говорить о протоколе и библиотеке, называя их DRI2.
Раз уж мы немного отошли от темы и начали говорить об инфраструктурных вещах, я задам вопрос. Предположим, вы работаете на новом X-сервере или вы хотите отобразить графику в виртуальном терминале без использования X-сервера. Как, в таком случае, вы это сделаете?
Вам надо сконфигурировать железо таким образом, чтобы оно могло отображать графику.
Внутри у libdrm и ядра есть специальная подсистема KMS, делающая именно это. Аббревиатура KMS расшифровывается, как “Kernel Mode Setting” («настройка режима из ядра»). Опять же, эта подсистема через набор ioctl’ей позволяет установить графический режим, настроить кадровый буфер и сделать всё нужное для того, чтобы показывать графику прямо в TTY. До появления KMS в ядре был (да так никуда пока и не делся) разношёрстный набор ioctl’ей, для замены и стандартизации которого, собственно, и создали разделяемую библиотеку libkms с единым и документированным API.
Правда, внезапно (как это принято в мире Linux) после libkms в ядре появился новый API, буквально называнный «тупыми ioctl’ями». Поэтому в настоящее время рекомендуется пользоваться не libkms, а этим набором ioctl’ей.
Насмотря на то, что эти ioctl’и очень низкоуровневые и простые, они позволяют сделать практически всё. Примером для этого может служить plymouth, который практически во всех современных дистрибутивах Linux отвечает за графическое отображение процесса загрузки без запуска X-сервера.
Модель “Expose”, Redirection (перенаправление), TFP, Compositing (композиция), AIGLX
Нельзя говорить о термине “композиционный менеджер окон“ без понимания того, что такое “композиция” и что делает менеджер окон.
В те далёкие 80-е, когда разрабатывалась для операционных систем UNIX архитектура X Window System, куча компаний типа HP, DEC, Sun и SGI разрабатывали свои продукты, базировавшиеся на X Window System. При этом протокол X11 никак не регламентировал правила управления окнами и делегировал ответственность за их поведение отдельному процессу, который назывался “window manager” («менеджер окон»).
Например, CDE, популярная оконная среда для своего времени, исповедовала поведение окон, которое было названо «фокус следует за мышью». Суть его в том, что фокус ввода передавался в окно, когда пользователь наводил на него курсор мыши. Это отличается от поведения окон в Windows или Mac OS X, в которых фокус окну передаётся кликом.
По мере того, как оконные среды начали набирать популярность и становиться всё более сложными, начали появляться соответствующие документы, регламентирующие общее поведение разных оконных сред. Правда, эти документы точно так же не оговаривали политику реализации передачи фокуса.
Опять же, в те далёкие 80-е у многих систем был банальный недостаток памяти, поэтому они не могли хранить в пиксельном виде всё содержимое окна. И Windows, и X11 решили эту проблемы одинаково: каждое окно X11 не должно иметь пиксельного состояния. По необходимости приложение получало уведомление о необходимости перерисовать часть своего окна (произвести «экспозицию», “expose”).
Представьте такой набор окон. Теперь переместим окно GIMP’а:
Область, закрашенная тёмно-коричневым, экспонирована. Событие ExposeEvent посылается приложению, которому принадлежит окно и приложение перерисовывает область экрана, соответствующую экспонированной. Именно из-за этой модели перерисовки окна подвисших приложений в Windows и Linux имеют белые области, когда вы перетаскиваете поверх них какое-нибудь другое окно. Учитывая тот факт, что в Windows рабочий стол отрисовывается точно такой же программой без особых привилегий, которая точно так же может зависнуть, легко можно понять причины этого весёлого артефактного поведения.
Сегодня у компьютеров много памяти. Поэтому мы имеем возможность сделать с помощью X11 окна, не теряющие своё пиксельное представление. Делается это с помощью механизма, называемого “redirection” («перенаправление»). Когда мы перенаправляем окно, X-сервер создаёт пиксельные буферы для рисования каждого окна, а не рисует напрямую во внеэкранный кадровый буфер. Это значит, что содержимое окна напрямую никогда не появляется на экране. Кое-что другое отвечает за отрисовку пикселей на внеэкранном кадровом буфере.
Расширение композиции позволяет композиционному менеджеру окон (или “compositor”’у, «композитору») создать так называемое Composite Overlay Window (“окно композиционного слоя”) или COW. После этого композитор назначается владельцем окна COW и может проводить его отрисовку.
Когда вы запускаете Compiz или GNOME Shell, эти приложения используют OpenGL для отображения перенаправленных окон на экране. X-сервер даёт им пользоваться содержимым окон с помощью GL-расширения “Texture from Pixmap” («текстура из пиксельной карты») или TFP. Это расширение позволяет OpenGL-приложению использоваться пиксельные карты X11 так, как если бы это были нативные текстуры OpenGL.
Композиционные менеджеры окон, в принципе, могут не использовать TFP или OpenGL. Просто TFP и OpenGL — самый лёгкий способ сделать композицию. Ничто не мешает менеджеру окон просто рисовать пиксельные карты окон на COW стандартными средствами. Мне рассказывали, что kwin4 так и поступает, напрямую используя Qt для композиции.
Композиционные менеджеры окон получают пиксельную карту от X-сервера через TFP и отрисовывают её в OpenGL-сцене в нужном месте, создавая иллюзию того, что вы работаете с обычным окном X11. Может показаться глупым называть это «иллюзией», но вы можете убедиться в «иллюзионности» композиции, если используете, например, GNOME Shell. Для этого можно изменить размер и позицию действующих окон, введя в looking glass GJS-код:
Иллюзия композиции исчезнет сразу, как только вы поймёте, что вы тыкаете мышью не в то окно, в которое хотели, а в другое. Для того, чтобы вернуть всё назад, введите в looking glass этот же код, поменяв 0.5 на 1.0.
Теперь, когда вы в курсе всех этих деталей, можно рассказать об ещё одном сокращении — об AIGLX. AIGLX расшифровывается как “Accelerated Indirect GLX” («ускоренный транзитный/непрямой GLX»). Поскольку X11 — это сетеориентированный протокол, OpenGL должен уметь работать через сеть. Когда OpenGL используется в таком режиме, режим называется “indirect context” («транзитный контекст»), в отличие от стандартного режима “direct context”, в котором OpenGL используется на этой же машине. Грусть в том, что сетевой протокол для транзитного контекста ужасающе неполный и нестабильный.
Для того, чтобы понять компромиссность архитектурных решений AIGLX, надо понять проблему, которую пытались ими решить: необходимость сделать композиционные менеджеры типа Compiz’а реально быстрыми. В то время, когда у проприетарного драйвера NVidia есть свой собственный интерфейс управления памятью на уровне ядра, у открытого графического стека его нет. Поэтому прямой перенос пиксельной карты окна в виде текстуры из X-сервера на графическое железо выливался бы в копирование этой пиксельной карты каждый раз, когда окно обновляется. Дико медленно. Поэтому AIGLX заранее был признан временным костылём для быстрой программной реализации OpenGL с целью исключения копирования пиксельных карт при аппаратном ускорении. Ну и, поскольку сцена, которая рисуется Compiz’ом, обычно не очень сложная, работало это вполне приемлемо.
Несмотря на кучу похвалы и статьи Phoronix’а, AIGLX так никогда и не использовался для серьёзных вещей — просто потому, что у нас сейчас есть нормальный DRI-стек, в котором можно реализовать TFP без копирования.
Теперь вам должно быть понятно, что копирование (или, если говорить более точно, подстановка) содержимого пиксельной карты окна так, чтобы оно могло быть передано в отрисовку в виде текстуры OpenGL невозможно без непосредственного копирования данных. Из-за этого у большинства оконных менеджеров в настройках есть фича, которая позволяет отключать перенаправление для окон, развёрнутых на весь экран. Возможно, называть это “unredirection“ («деперенаправление») глупо, потому что в результате мы получаем окно таким, каким оно и должно быть по логике X Window System. Да, исторически это так. Но, в современном Linux, такое состояние трудно назвать обычным состоянием окна. Зачем нужно деперенаправление? Да затем, что в развёрнутом состоянии любое окно всё равно целиком закрывает COW, поэтому не надо проводить комплексную композицию и её можно отключить. Эта фича нужна для того, чтобы дать полноэкранным приложениям типа игр и видеопроигрывателей работать без дополнительного копирования данных окна с максимальной производительностью обновления, достигающей позволенных 60 кадров в секунду.
Wayland
Выше мы вычленили достаточно большой кусок инфраструктуры из монолитной архитектуры иксов. Но графическая подсистема — это не всё, что вывалилось со временем из монолита: практически вся обработка устройств ввода переместилась в ядро с помощью evdev, а поддержка горячего подключения устройств вернулась обратно в udev.
Причина того, что X Window System живёт и сейчас в том, что всё это время усилия сообщества направлялись на работы по его замене. Эта замена — Xorg, с большим количеством разнообразных расширений, обеспечивающих необходимую для современного графического окружения функциональность. Можно сказать, что классический X Window System — списанный хлам.
Въезжаем в Wayland. Wayland переиспользует очень большой объём той инфраструктуры, что мы создали на замену X Window System. Единственная противоречивая вещь в архитектуре Wayland — это непрозрачность сетевого и отрисовочного протоколов. С другой стороны, в наше время колоссальная гибкость сетевого протокола становится ненужной, ведь львиная доля функциональность иксов уже раскидана по другим службам — например, DBus. На самом деле, стыдно смотреть на те хаки в архитектуре X Window System, что понаделаны в вещах типа буфера обмена или поддержки Drag and Drop исключительно для совместимости с сетевым прошлым иксов.
Как уже было сказано, Wayland может использовать весь вышеописанный стек для того, чтобы получить кадровый буфер для монитора и запуститься. У Wayland сохраняется определённый протокол обмена, но он основан исключительно на сокетах UNIX и локальных ресурсах. Самое большое отличие Wayland от Xorg в том, что он не запускается с помощью /usr/bin/wayland и не висит в памяти отдельным процессом. Он, в соответствии с духом времени и требованиями к современным средам рабочего стола, связывает всё непосредственно с процессами менеджеров окон. Такой оконный менеджер или, точнее, «композитор» в терминологии Wayland, подтягивает события из ядра с помощью evdev, настраивает кадровый буфер с помощью KMS или DRM и отрисовывает на нём картинку с помощью любого графического стека, включая OpenGL. Несмотря на то, что упоминание такого клеевого слоя сразу вызывает ассоциации с тоннами кода (потому что во взаимодействии участвует куча разбросанных везде систем), на самом деле порядок объёма укладывается в две-три тысячи строк кода. Кажется, что довольно много? Представьте, что только небольшая часть mutter, описывающая механизм фокуса, стэкирования окон и синхронизирующая их с X-сервером — это уже четыре-пять тысяч строк кода.
Хотя у Wayland есть эталонная библиотека реализации протокола и настойчиво рекомендуется её использовать как для клиентов, так и для композиторов, — ничто не мешает кому-нибудь написать всего композитора для Wayland на Python. Или на Ruby. И реализовать протокол на чистом Python, без использования libwayland.
Клиенты Wayland общаются с композитором и запрашивают буфер. Композитор отдаёт буфер, в который они могут рисовать хоть с помощью cairo, хоть с помощью OpenGL, хоть самостоятельно. Композитор потом уже сам решает, что делать с этим буфером — показывать его просто так, дать ему приоритет из-за настойчивости приложения или повращать его гм… на кубике потому, что нам хочется выложить в YouTube новую видюшку с окнами Linux, вращающимися на кубике. Ну, вы поняли.
Кроме этого, композитор ответственен за ввод и за обработку событий. Если вы пробовали запустить кусок GJS-кода для GNOME Shell, вы наверняка были озадачены вопросом — «Почему мышь работает с нетрансформированными окнами»? А потому, что мы воздействовали на отображение окна, а не на само окно внутри X11. X-сервер отслеживает окна самостоятельно и надеется, что композиционный менеджер окон их отображает соответствующим образом. Если это не так, то приходится озадачиваться, как в случае выше.
Поскольку композитор Wayland’а работает с evdev и отдаёт события окнам, то он гораздо лучше знает, где окна находятся, как отображаются и может проводить все необходимые трансформации самостоятельно. Поэтому, работая с таким композитором, мы можем не только вращать окна на кубике, но ещё и работать с ними прямо на кубике.
Выводы
Я часто слышу высказывания о том, что реализация Xorg монолитна. Доля истины в таких высказываниях, конечно же, присутствует, но со временем истины в таких высказываниях всё меньше и меньше. Это не результат некомпетентности разработчиков Xorg, нет. Просто нам надо жить не только с Xorg, но и со всем багажом, накопленным за долгие годы — а это, например, аппаратно-ускоренный протокол XRender или, если взять что-то более раннее, — команды рисования без антиалиасинга типа XPolyFill. Понятно, что со временем X уйдёт со сцены и будет заменён Wayland’ом. Но я хочу, чтобы было понятно и то, что это делается с пониманием и колоссальной помощью от разработчиков окружений рабочего стола и Xorg. Они не упрямы и они не некомпетентны. Чёрт возьми, поддерживать протокол тридцатилетней давности без поломок и перестраивать его архитектуру, — это отличная работа с их стороны.
Также я хочу выразить признательность всем, кто работал над вещами, о которых эта статья. Огромное спасибо Оуэну Тэйлору, Рэю Строуду и Эдэму Джексону за долготерпение и ответы на все мои тупые вопросы. Отдельное спасибо Дэйву Эйрли и Эдэму Джексону за помощь в технической вычитке этой статьи.
Несмотря на то, что я мельком пробежал по основным вещам графического стека Linux, вы всегда можете копнуть глубже, если вам это интересно. Например, вы можете почитать про геометрические алгоритмы и теории, которые лежат в основе разбиения cairo примитивов на четырёхугольники. Или, может быть, стоит взглянуть на алгоритм быстрой программной растеризации этих четырёхугольников и разобраться в причинах высокой скорости его работы. Попробуйте поковыряться в DRI2. А вдруг вам интересно само железо и то, как оно рисует, и вы разберётесь в даташитах и попробуете сами его запрограммировать? В любом случае, если вы решите углубиться в какую-нибудь из этих областей, — сообщество и проекты, перечисленные выше, будут счастливы принять вас с вашим вкладом.
Я планирую написать больше про всё это. В Linux используется много разнообразных стеков технологий, а у сообщества GNOME до сих пор нет вменяемых обзорных документов, описывающих их на более-менее высоком уровне.
Спасибо хабрапользователям Roosso, trollsid и Xitsa за вычитку.