LINUX.ORG.RU

Прокрутка(неполная перерисовка) изображения в иксах

 , , , ,


1

1

Допустим я делаю на xcb нечто графическое, и мне надо прокрутить что-то, например это может быть браузер, и мне надо проскроллить вниз, чтобы прочитать дальше. Или может я делаю сайд-скроллер типа какого-нибудь супермарио, и человечек идет влево, я хочу плавно прокручивать это дело. Мне не хочется на каждый шаг влево перерисовывать всю картинку с нуля (как при событи Expose), я хочу сдвигать уже нарисованный «фон» со всеми врагами, чтоб экономить процессорное время. Каким образом это можно реализовать в xcb? Есть ли там способ сдвигать уже нарисованное куда-нибудь вбок, дорисовывая новое с края? Может для этого мне стоит использовать opengl?

★★★★★

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

нет,можно детектить перерисовываемые участки и их перерисовывать,так собственно и устроены ВСЕ DE что в гноме что в кде что другие включая винду,это если говорить про «рисование в vesa режиме без ускорений)

либо таки осилить opengl

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

ты сам описал и проблему и решение

...не буду строчить стену коротко:

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

вобщем ты правильно спросил-в иксах такого нет-это делают внешние библиотеки,начиная от GTK или Cairo или QT или SDL ....и прочих сотнях фреймворков

тоесть бери либо сразу OPENGL и костыляй свой рендер,либо бери готовых(хоть софтварный)-выше перечислено,или гугли

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

нет,можно детектить перерисовываемые участки и их перерисовывать

Мне не просто надо детектить и перерисовывать какие-то участки, мне надо сдвигать уже нарисованное, дорисовывая что-то новое с краев

вобщем ты правильно спросил-в иксах такого нет-это делают внешние библиотеки,начиная от GTK или Cairo или QT или SDL ....и прочих сотнях фреймворков

А разве все эти GTK Qt Cario и прочее не работают ПОВЕРХ xcb или xlib? Какие библиотечные вызовы из xcb позволят мне сдвигать нарисованный фон, если я не хочу пока что заморачиваться с этим непонятным opengl?

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

cast Zubok (он что-то подсказывал по теме этих xcb xlib в каких-то старых темах)

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

Теневой буфер, в который рисуется мир, сдвигается любым удобным для вас способом. В буфер дорисовывается недостающая информация. Далее этот буфер рендерится в окно приложения.

Еще есть понятие dirty rectangles. Такой подход часто применяли на zx-spectrum 48 (поскольку видеобуфер там был только один). Иногда его применяли и на zx-spectrum 128, хотя там было несколько страниц, которые могли мапиться на видео - зависит от задачи, нет серебряной пули. Этот этот подход я применял и на телевизионной приставке PowerTV в нескольких играх. Подход рабочий, но не очень удобный. А если двигающихся объектов много, то такой подход и вовсе слишком дорогой получается, дешевле будет перерисовать весь мир.

andreyu ★★★★★
()
Последнее исправление: andreyu (всего исправлений: 1)

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

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

Мне нужно больше конкретики. Я использую xcb. Какие из этих https://xcb.freedesktop.org/manual/group__XCB____API.html#func-members функций будут мне сдвигать буфер? Как это делать?

Вот например код https://paste.fedoraproject.org/332708/91779145/ крестиков-ноликов через этот xcb, там отрисовывается сетка и кресики-нолики. Компилировать вот так gcc -O3 -std=c99 tictactoe.c -lxcb. Я хочу эту сетку сдвигать(размер игрового поля может быть значительно больше размера окна) вместе с нарисованными на ней кресиками-ноликами, но не хочу перерисовывать их все при сдвигании, а перерисовывать только часть, которая «приползла» из той области, которая до этого сдвигания не была видна. Что надо делать? Какие функции xcb использовать?

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

И еще. Если я просто смещаю(двигаю мышкой) уже отрисованное окно, событие XCB_EXPOSE не вызывается. И при этом само отрисованное окно смещается на экране. Никакой перерисовки делать при этом не надо. Как можно это задействовать чтобы сделать подобный скроллинг?

