LINUX.ORG.RU

Ситуация с Wayland: факты о X и Wayland.

 ,


29

7

Это вольный перевод статьи, намедни размещённой на phoronix. Оринальная статья — обзор недостатков, их исправлений и преимуществ между X и Wayland. Её написал Eric Griffith, при участии Daniel Stone, специально для ресурса phoronix. Работа собрана по кусочкам из презентаций Keith Packard, David Airlie, Kristian Høgsberg, из страниц про X11, X12, Wayland в вики и на freedesktop.org, из прямых интервью с разработчиками.

Оригинал выпущен под Creative Commons версия 3, с указанием авторства; перевод доступен на тех же условиях (с указанием на авторов оригинала, как мне кажется).

Недостатки X

Прежде всего автор думает, что преимущества Wayland лучше всего понятны через перспективу недостатков X11. Итак, начнём...

  1. Мы потратили последние десять лет на «исправление» X с помощью оборачивания его расширениями и плагинами. Однако, X имеет минимальную поддержку версионирования расширений.
    • Версионирование ведётся для одного клиента, а не для одного соединения с API расширения; если ваше приложение поддерживает одну версию расширения, а библиотеки — другую, вы не можете предсказать, какая версия расширения будет получена в итоге.
    • Мысленный эксперимент: Rekonq поддерживает Xinput 2.2, библиотеки KDE — Xinput 2.0, а плагин Flash — только базовый X11. Все они будут определять, какая версия подсистемы ввода поддерживается браузером Rekonq, и в результате будет отдана одна версия для работы со всем вводом... И это может быть не та версия, которая имеет всё необходимое.
    • Если вы счастливчик, вы получите минимальную поддерживаемую версию и приложение будет работать хорошо. Если вы не очень удачливый, вы получите максимальную версию и будете посылать бесполезные сообщения между клиентом и X.
  2. X имеет четыре подсистемы ввода: базовый протокол X11, Xinput 1.0, Xinput 2.0, Xinput 2.2. Xinput 1.0 канул в Лету, но оставшиеся три остаются взаимосвязанными. Daniel Stone описал это так: «Есть всего три человека, которые действительно понимают, как подсистемы ввода уживаются вместе... И я бы хотел не быть одним из них».
  3. Много лет назад у кого-то появилась идея «механизм, а не алгоритм». Фраза является отсылкой к тому, что X имеет свой уникальный API для рисования и собственную библиотеку вроде GTK+ или Qt. X определяет низкоуровневые понятия, такие как прямая линия, толстая прямая линия, дуга, окружность, неполноценные шрифты и другие элементы конструктора, бесполезные по отдельности. Примечание от Daniel: «Внешний вид толстых линий должен точно соответствовать спецификации, которая обязывает их выглядеть уродливо».
  4. X большой и тупой. Прежде чем мы (сообщество) начали выкидывать его компоненты и использовать обходные пути, X имел внутри почти полную ОС, включая свой сервер печати и свой бинарный транслятор для ELF, COFF и a.out.
  5. Композитинг и синхронизация окон. Разработчики научили X композитингу с помощью Composite Extension. Композитинг хорош для простых случаев, как то: рабочий стол, OpenGL. Но если вы захотите использовать hardware overlays (т.е видео), может случиться катастрофа. В том же браузере содержимое вкладки и окно flash-плагина обрабатываются отдельно и не синхронизируются, так что остаётся лишь скрестить пальцы в надежде. что разница во времени обработки не будет слишком большой. В результате при прокрутке страницы с играющим видео иногда возникают разрывы и артефакты.
  6. Шрифты. Разработчики пытались перенести шрифты под управление X-сервера с помощью расширения STSF, и предоставить клиентам достаточную информацию, чтобы те могли правильно определить расположение шрифтов на экране. Но количество информации, достаточной для выполнения данной задачи, превышало размер самих шрифтов. В итоге было решено предоставить клиентам полную свободу действий, избавившись от шрифтов на сервере.
  7. Протокол без состояний. Иными словами, X ничего не запоминает.
    • «Пожалуйста, создайте мне X.conf. Пожалуйста, используйте его для настройки.» Зачем?! Со временем это было исправлено: файл конфигурации используется для перезаписи параметров по умолчанию, а сами параметры по умолчанию подчищены и могут теперь определяться автоматически.
    • Многие имели проблемы с многомониторными конфигурациями в Linux, ну или хотя бы перенастраивали X после перезагрузки. Недостаток X в том, что он помнит эти конфигурации только после создания /etc/X11/xorg.conf.d/50-monitors.conf, который скорее всего придётся писать вручную.
    • Мы надеемся, что это было исправлено созданием libkscreen, обёртки над xrandr, которая наконец-то стала запоминать параметры мониторов, используя их уникальный EDID.
    • В течение длительного периода (а может быть и до сих пор) при подключении дополнительного монитора в Linux основной монитор имел композитинг, а дополнительный — нет. Это, возможно, исправлено в RandR1.4, но его автор не может найти убедительных доказательств.
  8. Бесполезная иерархия окон. В X каждое поле ввода и текстовая надпись имеют своё окно со своим родителем. Никто не знает, какую же функцию выполняет эта иерархия. Реальные библиотеки (т.е не основанные на компонентах протокола X11) уже давно выбросили весь этот мусор в окно.
  9. Отчасти придирка, отчасти разумное беспокойство... В X11 каждая из координат— 2-байтное число со знаком. То есть, на всех ваших дисплеях должно быть не более 32,768 пикселей. При 100dpi это даёт вам 8,3-метровый дисплей. Замечательно... Но вот факты для сравнения: Windows XP имеет 96 DPI, а мой телефон — 320+. Добавьте сюда растущие разрешения и несколько мониторов, и вы увидите, что проблема приближается очень даже быстро.
  10. Для X всё является окном, и разных типов окон с его точки зрения нет.
    • Скринсейвер — это окно, которое просит X расположить его поверх всех окон, сделать полноэкранным и отдать весь ввод.
    • Всплывающее окно просит X расположить его в заданной точке и отдать весь ввод.
    • Они конфликтуют: скринсейвер не будет активирован, пока показано всплывающее окно.
    • Наверняка ваши скринсейвер и скринлокер не прокинули хуки во все необходимые библиотеки, распознающие клавиши для управления медиа... Представьте, что вы слушали музыку, работая на ноутбуке, а затем закрыли крышку. Ноутбук уснул, скринсейвер стал активным окном. Как только вы откроете крышку, ноутбук проснётся и музыка загромыхает снова, так что снова закрыть крышку окажется проще, чем вбить проль, затем открыть плеер и поставить его на паузу либо выключить звук.
    • Разработчики пытались исправить проблему и сделали спецификацию нового расширения, которое в теории работало. Но когда его попытались реализовать, оказалось, что оно серьёзно ломает модель работы X-сервера. Так что проблема существовала 26 лет и продолжает существовать. Расслабьтесь и получайте удовольствие.
  11. «Но Eric, если X11 настолько плох, то почему бы не сделать X12 вместо нового протокола?». Ну, формально, это уже сделано. При сохранении его под знаменем X возникает практический недостаток: все, кто беспокоится о X, будут иметь право голоса в разработке следующей версии. С помощью названия «Wayland» этой проблемы можно избежать. Никого ничто не волнует. Это не связанный с X проект, разработчики могут творить с будущим дисплейным сервером всё, что душа пожелает, ну а те, кто беспокоится о X, могут пойти разрабатывать X12.

