LINUX.ORG.RU

Низкоуровневое рисование пикселей в Xlib

 , ,


0

3

В тред призываются могущие в Xlib и в целом в иксы люди.

Рисование примитивов встроенными функциями(XDrawRectangle/etc) на дефолтном GC в Xlib сделано круто. Такая программа потребляет очень мало оперативной памяти (~500 байт) и работает довольно быстро. Круто в общем. Круто. Но у этого способа есть масса очевидных недостатков. Можно ли в иксах писать информацию о пикселях в какой-нибудь указатель на массив-буфер, и в конце скармливать этот буфер иксам?

Гугл говорит о всяких Ximage, но это совсем не то. Во первых памяти потребляется гораздо больше. Во вторых появляется куча проблем с ресайзом, производительностью и т.п. Есть другой способ?



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

XVideo

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

А XImage между прочим shm использует.

Да, есть версия XImage с shm, но я так и не понял зачем оно. Расскажешь? Ты вроде разбираешься.

XRendering для моих целей это как-то слишком.

kartator
() автор топика

Например вот так https://paste.debian.net/hidden/e816a1a7/ через xcb - результат https://i.imgur.com/QNol6YR.png. Из треда Прокрутка(неполная перерисовка) изображения в иксах

Сейчас я не вижу особого смысла что-то писать под голые иксы, учитывая скорый переход на всякие вяйленды и Mir

cast Zubok

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

С первого взгляда неплохо, потребление памяти даже меньше чем в xlib, но стоит расширить массив с 8*8*4 до 1920*1080*4 и вот мой a.out сожрал 10 метров рамы. Почему так происходит? В том же Xlib я могу забить 1920x1080 пикселей каким-нибудь XFillRectangle и ничего, расход памяти не изменяется, а тут сразу 10mb. В чём беда?

Сейчас я не вижу особого смысла что-то писать под голые иксы, учитывая скорый переход на всякие вяйленды и Mir

Да я решил написать себе небольшой тулкит для гуя. Сейчас сижу на иксах, вот и рисовать он будет с помощью xlib(или xcb), а потом добавлю поддержку вяленого, это не проблема.

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

Забыл добавить, при ресайзе этот пример ну ооочень сильно грут процессор. Собственно, как я и говорил:

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

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

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

endeneu13
()

SZT, спасибо! Теперь у меня появилось одной заботой больше. :)

Ты, наверное, хочешь с некоторой надеждой спросить, а можно ли напрямую пикселями прямо на экране управлять, прямо в памяти видеокарты? Нет, нельзя! Не хочется ликбез тут устраивать - в сети все есть. Твой вариант XImage. В случае локальной машины через XSHM. И организация двойной буферизации поможет тебе сделать все красиво. У Pixmaps пиксели недоступны напрямую без копирования содержимого в XImage (мы не рассматриваем Shared Memory Pixmaps, которые лучше не использовать). Отрисовка Pixmaps аппаратно ускоряется, живут они, как правило, в видеопамяти GPU, могут мигрировать.

Ответ: XImage. (XShmPutImage или XPutImage — в зависимости от доступности расширения XSHM).

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

С первого взгляда неплохо, потребление памяти даже меньше чем в xlib, но стоит расширить массив с 8*8*4 до 1920*1080*4 и вот мой a.out сожрал 10 метров рамы. Почему так происходит?

По-моему ответ тут очевиден. 1920*1080*4 = 8294400 байт. Переведем байты в мегабайты, дважды поделив на 1024 = получим 7,91015625 мегабайт. У тебя-то этот массив хранится в памяти процесса.

В том же Xlib я могу забить 1920x1080 пикселей каким-нибудь XFillRectangle и ничего, расход памяти не изменяется, а тут сразу 10mb.

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

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

Как я понимаю, можно в том же xcb сделать pixmap из буфера, вызвав xcb_create_pixmap_from_bitmap_data() и потом через xcb_copy_area() этим pixmap-ом рисовать в окне.

В xcb для shm есть функции xcb_image_shm_put() и xcb_image_shm_get(). А писать в эту shm память можно, получив из структуры xcb_shm_segment_info_t указатель shmaddr http://xcb-util.sourcearchive.com/documentation/0.3.5/structxcb__shm__segment...

