Commit cb68f729 by Ludmány Balázs

Move copy to the rendering thread

parent 0b287fd5
...@@ -36,4 +36,8 @@ DISTFILES += \ ...@@ -36,4 +36,8 @@ DISTFILES += \
draw_shader.fsh \ draw_shader.fsh \
draw_shader.vsh \ draw_shader.vsh \
copy_shader.vsh \ copy_shader.vsh \
copy_shader.fsh copy_shader.fsh \
fill_shader.vsh \
fill_shader.fsh \
bitmap_shader.vsh \
bitmap_shader.fsh
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.5.1, 2016-07-29T11:10:46. --> <!-- Written by QtCreator 3.5.1, 2016-08-01T17:47:15. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{9fe100e5-65f5-4993-908d-e24f092a1cff}</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{9fe100e5-65f5-4993-908d-e24f092a1cff}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value> <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
......
uniform sampler2D texture;
varying highp vec4 vartexcoord;
void main(void)
{
gl_FragColor = texture2D(texture, vartexcoord.st);
//gl_FragColor = vec4(vartexcoord.st, 0.0, 1.0);
}
uniform highp mat4 ortho;
uniform highp mat4 texortho;
attribute highp vec2 position;
attribute highp vec2 texcoord;
varying highp vec4 vartexcoord;
void main(void)
{
gl_Position = ortho * vec4(position, 0.0, 1.0);
vartexcoord = texortho * vec4(texcoord, 0.0, 1.0);
}
...@@ -49,6 +49,13 @@ void Dispatcher::FinishedFrameBufferUpdate(rfbClient *client) ...@@ -49,6 +49,13 @@ void Dispatcher::FinishedFrameBufferUpdate(rfbClient *client)
dispatcher->uploader()->finishedUpdate(); dispatcher->uploader()->finishedUpdate();
} }
char *Dispatcher::GetPassword(rfbClient *client)
{
char* password = new char[9];
strcpy(password, "asdfasdf");
return password;
}
bool Dispatcher::mouseEvent(const int x, const int y, const bool left, const bool middle, const bool right, const bool up, const bool down) bool Dispatcher::mouseEvent(const int x, const int y, const bool left, const bool middle, const bool right, const bool up, const bool down)
{ {
if(m_client == NULL) if(m_client == NULL)
...@@ -96,12 +103,13 @@ void Dispatcher::open(const QString host, const int port, const int width, const ...@@ -96,12 +103,13 @@ void Dispatcher::open(const QString host, const int port, const int width, const
m_client->GotBitmap = Dispatcher::GotBitmap; m_client->GotBitmap = Dispatcher::GotBitmap;
m_client->GotJpeg = Dispatcher::GotJpeg; m_client->GotJpeg = Dispatcher::GotJpeg;
m_client->FinishedFrameBufferUpdate = Dispatcher::FinishedFrameBufferUpdate; m_client->FinishedFrameBufferUpdate = Dispatcher::FinishedFrameBufferUpdate;
m_client->appData.useRemoteCursor = TRUE; m_client->GetPassword = Dispatcher::GetPassword;
// Set the format requested by the user // Set the format requested by the user
m_client->appData.useRemoteCursor = TRUE;
m_client->width = width; m_client->width = width;
m_client->height = height; m_client->height = height;
m_client->appData.compressLevel = 0; m_client->appData.compressLevel = 9;
m_client->appData.qualityLevel = 0; m_client->appData.qualityLevel = 0;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
m_client->format.bigEndian = TRUE; m_client->format.bigEndian = TRUE;
...@@ -137,6 +145,7 @@ void Dispatcher::open(const QString host, const int port, const int width, const ...@@ -137,6 +145,7 @@ void Dispatcher::open(const QString host, const int port, const int width, const
// 16 bit: RGB444, RGB555, RGB565 // 16 bit: RGB444, RGB555, RGB565
refresh(); refresh();
decode();
} }
void Dispatcher::refresh() void Dispatcher::refresh()
{ {
...@@ -154,6 +163,13 @@ void Dispatcher::refresh() ...@@ -154,6 +163,13 @@ void Dispatcher::refresh()
return; return;
} }
} }
}
void Dispatcher::decode()
{
if(m_client == NULL)
return;
m_uploader->startDecoding();
if(!HandleRFBServerMessage(m_client)) { if(!HandleRFBServerMessage(m_client)) {
terminate(); terminate();
......
...@@ -33,6 +33,7 @@ public: ...@@ -33,6 +33,7 @@ public:
static void GotBitmap(rfbClient* client, const uint8_t* buffer, int x, int y, int w, int h); static void GotBitmap(rfbClient* client, const uint8_t* buffer, int x, int y, int w, int h);
static rfbBool GotJpeg(rfbClient* client, const uint8_t* buffer, int length, int x, int y, int w, int h); static rfbBool GotJpeg(rfbClient* client, const uint8_t* buffer, int length, int x, int y, int w, int h);
static void FinishedFrameBufferUpdate(rfbClient* client); static void FinishedFrameBufferUpdate(rfbClient* client);
static char *GetPassword(rfbClient* client);
// input events // input events
bool mouseEvent(const int x, const int y, const bool left, const bool middle, const bool right, const bool up, const bool down); bool mouseEvent(const int x, const int y, const bool left, const bool middle, const bool right, const bool up, const bool down);
...@@ -59,6 +60,7 @@ public slots: ...@@ -59,6 +60,7 @@ public slots:
// manage VNC connection // manage VNC connection
void open(QString host, int port, const int width, const int height); void open(QString host, int port, const int width, const int height);
void refresh(); void refresh();
void decode();
void terminate(); void terminate();
}; };
......
varying highp vec4 varcolor;
void main(void)
{
gl_FragColor = varcolor;
}
uniform highp mat4 ortho;
attribute highp vec2 position;
attribute highp vec4 color;
varying highp vec4 varcolor;
void main(void)
{
gl_Position = ortho * vec4(position, 0.0, 1.0);
varcolor = color;
}
...@@ -18,8 +18,11 @@ int main(int argc, char *argv[]) ...@@ -18,8 +18,11 @@ int main(int argc, char *argv[])
format.setMajorVersion(2); format.setMajorVersion(2);
format.setMinorVersion(0); format.setMinorVersion(0);
format.setRenderableType(QSurfaceFormat::OpenGLES); format.setRenderableType(QSurfaceFormat::OpenGLES);
format.setSwapBehavior(QSurfaceFormat::SingleBuffer); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
format.setSwapInterval(0); format.setSwapInterval(1);
#ifdef OGL_DEBUG
format.setOption(QSurfaceFormat::DebugContext, true);
#endif
QSurfaceFormat::setDefaultFormat(format); QSurfaceFormat::setDefaultFormat(format);
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES, true); QGuiApplication::setAttribute(Qt::AA_UseOpenGLES, true);
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
......
...@@ -16,7 +16,6 @@ QVnc::QVnc(QQuickItem *parent) : ...@@ -16,7 +16,6 @@ QVnc::QVnc(QQuickItem *parent) :
m_uploader->moveToThread(m_threads[0]); m_uploader->moveToThread(m_threads[0]);
connect(m_threads[0], &QThread::finished, m_uploader, &QObject::deleteLater); connect(m_threads[0], &QThread::finished, m_uploader, &QObject::deleteLater);
// connect(m_uploader, &Uploader::uploadFinished, this, &QVnc::update);
m_dispatcher = new Dispatcher(m_uploader); m_dispatcher = new Dispatcher(m_uploader);
m_dispatcher->moveToThread(m_threads[0]); m_dispatcher->moveToThread(m_threads[0]);
...@@ -25,7 +24,10 @@ QVnc::QVnc(QQuickItem *parent) : ...@@ -25,7 +24,10 @@ QVnc::QVnc(QQuickItem *parent) :
connect(this, &QVnc::open_connection, m_dispatcher, &Dispatcher::open); connect(this, &QVnc::open_connection, m_dispatcher, &Dispatcher::open);
connect(this, &QVnc::terminate_connection, m_dispatcher, &Dispatcher::terminate); connect(this, &QVnc::terminate_connection, m_dispatcher, &Dispatcher::terminate);
connect(m_dispatcher, &Dispatcher::error, this, &QVnc::dispatch_error); connect(m_dispatcher, &Dispatcher::error, this, &QVnc::dispatch_error);
connect(m_uploader, &Uploader::uploadFinished, m_dispatcher, &Dispatcher::refresh); connect(m_uploader, &Uploader::uploadFinished, m_dispatcher, &Dispatcher::refresh);
// connect(m_uploader, &Uploader::uploadFinished, this, &QVnc::update);
connect(m_uploader, &Uploader::buffersSwapped, m_dispatcher, &Dispatcher::decode);
int i = 1; int i = 1;
foreach(JpegDecoder* d, m_decoders) { foreach(JpegDecoder* d, m_decoders) {
...@@ -88,20 +90,23 @@ void QVnc::winChanged(QQuickWindow *window) ...@@ -88,20 +90,23 @@ void QVnc::winChanged(QQuickWindow *window)
{ {
if(window != NULL) { if(window != NULL) {
connect(window, &QQuickWindow::openglContextCreated, m_uploader, &Uploader::createContext, Qt::BlockingQueuedConnection); connect(window, &QQuickWindow::openglContextCreated, m_uploader, &Uploader::createContext, Qt::BlockingQueuedConnection);
connect(window, &QQuickWindow::frameSwapped, m_uploader, &Uploader::frameSwapped); connect(window, &QQuickWindow::frameSwapped, m_uploader, &Uploader::swapBuffers, Qt::BlockingQueuedConnection);
} }
} }
QQuickFramebufferObject::Renderer *QVnc::createRenderer() const QQuickFramebufferObject::Renderer *QVnc::createRenderer() const
{ {
VncRenderer *renderer = new VncRenderer(window(), return new VncRenderer(window(),
m_uploader->vertices(), m_uploader->fillBuffer(),
m_uploader->indices(), m_uploader->copyBuffer(),
m_uploader->texture(), m_uploader->bitmapBuffer(),
m_uploader->drawCount()); m_uploader->texture(),
connect(renderer, &VncRenderer::FBOTextureChanged, m_uploader, &Uploader::changeFBOTexture); NULL,
connect(renderer, &VncRenderer::finishedRendering, m_uploader, &Uploader::finishedRendering); NULL,
return renderer; NULL,
m_uploader->fillCount(),
m_uploader->copyCount(),
m_uploader->bitmapCount());
} }
QString QVnc::host() const QString QVnc::host() const
...@@ -200,6 +205,11 @@ void QVnc::hoverMoveEvent(QHoverEvent *event) ...@@ -200,6 +205,11 @@ void QVnc::hoverMoveEvent(QHoverEvent *event)
// } // }
} }
Uploader *QVnc::uploader() const
{
return m_uploader;
}
void QVnc::keyPressEvent(QKeyEvent *event) void QVnc::keyPressEvent(QKeyEvent *event)
{ {
} }
......
#ifndef VNC_H #ifndef VNC_H
#define VNC_H #define VNC_H
#define DECODER_COUNT 8 #define DECODER_COUNT 5
// #define OGL_DEBUG
#include <QQuickWindow> #include <QQuickWindow>
#include <QObject> #include <QObject>
...@@ -9,11 +11,14 @@ ...@@ -9,11 +11,14 @@
#include <QThread> #include <QThread>
#include <QOffscreenSurface> #include <QOffscreenSurface>
#include <QMouseEvent> #include <QMouseEvent>
#include <QOpenGLDebugLogger>
#include "dispatcher.h" #include "dispatcher.h"
#include "vncrenderer.h" #include "vncrenderer.h"
#include "uploader.h" #include "uploader.h"
class VncRenderer;
/*! /*!
* \brief The public interface of the VNC functionality * \brief The public interface of the VNC functionality
*/ */
...@@ -30,6 +35,7 @@ public: ...@@ -30,6 +35,7 @@ public:
Renderer *createRenderer() const; Renderer *createRenderer() const;
QString host() const; QString host() const;
int port() const; int port() const;
Uploader *uploader() const;
protected: protected:
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);
...@@ -49,6 +55,9 @@ private: ...@@ -49,6 +55,9 @@ private:
int m_port; int m_port;
ulong m_lastMouseEvent; ulong m_lastMouseEvent;
bool m_swapped;
bool m_finished;
signals: signals:
void open_connection(const QString host, const int port, const int width, const int height); void open_connection(const QString host, const int port, const int width, const int height);
void terminate_connection(); void terminate_connection();
...@@ -57,6 +66,8 @@ signals: ...@@ -57,6 +66,8 @@ signals:
void portChanged(int port); void portChanged(int port);
void operate(); void operate();
void refresh();
public slots: public slots:
void open(); void open();
void terminate(); void terminate();
......
...@@ -16,64 +16,42 @@ ...@@ -16,64 +16,42 @@
#ifndef UPLOADER_H #ifndef UPLOADER_H
#define UPLOADER_H #define UPLOADER_H
#define TEXTURE_WIDTH 2048 #define TEXTURE_WIDTH 4096
#define TEXTURE_HEIGHT 2048 #define TEXTURE_HEIGHT 4096
#define COPY_BUFFER 1024
#define VERTEX_BUFFER 1024 #define VERTEX_BUFFER 1024
// #define OGL_DEBUG
#include <utility> #include <utility>
#include <QObject> #include <QObject>
#include <QQuickWindow>
#include <QDebug> #include <QDebug>
#include <QVector>
#include <QOffscreenSurface> #include <QOffscreenSurface>
#include <QOpenGLContext> #include <QOpenGLContext>
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
#include <QOpenGLBuffer> #include <QOpenGLBuffer>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLFramebufferObject>
#include <QSharedPointer>
#include <QtMath> #include <QtMath>
#include <QTime> #include <QTime>
#include <QOpenGLDebugLogger>
extern QTime elapsed; extern QTime elapsed;
struct Indices struct Bitmap
{
// 4 corner/rectangle and the first and last one duplicated except for the first and last rectangle
unsigned short i[(VERTEX_BUFFER / 4) * 6 - 2];
Indices() : i()
{
i[0] = 0;
auto index = 1;
for(auto value = 1; value < VERTEX_BUFFER; value++) {
i[index++] = value;
if(value % 4 == 0 || value % 4 == 3)
i[index++] = value;
}
}
};
const struct Indices ind;
struct Vertex
{ {
GLushort x; GLushort x;
GLushort y; GLushort y;
GLubyte red;
GLubyte green;
GLubyte blue;
GLubyte alpha;
GLushort texX; GLushort texX;
GLushort texY; GLushort texY;
}; };
struct Copy struct Fill
{ {
GLushort x; GLushort x;
GLushort y; GLushort y;
GLushort texX; GLubyte red;
GLushort texY; GLubyte green;
GLubyte blue;
GLubyte alpha;
}; };
/*! /*!
...@@ -88,10 +66,14 @@ public: ...@@ -88,10 +66,14 @@ public:
Uploader(QObject *parent = Q_NULLPTR); Uploader(QObject *parent = Q_NULLPTR);
~Uploader(); ~Uploader();
QOpenGLBuffer **vertices() const;
QOpenGLBuffer indices() const;
GLuint **texture() const; GLuint **texture() const;
unsigned int *drawCount() const; QOpenGLBuffer **fillBuffer() const;
QOpenGLBuffer **copyBuffer() const;
QOpenGLBuffer **bitmapBuffer() const;
unsigned int *fillCount() const;
unsigned int *copyCount() const;
unsigned int *bitmapCount() const;
void swapBuffers();
// VNC events // VNC events
void gotFill(const GLushort x, const GLushort y, void gotFill(const GLushort x, const GLushort y,
...@@ -105,69 +87,56 @@ public: ...@@ -105,69 +87,56 @@ public:
const GLushort width, const GLushort height); const GLushort width, const GLushort height);
void gotJpeg(); void gotJpeg();
void finishedUpdate(); void finishedUpdate();
void startDecoding();
private: private:
QOffscreenSurface m_surface; QOffscreenSurface m_surface;
QOpenGLContext m_context; QOpenGLContext m_context;
QOpenGLFunctions *m_functions; QOpenGLFunctions *m_gl;
QOpenGLBuffer m_indices; QOpenGLBuffer **m_uploadFill;
QOpenGLBuffer **m_renderFill;
Fill *m_fillPointer;
size_t m_fillIndex;
unsigned int *m_fillCount;
QOpenGLBuffer **m_uploadCopy;
QOpenGLBuffer **m_renderCopy;
Bitmap *m_copyPointer;
size_t m_copyIndex;
unsigned int *m_copyCount;
QOpenGLBuffer **m_uploadVertices; QOpenGLBuffer **m_uploadBitmap;
QOpenGLBuffer **m_renderVertices; QOpenGLBuffer **m_renderBitmap;
Vertex *m_vertexPointer; Bitmap *m_bitmapPointer;
size_t m_vertexIndex; size_t m_bitmapIndex;
unsigned int *m_bitmapCount;
GLuint m_FBOId;
GLuint m_texId[2]; GLuint m_texId[2];
GLuint **m_uploadTexture; GLuint **m_uploadTexture;
GLuint **m_renderTexture; GLuint **m_renderTexture;
unsigned int *m_drawCount;
QOpenGLShaderProgram m_program;
GLuint m_FBOTexture;
int m_jpegs; int m_jpegs;
// Got a FinishedUpdate event from libvnc
bool m_finished; bool m_finished;
// The rendering thread finished rendering the previous frame bool m_swap;
bool m_rendered;
// Framebuffer swapped
bool m_swapped;
unsigned short m_atlasX; unsigned short m_atlasX;
unsigned short m_atlasY; unsigned short m_atlasY;
unsigned short m_atlasRowHeight; unsigned short m_atlasRowHeight;
unsigned short m_atlasLastWidth; unsigned short m_atlasLastWidth;
QOpenGLBuffer m_copyBuffer;
Copy *m_copyPointer;
size_t m_copyIndex;
bool refreshAtlas(const int width, const int height); bool refreshAtlas(const int width, const int height);
// Called when:
// - got a Finished update event from libvnc
// - and every jpeg was uploaded
// - and the rendering thread swapped buffers
void startRendering(); void startRendering();
// Called when:
// - got a Finished update event from libvnc
// - and the rendering thread swapped buffers
void copyRectangles();
signals: signals:
// Emit from startRendering only!
void uploadFinished(); void uploadFinished();
void buffersSwapped();
public slots: public slots:
void changeFBOTexture(const unsigned int FBOTexture, const QMatrix4x4 &ortho);
void createContext(QOpenGLContext *context); void createContext(QOpenGLContext *context);
void finishedJpeg(const unsigned char *image, void finishedJpeg(const unsigned char *image,
const GLushort x, const GLushort y, const GLushort x, const GLushort y,
const GLushort width, const GLushort height); const GLushort width, const GLushort height);
void finishedRendering(); private slots:
void frameSwapped(); void handleDebugMessage(const QOpenGLDebugMessage &debugMessage);
}; };
#endif // UPLOADER_H #endif // UPLOADER_H
...@@ -11,32 +11,78 @@ ...@@ -11,32 +11,78 @@
#include <QOpenGLBuffer> #include <QOpenGLBuffer>
#include <QTime> #include <QTime>
#include "qvnc.h"
struct Indices
{
// 4 corner/rectangle and the first and last one duplicated except for the first and last rectangle
unsigned short i[(VERTEX_BUFFER / 4) * 6 - 2];
Indices() : i()
{
i[0] = 0;
auto index = 1;
for(auto value = 1; value < VERTEX_BUFFER; value++) {
i[index++] = value;
if(value % 4 == 0 || value % 4 == 3)
i[index++] = value;
}
}
};
const struct Indices ind;
class VncRenderer : public QObject, public QQuickFramebufferObject::Renderer class VncRenderer : public QObject, public QQuickFramebufferObject::Renderer
{ {
Q_OBJECT Q_OBJECT
public: public:
VncRenderer(QQuickWindow *window, VncRenderer(QQuickWindow *window,
QOpenGLBuffer **vertices, QOpenGLBuffer **fillBuffer,
QOpenGLBuffer indices, QOpenGLBuffer **copyBuffer,
GLuint **textures, QOpenGLBuffer **bitmapBuffer,
unsigned int *drawCount, GLuint **rgbTexture,
QObject *parent = 0); GLuint **yTexture,
GLuint **cbTexture,
GLuint **crTexture,
unsigned int *fillCount,
unsigned int *copyCount,
unsigned int *bitmapCount,
QObject *parent = nullptr);
protected: protected:
void render() override; void render() override;
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override; QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override;
private: private:
QQuickWindow *m_window; QQuickWindow *m_window;
QOpenGLBuffer **m_vertices;
QMatrix4x4 m_copyOrtho;
QMatrix4x4 m_copyTexortho;
QMatrix4x4 m_bitmapOrtho;
QMatrix4x4 m_bitmapTexortho;
QOpenGLBuffer **m_fillBuffer;
QOpenGLBuffer **m_copyBuffer;
QOpenGLBuffer **m_bitmapBuffer;
GLuint **m_rgbTexture;
GLuint **m_yTexture;
GLuint **m_cbTexture;
GLuint **m_crTexture;
unsigned int *m_fillCount;
unsigned int *m_copyCount;
unsigned int *m_bitmapCount;
QOpenGLBuffer m_indices; QOpenGLBuffer m_indices;
GLuint **m_texture; QOpenGLShaderProgram m_fillProgram;
unsigned int *m_drawCount; QOpenGLShaderProgram m_bitmapProgram;
QVector3D m_colorMax; QOpenGLShaderProgram m_ycbcrProgram;
QOpenGLShaderProgram m_program; GLuint m_textureTarget;
QOpenGLFunctions *m_functions; QOpenGLFunctions *m_gl;
bool m_rendered;
signals: QOpenGLFramebufferObject *m_framebufferObject;
void FBOTextureChanged(const unsigned int FBOTexture, const QMatrix4x4 &ortho);
void finishedRendering(); int frameCount;
QTime frameTime;
private slots:
void handleDebugMessage(const QOpenGLDebugMessage &debugMessage);
}; };
#endif // VNCRENDERER_H #endif // VNCRENDERER_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment