summaryrefslogtreecommitdiffstats
path: root/src/client/vnc/vncthread.cpp
diff options
context:
space:
mode:
authorSimon Rettberg2018-07-20 18:21:41 +0200
committerSimon Rettberg2018-07-20 18:21:41 +0200
commit7b57706df76a675592c026264d3a2028ed4b47b5 (patch)
tree3db5146b718e9cfb29e6d61461e36a3b587eb2b8 /src/client/vnc/vncthread.cpp
parentCMake: Add config fields for compiler flags (diff)
downloadpvs2-7b57706df76a675592c026264d3a2028ed4b47b5.tar.gz
pvs2-7b57706df76a675592c026264d3a2028ed4b47b5.tar.xz
pvs2-7b57706df76a675592c026264d3a2028ed4b47b5.zip
[client] Rewrite thread sync for VNC yet again
Move processing of image (scaling) to GUI thread. Get rid of second (scaled) image buffer. Instead, whenever we redraw parts of the VNC viewer, the according image parts will be copied and scaled from the buffer the vncclient thread is using. The buffer is wrapped in a QImage and handed over using a QSharedPointer, so reinitializing the buffer on the fly should yield no problems.
Diffstat (limited to 'src/client/vnc/vncthread.cpp')
-rw-r--r--src/client/vnc/vncthread.cpp111
1 files changed, 9 insertions, 102 deletions
diff --git a/src/client/vnc/vncthread.cpp b/src/client/vnc/vncthread.cpp
index dcc61d0..1dbe005 100644
--- a/src/client/vnc/vncthread.cpp
+++ b/src/client/vnc/vncthread.cpp
@@ -22,20 +22,6 @@
#include <netinet/tcp.h>
/**
- * Calc greatest common divisor.
- *
- * @param a one number
- * @param b another number
- * @return greatest common divisor of a and b
- */
-static int gcd(int a, int b)
-{
- if (b == 0)
- return a;
- return gcd(b, a % b);
-}
-
-/**
* Initialize this VNC client connection worker thread.
*
* @param host The IP address of the VNC server we're going to connect to
@@ -44,9 +30,8 @@ static int gcd(int a, int b)
* @param quality The desired quality level for the VNC stream
*/
VncThread::VncThread(QString host, int port, QString passwd, int quality) :
- QThread(), _frameBuffer(NULL), _run(true), _started(false)
+ QThread(), _run(true), _started(false)
{
- _srcStepX = _srcStepY = _dstStepX = _dstStepY = 0;
_host = host;
_port = port;
_passwd = passwd;
@@ -60,57 +45,18 @@ VncThread::~VncThread()
{
qDebug("VNC worker destructor called.");
Q_ASSERT(_run == false);
- if (_frameBuffer != NULL)
- delete[] _frameBuffer;
if (_client != NULL) {
if (_client->sock != -1)
::close(_client->sock);
_client->sock = -1;
- _client->frameBuffer = NULL;
rfbClientCleanup(_client);
}
}
-/**
- * When using image scaling, calc matching pixel borders for both
- * resolutions to prevent artifacts through bilinear scaling.
- * If you simply round to the nearest number when scaling, you would
- * slightly stretch or shrink the image area, which leads to strange
- * sub-pixel-movements of parts of the image when being updated.
- * The values calculated here are used to determine a larger area around
- * the area that should actually be updated, that will not cause any
- * artifacts when scaling down/up.
- */
-void VncThread::calcScaling()
-{
- if (_localSize.isEmpty())
- return;
- if (_clientSize.isEmpty())
- return;
- const int gcdX = gcd(_localSize.width(), _clientSize.width());
- const int gcdY = gcd(_localSize.height(), _clientSize.height());
- _srcStepX = _clientSize.width() / gcdX;
- _srcStepY = _clientSize.height() / gcdY;
- _dstStepX = _localSize.width() / gcdX;
- _dstStepY = _localSize.height() / gcdY;
- qDebug() << "Scaling updated to " << _clientSize << " -> " << _localSize;
- emit imageUpdated(0, 0, _localSize.width(), _localSize.height());
-}
-
////////////////////////////////////////////////////////////////////////////////
// Public
/**
- * Tell the client that the size of the viewer window has changed.
- *
- * @param size The new size of the viewer window
- */
-void VncThread::setTargetBuffer(QSharedPointer<QImage> &buffer)
-{
- _imgScaled = buffer;
-}
-
-/**
* Worker thread's mainloop, connecting to the VNC server and handling the
* connection. The vnc client library is written in a blocking manner, so we
* just do everything in our own thread and just hand over the image updates to
@@ -207,41 +153,6 @@ const QString VncThread::getDesktopName() const
*/
void VncThread::processImageUpdate(int x, int y, int w, int h)
{
- QSharedPointer<QImage> buffer = _imgScaled;
- QPainter painter(buffer.data());
- if (buffer->size() != _localSize) {
- _localSize = buffer->size();
- this->calcScaling();
- x = 0;
- y = 0;
- w = _img.width();
- h = _img.height();
- }
- if (_srcStepX > 1 || _srcStepY > 1) {
- // Scaling is required as vnc server and client are using different resolutions
- // Calc section offsets first
- const int startX = x / _srcStepX;
- const int startY = y / _srcStepY;
- const int endX = (x + w - 1) / _srcStepX + 1;
- const int endY = (y + h - 1) / _srcStepY + 1;
- // Now pixel offsets for source
- const int srcX = startX * _srcStepX;
- const int srcY = startY * _srcStepY;
- const int srcW = endX * _srcStepX - srcX;
- const int srcH = endY * _srcStepY - srcY;
- // Pixel offsets for destination
- x = startX * _dstStepX;
- y = startY * _dstStepY;
- w = endX * _dstStepX - x;
- h = endY * _dstStepY - y;
- // Rescale
- QImage scaled(
- _img.copy(srcX, srcY, srcW, srcH).scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
- painter.drawImage(x, y, scaled, 0, 0, w, h);
- } else {
- // Same resolution, nothing to do
- painter.drawImage(x, y, _img, x, y, w, h);
- }
emit imageUpdated(x, y, w, h);
}
@@ -275,16 +186,18 @@ char* VncThread::passwdHandler(rfbClient *client)
rfbBool VncThread::frameBufferHandler(rfbClient *client)
{
VncThread *t = (VncThread*)rfbClientGetClientData(client, 0);
- const int width = client->width, height = client->height, depth = 32; // client->format.bitsPerPixel;
+ const int width = client->width, height = client->height, depth = 32;
const int size = width * height * (depth / 8);
qDebug("[%s] Remote desktop: %ix%ix%i", t->metaObject()->className(), width, height, depth);
- if (t->_frameBuffer != NULL)
- delete[] t->_frameBuffer;
-
- t->_frameBuffer = new uint8_t[size];
- client->frameBuffer = t->_frameBuffer;
+ t->_img = QSharedPointer<QImage>(new QImage(width, height, QImage::Format_RGB32));
+ if (size > t->_img->byteCount()) {
+ qDebug() << "Fatal: Created image too small:" << t->_img->byteCount() << "<" << size;
+ ::exit(1);
+ }
+ client->frameBuffer = t->_img->bits();
memset(client->frameBuffer, '\0', size);
+ client->format.trueColour = 1;
client->format.bitsPerPixel = depth;
client->format.redShift = 16;
client->format.greenShift = 8;
@@ -320,12 +233,6 @@ rfbBool VncThread::frameBufferHandler(rfbClient *client)
}
SetFormatAndEncodings(client);
- t->_clientSize = QSize(width, height);
-
- t->_img = QImage(client->frameBuffer, client->width, client->height, QImage::Format_RGB32);
-
- t->calcScaling();
-
SendFramebufferUpdateRequest(client, 0, 0, width, height, false);
if (!t->_started) {