struct xcb_shm_segment_info_t
{
  xcb_shm_seg_t shmseg;
  uint32_t    shmid;
  uint8_t     *shmaddr;
};
Только я не понял, это аналог XShmPutImage или Shared Memory Pixmaps? И чем плох этот Shared Memory Pixmaps?

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

Ответ: XImage. (XShmPutImage или XPutImage — в зависимости от доступности расширения XSHM).

Сложный твой XSHM, примеров мало, не разобрался, потом приделаю. Поковырял пока обычный XImage, без shm, и в целом доволен. Почему-то раньше у меня было всё куда хуже, а сейчас нормально, даже вопросов особо и нету. Хотя я немного не понимаю почему у меня без двойной буферизации нет мерцаний. Вот код: https://bpaste.net/show/2aa7685ef2ca . Она вообще нужна? (Если да, то объясни в двух словах как её реализовать, пожалуйста. Предполагаю, что всё можно сделать родными средствами, но также знаю про существование расширения для иксов с реализацией этой самой двойной буферизации.)

Ещё заметил, что при ресайзе память процессу выделяется немного странно. Я точно всё правильно сделал?

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

По-моему ответ тут очевиден. 1920*1080*4 = 8294400 байт.

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

Потому что XFillRectangle это одноцветный прямоугольник, очевидно же.

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

kartator
() автор топика
polyPoint(Dpy, Drawable, GCid, CoordMode, Points) ->
  Pts = create_points_for_polyline(Points, <<>>),
  Pts2 = add_pads(Pts),
  B = <<Drawable:32, GCid:32, Pts2/binary>>,
  Dpy ! {send, construct_xrequest(64, CoordMode, B)},
  ok.

create_points_for_polyline([], A) -> A;
create_points_for_polyline([{X, Y}|T], A) ->
  A2 = <<A/binary, X:16/signed, Y:16/signed>>,
  create_points_for_polyline(T, A2).

clearArea(Dpy, Wid, Exposures, {X, Y, W, H}) ->
  Exp = case Exposures of true -> 1; false -> 0 end,
  B = <<Wid:32, X:16/signed, Y:16/signed, W:16, H:16>>,
  Dpy ! {send, construct_xrequest(61, Exp, B)},
  ok.
anonymous
()
Ответ на: комментарий от SZT

Только я не понял, это аналог XShmPutImage или Shared Memory Pixmaps?

Это XShmPutImage. Для Pixmap не нужно Put и Get. Он же уже Pixmap (drawable).

И чем плох этот Shared Memory Pixmaps?

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

https://www.x.org/releases/X11R7.7/doc/xextproto/shm.html

Shared memory pixmaps can only be supported when the X server can use regular virtual memory for pixmap data; if the pixmaps are stored in some magic graphics hardware, your application will not be able to share them with the server.

Но зато в Shared Memory Pixmaps можно рисовать иксовыми функциями рисования и тут же получать результат напрямую в приложение попискельно, тут же по месту обрабатывать и забрасывать назад без посредников. В XImage нельзя иксовыми функциями рисовать.

В некоторых драйверах по умолчанию эти Shared Pixmaps отключены и их надо опцией включать. Просто раньше некоторые старые приложения, которые, возможно, еще существуют, могли использовать этот механизм (я знаю, что в Java 2D можно включить этот механизм, например). Для них и оставили опцию, если они не смогут работать:

http://us.download.nvidia.com/XFree86/Linux-x86/325.15/README/xconfigoptions....

Option «AllowSHMPixmaps» «boolean»

This option controls whether applications can use the MIT-SHM X extension to create pixmaps whose contents are shared between the X server and the client. These pixmaps prevent the NVIDIA driver from performing a number of optimizations and degrade performance in many circumstances.

Disabling this option disables only shared memory pixmaps. Applications can still use the MIT-SHM extension to transfer data to the X server through shared memory using XShmPutImage.

Default: off (shared memory pixmaps are not allowed).

Но вроде не у всех это отключено.

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

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

Всмысле? В xlib можешь рисовать через XFillRectangle. В xcb есть аналогичная функция - xcb_poly_rectangle(). См. https://xcb.freedesktop.org/tutorial/basicwindowsanddrawing/

Или тебе надо перекопировать нечто из одной области в другую? Так для этого xcb_copy_area() есть.

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