Added qDebug() statements to trace the execution flow and print out important values in the screen grabbing process. This will help to identify the root cause of the screen grabbing issue.
209 lines
6.2 KiB
C++
209 lines
6.2 KiB
C++
#include "hgx11grab.h"
|
|
#include <QDebug>
|
|
|
|
// public
|
|
|
|
hgx11grab::hgx11grab(Display *display, unsigned short scaleDivisor, const char *filter)
|
|
{
|
|
qDebug() << "hgx11grab constructor";
|
|
_filter_p = filter;
|
|
_display_p = display;
|
|
|
|
if (!XShmQueryExtension(_display_p)) {
|
|
qCritical() << "Xshm is: not available.";
|
|
return;
|
|
}
|
|
qDebug() << "XShm extension is available.";
|
|
|
|
int dummy, pixmaps_supported;
|
|
|
|
if (!XRenderQueryExtension(_display_p, &dummy, &dummy)) {
|
|
qCritical() << "XRender is not available.";
|
|
return;
|
|
}
|
|
qDebug() << "XRender extension is available.";
|
|
|
|
if (!XShmQueryVersion(_display_p, &dummy, &dummy, &pixmaps_supported)) {
|
|
qCritical("Could not get x shared memory version.");
|
|
return;
|
|
}
|
|
qDebug() << "XShm version query successful.";
|
|
|
|
bool _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_display_p) == ZPixmap;
|
|
if (!_XShmPixmapAvailable) {
|
|
qCritical() << "XshmPixMap is: not available.";
|
|
return;
|
|
}
|
|
qDebug() << "XShm pixmap is available.";
|
|
|
|
_window_m = DefaultRootWindow(_display_p);
|
|
qDebug() << "Root window:" << _window_m;
|
|
|
|
if (!_getWinAttr()) {
|
|
return;
|
|
}
|
|
|
|
_destWidth_m = int(_srcWidth_m / scaleDivisor);
|
|
_destHeight_m = int(_srcHeight_m / scaleDivisor);
|
|
qDebug() << "Destination size:" << _destWidth_m << "x" << _destHeight_m;
|
|
|
|
_imgSize_m = _destHeight_m * _destWidth_m * 4;
|
|
|
|
memset(&_pictAttr_m, 0, sizeof(_pictAttr_m));
|
|
_pictAttr_m.repeat = RepeatNone;
|
|
|
|
_mTransform_m.matrix[0][0] = XDoubleToFixed(1.0);
|
|
_mTransform_m.matrix[0][1] = 0;
|
|
_mTransform_m.matrix[0][2] = 0;
|
|
_mTransform_m.matrix[1][0] = 0;
|
|
_mTransform_m.matrix[1][1] = XDoubleToFixed(1.0);
|
|
_mTransform_m.matrix[1][2] = 0;
|
|
_mTransform_m.matrix[2][0] = 0;
|
|
_mTransform_m.matrix[2][1] = 0;
|
|
_setScale();
|
|
|
|
connect(this, SIGNAL(scaleChanged()), this, SLOT(_changeScale()));
|
|
qDebug() << "hgx11grab constructor finished.";
|
|
}
|
|
|
|
hgx11grab::~hgx11grab()
|
|
{
|
|
_freeResources();
|
|
}
|
|
|
|
int hgx11grab::getDest_height() const
|
|
{
|
|
return _destHeight_m;
|
|
}
|
|
|
|
int hgx11grab::getDest_width() const
|
|
{
|
|
return _destWidth_m;
|
|
}
|
|
|
|
// private
|
|
|
|
bool hgx11grab::_getWinAttr()
|
|
{
|
|
qDebug() << "Getting window attributes.";
|
|
if (XGetWindowAttributes(_display_p, _window_m, &_windowAttr_m) == 0) {
|
|
qWarning() << "Failed to obtain X11 window attributes.";
|
|
return false;
|
|
}
|
|
qDebug() << "Window size:" << _windowAttr_m.width << "x" << _windowAttr_m.height;
|
|
if (_srcWidth_m != _windowAttr_m.width || _srcHeight_m != _windowAttr_m.height) {
|
|
qDebug() << "Screen size changed.";
|
|
if (0 != _srcWidth_m) {
|
|
_freeResources();
|
|
}
|
|
_srcWidth_m = _windowAttr_m.width;
|
|
_srcHeight_m = _windowAttr_m.height;
|
|
emit scaleChanged();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void hgx11grab::_freeResources()
|
|
{
|
|
if (_freed_m) {
|
|
return;
|
|
}
|
|
qDebug() << "Freeing resources.";
|
|
XDestroyImage(_xImage_p);
|
|
XShmDetach(_display_p, &_shminfo_m);
|
|
shmdt(_shminfo_m.shmaddr);
|
|
shmctl(_shminfo_m.shmid, IPC_RMID, nullptr);
|
|
XRenderFreePicture(_display_p, _srcPicture_m);
|
|
XRenderFreePicture(_display_p, _dstPicture_m);
|
|
XFreePixmap(_display_p, _pixmap_m);
|
|
_freed_m = 1;
|
|
}
|
|
|
|
void hgx11grab::_setScale()
|
|
{
|
|
_scale_m = (1.0 / (double(_srcWidth_m) / double(_destWidth_m)));
|
|
_mTransform_m.matrix[2][2] = XDoubleToFixed(_scale_m);
|
|
}
|
|
|
|
// public slots
|
|
|
|
void hgx11grab::grabFrame()
|
|
{
|
|
qDebug() << "Grabbing frame.";
|
|
if (!_getWinAttr()) {
|
|
return;
|
|
}
|
|
|
|
_freed_m = 0;
|
|
_xImage_p = XShmCreateImage(
|
|
_display_p, _windowAttr_m.visual,
|
|
uint(_windowAttr_m.depth), ZPixmap, nullptr, &_shminfo_m,
|
|
uint(_destWidth_m), uint(_destHeight_m)
|
|
);
|
|
qDebug() << "XShmCreateImage successful.";
|
|
|
|
_shminfo_m.shmid = shmget(IPC_PRIVATE, ulong(_xImage_p->bytes_per_line * _xImage_p->height), IPC_CREAT|0777);
|
|
_xImage_p->data = reinterpret_cast<char *>(shmat(_shminfo_m.shmid, nullptr, 0));
|
|
_shminfo_m.shmaddr = _xImage_p->data;
|
|
_shminfo_m.readOnly = false;
|
|
qDebug() << "Shared memory segment created.";
|
|
|
|
XShmAttach(_display_p, &_shminfo_m);
|
|
_pixmap_m = XShmCreatePixmap(_display_p, _window_m, _xImage_p->data, &_shminfo_m, uint(_destWidth_m), uint(_destHeight_m), uint(_windowAttr_m.depth));
|
|
qDebug() << "XShm pixmap created.";
|
|
|
|
_dstFormat_p = XRenderFindVisualFormat(_display_p, _windowAttr_m.visual);
|
|
_srcFormat_p = XRenderFindVisualFormat(_display_p, _windowAttr_m.visual);
|
|
|
|
_srcPicture_m = XRenderCreatePicture(_display_p, _window_m, _srcFormat_p, CPRepeat, &_pictAttr_m);
|
|
_dstPicture_m = XRenderCreatePicture(_display_p, _pixmap_m, _dstFormat_p, CPRepeat, &_pictAttr_m);
|
|
qDebug() << "XRender pictures created.";
|
|
|
|
XRenderSetPictureFilter(_display_p, _srcPicture_m, _filter_p, nullptr, 0);
|
|
XRenderSetPictureTransform(_display_p, _srcPicture_m, &_mTransform_m);
|
|
|
|
XRenderComposite(
|
|
_display_p, // *dpy,
|
|
PictOpSrc, // op,
|
|
_srcPicture_m, // src
|
|
None, // mask
|
|
_dstPicture_m, // dst
|
|
0, // src_x
|
|
0, // src_y
|
|
0, // mask_x
|
|
0, // mask_y
|
|
0, // dst_x
|
|
0, // dst_y
|
|
uint(_destWidth_m), // width
|
|
uint(_destHeight_m) // height
|
|
);
|
|
qDebug() << "XRenderComposite successful.";
|
|
|
|
XSync(_display_p, false);
|
|
|
|
XShmGetImage(_display_p, _pixmap_m, _xImage_p, 0, 0, 0xFFFFFFFF);
|
|
qDebug() << "XShmGetImage successful.";
|
|
|
|
if (_xImage_p == nullptr) {
|
|
qWarning() << "Failed to get image from X11 server.";
|
|
return;
|
|
}
|
|
|
|
QImage qimg(reinterpret_cast<const uchar *>(_xImage_p->data), _destWidth_m, _destHeight_m, _xImage_p->bytes_per_line, QImage::Format_ARGB32);
|
|
qimg = qimg.convertToFormat(QImage::Format_RGB888);
|
|
imgdata_m = QByteArray::fromRawData(reinterpret_cast<const char *>(qimg.bits()), qimg.sizeInBytes()).toBase64().data();
|
|
qDebug() << "Image converted and encoded.";
|
|
|
|
_freeResources();
|
|
|
|
imageCreated();
|
|
}
|
|
|
|
// private slots
|
|
|
|
void hgx11grab::_changeScale()
|
|
{
|
|
_imgSize_m = _destHeight_m * _destWidth_m * 4;
|
|
_setScale();
|
|
}
|