Пользователь
0,0
рейтинг
2 августа 2012 в 19:23

Разработка → Графический стек 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


  1. Программа стартует, используя для отрисовки OpenGL;
  2. Библиотека mesa предоставляет вам этот самый API OpenGL. Она использует конкретные драйверы вашей видеокарты для преобразования вызовов OpenGL к приемлемому для видеокарты виду. Если внутри драйвера используется Gallium, то подключается ещё и разделяемый компонент, который превращает вызовы OpenGL в общее промежуточное представление, TGSI. После преобразования вызовов внутри Gallium низкоуровневому драйверу остаётся лишь оттранслировать TGSI в аппаратные команды, понятные железке;
  3. libdrm использует специальные ioctl для связи с ядром Linux;
  4. Ядро Linux (поскольку имеет право на это) может выделять области памяти для видеокарты как непосредственно на видеокарте, так и в системной памяти;
  5. После всего этого mesa на своём уровне использует DRI2 для связи с Xorg, чтобы убедиться, что произошло переключение буфера, а позиции окон и т.д. — синхронизированы.


Двухмерная отрисовка с помощью cairo


  1. Программа стартует, используя  для отрисовки cairo;
  2. Вы рисуете несколько градиентных окружностей. Cairo производит разбиение окружностей на четырёхугольники и шлёт эти четырёхугольники и градиенты X-серверу используя расширение XRender. В том случае, когда X-сервер не поддерживает XRender, cairo отрисовывает их само с использованием libpixmap и использует другой метод для отправки отрисованной пиксельной карты X-серверу;
  3. X-сервер принимает запрос от XRender. Xorg может в этом случае использовать разные специализированные драйвера:
    1) В случае отката к программной отрисовке или в случае неготовности драйвера Xorg использует libpixman для отрисовки своими силами, прямо как cairo;
    2) В случае аппаратного ускорения драйвер Xorg связывается посредством libdrm с ядром и посылает видеокарте текстуры и команды.


Ну, и для того, чтобы получить нарисованное на экране, Xorg сам с помощью KMS и драйверов видеокарты подготавливает кадровый буфер.

X Window System, X11, Xlib, Xorg


X11 напрямую не относится к графической системе — в него включена система доставки сообщений, описание свойств окон и многое другое. Кроме того, поверх X11 реализована куча вещей, вообще не имеющих отношение к графике (например, буфер обмена и поддержка “drag-and-drop”). Я пишу о X11 тут только для общего понимания его места внутри X Window System. Надеюсь, когда-нибудь получится написать отдельный пост об X Window System, X11 и их странной архитектуре.

  • X11
    Коммуникационный протокол X Window System;

  • Xlib
    Библиотечная реализация клиентской части X Window System и основа для прикладной логики управления окнами. Используется тулкитами типа GTK+ или Qt. В нынешних приложениях напрямую практически не используется;

  • XCB
    The X protocol C-language Binding («привязки протокола X11 для языка C»). Иногда упоминается как альтернатива Xlib. Содержит реализацию большой части протокола X11. Программный интерфейс XCB гораздо более низкоуровневый, чем у той же Xlib, причём современный Xlib полностью построен поверх XCB. Будем считать, что просто вспомнили и расшифровали ещё одно сокращение;

  • Xorg
    Библиотечная реализация серверной части X Window System.

Я стараюсь быть максимально аккуратным в именованиях. Если я пишу «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 — это библиотека для отрисовки векторной графики, использующаяся как обычными приложениями напрямую (например, Firefox), так и различными тулкитами типа GTK+. Например, модель отрисовки GTK+3 полностью основана на cairo. Если вы работали с HTML-элементов <canvas>, то вы имеете достаточно полное представление и о cairo, поскольку, на самом деле, их API схоже. Несмотря на то, что <canvas> изначально был представлен фирмой Apple, векторная графика родилась гораздо раньше (ещё начиная  с модели отрисовки PostScript, которая нашла своё отражение в таких стандартах, и технологиях как PDF, Flash, SVG, Direct2D, Quartz 2D, OpenVG и так далее, тысячи их).