Лекарство от Wayland (пронумерованы попарно с недостатками X).

  1. Весь протокол версионирован. Каждый слушатель получает именно ту версию, которую он поддерживает, и ничего поверх этого. Никаких случайностей.
  2. Подсистема ввода в Wayland очень похожа на Xinput 2.2, за вычетом всего старья и отношения Master/Slave между источниками ввода. Слушатель получит одну виртуальную клавиатуру, одну виртуальную мышь и один невиртуальный сенсорный ввод. Кошмар под названием «мультитач» в конце концов упорядочен. Примечание от Daniel: как один из авторов мультитача в X, я считаю себя достаточно компетентным, чтобы назвать его кошмарным.
  3. У Wayland нет API для рисования, в обход которого можно было бы работать. Wayland ожидает заполнения клиентом буфера рисования, и его не волнует способ заполнения, если не считать контроля за попытками задеть чужие буфера.
  4. Wayland минималистичен, он не хранит внутри себя псевдо-ОС ради контроля вывода графики. Клиенты принимают на себя этот удар, что хорошо — им не придётся заботиться о сверхдолгом сопровождении обратной совместимости. Qt5 избавилось от модуля qt3support. X всё ещё сопровождает то, что было написано 26 лет назад. Примечание от Daniel: кроме того, вызовы к вейланду — не блокирующие, рисование всего рабочего стола не остановится из-за зависания или очень дорогой операции на стороне одного из клиентов: остановится только этот клиент.
  5. В вейланде — принудительный композитинг. Это не означает, что везде должны быть 3D-эффекты или изгибающиеся окна. Под композитингом мы подразумеваем отсутствие разрывов, необновлённых кусков и проблесков. Лозунг вейланда — «каждый кадр будет идеальным». Каждый пиксель прорисован как должно и расположен где должно, и появляется, когда клиент того потребует.
  6. Шрифты отданы клиентам.
  7. Многомониторные конфигурации и гибридная графика (Optimus) отданы клиентам, вейланду нужен только буфер с пикселями и информация о том, где его расположить.
  8. В вейланде есть два вида окон: окна верхнего уровня и подповерхности (в основном для проигрывания видео). Причём, в отличие от X, они синхронизируются. При прокрутке страницы с видео в браузере у вас не будет ни разрывов, ни артефактов.
  9. С точки зрения клиентов, вейланд не оперирует глобальными координатами, предпочитая систему отсчёта поверхности для рисования. Счётчик координат 31-битный, то есть каждая поверхность может иметь 2,147,483,648 пикселей как в ширину, так и в высоту.
  10. Для обеспечения дополнительной безопасности, ваш скринсейвер и скринлокер являются частью композитора. Кроме того, композитор распознает клавиши управления медиа, так что даже при заблокированном экране можно выключить звук.

