Я пытаюсь решить то, что считал очень простой проблемой. Я хочу, чтобы QPixmap обновлял все содержимое экрана. Вы можете получить такое растровое изображение, выполнив следующие действия:
QDesktopWidget *w = QApplication::desktop();
if (w)
{
QRect r = w->screenGeometry();
QPixmap p = QPixmap::grabWindow(w->winId(), 0, 0, r.width(), r.height())
QByteArray bitmap;
}
Проблема заключается в том, что QDesktopWidget в конечном итоге повторно захватывает все изображение экрана с сервера X11 каждый раз, когда вы его запрашиваете, даже если ничего не изменилось.
Мне нужно, чтобы этот код был быстрым, поэтому я пытаюсь сделать это сам. Моей отправной точкой была демонстрация qx11mirror, однако она в основном делает то же самое. Он использует расширение XDamage, чтобы работать, когда что-то изменилось, но вместо использования информации о поврежденном прямоугольнике для обновления этой части кэшированного растрового изображения он просто устанавливает флаг «грязный», который в любом случае запускает полное обновление.
Итак, я пытаюсь изменить пример qx11mirror, чтобы просто обновить поврежденную часть окон, но я не могу заставить что-либо работать - все, что я получаю, это пустое (черное) растровое изображение. Я использую следующий код:
void QX11Mirror::x11Event(XEvent *event)
{
if (event->type == m_damageEvent + XDamageNotify)
{
XDamageNotifyEvent *e = reinterpret_cast<XDamageNotifyEvent*>(event);
XWindowAttributes attr;
XGetWindowAttributes(QX11Info::display(), m_window, &attr);
XRenderPictFormat *format = XRenderFindVisualFormat(QX11Info::display(), attr.visual);
bool hasAlpha = ( format->type == PictTypeDirect && format->direct.alphaMask );
int x = attr.x;
int y = attr.y;
int width = attr.width;
int height = attr.height;
// debug output so I can see the window pos vs the damaged area:
qDebug() << "repainting dirty area:" << x << y << width << height << "vs" << e->area.x << e->area.y << e->area.width << e->area.height;
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors; // Don't clip child widgets
Picture picture = XRenderCreatePicture(QX11Info::display(),
m_window,
format,
CPSubwindowMode,
&pa);
XserverRegion region = XFixesCreateRegionFromWindow(QX11Info::display(),
m_window, WindowRegionBounding);
XFixesTranslateRegion(QX11Info::display(), region, -x, -y);
XFixesSetPictureClipRegion(QX11Info::display(), picture, 0, 0, region);
XFixesDestroyRegion(QX11Info::display(), region);
//QPixmap dest(width, height);
XRenderComposite(QX11Info::display(), // display
hasAlpha ? PictOpOver : PictOpSrc, // operation mode
picture, // src drawable
None, // src mask
dest.x11PictureHandle(), // dest drawable
e->area.x, // src X
e->area.y, // src Y
0, // mask X
0, // mask Y
e->area.x, // dest X
e->area.y, // dest Y
e->area.width, // width
e->area.height); // height
m_px = dest;
XDamageSubtract(QX11Info::display(), e->damage, None, None);
emit windowChanged();
}
else if (event->type == ConfigureNotify)
{
XConfigureEvent *e = &event->xconfigure;
m_position = QRect(e->x, e->y, e->width, e->height);
emit positionChanged(m_position);
}
}
Может кто-то указать мне верное направление? Документация для XRender, XDamage и других расширений X11 довольно плохая.
Причины использования XRender вместо XCopyArea
Следующий текст взят из здесь.
Вполне возможно создать GC для окна и использовать XCopyArea () для копирования содержимого окна, если вы хотите использовать основной протокол, но поскольку расширение Composite предоставляет новые визуальные элементы (например, с альфа-каналами), нет Гарантировать, что формат исходного чертежа будет соответствовать формату места назначения. С основным протоколом такая ситуация приведет к ошибке сопоставления, чего не произойдет с расширением Xrender.
Кроме того, основной протокол не понимает альфа-каналов, а это означает, что он не может составлять окна, использующие новый визуальный элемент ARGB. Когда исходный и целевой формат имеют одинаковый формат, также отсутствует преимущество в производительности от использования основного протокола, как в X11R6.8. Этот выпуск также является первым, поддерживающим новое расширение Composite.
Итак, в заключение, нет никаких недостатков и есть только преимущества в выборе Xrender по сравнению с основным протоколом для этих операций.