Я пытаюсь решить то, что я думал, было бы очень простой проблемой. Я хочу, чтобы 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 по сравнению с базовым протоколом для этих операций.