Некоторые заблуждения в плане X и Wayland.

  1. «X — это юниксвейно». X обрабатывает печать, управление буферами для рисования, имел свой тулкит, обрабатывал шрифты, имел бинарный транслятор — и всё это помимо других задач.
  2. «В X есть сетевая прозрачность» — её нет. Базовый протокол X и DRI-1 имели сетевую прозрачность, но никто не использует ни то, ни другое. Shared-memory, DRI2 и DRI-3000 не имеют сетевой прозрачности и не работают по сети. В наше время X превратился в синхронный, плохо сделанный VNC. Если бы он был плохо сделанным асинхронным VNC, то может быть мы бы и заставили его работать. Но он не такой: XLib синхронная, а переход на XCB медленный, что делает передачу по сети настоящим кошмаром.
  3. «Разработчики Wayland наступают на те же грабли, что и X11, потому что не знают его» — неверно, потому что большинство разработчиков Wayland являются бывшими разработчиками X11.
  4. «Вейланд требует 3D.» — неверно, он требует только композитинга, так что есть даже бекенд на pixman для программной отрисовки.
  5. «Вейланд не умеет в удалённый доступ» — умеет, и должен справиться с этой задачей лучше чем X, отчасти из-за асинхронности протокола. Скорее всего Wayland станет высокопроизводительной версией VNC, и прототип уже есть. Причём мы ещё ни разу не давали идей по его улучшению, и скорее всего сможем сделать его лучше, если приложим усилия.
  6. «Вейланд нарушает обратную совместимость» — с тех пор как XWayland закончен и принят в основную ветку, у нас должна появиться почти совершенная обратная совместимость, потому что каждое приложение, использующее X, получает маленький X-сервер для дальнейшей работы с ним. Нам известно одно препятствие — трансформации окна, ведь приложение думает, что оно расположено в верхнем правом углу экрана, оттого, что клиентский X-сервер приведён к размерам клиентского окна.

Парочка характерных преимуществ Wayland

  1. «Каждый кадр будет идеальным». Каждый кадр будет представлен в правильном порядке (возможен сброс лишних кадров, но вы не получите кадр 199, затем 205, а затем 200 оттого, что сервер извлёк их в произвольном порядке. Каждый кадр имеет свой timestamp.)
  2. Минималистичный! Мы способствуем славному будущему Wayland путём уменьшения пространства для возможных ошибок.
  3. Бекенды, специфичные для оборудования. Думается, некоторые люди заметили появление бекенда Wayland, предназначенного для Rasberry Pi — он позволяет использовать все особенности этой платформы. Такой подход используется не везде, многие вещи не потребуют бекенда для конкретного оборудования, но неплохо бы иметь возможность сделать доработку, когда потребуется.

P.S. От переводчика: заметно, что в статье мало технических деталей или же ссылок, а лозунги я наоборот вырезал. К слову, о минималистичности: для вейланда уже есть композитор, способный отображать окна в 3d-пространстве на манер quake, но что-то я сомневаюсь в правильной обработке звука в таком 3d. Для игр есть OpenAL, который имеет 3d-координаты, соответствующие координатам OpenGL (синхронизация позиций источников звука и слушателя с позициями объектов и камеры производится программистом). Для вейланда нет ничего подобного OpenAL.

Если же кто-то имеет вопросы к авторам статьи — он может задать их на Phoronix.

>>> Подробности

Ответ на: комментарий от anonymous

Вообще говоря текущие API создают такого рода «css», например в офтопике вызываем CreateBrush() и получившийся хэндл используем для отрисовки разного рода объектов. Вроде в иксах аналогично, парамтеры графических операций определяется в GC.

это не css — это даже жалким огрызком css назвать нельзя

css-ом это стало бы, если бы API для рисования знало, что вот сейчас наш CreateBrush/GC используется для рисования поля ввода — и пусть используется, а вот миллисекундой позже он же используется для рисования кнопки, поэтому надо его подменить на заданный юзером

Лайоут предполагает что определение фактических координат элементов будет происходить сервере?

да, на дисплее (это слово удобнее, чем сервер)

Сейчас это вроде бы всегда делают на клиенте (зная размер экрана/окна клиент сам расчитывает расположение).

афайк да

Чтобы не моргало нужно что-то другое использовать (flush, дисплей списки, буферизацию, итд).

соглашусь наверно с любым вариантом, особенно выделив двойную буферизацию... (тяжелый вздох) но ведь это уход еще дальше от хтмл

вот если бы размер формочки менялся именно на дисплее, то менять его можно было бы без задержек по сети (и без гонок) хотя бы в том случае, когда клиент не подписан на сообщения изменения размера — а может быть даже и в последнем случае

www_linux_org_ru ★★★★★ ()
Последнее исправление: www_linux_org_ru (всего исправлений: 3)
Ответ на: Пожалуй, это не имеет смысла... от anonymous

Re: Пожалуй, это не имеет смысла...

Нам бы по-хорошему дотянуть Х11 до Х12, а мы тут уже супер-спецификации супер-протоколов готовы родить... =) IMHO, несколько не то... =)

ага-ага, надо дотянуть до Х100500, но при этом делать вид, что мы не замечаем, как тулкиты плюют на эти спецификации, и просто гоняют битмапы

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от anonymous

Чтобы не моргало нужно что-то другое использовать (flush, дисплей списки

и что, дисплей списки существенно проще, чем scene graph?

www_linux_org_ru ★★★★★ ()
Последнее исправление: www_linux_org_ru (всего исправлений: 2)
Ответ на: Пожалуй, это не имеет смысла... от anonymous

... на 1000-м постинге до меня начинает доходить что копаем глубоко, но похоже не в ту сторону... =) Нам бы по-хорошему дотянуть Х11 до Х12, а мы тут уже супер-спецификации супер-протоколов готовы родить... =) IMHO, несколько не то... =)

На самом деле Х12 в том виде, как он в общих чертах описан, бесполезен и не нужен. Что нужно:

  • Разумеется, исправить все Encoding bugs, как это описано в http://www.x.org/wiki/Development/X12 , но этого не достаточно. Core Protocol надо выкинуть почти весь. От Core Protocol нужны только средства interclient communication.
  • Продумать API, которое будет служить драйверо-независимым клеем между следующими сущностями: различными рисующими API (собственно, OGL и XRender) со стороны клиента и GPU со стороны сервера. Такое API абстрагирует нас от деталей реализации как дисплея, так и клиента, даёт возможность при помощи расширений протокола объявлять новые рисующие API в будущем, автоматически предоставляет сетевую прозрачность на уровне команд отрисовки и (теоретически, при поддержке на клиенте) даёт возможность динамической реконфигурации сервера, вплоть до смены GPU и драйверов «на лету».
  • Новая подсистема обработки ввода и API для неё. Насколько я понимаю, XInput 2 хорошо подходит. Но вот что там с раскладками, не уверен, т.к. не знаком в деталях с подсистемой ввода иксов. Тут хорошо бы кого-то, кто в теме.
  • Подсистема для абстракции «окно». Т.е. API для работы с деревом окон, встроенный композитор, возможность подменять встроенный композитор внешним.

Над пунктами 1, 2 и 4 я помаленьку думаю в свободное время. Постеперенно вырисовывается, как всё организовать.

В принципе, я не считаю задачу неподъемной. Если есть финансы и отчётливое желание реализовать систему с хорошими API с запасом на будущее, то проект вполне реален.

geekless ★★ ()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от ckotinko

Ага, спасибо. Еще у меня есть просьба оценить нижеизложенное.

Я пытаюсь продумать механизм взаимодействия клиента с дисплеем таким образом, чтобы:

  • Рендеринг осуществлялся с максимальной производительностью при выводе на локальной машине.
  • Клиенту не нужно было заботиться о том, локальный дисплей или нет: если дисплей удаленный, команды рендеринга просто прозрачно для клиента форвардятся на удаленную машину.
  • Клиент мог пережить динамическое переконфигурирование дисплея: подключение и отключение мониторов, gpu, перезапуск драйверов и т.п., т.е. ситуации потери контекста рендеринга.

Для этого нам нужен промежуточный API, абстрагированный как от кишок реализации дисплея, так и от конкретного рисующего API. В рамках изложения условно назовём этот промежуточный API — XNext. Вот мои соображения:

В качестве примеров рисующего API я рассматриваю следующие: OpenGL и некий аналог XRender (обернутый в cairo). Можно умозрительно заменить XRender на Direct2D, например. В общем, это какое-то API, которое более понятно для типичного прикладного программиста, чем навороченный OGL.

Клиент обменивается не критичными к производительности данными с дисплейным сервером через сокет. XNext предоставляет следующие сущности клиенту:

Экраны (Screens). Это абстрактные сущности, служащие местом отображения данных. Каждый экран содержит один или несколкьо вьюпортов.

Вьюпорты (Viewports). Это области на экране, которые сопоставлены устройствам отображения графики, т.е. мониторам. Если у нас мультимониторная конфигурация с общим рабоим столом, у нас как раз будет несколько вьюпортов на одном экране.

Устройства (Devices). Это, собственно, GPU. С каждым экраном связано устройство. API позволяет приложению узнать: «если хочешь выводить графику на вот этот экран, используй вот такое устройство». Кроме того, могут быть устройства, не связанные с какими-либо экранами (предназначены только для вычислений, без показа результата на экране).

Вся эта конфигурация может меняться динамически. Вьюпорты могут менять расположение, появляться и исчезать. Устройство вместе с экраном может полностью «отвалиться», т.е. быть выключенным «на горячую» или просто пропасть в результате программного сбоя. Клиенту нужно быть к этому готовым.

Полотна (Canvases). Полотно — это хэндл для рендеринга графики на устройстве. Полотно привязано к устройству. Если устройство исчезает, полотно становится невалидным. Полотно имеет размеры (ширина и высота в пикселях) и, вероятно, еще какие-то аттрибуты. (Не уверен, относится ли формат хранения пикселей к полотну или к контексту рисования в нём.)

Полотно служит для следующего:

  • На полотне можно инициализировать контекст рисующего API и писать туда графику. На полотне также можно инициализировать контекст рисующего API и читать оттуда графику. При этом ввод и вывод полностью развязаны: например, один клиент может рисовать в полотно при помощи OpenGL, а другой использовать эти данные при помощи XRender. Таким образом, полотно служит абстракцией от способа рисования. Через 10 лет у нас для риcования могут использоваться совершенно новые API, но точкой их стыковки друг с другом будет служить всё так же полотно.
  • Клиент может послать полотну уведомление о изменении содержимого, и оно придёт всем клиентам, кто подписан на данное уведомление. (Аналог расширения DAMAGE в X11.) Основное предназначение этой фичи — возможность посылать в композитор уведомления о том, что следует обновить отображение.

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

