вторник, 29 января 2019 г.

RetroArch и Wayland

Последние 3 месяца я потратил на доработку одной из самых нужных мне программ - RetroArch. Если вкратце - это мультисистемный, мультиплатформенный эмулятор различных игровых консолей. За подробностями прошу на официальный сайт. Вся суть доработки заключается в улучшении работы RetroArch в окружениях на базе композитного сервера Wayland.


На самом деле, RetroArch уже давно имеет не только поддержку работы в Wayland, но и может работать в Wayland через Vulkan-видеодрайвер, при чём поддержка Vulkan была в него добавлена в день официального выхода спецификации Vulkan 1.0 и именно в Wayland. Однако, несмотря на то, что сам протокол Wayland уже много лет является стабильным, а его поддержка в графических окружениях и тулкитах с каждым годом улучшается и крепчает, RetroArch нуждался в некоторой доработке/рефакторинге. Главное из них - xdg-shell.

XDG-Shell


В базовом протоколе Wayland, описанном в wayland.xml, есть интерфейсы для создания окна, его перемещения, изменения размера и т.д. Однако по своим возможностям они не дотягивают до возможностей современных рабочих столов. Дело в том, что Wayland создавался как очень простой и гибкий протокол, который можно было бы применять не только на десктопных системах, но и в мобильных, киосках, автомобильных интерфейсах. И там он уже активно применяется (например SailfishOS, Tizen). И зачастую того, что есть в базовом протоколе, вполне достаточно. А в случае необходимости - можно написать дополнительный протокол-расширение, и там реализовать что нужно. Но об этом чуть позже. Если же запихнуть в один протокол всё, ну в смысле ВСЁ, то на выходе мы получим страшного, толстого, огромного и неповоротливого монстра. Что абсолютно противоречит изначальной концепции Wayland. Те самые возможности изменения размеров окна, перемещения и так далее, описаны в интерфейсе wl_shell, находящимся в основном протоколе Wayland. Первоначально на нём и были построены те же GNOME Shell или Plasma 5, когда в них только зарождалась поддержка Wayland. Однако вскоре стало понятно, что wl_shell будет недостаточно для реализации всех востребованных пользователями возможностей рабочего стола. И потому разработчики приступили к созданию расширения, специально предназначенного для десктопов и дескопных графических оболочек - xdg-shell.

Протокол xdg-shell реализует в себе всё те же возможности изменения размера окна, перемещения, полноэкранного отображения окна, сворачивания/разворачивания и так далее, однако он гораздо более гибок и удобен с точки зрения разработки десктопной оболочки. Я не буду сейчас углубляться в его нутро, в контексте данной статьи это не имеет смысла. Скажу лишь то, что за несколько лет было выпущено несколько версий этого расширения, прежде чем оно окончательно стабилизировалось в конце 2017 года, правда ходовыми были всего два - xdg_shell_v5 и xdg_shell_v6. Первое было сразу вытеснено вторым, и даже сейчас в той же Plasma 5.14 используется именно шестая, нестабильная версия этого протокола. Что это значит? Нестабильность в данном контексте говорит о том, что в новой версии могут сломать обратную совместимость с предыдущей, и придётся программу дорабатывать. В расширениях, признанных стабильными, гарантируется обратная совместимость, даже если будут добавлены новые функции. Поддержка стабильной версии протокола xdg-shell уже реализована в GNOME начиная с 3.28, в Plsama 5.15, Enlightenment E22, Sway 1.0_beta и Mir. Поддержка в Weston (референсном Wayland-композиторе) пока не реализована.

wl_shell признан устаревшим и не рекомендуется для использования в продакшене. Однако из основного протокола Wayland его выкинуть нельзя, это нарушит обратную совместимость. Теперь непосредственно о том, что сделал я. Изначально я полностью удалил из кода RetroArch поддержку wl_shell, и реализовал только стабильную версию xdg-shell (при чём сделать это удалось далеко не сразу, но тут сказалась моя неопытность и как программиста, и как Wayland-разработчика). Однако почесав репу, и решив что есть люди, которые будут пользоваться чем-то, что имеет только поддержку xdg_shell_v6, а то и вовсе её не имеет, я позже добавил в качестве запасного варианта поддержку xdg_shell_v6, а также до кучи вернул wl_shell. Здесь я последовал примеру разработчиков SDL2. Далее были некоторые доработки, поломки, фиксы, но в целом основная задача была решена - RetroArch получил поддержку работы в современных Wayland-окружениях.

