Ich versuche zu lösen, was ich für ein sehr einfaches Problem hielt. Ich möchte eine QPixmap mit dem gesamten Bildschirminhalt auf dem neuesten Stand halten. Sie können eine solche Pixmap folgendermaßen erhalten:
QDesktopWidget *w = QApplication::desktop();
if (w)
{
QRect r = w->screenGeometry();
QPixmap p = QPixmap::grabWindow(w->winId(), 0, 0, r.width(), r.height())
QByteArray bitmap;
}
Das Problem dabei ist, dass QDesktopWidget jedes Mal, wenn Sie danach fragen, die gesamte Bildschirmdarstellung erneut vom X11-Server abruft, auch wenn sich nichts geändert hat.
Der Code muss schnell sein, also versuche ich, ihn selbst zu schreiben. Mein Ausgangspunkt war die qx11Spiegel Demo die im Grunde das Gleiche tut. Es verwendet die XDamage-Erweiterung, um herauszufinden, wann sich etwas geändert hat, aber anstatt die Informationen über das beschädigte Rechteck zu verwenden, um nur diesen Teil der zwischengespeicherten Pixmap zu aktualisieren, wird einfach ein "Dirty"-Flag gesetzt, das ohnehin eine vollständige Aktualisierung auslöst.
Ich versuche, das qx11mirror-Beispiel zu ändern, um nur den beschädigten Teil des Windows zu aktualisieren, aber ich kann nicht scheinen, um etwas zu arbeiten - alles, was ich bekomme, ist eine leere (schwarz) pixmap. Der Code, den ich verwende, ist:
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);
}
}
Kann mir jemand die richtige Richtung weisen? Die Dokumentation für XRender, XDamage und die anderen X11-Erweiterungen ist ziemlich schlecht.
Gründe für die Verwendung von XRender gegenüber XCopyArea
Der folgende Text stammt aus aquí .
Es ist durchaus möglich, eine GC für ein Fenster zu erstellen und XCopyArea() zu verwenden, um den Inhalt des Fensters zu kopieren, wenn Sie das Kernprotokoll verwenden möchten, aber da die Composite-Erweiterung neue visuelle Elemente (z. B. solche mit Alphakanälen) bereitstellt, gibt es keine Garantie, dass das Format des Quell-Drawables mit dem des Ziels übereinstimmt. Mit dem Kernprotokoll wird diese Situation zu einem Match-Fehler führen, was mit der Xrender-Erweiterung nicht passieren wird.
Darüber hinaus versteht das Kernprotokoll keine Alphakanäle, was bedeutet, dass es keine Composite-Windows, die das neue ARGB-Visual verwenden, verarbeiten kann. Wenn die Quelle und das Ziel dasselbe Format haben, gibt es auch keinen Leistungsvorteil bei der Verwendung des Kernprotokolls ab X11R6.8. Diese Version ist auch die erste, die die neue Composite-Erweiterung unterstützt.
Zusammenfassend lässt sich also sagen, dass es keine Nachteile, sondern nur Vorteile hat, Xrender gegenüber dem Kernprotokoll für diese Vorgänge zu wählen.