Если сервер находится на удаленной машине, он возвращает пустую строку вместо имени библиотеки. После этого клиент делает следующее: подгружает (стандартную, девайсо-независимую) библиотеку, которая предоставляет тот же самый API. Данная библиоткека прозрачно для клиента перенаправляет команды рисования через сокет на сервер. На сервере осуществляется вызор реальных функций рисования.

Итак, что получается. Для того, чтобы что-нибудь нарисовать, клиент после запуска делает делает следующее:

  • Получает ID устройства.
  • Запрашивает для данного устройства имя библиотеки, реализующей API рисования.
  • Загружает эту библиотеку в своё адресное пространство. Если сервер вернул пустое имя библиотеки, то загружает некоторую «стандартную» библиотеку.
  • Создаёт на устройстве полотно.
  • В рисующей библиотеке вызывает функцию для создания контекста на этом полотне.
  • Рисует в созданном контексте при помощи стандартного рисующего API.

Клиенту следует быть готовым, что контекст и полотно в любой момент могут стать невалидными. В этом случае он может заново получить ID устройства и переинициализировать библиотеку, полотно и контекст. (Сервер может иметь любые скрытые механизмы управления выводом графики. Например, отключить клиента от локального GPU и подключить удаленное GPU. Если клиент готов к динамической переконфигурации графического стека, он это переживёт.)

// Тут еще можно написать много буков о том, как это всё взаимодействует с оконной подсистемой и композитором, но наверное пока хватит.

geekless ★★ ()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от www_linux_org_ru

вот если бы размер формочки менялся именно на дисплее, то менять его можно было бы без задержек по сети (и без гонок) хотя бы в том случае, когда клиент не подписан на сообщения изменения размера — а может быть даже и в последнем случае

Это всё очень абстрактно, в том смысле, что требует более низкоуровневого фундамента. Нам нужна основа, от которой плясать, наподобие той, что я комментом выше изложил.

В принципе, если у нас есть полотно, на котором можно рисовать любым поддерживаемым API, и есть высокоуровневый API такой как OpenGL, то при помощи ловкости рук можно запилить новый API рисования, который реализует scene graph над OpenGL.

И дальше всё просто: создаём на полотне контекст рисования нашего SceneGraphAPI, закидываем на сервер оный граф, и пусть оно там всё рисуется автоматически.

Но это: именно отдалённая перспектива, когда до победы коммунизма полноценной реализаций дисплейного сервера буцдет совсем ничего.

geekless ★★ ()
Ответ на: комментарий от geekless

А если я захочу написать свой API для рисования по полотну, при этом не хочу его встраивать в текущую реализацию, а хочу сделать её 3rd party, куда мне её вставлять? Как запускать? Например, не нравятся мне ни opengl ни xrender, хочу черепашью графику, но при этом писать её в коде дисплея мне никакого кайфа нет.

thesame ★★★★ ()
Ответ на: комментарий от thesame

Например, не нравятся мне ни opengl ни xrender, хочу черепашью графику, но при этом писать её в коде дисплея мне никакого кайфа нет.

А зачем тебе тогда её «встраивать»? Делаешь свою библиотеку рисования (которая использует XRender в качестве собственного бэкэнда, если тебе нужен вывод на дисплей). Смотри, например, как cairo сделана. У ней есть собственное высокоуровневое API и есть набор бэкэндов, которые позволяют выводить изображение через Xrender, OGL, или просто в буфер памяти, и т.п.

geekless ★★ ()

Продолжу. Итак, оконная подсистема и композитор.

Абстракция окна служит нескольким целям: interclient communication (ICC), логическая организация пользовательского интерфейса, физическая организация пользовательского интерфейса. Подробнее:

  • С точки зрения взаимодействия производных клиентов: клиентам нужен механизм ICC. Поэтому окно является основным объектом для работы ICC. Клиенты могут отправлять окнам сообщения, устанавливать и получать значения произвольных свойств, подписываться на получение сообщений от окон и т.п. Тот механизм ICC, который имеется в X11, сделан в достаточной мере хорошо. Его имеет смысл взять за основу. (Возможно, с некоторым расширением фич.)
  • С точки зрения оконного менеджера: WM служит для логического («смыслового») управления элементами пользовательского интерфейса. Поэтому требуется возможность организовывать окна иерархически.
  • С точки зрения композитного менеджера: CM служит для диспетчеризации ввода между клиентами и для «сборки» итогового изображения, т.е. для «физического» управления элементами интерфейса. Для CM можно использовать либо ту же иерархию, что и для WM, либо реализовывать собственную («вручную», да).
  • С точки зрения возможности встраивания одного агента в графический интерфейс другого агента. Одно приложение может захотеть управлять интерфейсом другого приложения — логически и/или физически — т.е. выполнять функции WM или CM. Поэтому понятия WM и CM следует рассматривать не как специальные приложения или часть сервера (привет вейланду), а как роли, которые может на себя взять любой клиент по отношению к любому другому клиенту. Сервер должен быть так спроектирован, чтобы этому просто не мешать. (Снова привет вейланду.)

Про ICC я писать не буду, в первом приближении можно считать, что оно принципиально не отличается от используемого в X11.

