TL;DR — Если ваше графическое окружение Linux во время просмотра видео, сеанса игры или прокрутки интерактивной веб страницы не успевает вовремя обновлять картинку целиком, то тогда для вас имеет смысл установить последнюю стабильную версию ядра ? 4.10.


Давным давно, то есть несколько лет назад каждая реализация протокола X11 предполагала смену режима видео напрямую, поперек батьки кернела. Затем появился KMS (kernel mode setting) и эта важная функция перешла к ядру. Но остались некоторые шероховатости. Атомарная смена режима является дальнейшим улучшением механизма KMS.


Для чего нужны атомарные операции KMS? Главным образом для того, чтобы избежать вот таких моментов.





Атомарная смена режима видео


DRM драйвер с поддержкой атомарной смены режима, a? k? a? atomic mode setting имеет полезное свойство, которое заключается в том, что изменения видео режима проходят полную проверку прежде, чем вступят в силу. Это делается с целью обеспечить их корректное исполнение в драйверах и на дисплее с тем, чтобы избавить пользователей от мерцания, тиринга и прочих артефактов изображения. Скорость исполнения при этом также повышается. Звучит неплохо, а как это работает?


  • Framebuffer — Видео память, однако в терминологии KMS это скорее пул источников памяти видео — объектов GEM, для которого заданы такие характеристики как активная зона памяти, или то, что будет изображено, а также формат данных, длина шага.

Framebuffer





DRM/KMS Components:  Framebuffer
struct drm_framebuffer {
[...]
    unsigned int pitches[4];
    unsigned int offsets[4];
    unsigned int width;
    unsigned int height;
    int flags;
    [...]

  • CRTC — Аббревиатура расшифровывается как Cathode Ray Tube Controller, CRT Controller. Мало кто в нынешнее время использует мониторы на электронно-лучевых трубках, однако историческое название сохранилось с виде абстракции железа, которое считывает байты с памяти видео-карты и выдает пиксели на шину данных.
  • Encoder — Интерфейс между разнородными источниками видео, читает с CRTC и передает в соединительный разъем, a? k? a? Connector. Один CRTC может иметь несколько кодеров.
  • Connector — Это может быть представлением для соединительного разъема монитора или же самим монитором в случае встроенных устройств с подключенных внешним экраном.
  • Planes — Слой или план изображения на CRTC.




Для этого надо понять как изменяется видео режим без этого нововведения. Рассмотрим обычный сценарий, в котором пользователь смотрит видео в окне браузера или плеера, не в полный экран, используя аппаратное ускорение. Видео образует передний план, окно и декорации браузера или плеера, это второй — задний план.


  1. Драйверу видео передается список различных параметров: кадровый буфер, CRTC, экраны, режим.
  2. Пользователь перемещает окно плеера.
  3. Для этого нужно подгрузить новую страницу, a? k? a? page flip, например.
  4. Если новая страница не синхронизирована между передним и задним планом, видео сместится относительно своего окна.

struct drm_mode_crtc_page_flip {
     __u32 crtc_id;
     __u32 fb_id;
     __u32 flags;
     __u32 reserved;
     __u64 user_data;
};

Механизма, обеспечивающего синхронизацию на предпоследнем шаге нет, отсутствовал ioctl(), который выполнял бы всю работу. Например, только основной план имел механизм неблокирующих обновлений критичных с точным завершением событий. А для того, чтобы обновления произошли в нескольких слоях, требовалось куча системных вызовов из пользовательского пространства в надежде на то, что они завершатся синхронно. В то же время атомарные операции KMS имеют встроенную защиту от этого. Вместо трех разных ioctl(), все изменения проходят в одном единственном ioctl().


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


Работы над «атомным» проектом началась в 2015-м с патчей Дейва Эйрли (Dave Airlie), затрагивающих интеловские i915 и еще несколько драйверов, плюс новое атомарное API.


В настоящий момент атомарный процесс обновлений происходит следующим образом.


  1. Все изменения передаются ядру одним списком свойств (в середине картинки Properties).
  2. Ядро генерирует состояние устройства (справа на картинке State).
  3. atomic_check() проверяет валидность всех элементов списка свойств. Если есть ошибка ioctl() вернет уведомление об ошибка и отменит обновления.
  4. atomic_commit() также в соответствии с названием вводит изменения в действие, если на предыдущем шаге atomic_check() завершился без ошибок.




Структура атомарной KMS определена в файле /usr/include/uapi/drm/drm_mode.h.


#define DRM_MODE_PAGE_FLIP_EVENT 0x01
#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100
#define DRM_MODE_ATOMIC_NONBLOCK 0x0200
#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400
struct drm_mode_atomic {
    __u32 flags;
    __u32 count_objs;
    __u64 objs_ptr;
    __u64 count_props_ptr;
    __u64 props_ptr;
    __u64 prop_values_ptr;
    __u64 reserved;
    __u64 user_data;
};

Для открытых драйверов Nouveau от Nvidea атомарный KMS включен по умолчанию начиная с версии Linux 4.10, для драйверов Intel — начиная с 4.12. Дальше — больше!


Использованные материалы


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


