commit -m "better"
Будни #bootstrap, обещаный текст про сборку reddit desktop, #imgui * оно требует libmpv, для просмотра видосиков. Почему не ffmpeg напрямую - загадка. Все бы ничего, но сборка libmpv(или это свойство waf вообще) страдает обычным для OSS багом - "а давайте…
#imgui, #wayland, #sdl, #hidpi #gold
Так, третья, заключительная, часть рассказа про "собрать какое-нибудь приложение c imgui".
Прошлый рассказ я закончил на том, что у меня все собралось, запустилось, но было очень сильно замылено.
Скриншот мне делать лень, поэтому просто представьте себе, что картинка была rendered в буфер 100x100, который был растянут на экран 200x200.
Кстати, ровно та же проблема у меня наблюдалась с #dosbox.
Суммарно на решение это проблемы я потратил часов 10, фактически, все прошлые выходные. Зачем? Ну, потому что интересен процесс, а не результат. И потому что, предполагается, что владелец дистрибутива способен такие проблемы пользователей решать, я так думаю.
Я, пожалуй, не буду вдаваться в детали процесса, это слишком долго, я просто расскажу, как устроен hidpi в wayland, к чему это привело в модели sdl, и что я с этим сделал.
* В wayland у каждого буфера, в том числе on screen, есть, кроме обычных WxH(+ формат, но нам это не интересно), еще параметр scale. На мой взгляд, назван он неверно, и это долго меня сбивало с толку.
* Когда композитор отрисовыает буфер приложения в экранный буффер, он масштабирует буфер приложения в отношение scale этих двух буферов. Ну, то есть, если screen->scale == 2, app->scale == 1, то буфер от приложения будет увеличен в 2 раза.
* После чего композитор попиксельно отображает буфер приложения в экранный буффер, отсекая лишнее.
Давайте на примерах:
* screen == 200x200x2, app == 100x100x1. Увеличим app buffer в 2 раза, отобразим получившуюся картинку 200x200 as is. Так, фактически, работают старые приложения, которые не hidpi-aware.
* screen == 200x200x2, app == 100x100x2. Мы получим, что приложение заняло верхнюю левую четверть отведенного ей экрана.
* screen == 200x200x2, app == 200x200x2. Четкая, pixel perfect, картинка.
Что еще важно понимать?
Если композитор имеет размер буфера для приложения 200x200, и screen scale 2, то он, в качестве желаемых размерностей пошлет приложению 100x100, чтобы non-hidpi-aware приложения как-то работали. hidpi aware приложения, для того, чтобы рассчитать размер буфера для отрисовки, должны эту величину умножить на переданный scale.
А дальше все тулкиты изголяются, кто во что горазд.
Например, что делает SDL:
* Он hidpi aware, поэтому он выделяет буфер размера w * scale, h * scale. То есть, цепочка: композитор имеет буфер 200x200x2, он передает в SDL 100x100x2, SDL выделяет буфер для рисования 200x200x2. https://github.com/libsdl-org/SDL/blob/main/src/video/wayland/SDL_waylandwindow.c#L1901-L1905
* Далее SDL делает что-то странное. Он говорит, что всю отрисовку теперь мы будем делать в неких point, point у нас 100x100, каждый point физически отображается в 2 пикселя. https://discourse.libsdl.org/t/high-dpi-mode/34411
* ImGui берет размерности экрана в этих point, 100x100, делает gl viewport 100x100 над буфером 200x200, и рисует в свое удовольствие заблюренный контент.
То есть, как будто hidpi aware приложение само готовит контент низкого разрешения.
Я пробовал починить это разными способами, лучше всего сработал такой - https://git.sr.ht/~pg/ix/commit/fab9a5086801ea5e41d1e454f6c3a26abe9a06ed#pkgs/bin/reddit/desktop/hidpi/imgui_impl_sdl.cpp:
* В коде ImGui умножить размеры, передаваемые SDL, на scale.
* Получится так, что мы создадим viewport 200x200 над буфером 200x200, и отрисовка будет pixel perfect.
Почему я не могу расценивать это как финальное решение:
* Потому что, кроме gui, SDL возвращает масштабированными события от мыши, и получается, когда я их умножаю на scale, я теряю точность(мышка двигается по 2 пикселя по вертикали и гризонтали). Я не смог это заметить глазами на retina display, но как-то неаккуратно. https://forums.libsdl.org/viewtopic.php?p=43373
На мой взгляд, тут баг в SDL, что, когда приложение говорит, что оно hidpi aware, то надо ему возвращать настоящие пиксели, а не points.
Что мне делать с моим патчем в ImGui, я пока не понимаю.
BTW, должен сказать, что, после моего фикса, hidpi support в imgui кажется очень классным, потому что все размеры во float, и привязаны к размеру шрифта.
Так, третья, заключительная, часть рассказа про "собрать какое-нибудь приложение c imgui".
Прошлый рассказ я закончил на том, что у меня все собралось, запустилось, но было очень сильно замылено.
Скриншот мне делать лень, поэтому просто представьте себе, что картинка была rendered в буфер 100x100, который был растянут на экран 200x200.
Кстати, ровно та же проблема у меня наблюдалась с #dosbox.
Суммарно на решение это проблемы я потратил часов 10, фактически, все прошлые выходные. Зачем? Ну, потому что интересен процесс, а не результат. И потому что, предполагается, что владелец дистрибутива способен такие проблемы пользователей решать, я так думаю.
Я, пожалуй, не буду вдаваться в детали процесса, это слишком долго, я просто расскажу, как устроен hidpi в wayland, к чему это привело в модели sdl, и что я с этим сделал.
* В wayland у каждого буфера, в том числе on screen, есть, кроме обычных WxH(+ формат, но нам это не интересно), еще параметр scale. На мой взгляд, назван он неверно, и это долго меня сбивало с толку.
* Когда композитор отрисовыает буфер приложения в экранный буффер, он масштабирует буфер приложения в отношение scale этих двух буферов. Ну, то есть, если screen->scale == 2, app->scale == 1, то буфер от приложения будет увеличен в 2 раза.
* После чего композитор попиксельно отображает буфер приложения в экранный буффер, отсекая лишнее.
Давайте на примерах:
* screen == 200x200x2, app == 100x100x1. Увеличим app buffer в 2 раза, отобразим получившуюся картинку 200x200 as is. Так, фактически, работают старые приложения, которые не hidpi-aware.
* screen == 200x200x2, app == 100x100x2. Мы получим, что приложение заняло верхнюю левую четверть отведенного ей экрана.
* screen == 200x200x2, app == 200x200x2. Четкая, pixel perfect, картинка.
Что еще важно понимать?
Если композитор имеет размер буфера для приложения 200x200, и screen scale 2, то он, в качестве желаемых размерностей пошлет приложению 100x100, чтобы non-hidpi-aware приложения как-то работали. hidpi aware приложения, для того, чтобы рассчитать размер буфера для отрисовки, должны эту величину умножить на переданный scale.
А дальше все тулкиты изголяются, кто во что горазд.
Например, что делает SDL:
* Он hidpi aware, поэтому он выделяет буфер размера w * scale, h * scale. То есть, цепочка: композитор имеет буфер 200x200x2, он передает в SDL 100x100x2, SDL выделяет буфер для рисования 200x200x2. https://github.com/libsdl-org/SDL/blob/main/src/video/wayland/SDL_waylandwindow.c#L1901-L1905
* Далее SDL делает что-то странное. Он говорит, что всю отрисовку теперь мы будем делать в неких point, point у нас 100x100, каждый point физически отображается в 2 пикселя. https://discourse.libsdl.org/t/high-dpi-mode/34411
* ImGui берет размерности экрана в этих point, 100x100, делает gl viewport 100x100 над буфером 200x200, и рисует в свое удовольствие заблюренный контент.
То есть, как будто hidpi aware приложение само готовит контент низкого разрешения.
Я пробовал починить это разными способами, лучше всего сработал такой - https://git.sr.ht/~pg/ix/commit/fab9a5086801ea5e41d1e454f6c3a26abe9a06ed#pkgs/bin/reddit/desktop/hidpi/imgui_impl_sdl.cpp:
* В коде ImGui умножить размеры, передаваемые SDL, на scale.
* Получится так, что мы создадим viewport 200x200 над буфером 200x200, и отрисовка будет pixel perfect.
Почему я не могу расценивать это как финальное решение:
* Потому что, кроме gui, SDL возвращает масштабированными события от мыши, и получается, когда я их умножаю на scale, я теряю точность(мышка двигается по 2 пикселя по вертикали и гризонтали). Я не смог это заметить глазами на retina display, но как-то неаккуратно. https://forums.libsdl.org/viewtopic.php?p=43373
На мой взгляд, тут баг в SDL, что, когда приложение говорит, что оно hidpi aware, то надо ему возвращать настоящие пиксели, а не points.
Что мне делать с моим патчем в ImGui, я пока не понимаю.
BTW, должен сказать, что, после моего фикса, hidpi support в imgui кажется очень классным, потому что все размеры во float, и привязаны к размеру шрифта.
GitHub
SDL/src/video/wayland/SDL_waylandwindow.c at main · libsdl-org/SDL
Simple Directmedia Layer. Contribute to libsdl-org/SDL development by creating an account on GitHub.
🔥9👍2