Иерархия окон:

Каждый экран имеет корневое окно (root window).
Каждое окно может иметь произвольное число дочерних окон. Каждое окно имеет ровно одного родителя (кроме корневого окна, не имеющего родителя).
При уничтожении окна уничтожаются все дочерние окна. (TODO: возможно, требует доработки в рамках работы над сессионностью.)
Иерархию можно произвольно модифицировать, т.е. переносить окно от одного родителя к другому.
Каждое окно имеет координаты (относительно родительского окна) и размер.
Каждое окно имеет z-координату для упорядочивания всех окон с общим родителем в стек.

Таким образом, логическая иерархия окон также не отличается принципиально от используемой в X11.

Прикладной «смысл» оконной иерархии лежит за пределами спецификации Xnext. (Даём механизм, а не политику.) Управление верхнеуровневыми окнами приложений должно быть описано в отдельном стандарте, разработанном на основе NETWM.

Рендеринг, комозитинг:

У окна имеются аттрибуты color-canvas, mask-canvas и sensitivity-canvas, содержащие идентификаторы поверхностей.
color-canvas хранит значения RGBA пикселей окна.
mask-canvas хранит маску, определяющую изменяется ли данный пиксель при наложении изображения дочерних окон.
sensitivity-canvas хранит битовый признак для каждого пикселя, определяющий чувствительность окна к событиям ввода.

Если у окна color-canvas не установлен (равен none), композитный менеджер должен обрабатывать это так, будто все пиксели color-canvas полностью прозрачны.
Если у окна mask-canvas не установлен (равен none), композитный менеджер должен обрабатывать это так, будто все фрагменты mask-canvas равны единице.
Если у окна sensitivity-canvas не установлен (равен none), композитный менеджер должен обрабатывать это так, будто все фрагменты sensitivity-canvas равны единице.

Если размеры color-canvas, mask-canvas или sensitivity-canvas не совпадают с размерами окна, результат рендеринга такого окна не определен.

У окна имеется аттрибут blending-mode, указывающий, как при рендеринге следует интепретировать альфа-канал полотна color-canvas. Значения: const — альфа-канал полотна color-canvas без изменений попадает в альфа-канал результирующего полотна; layered — color-canvas обрабатывается по тому же алгоритму, что и полотна дочерних окон.

У окна имеется булев аттрибут mapped, указывающий, учитывается ли окно в рендеринге вывода и обработке ввода.
У окна имеется булев аттрибут visible, указывающий, следует ли клиенту, отвечающему за это окно, обновлять его содержимое.

Композитный менеджер выполняет в оконной подсистеме две связанные функции:

  • Осуществляет рендеринг иерархии окон для получения результирующего полотна (пригодного для вывода на экран или дальнейшей обработки).
  • Осуществляет диспетчерезацию событий ввода от устройств позиционирования вглубь иерархии.

У каждого окна есть аттрибут target-canvas, который указывает на полотно, содержащее результат рендеринга данного окна композитным менеджером. Любой клиент может запросить значение target-canvas, чтобы «видеть», как «выглядит» «готовое» окно. Обычно это требуется композитному менеджеру родительского окна для наложения изображения дочерних окон, но не ограничивается этим. Другие возможные применения: утилиты для снятия скриншотов, отображение превью окон в различных утилитах управления окнами и т.п.

Пусть клиент C желает выступить композитным менеджером для окна W. Для этого он подписывается на событие composite-render данного окна. Одновременно только один клиент может быть подписан на событие composite-render, таким образом у окна может быть только один композитный менеджер. Если на это событие уже был подписан другой клиент, ему отправляется сообщение composite-render, и после этого он сразу теряет подписку на это сообщение. Если ни один клиент не подписан на composite-render, рендеринг данного окна осуществляется встроенным композитным менеджером.

Композитный менеджер обязан своевременно обновлять target-canvas. Для этого он должен подписаться на все события окна W и его дочерних окон, сообщающих о изменениях состояния, после которых требуется обновить результирующий вид окна.

По аналогии с composite-render, существует событие composite-input для регистрации клиента как менеджера, отвечающего за диспетчерезацию событий от устройств позиционирования. Если на composite-input не подписан ни один клиент, диспетчерезацию выполняет встроенный композитный менеджер.

Когда серверу требуется доставить событие от устройства позиционирования, он посылает клиенту, который подписан на composite-input, сообщение composite-input-pointer-state. Клиент обязан определить путь «прохождения» сообщения по его дочерним окнам и ответить одним из следующих запросов:

  • composite-input-pointer-state-dispath-list. Если сообщение «попадает» в дочерние окна, клиент отсылает запрос composite-input-pointer-state-dispath-list, который содержит исходное событие и упорядоченный по «высоте» список дочерних окон, которые «задевает» данное сообщение, а также координаты точки «задевания» для каждого дочернего окна. Сервер попробует диспетчеризировать сообщение каждому из указанных окон. Если все они вернут composite-input-pointer-state-dispath-down, событие pointer-state будет отослано «данному» окну.
  • (снова) composite-input-pointer-state-dispath-list. Если сообщение не «задевает» ни одного дочернего окна, но задевает «данное» окно, клиент отсылает запрос composite-input-pointer-state-dispath-list с пустым списком окон. После этого сервер отошлет «данному» окну событие pointer-state.
  • composite-input-pointer-state-dispath-down. Если событие прошло «насквозь», не задев ни дочерние окна, ни поверхность «данного» окна, клиент отсылает запрос composite-input-pointer-state-dispath-down для диспетчеризации события дальше «вниз» по z-координате.
