LINUX.ORG.RU

Задача обойти XGetImage

 ,


0

2

Есть задачка, не знаю как решить:

Есть моя программа, которая открывает Display, в нем создает Window и gc. Затем, в цикле в окне происходит рисование примитивов всяких типа XDrawLine и подобных им. Затем, когда один кадр отрисовался - мне надо полученную картинку в виде битмапа сохранить в файл. Для этого я делаю XGetImage и его сохраняю. Дальше рендерится следующий кадр, и так по кругу. Все работает, но очень медленно. Рисование примитивов занимает сотню микросекунд (окно небольшое и рисования не много), а вот получение картинки с X-сервера функцией XGetImage занимает почти миллисекунду. Под виндой на этой же машине такое-же рисование с получением памяти занимает примерно в 10 раз меньше времени.

XSHMGetImage проблему особо не решает, т.к. продолжает копировать память через pipe.

И вот задача, как бы обойти этот XGetImage? Мне по факту не нужно окно, рисование в некие области памяти вполне подойдет, лишь бы был быстрый перевод того что находится в Window и gc в Image/битмап. Но при текущей реализации окно по факту есть, и отрисовка в него тоже.

Видится мне такое решение - так как XDrawLine по сути выполняется на X-сервере, и так или иначе память кадра будет в любом случае формироваться именно там, а дальше получить ее можно только через XGetImage/XSHMGetImage - то исключить впринципе Xorg из процесса, написав на все функции рисования примтивов - обертки, которые по факту меняют бмп, которая затем идет в файл. Но это много кода и довольно нетривиальная задача.

Может есть способ проще?



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

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

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

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

Рисует не человек я так понял, тогда вообще никакая графика в принципе не нужна. Взять tga/bmp формат, написать функции которые в нём будут рисовать (прям напрямую) тоже самое что и «XDrawLine и подобных им», рисуешь и результат сразу как есть на месте доступен готовый блоб с картинкой, отправляй его прям сразу как есть.

Аллоцируешь новую картинку , опять в ней рисуешь, отправляешь и так по кругу.

Картинка не сложная но очень быстро меняющаяся

Капчи генерируешь? :)

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 2)

Есть моя программа, которая открывает Display, в нем создает Window и gc. Затем, в цикле в окне происходит рисование примитивов всяких типа XDrawLine и подобных им.

Зачем ты вообще ковыряешь ложкой этот древний иксовый кал?

Делай так, как делают нормальные люди – возьми AGG, Blend2D, Skia, Cairo или вообще Qt с QPainter, Graphics View Framework и заодно получишь не только адекватную отрисовку и рендеринг хоть в файл BMP/PNG, хоть в PDF, хоть в окно со всеми нормальными шрифтами, сглаживаниями и пр. но и вот это вот:

под соврешенно разными операционными системами

Или цель просто страдать?

EXL ★★★★★
()

1. Сделать окно кратно больше, нарисовать много изображений за раз, получить их оптом одним XGetImage, нарезать на части, сохранить части.

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

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

Для скорости на видеокарте текстурки должны лежать в видеопамяти, а для скорости на процессоре - в системной. Вдобавок до внедрения resizable bar видеопамять не была доступна напрямую для процессора из обычных api, потому что там было жалкое окошко в 256мб и его использованием заведовал драйвер.

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

И что? Автор рисует простые картинки в одном кадре, который и 10мб не занимает. И рисует скорее всего процом.

видеопамять не была доступна напрямую для процессора

Что это за враньё? Она была доступна с начала времён PC.

firkax ★★★★★
()

Мне по факту не нужно окно, рисование в некие области памяти вполне подойдет…

Никого не слушай, тебе рисовать можно в drawable это не только window это и pixmap который также может быть на SHM который быстрый.

обертки, которые по факту меняют бмп, которая затем идет в файл

это тоже просто - делаешь файловый mmap, пишешь в память автоматом сохраняется на диск.

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

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

В любом случае, в чему это всё, как это связано с вопросом автора? У автора нужная картинка находится в юзерспейсной памяти процесса Xorg, он хочет вытащить её побыстрее в свой процесс.

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

Зачем ты вообще ковыряешь ложкой этот древний иксовый кал?

Делай так, как делают нормальные люди – возьми …

Совсем друг другу не противоречат. Пусть готовит кадр графическими библиотеками, и блитит (putimage) и сохраняет в файл.

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

картинка находится в юзерспейсной памяти процесса Xorg

который через сетевую прозрачность может находиться в «юзерспейсной памяти процесса Xorg» на другом компьютере в сети. Область памяти сериализуется через всю эту «сетевую» прозрачность. Для «прямой работы с видеопамятью» нужен dri.

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

Ты про проблему автора пишешь или о чём вообще? У автора Xorg на том же компе и ему доступен XShm чтобы через сокет картинки не слать. И никакой прямой работы с видеопамятью ему не нужно, ему вообще видеопамять не нужна. Хватит флудить.

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

XShm не сильно поможет в случае GetImage, так как картинка будет вытаскиваться из видеопамяти на видеокарточеке в юзерспейс (хотя это зависит от кривизны/прямизны драйверов).

Ему надо делать наоборот. Готовить кадр или картинку (часть) в своём процессе, и слать готовую картинку в иксы и в файл. А не оперировать гланды через весь графический стек: сперва рисовать в иксах, потом вытаскивать из иксов.

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

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

И хотя твоё заявление про «долгое вытаскивание из видеопамяти» доверия совершенно не вызывает, ему уже предложили рисовать в Pixmap вместо окна - тогда точно никакой видеопамяти не будет участвовать.

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

он иксы использует как библиотеку для рисования

И каждая операция в Xlib - это синхроннная операция с переключением контекста. Вроде, xcb умеет в асинхронщину, возможно даже группировать запросы. И проходит ли каждая операция через драйвер видеокарты (видеоускорение?) - это тоже вот вопрос.

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

Вовсе нет. Вызов какого-нить XDrawLine() это по сути обёртка к буферизованной отправке в сокет с помощью send() какого-то пакета в иксовый сокет. Сервер примет этот пакет, наверно даже скоро, но без каких-то строгих обязательств. Если хочешь чтобы отправка сделалась сразу (и потратить время на переключение в ядро и назад для сисколла) - делай XFlush(). Если хочешь ещё и узнать что тебе ответил икс-сервер - делай XSync(). Но это всё не дефолт а только если явно сделаешь.

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

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

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

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

100500/1 что ничего такого ТС не делал..он даже и не рисовал :-)

научился по id окна делать скриншот и хочет это убыстрить, дабы недо-LLM-распознавалки всё успевали. Вся хрень про рисование примитивов через XLib - езда по ушам.

иначе это необъяснимо :-)

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

100500/1 что ничего такого ТС не делал..он даже и не рисовал :-)

O ! минуснюк появился..

если закопипастите свой код реального приложения, рисующий примитивы XLib, может и соглашусь. А так - НЕТ, процитированное ВЕРНО

в 99.99% реальных случаев рисование(по нисходящей) это cairo, gl, gtk, Qt, wx и итоговая отправка дельты результата в X (собственно потому его и критикуют и оттого он и тормозит).

MKuznetsov ★★★★★
()