Блокировка экранной заставки


Следующее, что я сделал, это добавил в программу поддержку Wayland-расширения idle-inhibit-unstable-v1. Данный интерфейс нужен для блокировки скринсивера (экранной заставки) во время работы приложения. Ранее данная функция была реализована через D-bus, но я посчитал это костылём и сделал всё более менее стандартно. Это было самое простое, что я сделал, протокол невероятно прост. Попутно благодаря этой работе я раскрыл один баг в KDE Plasma, при котором блокировка экранной заставки не срабатывала корректно. Баг успешно пофикшен.

Декорация окна


А вот это моя любимая часть - декорации окон. В Wayland (как впрочем и в X11) нет интерфейсов для отрисовки рамки окна приложения. Исторически этим занимались оконные менеджеры, которые лепят одну стандартную декорацию окон всем приложениям, будь то медиаплеер, браузер или окно эмулятора терминала. Wayland не занимается отрисовкой вообще, эта задача целиком и полностью ложится на графические библиотеки (GTK+, Qt и так далее), композитор оперирует уже готовыми буферами изображений, связывая их в единое целое и выводя на экран. Это же сейчас происходит в классическом Xorg - он не принимает участие в отрисовке потому должен быть уничтожен. Однако, рамку окна может рисовать как оконный менеджер (композитор в случае с Wayland), так и само приложение. Это сейчас и происходит в GNOME, Weston и например Google Chrome. Те, кто пользуются Гномом, знают что это.



Так как рамку окна приложение рисует себе само, есть возможность кроме стандартных кнопок закрытия, сворачивания и разворачивания, разместить там что угодно. С одной стороны это выглядит современно, функционально, и та же macOS переняла к себе эту фичу. С другой - это невероятный геморрой по обеспечению единого стиля оформления, а также контроля окна (так как оконный менеджер не участвует в отрисовке окна, зависшее приложение невозможно сдвинуть с места). Всё это называется отрисовкой декораций окон на стороне клиента - Client-Side Decorations, или CSD. В противоположность этому, рисовать рамку окна может сам оконный менеджер/композитор - SSD - Server-Side Decorations. Именно этот путь избрали для себя разработчики KDE, и именно это решение поддержало адекватное большинство (например разработчики MPV, SDL2, Qt5, VLC, Sway, wlroots), выпустив стандартное Wayland-расширение xdg-decoration-unstable-v1, заменившее собой аналогичное расширение KDE - server-decoration. Это избавляет от ряда проблем, и самое главное - все приложения выглядят единым стилем, а не каждый во что горазд, как в Windows. Однако разработчики GNOME категорически против этого, и стараются всех склонить к использованию CSD и своего стека технологий. Так что эта война закончится нескоро.



RetroArch в GNOME на Wayland. Рамки окна нет и не предвидится.


RetroArch под Wayland, как нетрудно догадаться, запускался без рамки окна. И здесь, как уже было сказано, два пути: реализовать для RetroArch возможность рисовать рамку окна своими силами, что чрезвычайно сложно, либо - вежливо попросить об этом композитор. Поэтому я реализовал поддержку xdg-decoration, и теперь в окружениях, поддерживающих этот протокол (Sway, Plasma 5.15 пока что) RetroArch получает свою заслуженную рамку окна!

RetroArch запущенный в Plasma Wayland 5.15


Это основное, что было реализовано, не считая кучи мелких правок и доработок. Но это ещё не всё, мест для улучшения на самом деле ещё хватает. Но о них поговорим в другой раз. Внизу оставлю ссылки на полезные материалы, объясняющие суть Wayland и работы всей современной графики в Linux простым понятным языком.

Что придёт на замену X?
Wayland на замену X Window System

Комментариев нет:

Отправить комментарий