LINUX.ORG.RU

Проблемы с XRenderComposite

 , , ,


1

2

Сделал проект демонстрирующий косяк(?): http://pastebin.com/jtCcRz9B.

Суть в том, что если получить через KWindowSystem::windows() список окон и для каждого сделать скрин через XRender, то если открыто несколько окон одного приложения вместо последнего в скриншоте будет фигня: http://postimg.org/image/3zmrvxtqz/. Если я меняю порядок получения скриншотов на обратный (рассортирую WId от большего к меньшему), то иногда всё нормально: http://postimg.org/image/4c3nbrzyr/, а иногда всё равно косяки при чём на одном и том же окне - окне с большим WId.

Это не зависит от числа открытых окон, если одно - ок, если 2 - косяк со вторым, если 3 - с 3им, и т.д. При чём это только для окон одного приложения, если приложения разные то всё ок.

Собственно вопрос, что за фигня происходит и как это можно чинить? А так же детектировать в автоматическом режиме ибо ничего не отваливается, а в консоль просто сыпятся сообщения вида?

X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Extension:    139 (RENDER)
  Minor opcode: 4 (RenderCreatePicture)
  Resource id:  0x7400005
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x7400005
X Error: RenderBadPicture (invalid Picture parameter) 143
  Extension:    139 (RENDER)
  Minor opcode: 7 (RenderFreePicture)
  Resource id:  0x1e0001f

ПС. Приложение делает скрины Dolphin'а

★★★★★

Последнее исправление: ya-betmen (всего исправлений: 2)

Ответ на: комментарий от ya-betmen

А какая программа в kwin этот скриншот получает, ты не выяснил? Или это сам kwin?

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

Насколько я понял, код вот:

Pixmap
XCompositeNameWindowPixmap (Display *dpy, Window window)
{
    XCompositeExtDisplayInfo	    *info = XCompositeFindDisplay (dpy);
    xCompositeNameWindowPixmapReq   *req;
    Pixmap			    pixmap;

    XCompositeCheckExtension (dpy, info, 0);
    LockDisplay (dpy);
    GetReq (CompositeNameWindowPixmap, req);
    req->reqType = info->codes->major_opcode;
    req->compositeReqType = X_CompositeNameWindowPixmap;
    req->window = window;
    pixmap = req->pixmap = XAllocID (dpy);
    UnlockDisplay (dpy);
    SyncHandle ();
    return pixmap;
}

Synchronous Calling
To ease debugging, each routine should have a call, just before returning to the user, to a routine called SyncHandle(). This routine generally is implemented as a macro. If synchronous mode is enabled (see XSynchronize()), the request is sent immediately. The library, however, waits until any error the routine could generate at the server has been handled.

Либо SyncHandle влияет, либо XAllocID отложенно аллоцирует.

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

Либо SyncHandle влияет, либо XAllocID отложенно аллоцирует.

XAllocID аллоцирует XID, а не pixmap! Уникальный XID. Саму область создает X Server. И при этом еще Realloc ей делает самостоятельно, когда окно меняет размер.

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

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

Нет, ну синхронизация при помощи XSync() пока выглядит не совсем противоречиво. Но нужны обоснования, что это правильно. X Composite Extension у нас в основном композитные WM пользуются, а их не так много.

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

А если посмотреть исходники разных программ, использующих X11, то «XSync(dpy, False)» (google) довольно часто используется. Он нужен только, чтобы убедиться, что запросы выполнились. Нам, кстати, именно это и надо. Но использование XComposite* настолько редкое, что такой же usecase еще поискать надо. Документация на протокол и Xlib не проясняет момент.

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

Ну раз ТС это подходит, то значит это решение для него. Меня, правда, смущает факт, что у него, когда он менял порядок идов на обратный все работало.

Но в любом случае я каску на стройке нашел.

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

Ну раз ТС это подходит, то значит это решение для него

А мне как-то не нравится, потому что не пойму, в чем дело. Можно, конечно, в рассылке xorg спросить...

Насколько я понимаю, offscreen storage одно на окно. А так как у него KWin, то там уже глобальный редирект всех окон идет, поэтому XCompositeNameWindow не создает новую область, а просто создает пиксмап как reference на offscreen pixmap окна.

Associating a Pixmap ID with the off-screen storage (0.2 and later)

    NameWindowPixmap

		window:				Window
		pixmap:				Pixmap

		errors: Window, Match, IDChoice

	This request makes 'pixmap' a reference to the off-screen storage
	for 'window'. This pixmap will remain allocated until freed, even
	if 'window' is unmapped, reconfigured or destroyed. However,
	'window' will get a new pixmap allocated each time it is
	mapped or resized, so this request will need to be reinvoked for
	the client to continue to refer to the storage holding the current
	window contents. Generates a 'Match' error if 'window' is not
	redirected or is not visible.
Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

Ну оно у меня по списку окон и так в цикле вертится. Если воткнуть цикл в метод то начинают падать ошибки уже при 2х итерациях, правда если закоментить XFreePixmap то ошибки пропадают.

Это вот в таком варианте, как ты привел, у тебя ошибки с XFreePixmap возникают? А если Xsync() еще и после qpxmp = QPixmap::fromX11Pixmap(pixmap).copy(); поставить дополнительно? Тоже возникают?

Еще можно спросить, кстати, в рассылке KWin. Они с Composite Extension хорошо знакомы (это их вотчина) и одновременно в Qt хорошо ориентируются. Просто скажешь, что пользуешься при этом KWin в момент эксперимента, чтобы совсем не за оффтопик посчитали.

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

Это вот в таком варианте, как ты привел, у тебя ошибки с XFreePixmap возникают?

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

А если Xsync() еще и после qpxmp = QPixmap::fromX11Pixmap(pixmap).copy(); поставить дополнительно? Тоже возникают?

Да.

Еще можно спросить, кстати, в рассылке KWin

Кстати мысль, заслал вопрос в xorg, но они пока молчат.

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