SZT ★★★★★
() автор топика

Наверное попробую использовать возможности 3D видеокарт, например сделаю плоскость и наложу на нее текстуры с прозрачными областями, потом можно эту плоскость двигать (как спрайты). Знать бы только, как все это работает на аппаратном уровне

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

Двойная буферизация + xcb_copy_area. Это если ты рисуешь средствами X11 (core protocol или Render). GLX - это уже другой механизм. И еще будет зависеть от того, где у тебя хранится изображение окна: на X-сервере или с клиентской стороны. Есть приложения, которые любят рисовать на стороне X-клиента, а результат забрасывать на сервер.

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

А разве все эти GTK Qt Cario и прочее не работают ПОВЕРХ xcb или xlib?

мда....учит матчасть

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

что и сделано в «фреймворках»-там и написаны функции для ускорения отрисовки,и да в томже QT или GTK тупая прокрутка цельного фона(разноцветного) будет быстрее попиксельной тупой из иксов,почему-потому что оптимизация(а какая-это смотри исходники или сходи в институт на 1(первый) курс,там учат основам дискретной математики)

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

Двойная буферизация + xcb_copy_area. Это если ты рисуешь средствами X11 (core protocol или Render).

Мне нужен некий пример кода. Как https://paste.fedoraproject.org/332708/91779145/ к этому коду прикрутить двойную буферизацию? Функции xcb_poly_line xcb_poly_arc в качестве аргументов принимают xcb_connection_t *connection и xcb_drawable_t window Судя по всему, для рисования этим функциям нужно действующее подключение к X серверу через сокет. Запустив некоторые простейшие программы на xcb под strace, я увидел что там для рисования графических примитивов делается вызов writev (т.е. программа пишет в сам X сервер какой-то набор инструкций для рисования). Если я хочу делать свой буфер для двойной буферизации, этот самый буфер должен быть в адресном пространстве процесса Xorg? Или мне надо создать обычный двухмерный массив в самой своей программе и с какой-то там периодичностью его отсылать в иксы на полную перерисовку? Покажите пример такого кода, если не трудно

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

(а какая-это смотри исходники или сходи в институт на 1(первый) курс,там учат основам дискретной математики)

Какая еще нафиг дискретная математика, если надо просто смещать прямоугольные области?

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

Esli sdvigat nado vverh\vniz, to memmove

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

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

Какая еще нафиг дискретная математика, если надо просто смещать прямоугольные области?

вот и узнаешь про операции с матрицами,для начала(на которых все 3д-ускорителя стоят)

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

Я и так знаю про матрицы поворота и всякие там матрицы перемещения, но ГДЕ эти матрицы поворота в иксах без OpenGL(GLX) используются? По-моему нигде

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

но ГДЕ эти матрицы поворота в иксах

удивительно правда?а теперь второй пункт-учимся читать собеседника

в иксах такого нет-это делают внешние библиотеки,начиная от GTK или Cairo или QT или SDL ....и прочих сотнях фреймворков

в первом посту в этой теме

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

Библиотеки GTK или Cairo или Qt или SDL не могут внести ничего нового в протокол иксов. Они могут использовать только имеющиеся возможности, заложенные в него. Это просто надстройки, которая в итоге работает через все те же XCB Xlib и прочее.
То что ты пишешь, это примерно как утверждать что вот в ассемблере у нас нет определенных инструкций процессора, но вот если взять Haskell то они непременно появиятся! Типа вот сам факт использования высокоуровневого языка или фреймворка может внезапно добавить в процессор какие-то новые инструкции. Но ведь любому здравомыслящему человеку очевидно, что это не так. Все, что реализуется на высоком уровне, можно реализовать и на низком. И если в каком-то там GTK я могу смещать изображение, то сам этот GTK по-любому будет использовать какие-то обращения к X серверу через Xlib XCB и он не может сделать ничего сверх того, что я могу сделать в этом XCB-Xlib напрямую.

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