geekless ★★ ()
Последнее исправление: geekless (всего исправлений: 3)

...дальше.

Как работает встроенный композитный менеджер:

Рендеринг target-canvas встроенный CM осуществляет следующим образом. Псевдокод:

/* копируем в target-canvas содержимое color-canvas */
copy(target-canvas, color-canvas);

/* цикл по всем дочерним mapped окнам в z-порядке снизу вверх */
foreach (reverse(zorder(filter(children, mapped))) => child) {
   /* наложить на target-canvas изображение дочернего окна */
   composite(
       target-canvas,
       mask-canvas, /* накладываем с учетом маски */
       child.target-canvas,
       child.x, child.y, /* по соответствующим координатам */
       child.width, child.heght,
       blend-mode /* с учётом режима изменения альфа-канала */
   );
}

Диспетчерезация ввода встроенным CM осуществляется следующим образом. Псевдокод:


/* если соответствующий фрагмент в sensitivity-canvas равен 0, событие проваливается "вниз" */
if (hittest(sensitivity-canvas, x, y) == false) {
   send(composite-input-pointer-state-dispath-down);
   return;
}

/* цикл по всем дочерним mapped окнам в z-порядке сверху вниз */
hit-children = list();
foreach (zorder(filter(children, mapped)) => child) {
    /* если событие проходит через окно, добавляем окно в список hit-children */
    if (child.x <= x &&
        child.y <= y &&
        x < child.x + child.width &&
        y < child.y + child.height
    ) {
        push(hit-children, tuple(child, x - child.x, y - child.y));
    }
}

/* посылаем composite-input-pointer-state-dispath-to-children */
send(composite-input-pointer-state-dispath-list, hit-children);

В случае, когда внешние CM не вмешиваются в логику работы сервера, алгоритмы рендеринга и диспетчеризации встроенного CM могут быть реализованы с очень хорошим уровнем эффективности. В случае, когда используются внешние CM (или просто приложения, которые запрашивают target-canvas), эффетивность внутреннего композитора менеджера «на стыке» с ними может быть ниже. В любом случае, наблюдаемая логика работы всегда соответствует описанным выше правилам и алгоритмам.

geekless ★★ ()
Ответ на: комментарий от thesame

Строго говоря, для абстрактного железа это не получится. Просто оно слишком разное

ckotinko ☆☆☆ ()
Ответ на: комментарий от geekless

Ага, спасибо. Еще у меня есть просьба оценить нижеизложенное.
Я пытаюсь продумать механизм взаимодействия клиента с дисплеем >

Ну единственное что режима защиту от сбоев не реализовано , а так что вы написали уже не шутка а очень похоже на графическую систему Be-Be .
Сейчас выпущен порт Haiku ,можно посмотреть исходники ,наверняка там есть вкусные вещи .Я тогда в шутку предложил портировать а сейчас и думаю ,а какого хрена ,вроде модель драйверов совместима с линуксом (говорили что драйвера ати (открытые ) портировали от нашей операционки)

maximnik0 ★★ ()
Ответ на: комментарий от geekless

Когда тебе по сети придётся прокидывать не просто прямоугольник пикселей, а весь тот набор метаданных, который необходим для нормальной интеграции окна в рабочее окружение, все проблемы длинного пинга вылезут на тех же самых местах.

Вам не кажется что разделить передачу собственно битмапов, и передачу метаданных на две разные либы - гораздо более KISS-way? Wayland - минималистичная прослойка, и отдельная библиотека взаимодействия мета-данных, на которую завязывают GUI-тулкиты.

Правда, скорее всего этого уже никогда не реализуют, так как с современным интернет-каналом проблема потеряла актуальность.

uhbif19 ()
Ответ на: комментарий от uhbif19

Вам не кажется что разделить передачу собственно битмапов, и передачу метаданных на две разные либы - гораздо более KISS-way?

Канал-то нужен общий. Не прокидывать же «стопицот» соединений tcp. А значит, нужен общий низкоуровневый формат обмена пакетами.

geekless ★★ ()
Ответ на: комментарий от geekless

Можно просто приделать к Wayland API возможность аттача произвольных (бинарных) метаданных. То есть передавать не только буфферы изображений, но и буфферы дополнительных данных.

uhbif19 ()
Ответ на: комментарий от Aceler

Кстати. А почему это в X-ах не сделали? Выглядит же предельно просто. Кэшировать по N запросов.

uhbif19 ()
Ответ на: комментарий от uhbif19

Иксы — в смысле, протокол и сервер — ни при чем: xlib синхронная и написана была изначально куринной лапой. Так и повелось.

geekless ★★ ()
Ответ на: комментарий от geekless

Да и команды отрисовки она умела кэшировать, вспомнил (хотя все остальные - нет).

geekless ★★ ()

дарю мысль:

«всю гуйню транслировать в байткод, выполняемый виртуальной машиной графического сервера»

курите )

geek ★★★ ()
Ответ на: комментарий от note173

