LINUX.ORG.RU

Набросать сценарий использования

 ,


0

1

Привет.

Задумал примерно следующее: консольное приложение, окошки открываются как вспомогательный инструмент (может быть много, а может ни одного), каждое окошко в своём потоке. Так понимаю, что пара gtk_application_new() g_application_run() из hello worlda не подходит в таком случае, почитываю мануал, но что-то пока из него не ясно. Может кто чего дельного подскажет и буду читать не всё подряд, а прицельно. Нужно примерно так:

int main() {
   // создаются потоки с окнами window_fn()
   ...
}

void window_fn() {
   // создаю и показываю окошко
   while(true) {
      // обработка gtk сообщений

      // обработка моей собственной очереди сообщений для потока
   }
}

т.е. интересует примерный каркас window_fn(), какое gtk api дёргать для создания окна и однократного запуска оконной процедуры.

★★

GTK+, however, is not thread safe. You should only use GTK+ and GDK from the thread gtk_init() and gtk_main() were called on. This is usually referred to as the “main thread”.

i-rinat ★★★★★
()

Ну ок, закостылю весь гуй в одном потоке (хотя и жаль). Но как обработать события окон без подвисания в цикле ожидая наступления следующих событий? Аналог fltk’шного Fl::check(), обработали текущие и сразу вышли из check.

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

Qt как-то совсем не зашёл. Монструозностью, да и они там приторговывают чем-то. Хотя и gtk не подарок, но под wayland это похоже что единственный приличный вариант.

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

Ты что, тупой? В одном потоке только гуй обновляется. Остальное в других потоках. И события твои сраные

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

В потоке 1 гуй. Поток 2 - главный, раздаёт всем команды. Как из потока 2 сказать потоку 1 открыть новое окно/нарисовать что-то в окне/…?

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

Вот чего хотел:

void gui_thread() {
   gtk_init (NULL, NULL);
   create_window();
   while (1) {
       gtk_main_iteration_do (FALSE);
       thread_message_queue_handler();
  }

Работает, но не годится к сожалению (грузит сильно ЦПУ по очевидным причинам). Надо инициировать события в ГТК цикле/потоке из другого потока. Наскоком не сделать, видимо, надо разбираться в архитектуре ГТК.

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

Удалось быстро победить:

gboolean generate_event(gpointer user_data) {
   g_signal_emit(...);
}

void not_gtk_thread() {
   gdk_threads_add_idle (generate_event, NULL);
}
pavlick ★★
() автор топика
Ответ на: комментарий от RazrFalcon

win32 gdi - reentrant, точнее по-большей части thread-affine. Отсюда скорее всего кстати изначально пошла история с move to thread в Qt.

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

Ну не все. Берешь такой OpenGL в руки и начинаешь мазать что душе угодно... Вывод тот да, будет синхронизироваться, а внутрях то кто мешает многопоточное говно размесить?

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

Ну текстурки генерировать я и в Qt параллельно генерировать. Проблема в user-events и прочем.

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

qt хоть и используют белые люди, но исключительно калеки.

anonymous
()

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

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

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

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

но вроде все GUI строго однопоточные

4.2

В WinApi можно произвольно (поток откуда был вызван CreateWindow[Ex]) выбирать в каком потоке будет работать окно. В Haiku каждое окно работает в отдельном потоке. Окна в разных потоках обрабатываются независимо и если окно в одном потоке зависло, окно в другом потоке продолжает работать. Также окна рисуются параллельно используя ядра CPU.

X512 ★★★★★
()
Последнее исправление: X512 (всего исправлений: 2)
Ответ на: комментарий от i-rinat

Не знал, что GTK оказывается не нужен.

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

В Haiku каждое окно работает в отдельном потоке.

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

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

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

В WinApi и Haiku могут.

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

В WinApi и Haiku могут.

То есть, они на каждый вызов API ещё и как минимум два раза примитивы блокировки вызывают?

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

То есть, они на каждый вызов API ещё и как минимум два раза примитивы блокировки вызывают?

В Haiku нужно блокировать оконный поток только если вызовы API происходят из другого потока. Если API вызывается из обработчика сообщений, то блокировка не нужна. Блокировка происходит без системных вызовов если в этом нет необходимости.

В WinApi методов нет, есть только сообщения, которые можно послать хоть из другого процесса.

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

В Haiku нужно блокировать оконный поток только если вызовы API происходят из другого потока.

Тут либо API потоконебезопасное, и тогда блокировки на совести программиста, либо API потокобезопасное, и блокировки вызываются всегда. Ты же понимаешь, что магии нет, и проверять нужно всегда? Даже если никто не пользуется потокобезопасностью, её всё равно нужно обеспечивать.

В WinApi методов нет, есть только сообщения, которые можно послать хоть из другого процесса.

Мутно там как-то всё. Написано, что CreateWindowA создаёт окно, и оно привязано к нити, которая создала окно, так? Если метода как такового нет, и всё сводится к посылке сообщения, это скорее всего, WM_CREATE, так? То есть, можно послать WM_CREATE любому приложению, и это создаёт окно. Тогда как окно привязывается к создавшему его потоку, если в CREATESTRUCTA нет поля, где задаётся поток? Как это работает? Магия?

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

Тут либо API потоконебезопасное, и тогда блокировки на совести программиста, либо API потокобезопасное, и блокировки вызываются всегда.

Не знаю что вы понимаете под потокобезопасностью, но в документации написано, что можно вызывать методы из другого потока, если сделать блокировку. По вашему для потокобезопасности надо обязательно блокировку внутрь методов вставлять?

Если метода как такового нет, и всё сводится к посылке сообщения, это скорее всего, WM_CREATE, так?

Нет, CreateWindow делает системный вызов в GUI сервер (win32k.sys) и он создаёт у себя структуру данных для окна и сохраняет в неё идентификатор вызывающего потока. WM_CREATE - это оповещение о том, что окно создано, оно отсылается GUI сервером.

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

Не знаю что вы понимаете под потокобезопасностью

Есть устоявшееся понимание thread safe — методы API можно вызывать из разных потоков, не заморачиваясь с блокировками или синхронизацией.

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

Это называется thread-aware или conditionally safe. GTK — thread-aware. Вызываешь gdk_threads_init(), а потом все вызовы оборачиваешь в gdk_threads_enter()/gdk_threads_leave(). Внутри gtk_main() библиотека сама отпускает блокировки, когда нужно. Большей частью бесполезная функциональность. В третьей ветке это API помечено устаревшим.

Нет, CreateWindow делает системный вызов в GUI сервер (win32k.sys)

Ну вот, уже оказывается, что не всё сообщениями делается. И это я только слегка копнул. Чего там ещё наберётся.

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

Ну вот, уже оказывается, что не всё сообщениями делается.

Неточно выразился. Я имел ввиду, что родные контролы вроде кнопки или списка управляются через сообщения. Например чтобы добавить элемент в список, надо отослать сообщение LB_ADDSTRING. Функционал GUI сервера вроде создания/удаления окон, отсылание и приём сообщений, рисования и прочее сделан через системные вызовы и включает все необходимые блокировки (иначе испортятся внутренние структуры данных GUI сервера, графика сломается и будет синий экран). Каждый поток может иметь свою очередь сообщений и набор окон.

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

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

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

То, что хочет сделать ТС, на GTK сделать невозможно, а на Haiku и WinApi можно.

Задумал примерно следующее: консольное приложение, окошки открываются как вспомогательный инструмент (может быть много, а может ни одного), каждое окошко в своём потоке.

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

на GTK сделать невозможно

Отдаёшь основной поток под основной цикл glib, с консолью работаешь во втором потоке, из третьего и выше обмениваешься сообщениями с основным потоком, который рисует все окошки и взаимодействует с пользователем. Не совсем так, как представлял себе ТС.

Судя по тому, что ты тут описывал, в Haiku и Windows роль основного потока исполняет дисплейный сервер. Причём в Windows даже если тебе не нужно много потоков, нужно активно обмениваться данными с этим скрытым GUI-потоком сообщениями, тогда как в линуксовых достаточно позвать функцию, которая не требует сериализацию данных в сообщения, потому что работает в том же потоке.

То есть, есть некоторая штука, которая запускается, требует на себя немного дополнительных ресурсов, ограничивает авторов ПО в возможностях, и это считается супер-фичей? Ну не знаю…

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

в Haiku и Windows роль основного потока исполняет дисплейный сервер.

В GUI сервере Haiku тоже много потоков, по одному на каждый оконный поток клиента. Это не мешает открывать сотни окон без тормозов и большого использования памяти. Отрисовка окон происходит параллельно и использует все ядра CPU. В Windows используется ядерный стек потоков из которых был сделан системный вызов и также всё работает параллельно.

ограничивает авторов ПО в возможностях

Как ограничивает? Скорее GTK ограничивает со своей прибитой гвоздями однопоточностью. Даже Windows 95 многопоточный GUI умеет.

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

Как ограничивает? Скорее GTK ограничивает со своей прибитой гвоздями однопоточностью.

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

В случае с Haiku и Windows, для каждого приложения как минимум два потока. Один скрытый, занимающийся GUI, к которому ты не имеешь доступа иначе как через обмен сообщениями. И один в твоём приложении, в котором ты можешь делать что хочешь. Но больше всего ты там хочешь принимать сообщения от скрытого потока. Так как у тебя нет непосредственного контроля за скрытым потоком, «как-бы сервер» из модели GTK тебе не доступен. Его отобрали. Зато все остальные потоки между собой равны, они клиенты.

Программисту не дают доступ к потоку, который непосредственно занимается GUI. Я понятно объясняю?

Отрисовка окон происходит параллельно и использует все ядра CPU.

X.Org вообще в один поток всё рисует. И знаешь, я видел, что он в 100% упирается только при запуске бенчмарков. Даже на Atom N270, который такой хилый, что даже подумать страшно. Если для графической системе для рисования нужно все ядра задействовать на относительно современных системах, что-то не так в этой графической системе. Возможно, она приличную долю времени тратит на межпроцессную синхронизацию, а не на собственно рисование.

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

Один скрытый, занимающийся GUI, к которому ты не имеешь доступа иначе как через обмен сообщениями.

Что за скрытый поток? Если поток в GUI сервере, то в X.Org тоже есть поток, которых принимает и обрабатывает сообщения из сокета по протоколу X11. Из оконного потока можно вызывать всё что угодно, не только графику, главное не вешать поток на длительное время. Можно даже произвольные процедуры вызывать в оконном потоке, COM так делает через скрытое окно, а в Haiku и костыли со скрытыми окнами не нужны, есть класс BHandler. Пример нескольких оконных потоков для WinApi: https://gist.github.com/X547/8561111d89657ed39df7f2d79cdea97e.

X.Org вообще в один поток всё рисует.

И это плохо.

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

Программа может использовать сложную векторную графику, для отрисовки которой выгодно использовать несколько потоков. Если используется GPU ускорение, то значительная часть векторной 2D графики всё равно обрабатывается на CPU, потому что GPU на неё не рассчитано.

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

Что за скрытый поток?

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

в X.Org тоже есть поток, которых принимает и обрабатывает сообщения из сокета по протоколу X11.

И он вполне справляется без порождения потоков для каждого клиента.

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

Это что, достижение??? Сколько у вас там возможностей отняли, что вы это за что-то особенное считаете?

Пример нескольких оконных потоков для WinApi

А сколько потоков оконная подсистема Windows запускает для клиентов мы всё равно не знаем.

X.Org вообще в один поток всё рисует.

И это плохо.

Если задача не упирается в 100% загрузки одного ядра, то это нормально. Потому что на синхронизацию между многими потоками тратятся ресурсы. Они не бесплатные.

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

Ага, в клиенте. Браузеры, например, так и делают. И под Windows тоже. Не знаю, что там с Haiku, но сильно сомневаюсь, что рисование делается вызовами функций ОС. На трафике туда-сюда всё время потеряется.

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

И он вполне справляется без порождения потоков для каждого клиента.

Как он обрабатывает подключения от нескольких клиентов? Что будет, если какая-нибудь команда будет долго выполняться или ответ от клиента придёт слишком поздно? Всё повиснет? Или они всё на async IO и promise переписали? С учётом большого объёма легаси плохо в это верится.

А сколько потоков оконная подсистема Windows запускает для клиентов мы всё равно не знаем.

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

Не знаю, что там с Haiku, но сильно сомневаюсь, что рисование делается вызовами функций ОС. На трафике туда-сюда всё время потеряется.

В Haiku графика рисуется GUI сервером, клиент посылает сообщения с графическими командами. Команды группируются для эффективности и чтобы не ждать ответа. Трафик особо не тормозит. Нет никаких композиторов и по 2 буфера на каждое окно, так что память экономно используется. Оригинальная система BeOS с такой же архитектурой работает даже на очень старых ПК.

В Windows GDI графика тоже сервером рисуется.

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

Как он обрабатывает подключения от нескольких клиентов? Что будет, если какая-нибудь команда будет долго выполняться или ответ от клиента придёт слишком поздно? Всё повиснет?

История репозитория X.Org начинается с 1999, и в самом первом коммите уже используется select() для асинхронной обработки.

С учётом большого объёма легаси плохо в это верится.

Ну да, подобные верования вполне укладываются в идеологию «не нужно»/«не нужен».

win32k.sys использует ядерный стек клиентских потоков

Что такое «ядерный стек клиентских потоков»? Это какая-то новая терминология? Кроме того, win32k.sys выглядит как загружаемый драйвер ядра, а не само ядро. Странно, что драйвер занимается потоками.

В Haiku графика рисуется GUI сервером, клиент посылает сообщения с графическими командами. Команды группируются для эффективности и чтобы не ждать ответа. Трафик особо не тормозит.

Разве есть приложения, которые плотно используют графику от ОС? Те же браузеры рисуют у себя, а в ОС отдают уже готовые кадры. Ты ведь не пытаешься сказать, что canvas в портированных под Haiku браузерах рисуется через API Haiku? Про Windows даже смысла говорить нет, я точно знаю, что там браузеры растеризуют сами.

Нет никаких композиторов и по 2 буфера на каждое окно, так что память экономно используется.

Через это все графические окружения проходят. Ничего страшного, я уверен, разработчики Haiku справятся с добавлением заднего буфера и композитора. (Даже гуглится запись в их блоге 2011 о том, как это планируется сделать. Наверняка ведь уже сделали.)

Оригинальная система BeOS с такой же архитектурой работает даже на очень старых ПК.

Да, я смотрел видео (https://www.youtube.com/watch?v=BsVydyC8ZGQ). Там перерисовка окон при перемещениях идёт со скоростью примерно 3–5 кадров в секунду, с диким тирингом и весьма заметными артефактами. На том железе можно было сделать лучше, хотя бы потому, что мультимедийные приложения вполне себе неплохо работают. Но они явно сделали выбор в пользу экономии памяти на буферизации. Это не преимущество технологий, как ты пытаешься их представить. Это осознанный размен.

В Windows GDI графика тоже сервером рисуется.

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

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

Что такое «ядерный стек клиентских потоков»?

Поток имеет 2 стека: стек ядра и стек пользовательского режима. При выполнении системного вызова поток переключается на ядерный стек. GUI сервер, реализованный как модуль ядра win32k.sys, с помощью KeAddSystemServiceTable добавляет свою таблицу системных вызовов. При вызовах API GUI сервера вроде CreateWindow или GetMessage делается системный вызов и переключение на ядерный стек.

Пример стека вызовов при обращении к GUI серверу:

...
win32kfull.sys!NtUserPeekMessage+0x1535
win32kfull.sys!NtUserGetMessage+0x92
ntoskrnl.exe!setjmpex+0x7bd5 // ^ kernel stack
win32u.dll!NtUserGetMessage+0x14 // v user stack
user32.dll!GetMessageW+0x2d
...

Разве есть приложения, которые плотно используют графику от ОС?

Все родные приложения. Qt приложения используют свою отрисовку и отсылают серверу растровый буфер в общей памяти.

Ты ведь не пытаешься сказать, что canvas в портированных под Haiku браузерах рисуется через API Haiku?

Родной браузер WebPositive рисует всё, включая canvas, на сервере. В отличии от X.Org, в Haiku более продвинутая серверная графика со сглаживанием, градиентам, аффинными преобразованиями и пр..

Ничего страшного, я уверен, разработчики Haiku справятся с добавлением заднего буфера и композитора.

В Haiku есть двойная буферизация всего экрана. Отдельный буфер для каждого окна не требуется и ничего не мигает.

(Даже гуглится запись в их блоге 2011 о том, как это планируется сделать. Наверняка ведь уже сделали.)

Не сделали и пока не собираются.

Там перерисовка окон при перемещениях идёт со скоростью примерно 3–5 кадров в секунду

В Windows 95/NT 3.51 вообще окна не показываются при перемещении.

3–5 кадров в секунду

Я вижу больше.

с диким тирингом

В Haiku всё ещё есть тиринг, это да. При желании можно исправить через retrace semaphore, но этим пока никто не занимается.

весьма заметными артефактами

В Haiku добавили двойную буферизацию экрана и этих артефактов больше нет.

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

GDI поломали с введением композитора. Теперь он работает на порядки медленнее и сильнее мигает по сравнению с Windows XP. Многие программы включая встроенные Windows программы по прежнему активно используют GDI.

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

Поток имеет 2 стека: стек ядра и стек пользовательского режима.

А, это. Так ведь везде же так. Как иначе реализовывать системные вызовы? Нужен код, который будет выполняться от имени процесса/потока, но в ядре. Не пользовательский же стек для этого использовать. Выражение «ядерный стек пользовательских потоков» звучит как «находящийся в ядре стек, составленный из пользовательских потоков», что довольно странно.

Пример стека вызовов при обращении к GUI серверу:

А вот и причина, по которой ничего не понятно. Тут в примере не «обращение к GUI серверу», а просто вызов обёртки, которая затем делает системный вызов. Что вообще никак не отрицает наличие дополнительных потоков в ядре. И не подтверждает тоже. Не знаю, зачем ты в эту степь разговор заводишь.

В Haiku всё ещё есть тиринг, это да.

В Haiku есть двойная буферизация всего экрана. Отдельный буфер для каждого окна не требуется и ничего не мигает.

Странно, что при двойной буферизации всего экрана всё ещё есть тиринг. Ты ничего не путаешь?

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

Я вижу больше.

6?

Родной браузер WebPositive рисует всё, включая canvas, на сервере. В отличии от X.Org, в Haiku более продвинутая серверная графика со сглаживанием, градиентам, аффинными преобразованиями и пр..

Покажи, пожалуйста, где в коде WebPositive реализация canvas. И пожалуйста, на то место, где API для серверной графики со сглаживанием, градиентами и афинными преобразованиями. Я не нашёл.

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

Тут в примере не «обращение к GUI серверу», а просто вызов обёртки, которая затем делает системный вызов.

То, что начинается с win32kfull.sys!NtUserGetMessage это уже код GUI сервера и фактическая реализация GetMessage. За счёт использования системных вызовов, сообщения и протокол взаимодействия не нужны. Дополнительные потоки для каждого клиента не создаются, проверял.

Странно, что при двойной буферизации всего экрана всё ещё есть тиринг. Ты ничего не путаешь?

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

Покажи, пожалуйста, где в коде WebPositive реализация canvas.

WebKit graphics context.

BView client side.

BView server side.

Растеризатор (AGG).

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

То, что начинается с win32kfull.sys!NtUserGetMessage это уже код GUI сервера и фактическая реализация GetMessage. За счёт использования системных вызовов, сообщения и протокол взаимодействия не нужны.

Опять какая-то каша из терминологии. Какой ещё GUI сервер, если это системный вызов? Ты же libс сервером не будешь называть. Что касается бектрейсов, там обычно дальше KeWaitForMultipleObjects, а ещё дальше KiSwapContext. Что в общем-то логично, это же функция для ожидания сообщений. Какой там ещё GUI-сервер?

Дополнительные потоки для каждого клиента не создаются, проверял.

OK.

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

Это будет работать нормально только если окна никогда не перекрываются. Судя по тому, что проблемы ещё есть, такой подход — не самая лучшая идея.

WebKit graphics context.

OK. До конца не верилось, что они ходят в ядро каждый чих, чтобы оно там рисовало. И зачем-то вырезали из кода бекенд на Skia.

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

Какой там ещё GUI-сервер?

Для единства терминологии я называю GUI сервером любой глобальный сервис, реализующий управление окнами, графику и ввод. Он может быть в виде процесса или модуля ядра, суть от этого не меняется. В начальных версиях Windows NT до 3.51 GUI сервер был в виде процесса (если не ошибаюсь csrss.exe), начиная с 4.0 его перенесли в модуль ядра win32k.sys.

Ты же libс сервером не будешь называть.

libc не глобальна в системе, а загружается заново в каждый процесс (с использованием общей памяти где возможно).

Это будет работать нормально только если окна никогда не перекрываются.

При перекрытии регион окна спереди вычитается из региона окна сзади. В результате регионы окон никогда не пересекаются. Прозрачные окна не поддерживаются.

что они ходят в ядро каждый чих

Не ходят. Сообщения группируются и потом отсылаются одним системным вызовом.

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

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

Не только. Ты ещё и фактически библиотечный код сервером называешь. И всё единство терминологии вылетает в трубу.

libc не глобальна в системе, а загружается заново в каждый процесс (с использованием общей памяти где возможно).

До недавних пор в Linux и Windows ядро мапилось в адресное пространство процесса. Принципиальной разницы с маппингом библиотек не было. Да и сейчас кроме переключения адресных пространств разницы особой нет: ядро тоже подключается заново в каждый процесс.

Не ходят. Сообщения группируются и потом отсылаются одним системным вызовом.

Не ходят, но ходят. Какая-то каша в голове.

Под Linux в браузерах использовали Cairo, который настраивали так, чтобы он был тонкой прослойкой над XRender, в котором есть градиенты, шрифты, линии, антиалиасинг. Однако сначала браузеры перешли на чисто-софтовый Cairo на стороне клиента, а потом вообще заменили на Skia, которая тоже на стороне клиента. Теперь этот путь пытается заново пройти Haiku, а ты почему-то считаешь это преимуществом.

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

ядро тоже подключается заново в каждый процесс.

У ядра, в отличии от so/dll библиотек, единые глобальные переменные (bss секция). В них можно хранить состояние, глобальное для всей системы, такое как список окон.

Не ходят, но ходят.

Чтобы отослать растровый буфер тоже нужно сделать системный вызов. Какая разница что отсылать, растровый буфер или буфер с векторными командами?

Теперь этот путь пытается заново пройти Haiku, а ты почему-то считаешь это преимуществом.

Серверная графика позволяет экономить память, а также удалённо подключаться к рабочему столу и принимать векторные команды в отличии от VNC. В Haiku есть реализация клиента рабочего стола на HTML5 и WebSocket которая принимает векторные команды и рисует их в canvas. Правда она пока не доделана.

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

У ядра, в отличии от so/dll библиотек, единые глобальные переменные (bss секция). В них можно хранить состояние, глобальное для всей системы, такое как список окон.

Ну, да. Такое возможно. Значит ли это, что такое происходит в GetMessage?

Чтобы отослать растровый буфер тоже нужно сделать системный вызов.

Для сигнализации нужно. Для собственно передачи данных — не особо. Буфер мапится в иксах и приложении.

Серверная графика позволяет экономить память

Да. Но можно мапить один и тот же буфер в сервере и клиенте. Потребление памяти такое же, как если бы буфер был только в сервере. По сравнению с таким подходом экономии нет.

а также удалённо подключаться к рабочему столу и принимать векторные команды в отличии от VNC.

И на мультимедии (чем BeOS гордилась) все преимущества теряются, потому что всё равно придётся гонять растры. Хорошо это работает, только на простых окошках, где поля ввода, кнопки и списки.

Сейчас проще просто видео жать встроенным в GPU кодеком, и это видео передавать по сети.

i-rinat ★★★★★
()

Тут люди не особо увлекаются тулкитами и не особо их любят. Лучше спроси у анлоговорящих, там побольше творческих будет.

anonymous
()
Ответ на: комментарий от i-rinat

Ну, да. Такое возможно. Значит ли это, что такое происходит в GetMessage?

GetMessage использует таблицу трансляции HWND -> WND*. Другие вызовы, вроде CreateWindow, используют список окон.

Буфер мапится в иксах и приложении.

Буфер с векторными командами тоже так умеет. create_area - это что-то вроде mmap.

По сравнению с таким подходом экономии нет.

Есть. В Haiku всего 2 буфера на всю систему, если явно не создавать новые. Растровые буферы для каждого окна не выделяются, используется экранный задний буфер.

И на мультимедии (чем BeOS гордилась) все преимущества теряются, потому что всё равно придётся гонять растры.

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

Сейчас проще просто видео жать встроенным в GPU кодеком, и это видео передавать по сети.

И будут артефакты сжатия. Я хочу иметь pixel-perfect отрисовку без артефактов.

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

GetMessage использует таблицу трансляции HWND -> WND*. Другие вызовы, вроде CreateWindow, используют список окон.

И это делает win32k.sys GUI-сервером?

Буфер с векторными командами тоже так умеет.

То есть приложение может смапить себе буфер, нарисовать там что-то самостоятельно, и так поломать удалённый десктоп? Удалённый клиент-то не будет видеть, что приложение что-то нарисовало, только команды серверной отрисовки.

Есть. В Haiku всего 2 буфера на всю систему. Растровые буферы для каждого окна не выделяются, используется экранный задний буфер.

Как я уже выше говорил, этот подход не работает, если допускать перекрытие окон. Если глобальный и принудительный тайлинг, то там сработает, да.

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

Воздушные замки — сразу мимо. Напридумывать можно всё, что угодно.

И будут артефакты сжатия. Я хочу иметь pixel-perfect отрисовку без артефактов.

Ага. Размен качества картинки на скорость обновления. Вариант с попиксельной точностью по производительности будет не лучше VNC.

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

И это делает win32k.sys GUI-сервером?

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

То есть приложение может смапить себе буфер, нарисовать там что-то самостоятельно, и так поломать удалённый десктоп?

Буфер выделяется клиентом и мапится сервером. К чужим буферам доступа нет.

Как я уже выше говорил, этот подход не работает

Отвечал выше, работает через регионы. На скриншотах видны перекрывающиеся окна.

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

Да

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

Буфер выделяется клиентом и мапится сервером. К чужим буферам доступа нет.

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

Если цель в облегчении удалённого доступа, давать прямую запись в буфер приложениям нельзя.

Отвечал выше, работает через регионы. На скриншотах видны перекрывающиеся окна.

Я не сомневаюсь, что работает. Я сомневаюсь, что ты правильно понимаешь, как оно работает.

Повторяю в третий раз. Если есть только два буфера, и они размером с экран, то полностью обеспечить все окна этими буферами можно только если окна никогда не перекрываются. Например, если есть десять окон размером с весь экран, для хранения их содержимого нужно десять буферов размером с экран. А задний буфер по твоим словам только один. Даже если вдруг оба буфера — задние, на десять окон всё равно не хватит.

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