  1. mrobespierre
    01.09.2017 02:30
    +2

    Включал эту штуку на Intel HSW — работало великолепно, butter-smooth, как охарактеризовал phoronix. В amdgpu, к сожалению, поддержки не завезли, и в этом году скорее всего уже не будет.


  1. monah_tuk
    01.09.2017 06:02

    для драйверов Intel — начиная с 4.12

    что-то, начиная с ядра 4.12 (4.13-rc6 — аналогично), стал ноутбук с непонятной зависимостью выпадать в осадок (фриз) после выхода из suspend. Навело на мысль — попытаться выключить данную функциональность.


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


    1. mrobespierre
      01.09.2017 06:45

      а в выводе

      journalctl -b -1

      после висяка есть что-то подозрительное?


      1. monah_tuk
        01.09.2017 07:08

        Нет. Точнее как. systemd нету, но в остальном в логах всё нормально. Выводил на экран tail -f /var/log/everything, куда валится в т.ч. выхлоп логов ядра и выводил логи ядра на консоль, через повышение приоритета до 9 через SysRq. Сразу после просыпания те же логи несколько мгновений ещё активны, в последнее зависание остановилось на:


        [ 1490.408672] ata2: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
        [ 1490.412964] ata2.00: ACPI cmd e3/00:1f:00:00:00:a0 (IDLE) succeeded
        [ 1490.414439] ata2.00: ACPI cmd e3/00:02:00:00:00:a0 (IDLE) succeeded
        [ 1490.424057] ata2.00: ACPI cmd e3/00:1f:00:00:00:a0 (IDLE) succeeded
        [ 1490.425337] ata1: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
        [ 1490.425462] ata2.00: ACPI cmd e3/00:02:00:00:00:a0 (IDLE) succeeded
        [ 1490.428787] ata2.00: configured for UDMA/133
        [ 1490.435960] ata1.00: ACPI cmd ef/02:00:00:00:00:a0 (SET FEATURES) succeeded
        [ 1490.435964] ata1.00: ACPI cmd f5/00:00:00:00:00:a0 (SECURITY FREEZE LOCK) filtered out
        [ 1490.437232] ata1.00: ATA Identify Device Log not supported
        [ 1490.437234] ata1.00: Security Log not supported
        [ 1490.438251] ata1.00: ACPI cmd ef/02:00:00:00:00:a0 (SET FEATURES) succeeded
        [ 1490.438254] ata1.00: ACPI cmd f5/00:00:00:00:00:a0 (SECURITY FREEZE LOCK) filtered out
        [ 1490.439246] ata1.00: ATA Identify Device Log not supported
        [ 1490.439248] ata1.00: Security Log not supported
        [ 1490.439252] ata1.00: configured for UDMA/133

        (это часть валидного лога пробуждения, но для невалидного случая — всё так же).


        Да, SysRq тоже в этом состоянии не работает.


        1. mrobespierre
          01.09.2017 07:17
          +1

          печаль-тоска, значит откатываться на 4.9 — оно LTS, ждать 4.14 и надеяться на лучшее


    1. temujin Автор
      01.09.2017 07:10

      У меня такое было со старым кернелом, но всего лишь 1-2 раза. После 4.12 некоторые особо интерактивные веб страницы, как https://arstechnica.com наконец стали плавно прокручиваться.


  1. Denega
    01.09.2017 06:50

    Ура, товарищи!


  1. Mercury13
    01.09.2017 08:31
    +2

    :)
    Да уж, в линуксе был DRM (direct rendering manager) — теперь есть и KMS (kernel-mode setting).
    Троллят виндовозников?


  1. RZK333
    02.09.2017 01:24

    для любителей экзотического — если у вас заводится kms, можно выкинуть дефолтный fbcon\getty и загрузить вот это www.freedesktop.org/wiki/Software/kmscon wiki.archlinux.org/index.php/KMSCON вместе с поддержкой любых извращенств с шрифтами.


    1. maxzhurkin
      02.09.2017 08:07

      Эта штука может давать неприятные моменты, такие, как каша в видеопамяти после переключения с иксов; помогает переключение в другую консоль, но их количество ограничено (каша возвращается после повторного переключения с иксов и уже на всех задействованных консолях).


      1. RZK333
        02.09.2017 13:37

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


        1. maxzhurkin
          02.09.2017 13:42

          Нет, не занимался этим вопросом на таком уровне