Почему такой упор именно на html? Есть немало используемых форматов разметки интерфейса, которые для него гораздо лучше приспособлены.

1. так перечисли их, любопытно

2. и особенно укажи те из них, что рассчитана на то, что энд-юзер с помощью *своего* css начнет их style-ить на *свое* усмотрение, вплоть до удаления ненужного тулбара или переноса его справа налево скажем, и готовят к такому повороту событий программиста

www_linux_org_ru ★★★★★ ()
Последнее исправление: www_linux_org_ru (всего исправлений: 1)
Ответ на: комментарий от geekless

поскольку beastie за каким-то хреном перенес твою тему в толкс, подальше от анонимусов, я отвечаю тут

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

это и означает плохую архитектуру

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

беглый взгляд на это чудо инженерной мысли показывает, что это обычное поле ввода, к которому приделано динамическое меню, реагирующее на onChange поля ввода

я *не призываю* все ивенты, кроме отправки формы, не пускать на клиент/хост, а призываю максимально агрессивно отбирать обработку этих ивентов у клиента, и делать обрабоку на дисплее, но если это не получается — они пусть идут на клиент — и очень странно, что Aceler, как я понял, считает, что людям не захочется пользоваться этим сервисом, если будет возможность обрабатывать event-ы самостоятельно, в коде аппликухи

в частности, как чисто гипотетический вариант, возможно даже скажем сделать интерпретатор glade-файлов/qml-файлов(?) с дополнительными хинтами, который будет агрессивно перехватывать и обрабатывать эвенты на дисплее

www_linux_org_ru ★★★★★ ()
Последнее исправление: www_linux_org_ru (всего исправлений: 3)
Ответ на: комментарий от geekless

GUI не должно быть stateless

ммм... над этим можно подумать

GUI не должно быть stateless, должна быть возможность прямо из декларативного представления интерфейса работать с его состоянием. По типу «нажали на кнопочку, и представление данных в рабочей области сменилось с таблицы на сетку иконок».

че-то тут лишнее... вроде... какой-то оверкилл чувствуется

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от geek

дарю мысль: «всю гуйню транслировать в байткод, выполняемый виртуальной машиной графического сервера» курите )

отнюдь не все, но кое-какой «ява-скрипт» можно исполнять как байткод

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от Aceler

Сей общий знаменатель показывает себя положительно именно в условиях, когда связь между сервером и клиентом тонюсенькая,

по-твоему типичные 10Мбит это тонюсенькая связь?

какая связь будет не тонюсенькой, и есть ли перспектива возникновения не тонюсенькой связи в обозримом будущем, если даже у мобильников скоро типичным будет full hd?

и еще — какая связь должна быть у сервера, рассчитанного на работу хотя бы с 500 гуевыми клиентами с «не тонюсенькой» связью?

www_linux_org_ru ★★★★★ ()
Последнее исправление: www_linux_org_ru (всего исправлений: 1)
Ответ на: комментарий от www_linux_org_ru

по-твоему типичные 10Мбит это тонюсенькая связь?

Пинги, главное пинги.

и еще — какая связь должна быть у сервера, рассчитанного на работу хотя бы с 500 гуевыми клиентами с «не тонюсенькой» связью?

Сервер должен быть в локальной сети — тогда ОК.

Твоя идея была бы прекрасной, если бы разработчики приложений тестировали свои приложения именно в среде с большими пингами. Но увы, подавляющее большинство тестирует на локальной машине, а терминалы — это не их проблемы.

Aceler ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

xaml (.net), xml (android), qml, fx (java fx). Все, что специально разрабатывалось под разметку приложений, а не текста. Все это точно так же динамически парсится перед отображением.

и особенно укажи те из них, что рассчитана на то, что энд-юзер с помощью *своего* css начнет их style-ить на *свое* усмотрение

Это была бы интересная функциональность, необходимая в двух случаях на миллион. Такого не будет.

note173 ★★★★★ ()
Ответ на: комментарий от Aceler

Сервер должен быть в локальной сети — тогда ОК.

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

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

я так оцениваю раз в 20 для full hd дисплея и шрифта приличного размера, а не 12 пикселов высотой

и подумай, есть ли шанс в обозримом будущем заиметь не-«тонюсенькие» каналы от сервера

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от note173

Это была бы интересная функциональность, необходимая в двух случаях на миллион.

кто бы сомневался — вам, хомячкам, это необходимо «в двух случаях на миллион», так что продолжай кушать что вам дают, не отвлекайся на пустые разговоры :-)

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

У меня лично есть возможность дописать все, что нужно, под себя. Кроме этого меня волнуют потребности большинства обычных пользователей. Проблемы пользователей-недопрограммистов не интересуют.

note173 ★★★★★ ()
Ответ на: комментарий от www_linux_org_ru

никто в таких условиях свои приложния тестировать не будет, повторюсь. А значит, в ход пойдут хаки и трюки, плохо совместимые с сетью вообще.

Если же делать протокол специально для терминальных решений - то другое дело.

Aceler ★★★★★ ()

> «В X есть сетевая прозрачность» — её нет. Базовый протокол X и DRI-1 имели сетевую прозрачность

> и DRI-1 имели сетевую прозрачность

Это как? HDMI, воткнутый в роутер?

ZenitharChampion ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.