ПРИЧЕМ ТУТ ПРОТОКОЛ ИКСОВ

божички

ты на VESA можешь рисовать «супербыстро» либо «супертормознуто» попиксельно проходя весь экран

тыкой бред пишешь мда

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

ну да

а потому что у тебя монитор двухмерный с ограниченным разрешением ты ничего кроме картинки одного разрешения и двумерной ничего выводить не можешь

вот это чтото на уровне твоего непонимания что такое рисовать и как можно медленно рисовать и как можно ыстро...

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

а потому что у тебя монитор двухмерный с ограниченным разрешением ты ничего кроме картинки одного разрешения и двумерной ничего выводить не можешь

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

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

Функции xcb_poly_line xcb_poly_arc в качестве аргументов принимают xcb_connection_t *connection и xcb_drawable_t window

Смотри, я вот выше написал, что надо выяснить, где же ты рисуешь: на стороне клиента или на стороне сервера. Если я правильно понимаю твой вот этот текст, ты пока рисуешь командами core protocol. Чтобы сделать теневой буфер, тебе нужно создать pixmap (он тоже drawable, как и window) и рисовать в этот pixmap, а не напрямую в окно. Этот pixmap и есть твой буфер на стороне сервера. А когда кадр готов, то делать xcb_copy_area в окно (то есть из drawable в drawable).

Если я хочу делать свой буфер для двойной буферизации, этот самый буфер должен быть в адресном пространстве процесса Xorg?

Если ты рисуешь командами сервера (core protocol или Render), то рисовать ими в пространство клиента ты просто не можешь. Поэтому тут буфером будет pixmap, и все работы с массивом берет на себя сервер. Ты ему только говоришь, откуда и куда скопировать.

Если же ты все рисуешь у себя, на X-клиенте, то тогда ты сам себе создаешь буфер и думаешь над тем, как тебе сдвигать. Когда все, что нужно, нарисовал, то можешь на сервер отсылать готовую картинку (xcb_put_image, xcb_shm_put_image).

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

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

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

Ничего толкового у меня не выходит с этим xcb_copy_area и xcb_put_image

https://paste.debian.net/412636/ — вот через xcb_copy_area с созданием pixmap

https://paste.debian.net/412637/ — вот через xcb_put_image с буфером из случайных пикселей

Ни в том ни в другом случае в окно ничего не выводится.

Пробовал еще код отсюда https://stackoverflow.com/a/27755418 но он вообще мне выдал Shm error...

ЧЯДНТ?

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

Я так с ходу не соображу. Первое, что сделай: добавь еще XCB_MAP_NOTIFY в обработку событий. Это первое событие, которое ты получишь:

switch (event->response_type & ~0x80) {
    
        case XCB_MAP_NOTIFY:
        case XCB_EXPOSE:
         ....
        break;
...

Что выходит?

UPD. Ай, а чего ты GC создаешь до окна? Окно еще не создал, а Graphic Context у тебя до create_window. У тебя даже id окна еще в этот момент не сгенерен. Вот он и не рисует.

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

UPD. Ай, а чего ты GC создаешь до окна? Окно еще не создал, а Graphic Context у тебя до create_window. У тебя даже id окна еще в этот момент не сгенерен. Вот он и не рисует.

Хотя сейчас увидел, что у тебя window еще до создания окна инициализирован на root window, поэтому дело не в этом.

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

Первое, что сделай: добавь еще XCB_MAP_NOTIFY в обработку событий. Это первое событие, которое ты получишь:
Что выходит?

Без изменений. Если б проблема была в том, что событие не вызывается, я б это выявил. Событие EXPOSE я могу сделать, максимизировав-минимизировав окно

UPD. Ай, а чего ты GC создаешь до окна? Окно еще не создал, а Graphic Context у тебя до create_window. У тебя даже id окна еще в этот момент не сгенерен. Вот он и не рисует.

Этот код был сделан на основе примера отсюда(в самом конце) https://xcb.freedesktop.org/tutorial/basicwindowsanddrawing/ и там все нормально работает и рисует, если брать код в том неизменном виде, в котором он там

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

Может быть проблема в глубине цвета? Можешь сам проверить этот код у себя

В нем, ага. Вот ты сам допер, а я не заметил. Надо глубину ставить, какую тебе сообщил сервер, а не явно 32 (у тебя. скорее всего, глубина 24). Перед тем, как рисовать в pixmap только не забудь фон закрасить белым ему (или там другим цветом, каким надо тебе).

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

При помощи xcb_get_geometry на окно или окно root ты сможешь получить depth.

Еще вот. Когда ты получаешь screen:

xcb_screen_t *screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data,

то там есть screen->root_depth

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

Да, xcb_copy_area с созданием pixmap при глубине цвета 24 работает.

Перед тем, как рисовать в pixmap только не забудь фон закрасить белым ему (или там другим цветом, каким надо тебе).

Закрашивать через xcb_poly_fill_rectangle или есть какой-то более правильный способ?

А с выводом через xcb_put_image у меня так ничего и не вышло
https://paste.debian.net/hidden/c357af25/ - последняя моя попытка. Выставил глубину в 24, вроде все правильно
Пример с использованием xcb_shm_put_image отсюда https://stackoverflow.com/a/27755418 тоже не хочет работать. В чем тут может быть проблема?

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

И что означают все эти XCB_IMAGE_FORMAT_XY_PIXMAP XCB_IMAGE_FORMAT_XY_BITMAP XCB_IMAGE_FORMAT_Z_PIXMAP? Может быть проблема в этом?
http://www.x.org/releases/current/doc/man/man3/xcb_put_image.3.xhtml - почему такая скудная документация?

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

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

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

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

Если речь идет о рисовании средствами исков, то тебе нужно расширение Render (xcb_render_...)

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

https://paste.debian.net/hidden/e816a1a7/ вот короче то, что получилось в итоге и работает https://i.imgur.com/QNol6YR.png - выводит 3 квадратика с полосками разных цветов.
Несмотря на то, что глубина цвета указана как 24 т.е. по 3 восьмибитных байта на пиксель, в самом массиве надо по 4 восьмибитных байта на пиксель использовать. Но почему? Я не понимаю. Я думал что 4 байт это такой альфа-канал (цветовое пространство BGRA), но 4 байт полностью игнорируется, никакого альфа-смешивания не происходит.

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

Никакого смешивания не будет. Core protocol не знает, что такое альфа-канал. Чтобы было смешивание, надо использовать Render. то есть рисовать картинку в picture, а потом композитить ее.

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

Уфф, в общем спасибо за советы. С этими смешиванием я пока толком не разобрался. https://xcb.freedesktop.org/manual/group__XCB__Render__API.html куча каких-то функций без какой-либо документации. Я не знаю как в этом разобраться. Исходники Xorg и XCB пытаться прочесть, или как? У всех этих XCB функций есть точный эквивалент в xlib?

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

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

У всех этих XCB функций есть точный эквивалент в xlib?

Есть. XRenderComposite (vs xcb_render_composite) и т. д. Xlib просто чуточку более высокоуровневая библиотека.

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

куча каких-то функций без какой-либо документации.

Я вообще рекомендую в случае именно xcb смотреть больше не на документацию Xlib (но на нее тоже за компанию, потому что она во многом совпадает), а на документацию по X-протоколу, потому что xcb - это буквально реализация протокола 1:1. Например, нужен xcb_render_composite. Это команда протокола Composite расширения Render (xcb_<расширение>_<команда>). Все параметры этой команды будут аргументами функции xcb_render_composite вплоть до названия. Но в описании протоколов нет примеров.

По расширению Render ищи renderproto.txt. Такие файлы есть для всех расширений протокола. К тому же, названия аргументов будут в точности совпадать с xcb, так как в xcb названия брали прямо из документации, чтобы путаницы не возникало.

http://www.x.org/releases/X11R7.7/doc/index.html

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 6)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.