С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 в исполнительные команды. Существует три программных бэкенда:

  • swrast — древний и ужасный. Помогите его закопать и никогда его не используйте;
  • softpipe — медленный;
  • lvmpipe — быстрый.


Кроме программных бэкендов mesa поддерживает аппаратные:

  • Компания Intel работает с mesa и разрабатывает под своё железо mesa-совместимые драйверы, которые потом поставляются в составе mesa. (Использует для этого свою собственную архитектуру драйверов, к которой много вопросов у различных OpenGL-разработчиков. Например, у Blender.);
  • Открытые драйверы radeon и noveau, которые построены поверх общей архитектуры gallium.


На самом деле, gallium — это набор компонентов, поверх которых можно достаточно просто построить драйвер. Смысл в том, что  драйвер состоит из:

  • набора машин состояний, реализующих какое-то конкретное API (OpenGL, GLSL, Direct3D);
  • набора преобразователей API в промежуточное представление (в так называемый Tungsten Graphics Shader Infrastructure или TGSI (для интересующихся — дословно «инфраструктура графических шейдеров «Вольфрам»);
  • бэкендов, транслирующих TGSI в команды конкретного железа.


К сожалению, разработчики Intel не используют gallium. Мои коллеги говорят, что это из-за нежелания разработчиков драйверов Intel иметь какие-либо прослойки между mesa и своим драйвером. 

Немного сокращений


Дальше будут встречаться сокращения, для которых мне бы не хотелось выделять отдельный большой абзац по ходу повествования. Поэтому я просто перечислю их тут. Многие из них имеют лишь историческую ценность, но, тем не менее, я про них напишу. Дабы вы были в курсе.

  • GLES
    OpenGL имеет несколько разных версий для разных платформенных реализаций. GLES — одна из них. Расшифровывается, как “GL Embedded System” или “GL Embedded Subset” («встраиваемая система/подмножество GL»). Это последняя на нынешний момент попытка OpenGL выйти на рынок встраиваемых решений. iPhone поддерживает GLES версии 2.0;

  • GLX
    Внутри OpenGL не оговариваются всякие заморочки конкретных платформ и реализация доступа к поверхностям для рисования (например, системы организации оконного интерфейса). Но, к сожалению, для различных платформ необходимы биндинги для преобразования результата вызова API OpenGL к реалиям мира типа протокола X11. GLX — прослойка, предназначенная для склейки OpenGL с X11;

  • WGL
    Смотрим на предыдущий пункт, заменяем “X11” на “Windows”. Да, всё то же самое, но для операционной системы фирмы Microsoft;

  • EGL
    EGL и GLES очень часто путают в силу похожести аббревиатур. EGL — очередной антиплатформенный набор API, разрабатываемый Khronos Group (той же самой группой, которая занимается OpenGL). EGL предоставляет инфраструктурный набор для быстрой настройки приложения и инициализации сцены безотносительно платформы, на которой это приложение работает. Как и OpenGL, EGL производителе-ориентирована. По сути, это альтернатива WGL/GLX, но не очередной костыль, построенный поверх них (типа GLUT);

  • fglrx
    Когда-то fglrx'ом назывался проприетарный OpenGL-драйвер компании AMD для Xorg. Сейчас он называется “Catalyst”. Расшифровывается как “FireGL and Radeon for X”. Т.к. драйвер проприетарен, то у него есть своя собственная, закрытая, libGL.so. Я не знаю, основана ли она на mesa и представляет ли для нас интерес. На самом деле, fglrx я тут упоминаю только из-за того, что его часто путают с AIGLX или GLX из-за того, что в во всех этих аббревиатурах есть “GL” и “X”;

  • DIX, DDX
    Графическая подсистема Xorg состоит из двух частей — из DIX, которая расшифровывается, как “Driver Independent X”, и из DDX, которая, соответственно, расшифровывается, как “Driver Dependent X” («Драйверонезависимый X» и «Драйверозависимый X», соответственно). Когда мы имеем в виду драйвер Xorg, правильнее было бы говорить о драйвере DDX;


Драйверы 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 из набора технологий Tungsten Graphics (да, того самого, в который входит gallium).


Между ними нет значимых различий. Они оба делают одно и то же, просто чуть-чуть различаются в реализации. Исторически GEM был представлен компанией Intel, в качестве простой альтернативы TTM. Через некоторое время GEM разросся и «простота» стала такой же, как у TTM. Такие дела.

К чему всё это? К тому, что, например, когда вы запускаете утилиту типа glxgears, она загружает mesa. Mesa загружает libdrm. Libdrm общается с драйвером ядра, используя GEM/TTM. Да, glxgears напрямую работает с ядром для того, чтобы показать вам несколько крутящихся шестерёнок, таким образом напоминая о том, что это бенчмаркинговая утилита.
Если вы выполните в консоли команду (подставив lib32/lib64 в зависимости от архитектуры):

ls /usr/lib32/libdrm_*

то увидите, что там лежат аппаратно-зависимые драйверы. Для тех случаев, когда функциональности, заложенной в GEM/TTM недостаточно, драйверы mesa и X-сервера предоставляют ещё более закрытый набор ещё более закрытых ioctl'ей для общения с ядром, которые, собственно, и находится в этих аппаратно-зависимых драйверах. Сам libdrm эти драйверы не загружает.

X-серверу необходимо знать, что же вообще происходит с графической подсистемой для того, чтобы реализовывать синхронизацию. Эта методология синхронизации (например, между запущенным вами glxgears, ядром и X-сервером) называется DRI или, более правильно, DRI2. DRI расшифровывается, как “Direct Rendering Infrastructure” («инфраструктура прямой отрисовки»). Вообще, под DRI понимают две вещи:

  • проект, который обеспечивает сожительство mesa и Xorg (DRM и вся обвязка вокруг него);
  • протокол DRI и соответствующую библиотеку.


Поскольку мы придерживаемся строгой терминологии, а DRI1 выглядит глупо, мы будем говорить о протоколе и библиотеке, называя их DRI2.

KMS


Раз уж мы немного отошли от темы и начали говорить об инфраструктурных вещах, я задам вопрос. Предположим, вы работаете на новом 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-код:

global.get_window_actors().forEach(function(w) { w.scale_x = w.scale_y = 0.5; });

Иллюзия композиции исчезнет сразу, как только вы поймёте, что вы тыкаете мышью не в то окно, в которое хотели, а в другое. Для того, чтобы вернуть всё назад, введите в 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 за вычитку.
@80x86
карма
83,2
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (47)

  • НЛО прилетело и опубликовало эту надпись здесь
    • +3
      Возможно для обратной совместимости.
      А статья очень понравилась, побольше бы таких.
      • 0
        Статья супер!

        «Чёрт возьми, поддерживать протокол тридцатилетней давности без поломок и перестраивать его архитектуру, — это отличная работа с их стороны.» — вот только зачем его поддерживать?
        • 0
          Задам встречный вопрос по аналогии с вашим: «Зачем поддерживать софт для win95 в win7?».

          Причина в экосистеме вокруг протокола. Чем больше объём экосистемы — тем сложнее менять протокол и тем больше сил приходится бросать на тестирование его совместимости. Теория надёжности информационных систем :)
          • –1
            Между win95 и win7 не 30 лет, и не все там поддерживается. Танцы же вокруг X11 смахивают на полноценную поддержку DOS 1.0 в Win8. Unix community банально не хватает яиц в органиме, чтобы произнести obsolete/deprecated, при чем не только в графической подсистеме.
            • 0
              Не совсем так.

              Windows-коммьюнити исторически строилось вокруг Microsoft и подчинялось законам игры этой фирмы. Все внутренние решения принимались Microsoft единолично, но даже в таком случае реально революционные решения принимались считанные разы — даже в условиях корпорации координация огромных массивов разработчиков давалась нелегко.

              Unix/Linux-коммьюнити исторически строились вокруг кучи вендоров и управлялись полуотраслевыми стандартами типа Posix, ISO или вот этого протокола, X11.

              В мире до сих пор существуют системы, которые работают с тех самых восьмидесятых годов. И к ним был написан софт, который гоняется на современных системах и не требует переписывания только из-за незыблемости «клея из стандартов».

              У linux-комьюнити яиц хватает (чего стоят истории с udev-evdev, kms и прочими pulseaudio). Просто всё компьютерном мире смена стандартов и поколений должна проходить эволюционно. Скажем так — параллельно со сменой поколений разработчиков.
              • 0
                Возможно, но IMHO как-то слишком затянуто все это происходит.

                Windows-коммьюнити исторически строилось вокруг Microsoft и подчинялось законам игры этой фирмы
                Потому что есть старая военная мудрость — одна голова хорошо, а две еще хуже.

                В мире до сих пор существуют системы, которые работают с тех самых восьмидесятых годов. И к ним был написан софт, который гоняется на современных системах
                Мне не очень понятно, зачем запускать этот софт на современных системах. Старой рыбе старый аквариум.

                Unix/Linux-коммьюнити исторически строились вокруг кучи вендоров и управлялись полуотраслевыми стандартами типа Posix, ISO или вот этого протокола, X11.
                Послать бы часть этих затхлых вендоров куда подальше — в этом и есть суть obsolete/deprecated. Вместо этого неотрубленные гниющие конечности продолжают пускать метастазы.
                • +1
                  Мне не очень понятно, зачем запускать этот софт на современных системах. Старой рыбе старый аквариум.

                  Представьте себе конверсию мейнфрейма с процессингом большой фирмы на западе. Софт был написан в восьмидесятые, с тех пор допиливался и обрастал функциональностью. Стоимость его — эквивалент десятков тысяч человекочасов. А железо мейнфреймов не выпускают и этот софт мигрирует на современные *nix-платформы вместе со всей инфраструктурой.

                  И такого софта много.

                  Естественно затянуто. На реально больших и живых системах, которые, на самом-то деле, питают индустрию (надеюсь, вы понимаете, что серьёзную индустрию двигают не домашние персональные компьютеры) — там революционная миграция между разными технологическими системами невозможна.
                  • 0
                    А железо мейнфреймов не выпускают
                    Зачем современным *nix-платформам калечить себя поддержкой мейнфреймов? Сделали бы версию для мейнфреймов отдельно от версии для современных компьютеров (несовместимые друг с другом, но в чем-то похожие). Примерно как Windows CE по отношению к Win32/64.
                    • +1
                      Linux тихонечко удушил идеологического родителя. А лицензии в экосистеме Linux, в основном, GPL. Вот и толкают всё это в апстрим, ибо ЛИЦЕНЗИЯ.

                      Это мои домыслы, если что. Всё может быть вообще не так :)
                      • 0
                        ясно :) так то CE у них есть в виде Linux System Z — там бы и содержать виварий из всяких X11.
    • +25
      А он его и не тянет. Это сопутствующие расходы для mesa. Тут всё расписано с шикарнейшей диаграммкой:

      image
  • +2
    Спасибо. Очень интересная статья. Сам бы никогда не осмелился все это копать.
  • –1
    За статью спасибо! Побольше бы таких!

    Однако когда я слышу утверждения вида «С другой стороны, в наше время колоссальная гибкость сетевого протокола становится ненужной, ведь львиная доля функциональность иксов уже раскидана по другим службам — например, DBus.», у лично меня почему-то возникает непреодолимое желание взять и у****ь разработчиков Wayland бейсбольной битой! А потом эту бейсбольную биту вставить им в анус, да еще и пожелать чтобы их черти драли в аду! Гибкость и возможность работы по сети это и есть реально сильные стороны X-протокола! А то, что они предлагают — это отказаться от реально сильных сторон зато навешать на юзера килотонну свистоперделок!

    P.S.: Предвижу вопросы, и сразу на них отвечаю. Да, я действительно использую сильную сторону как возможность работы X-протокола по сети (в виде ssh X11 forwarding). И да, всякие «свистоперделки» вроде 3d desktopов вызывают у меня рвотный рефлекс.

    • +7
      Я тоже использую проброс X11 :)

      Вэйлэнд — это решение оконных проблем для десктопов — онли.
      Иксы — это решение оконных проблем для сетевых инфраструктур.

      Думаю, что они это понимают и будут развивать концепцию оконных окружений соответствующим образом.
      Терминалу терминалово, игрушкам — игрушково.
      • 0
        Я думаю что со времен изобретения X-Window ситуация поменялось, и вместо X-Window все таки будут быстрые локальные графические подсистемы, основанные на OpenGL и без всякой сетевой штуки, и web приложения для сетевого взаимодействия.
        • +4
          Когда-нибудь, лет через пятнадцать, — обязательно. И WebGL, и Javascript во все поля, и кризис HTTP и REST-моделей. Когда-нибудь — обязательно.
        • 0
          «Сеть» это не только реальный ethernet или модемный шнурок, но также сокетовая абстракция для IPC между двумя адресными пространствами. К примеру, у меня линукс, на котором я запускаю мои x-клиенты, находится в виртуалке, тогда как x-сервер — на хосте под виндой.

          Поэтому, думаю, что X11 ещё лет 50 не умрёт, т.к., в отличие от веб, у него есть бинарная упаковка данных, т.е. ориентированные в конечном результате на десктоп приложения будут работать через X11-сокеты (а потом, скорее всего, разработают специальный протокол и инфраструктуру для работы индивидуальных клиентов).
          • 0
            Сетевая прозрачность реализуется при помощи VNC и аналогов, причём успешно (для Wayland вроде уже даже есть).

            А X11 сам по себе и впрямь не скоро умрёт так как приложения будет работать внутри Wayland да и уже работают причём быстрее чем напрямую. :) Но ИМХО после начала массовой миграции за год 80% мейнстрима будет уже нативно работать на wayland.
    • +7
      Пфффф. Сетевая прозрачность, говорите? Запустите на удалённом сервере браузер поверх X11 поверх SSH. И его же в VNC, к которому подключитесь поверх того же же SSH. А теперь попробуйте посерфить. Возможно, вы сильно удивитесь, но второй вариант работает на порядки быстрее.
      • +1
        Трудно не согласиться.
        Тоже любил форвардить иксы, пока у нас не образовалась удаленная площадка с серверами,
        до которой канал не шибко быстрый.
        VNC в этом случае единственное спасение, ибо приложение которое приехало к тебе
        через проброс, отвечает по несколько секунд на нажатия например.
        И очень бесят двойные нажатия и прочие неприятности фризов.
        • +3
          Насколько я успел заметить по своему опыту — скорость канала не так важна. Для X11 важен быстрый пинг. Заторможенность при пробросе X11 у меня была прямо пропорциональна моей удаленности от сервера, скорость же канала практически не имела никакого значения.

          Такое возможно в случае, если протокол сделан очень прямолинейно, по принципу: посылаем одну команду — ожидаем ответ.

          • +1
            Классическая протечка абстракции по Фаулеру.
  • +2
    Большое спасибо. Было интересно читать, узнал много нового.
  • +5
    Спасибо. Таких обзорных статей по компонентам сильно не хватает.
  • +8
    Присоединюсь к благодарящим. Ради таких статей(информативных и с не попсовым содержимым) и захожу на хабр. Жаль они не так часто встречаются.
  • +2
    Получил удовольствие от прочтения. Хочу ещё.
  • +6
    Это героический поступок перевести это! Я сам начинал, но так и не осилил объем, спасибо вам
    • 0
      Мне вот пока пару моментов интересны: можно ли сделать рисование декораций окон сторонней программой(ну блин, это ерудна какая-то, разные декорации, в разных тулкитах) и где брать информацию об активных окнах(я хочу написать панель, мне в ней рассматривать все существующие «композиторы» которые могут предоставить такую возможность)?
      • 0
        Вы про Wayland?
        • 0
          Да, как я понял в протоколе этот механизм не оговорен. В рассылке у них было написано, что получение списка окон и их декораций, все на совести композитора. И в таком случае получается может и не оказаться унификации интерфейса. Ровно как и возможности принудительного отключения декораций у окон. Возможно каждый тулкит реализует это по-своему. Хотя я может(наверняка) еще плохо разобрался в протоколе Wayland
          • 0
            декораций — информации о них (тип окна, свойства и т д)
          • 0
            Примерно так и будет. В идеологию Wayland вообще не закладывались декорации, как таковые. Впрочем, как и окна. Там, скорее, идёт разговор о неких “areas” — этот термин, думаю, лучше отражает сущность «окон» из протокола Wayland. В отличие от X11, в котором идеология, как и в майкрософтовском оконном подходе, обязывает синхронизировать все оконные примитивы с сервером. В Wayland серверу наплевать на богатый внутренний мир того, что крутится за area приложения.

            Соответственно, если я правильно понял, то на каждый сеанс будет по композитору, и, желательно, чтобы этот композитор использовал libwayland — там реализован стандартный механизм перечисления окон.

            Рисование всего, что на окнах, отходит на второй план — либо к клиенту Wayland, либо к нативному тулкиту, либо к самому приложению-owner'у этой area.

            В этом плане Wayland очень по подходу к связке mutter/clutter, что, в общем-то, и не удивительно.
            • 0
              По этому сейчас и подымается вопрос по унифицированной библиотеке рисования окон между разными тулкитами (или стандарта описания этих самых окон).
  • +1
    Спасибо, статья великолепна и содержит хорошую попытку систематизации этого бардака с графикой. Однозначно в закладки!
  • 0
    Вы супер!
    • +3
      То не я супер, то автор.
      • +3
        В следующий раз стоит создавать пост как перевод, тогда рядом с названием будет заметная надпись
        • 0
          Еле нашёл место, где это включается.

          Спасибо!
      • +1
        То, что перевели такой объем, достойно похвалы.
  • +3
    Вот она, рыба моей мечты исконно хабровская статья! Огромное спасибо автору и переводчику за такой материал!
  • +1
    Спасибо! Выражаю надежду, что автор продолжит писать статьи по этой тематике, а автор перевода будет их публиковать на Хабре! Спасибо еще раз.
    • 0
      Жаль только, что автор немного направление на GTK держит. О Qt упомянуто вскольз… аж 2 раза. Но что поделать, работя обязывает.
      • +2
        Да тут и GTK упомянуто очень вскользь.

        Если говорить про KDE/Qt, то у этой связки «свяо атмосфреа». Рисует она с помощью своей собственной, архитектурно закрытой композиции (в силу особенностей тулкита) и не лезет на те уровни, на которых работает связка mutter/clutter. Поэтому, по большому счёту, ему пофиг на низкоуровневые нюансы. А всё остальное у них точно такое же, как и в GNOME/GTK.

        С иксами сложно работать как-то иначе :)
  • 0
    Я правильно понял, что Wayland уже не предназначен для работы по сети? Это было бы серьёзным шагом назад.
    До сих пор многие виндовые админы тоскливо смотрят на меня, запускающего программы с графическим интерфейсом на домашнем компьютере, получая их окна на ноутбуке на другом конце города через шифрованное соединение — и всё это стандартными средствами (ssh + X forwarding). Им для этого приходится изобретать костыли вроде радминов, vnc, тимвьюеров или даже цитриксов, мутить VPN…
    • 0
      У них в официальном прогресс-листе на Wayland написано «Network support will be added soon».

      Только их сетевавя поддержка, наверняка, будет специфической в силу архитектуры. Одно приложение — один клиент Wayland. Очень жирно с точки зрения расхода памяти.
      • 0
        Вроде поддержку VNC внедряют или уже работает…
        но сетевой прозрачности аля X11 у них не будет.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.