我试图解决我以为是一个非常简单的问题.我想保持一个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 demo,但是,基本上做同样的事情.它使用XDamage扩展来解决某些事情发生变化,而不是使用损坏的矩形信息来更新缓存的pixmap的那部分,它只是设置一个“脏”标志,这将触发整个刷新.
所以我试图修改qx11mirror的例子,只是更新损坏的窗口部分,但我似乎无法做任何工作 – 我所得到的只是一个空白(黑色)像素图.我使用的代码是:
void QX11Mirror::x11Event(XEvent *event)
{
if (event->type == m_damageEvent + XDamageNotify)
{
XDamageNotifyEvent *e = reinterpret_cast(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扩展的文档是非常糟糕的.
在XCopyArea上使用XRender的原因
以下文字摘自here.
如果要使用核心协议,则可以创建一个窗口的GC,并使用XCopyArea()来复制窗口的内容,但由于Composite扩展公开了新的视觉效果(例如Alpha通道),因此没有保证source drawable的格式与目标的格式一致.使用核心协议,情况将导致匹配错误,这将不会发生在Xrender扩展.
另外核心协议还没有了解Alpha通道,这意味着它不能复合使用新的ARGB视觉的窗口.当源和目的地具有相同的格式时,与X11R6.8一样使用核心协议也没有性能优势.该版本也是第一个支持新的Composite扩展.
因此,总而言之,没有缺点,只有在这些操作的核心协议上选择Xrender才有优势.