Commit d4f375e9 by Ludmány Balázs

First somewhat working version

parent f37580d7
Pipeline #124 skipped in 0 seconds
......@@ -32,4 +32,5 @@ HEADERS += \
dispatcher.h
DISTFILES += \
draw_shader.fsh
draw_shader.fsh \
draw_shader.vsh
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.5.1, 2016-07-01T15:26:59. -->
<!-- Written by QtCreator 3.5.1, 2016-07-06T14:51:57. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
......
#include "dispatcher.h"
Dispatcher::Dispatcher(QObject *parent) : QObject(parent)
{
}
rfbBool Dispatcher::MallocFrameBuffer(rfbClient *client)
{
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0);
dispatcher->uploader().setFramebufferHeight(client->height);
emit dispatcher->resizeFramebuffer(QSize(client->width, client->height));
return TRUE;
}
......@@ -16,9 +21,9 @@ void Dispatcher::GotCopyRect(rfbClient *client, int src_x, int src_y, int w, int
void Dispatcher::GotFillRect(rfbClient *client, int x, int y, int w, int h, uint32_t colour)
{
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0);
int red = (colour >> m_client->format.redShift) & m_client->format.redMax;
int green = (colour >> m_client->format.greenShift) & m_client->format.greenMax;
int blue = (colour >> m_client->format.blueShift) & m_client->format.blueMax;
int red = (colour >> client->format.redShift) & client->format.redMax;
int green = (colour >> client->format.greenShift) & client->format.greenMax;
int blue = (colour >> client->format.blueShift) & client->format.blueMax;
dispatcher->uploader().gotFillRect(x, y, w, h, red, green, blue);
}
......@@ -46,15 +51,15 @@ void Dispatcher::GotBitmap(rfbClient *client, const uint8_t *buffer, int x, int
rfbBool Dispatcher::GotJpeg(rfbClient *client, const uint8_t *buffer, int length, int x, int y, int w, int h)
{
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0);
Dispatcher *dispatcher = static_cast<Dispatcher *>(rfbClientGetClientData(client, 0));
QByteArray jpeg;
jpeg.setRawData(buffer, length);
jpeg.setRawData((const char*) buffer, length);
JpegDecoder *decoder = new JpegDecoder(jpeg, position, size);
connect(decoder, &JpegDecoder::finished, dispatcher, &Dispatcher::decodingFinished);
QThreadPool::globalInstance()->start(decoder);
JpegDecoder *decoder = new JpegDecoder(jpeg, x, y, w, h);
dispatcher->incrementDecoderCount();
connect(decoder, &JpegDecoder::finished, dispatcher, &Dispatcher::decodingFinished, Qt::QueuedConnection);
QThreadPool::globalInstance()->start(decoder);
return TRUE;
}
......@@ -63,7 +68,7 @@ void Dispatcher::FinishedFrameBufferUpdate(rfbClient *client)
{
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0);
dispatcher->setFinished(true);
if(decoderCount() == 0) {
if(dispatcher->decoderCount() == 0) {
dispatcher->uploader().finishedUpdate();
emit dispatcher->updateFramebuffer();
}
......@@ -89,7 +94,7 @@ int Dispatcher::bitsPerPixel()
return m_client->format.bitsPerPixel;
}
Uploader &Dispatcher::uploader() const
Uploader &Dispatcher::uploader()
{
return m_uploader;
}
......@@ -104,12 +109,43 @@ bool Dispatcher::finished() const
return m_finished;
}
unsigned int Dispatcher::fill_count()
{
if(m_finished && m_decoderCount == 0)
return m_uploader.fill_count();
else
return 0;
}
unsigned int Dispatcher::copy_count()
{
if(m_finished && m_decoderCount == 0)
return m_uploader.copy_count();
else
return 0;
}
unsigned int Dispatcher::draw_count()
{
if(m_finished && m_decoderCount == 0)
return m_uploader.draw_count();
else
return 0;
}
void Dispatcher::create_context(QOpenGLContext *context)
{
m_uploader.create_context(context);
}
void Dispatcher::open(QString host, int port)
{
QByteArray tmp = host.toLocal8Bit();
m_client = rfbGetClient(8, 3, 4);
m_client->canHandleNewFBSize = FALSE;
m_client->serverHost = host.toLocal8Bit().data();
m_client->serverHost = new char[tmp.size() + 1];
strcpy(m_client->serverHost, tmp.constData());
m_client->serverPort = port;
m_client->MallocFrameBuffer = Dispatcher::MallocFrameBuffer;
m_client->GotCopyRect = Dispatcher::GotCopyRect;
......@@ -118,21 +154,32 @@ void Dispatcher::open(QString host, int port)
m_client->GotJpeg = Dispatcher::GotJpeg;
m_client->FinishedFrameBufferUpdate = Dispatcher::FinishedFrameBufferUpdate;
rfbInitClient(m_client, NULL, NULL);
rfbClientSetClientData(m_client, 0, this);
if(!rfbInitClient(m_client, NULL, NULL)) {
emit error();
return;
}
refresh();
}
void Dispatcher::refresh()
{
if(m_client == NULL)
return;
m_finished = false;
int message = WaitForMessage(m_client, 500);
setFinished(false);
m_uploader.startedUpdate();
int message = WaitForMessage(m_client, 10000);
if(message < 0) {
terminate();
emit error();
return;
} else if (message) {
}
if (message) {
if(!HandleRFBServerMessage(m_client)) {
terminate();
emit error();
return;
}
......@@ -147,9 +194,9 @@ void Dispatcher::terminate()
rfbClientCleanup(m_client);
}
void Dispatcher::decodingFinished(const QImage &bitmap, const QPoint &position, const QSize &size)
void Dispatcher::decodingFinished(const QImage &bitmap, const int x, const int y, const int w, const int h)
{
m_uploader.gotBitmap(bitmap, position, size);
m_uploader.gotBitmap(bitmap, x, y, w, h);
if(m_finished && decrementDecoderCount() == 0) {
m_uploader.finishedUpdate();
emit updateFramebuffer();
......
#ifndef RFBDISPATCH_H
#define RFBDISPATCH_H
#include <QOpenGLContext>
#include <QCoreApplication>
#include <QImage>
#include <QThreadPool>
#include <QObject>
#include <QPoint>
......@@ -17,6 +19,8 @@ class Dispatcher : public QObject
Q_OBJECT
public:
Dispatcher(QObject *parent = 0);
// libvnc hooks
static rfbBool MallocFrameBuffer(rfbClient* client);
static void GotCopyRect(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y);
......@@ -30,8 +34,13 @@ public:
unsigned int incrementDecoderCount();
unsigned int decrementDecoderCount();
int bitsPerPixel();
Uploader &uploader() const;
Uploader &uploader();
void setFinished(bool finished);
bool finished() const;
unsigned int fill_count();
unsigned int copy_count();
unsigned int draw_count();
private:
rfbClient *m_client;
......@@ -43,10 +52,11 @@ signals:
void updateFramebuffer();
void error();
public slots:
void create_context(QOpenGLContext *context);
void open(QString host, int port);
void refresh();
void terminate();
void decodingFinished(const QImage &bitmap, const QPoint &position, const QSize &size);
void decodingFinished(const QImage &bitmap, const int x, const int y, const int w, const int h);
};
#endif // RFBDISPATCH_H
uniform sampler2D qt_Texture0;
varying highp vec4 qt_TexCoord0;
uniform sampler2D texture;
varying highp vec2 vartexcoord;
void main(void)
{
gl_FragColor = texture2D(qt_Texture0, qt_TexCoord0.st);
gl_FragColor = texture2D(texture, vartexcoord);
}
uniform highp mat4 ortho;
attribute highp vec2 position;
attribute highp vec2 texcoord;
varying highp vec2 vartexcoord;
void main(void)
{
gl_Position = ortho * vec4(position, 0.0, 1.0);
vartexcoord = texcoord;
}
#include "jpegdecoder.h"
JpegDecoder::JpegDecoder(const QByteArray &jpeg, const QPoint &position, const QSize &size) :
m_jpeg(jpeg), m_position(position), m_size(size)
JpegDecoder::JpegDecoder(const QByteArray &jpeg, const int x, const int y, const int w, const int h, QObject *parent) :
QObject(parent), QRunnable(), m_jpeg(jpeg), m_x(x), m_y(y), m_w(w), m_h(h)
{
}
void JpegDecoder::run()
{
m_image.loadFromData(m_jpeg, "JPG");
emit finished(m_image, m_position, m_size);
emit finished(m_image, m_x, m_y, m_w, m_h);
}
......@@ -7,23 +7,26 @@
#include <QPoint>
#include <QSize>
#include <QImage>
#include <QDebug>
/*!
* \brief Loads JPEG files on a separate thread
*/
class JpegDecoder : public QRunnable
class JpegDecoder : public QObject, public QRunnable
{
Q_OBJECT
public:
JpegDecoder(const QByteArray &jpeg, const QPoint &position, const QSize &size);
JpegDecoder(const QByteArray &jpeg, const int x, const int y, const int w, const int h, QObject *parent = 0);
void run();
signals:
void finished(const QImage &image, const QPoint &position, QSize &size);
void finished(const QImage &image, const int x, const int y, const int w, const int h);
private:
QByteArray m_jpeg;
QImage m_image;
QPoint m_position;
QSize m_size;
int m_x;
int m_y;
int m_w;
int m_h;
};
#endif // JPEGDECODER_H
......@@ -6,9 +6,6 @@
int main(int argc, char *argv[])
{
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES);
QGuiApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QGuiApplication app(argc, argv);
qmlRegisterType<QVnc>("thinclient", 1, 1, "QVnc");
......
......@@ -4,8 +4,8 @@ import thinclient 1.1
ApplicationWindow {
visible: true
width: 640
height: 480
width: 1280
height: 1024
header: TabBar {
width: parent.width
......@@ -26,7 +26,7 @@ ApplicationWindow {
id: vnc
host: "vm.ik.bme.hu"
port: 10495
width: 1024
height: 768
width: 1280
height: 1024
}
}
......@@ -2,6 +2,8 @@
QVnc::QVnc()
{
connect(this, &QVnc::windowChanged, this, &QVnc::winChanged);
// Don't let Qt change the size of the OpenGL framebuffer
setTextureFollowsItemSize(false);
......@@ -14,6 +16,7 @@ QVnc::QVnc()
connect(this, &QVnc::terminate_connection, m_dispatcher, &Dispatcher::terminate);
connect(m_dispatcher, &Dispatcher::updateFramebuffer, this, &QVnc::update);
connect(m_dispatcher, &Dispatcher::error, this, &QVnc::dispatch_error);
QThreadPool::globalInstance()->reserveThread();
m_dispatcher_thread.start();
......@@ -53,11 +56,31 @@ void QVnc::setPort(int port)
emit portChanged(port);
}
void QVnc::dispatch_error()
{
qDebug() << "error";
}
void QVnc::winChanged(QQuickWindow *window)
{
if(window != NULL)
connect(window, &QQuickWindow::openglContextCreated, m_dispatcher, &Dispatcher::create_context, Qt::BlockingQueuedConnection);
}
Dispatcher *QVnc::dispatcher() const
{
return m_dispatcher;
}
QQuickFramebufferObject::Renderer *QVnc::createRenderer() const
{
VncRenderer *renderer = new VncRenderer();
connect(renderer, &VncRenderer::rendered, m_dispatcher, &Dispatcher::refresh);
connect(m_dispatcher &Dispatcher::resizeFramebuffer, renderer, &VncRenderer::invalidateFramebufferObject);
VncRenderer *renderer = new VncRenderer(window(),
m_dispatcher->uploader().fill_buffer(),
m_dispatcher->uploader().copy_source(),
m_dispatcher->uploader().copy_buffer(),
m_dispatcher->uploader().draw_buffer(),
m_dispatcher->uploader().draw_textures());
connect(renderer, &VncRenderer::finishedRendering, m_dispatcher, &Dispatcher::refresh);
return renderer;
}
......
#ifndef VNC_H
#define VNC_H
#include <QQuickWindow>
#include <QObject>
#include <QQuickFramebufferObject>
#include <QThread>
......@@ -26,6 +27,8 @@ public:
Renderer *createRenderer() const;
QString host() const;
int port() const;
Dispatcher *dispatcher() const;
signals:
void open_connection(QString host, int port);
void terminate_connection();
......@@ -34,17 +37,20 @@ signals:
void portChanged(int port);
public slots:
void open();
void update();
void terminate();
void setHost(QString host);
void setPort(int port);
void dispatch_error();
private:
Dispatcher *m_dispatcher;
QThread m_dispatcher_thread;
QString m_host;
int m_port;
private slots:
void winChanged(QQuickWindow *window);
};
#endif // VNC_H
#include "uploader.h"
Uploader::Uploader() : m_fill_buffer(QOpenGLBuffer(QOpenGLBuffer::VertexBuffer))
Uploader::Uploader()
{
// "applications must ensure that create() is only called on the main (GUI) thread"
m_surface.create();
m_uploader_context.setShareContext(QOpenGLContext::globalShareContext());
m_uploader_context.create();
m_uploader_context.makeCurrent(m_surface);
m_fill_buffer.create();
m_draw_buffer.create();
m_copy_source = QSharedPointer<QVector<copy>>(new QVector<copy>);
m_draw_textures = QSharedPointer<QVector<QOpenGLTexture*>>(new QVector<QOpenGLTexture*>);
// A single rectangle takes 20 float values to describe (4 vertices * (2 coordinate + 3 color))
m_fill_data.reserve(100);
m_draw_data.reserve(100);
m_copy_data.reserve(5);
m_copy_source->reserve(5);
m_draw_textures->reserve(5);
m_draw_buffer = QSharedPointer<QOpenGLBuffer>(new QOpenGLBuffer);
m_draw_buffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
}
void Uploader::create_context(QOpenGLContext *context)
{
m_uploader_context = new QOpenGLContext();
m_uploader_context->setShareContext(context);
m_uploader_context->create();
m_uploader_context->makeCurrent(&m_surface);
}
void Uploader::startedUpdate()
{
// TODO: bind the framebuffer as texture
// Clean up the data from the previous round
for(unsigned int i = 0; i < m_copy_count; i++) {
m_copy_source->at(i).texture->destroy();
delete m_copy_source->at(i).texture;
}
m_copy_data.clear();
m_copy_count = 0;
m_fill_data.clear();
m_fill_count = 0;
for(unsigned int i = 0; i < m_draw_count; i++) {
m_draw_textures->at(i)->destroy();
delete m_draw_textures->at(i);
}
m_draw_data.clear();
m_draw_count = 0;
}
void Uploader::gotCopyRect(const int &src_x, const int &src_y, const int &w, const int &h, const int &dest_x, const int &dest_y)
void Uploader::gotCopyRect(const int src_x, const int src_y, const int width, const int height, const int dest_x, const int dest_y)
{
// TODO: render parts of the framebuffer to temporary texture
QOpenGLTexture* texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
texture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::Float32);
// "Specify the window coordinates of the lower left corner
// of the rectangular region of pixels to be copied."
m_copy_source->append({src_x,
m_framebufferHeight - src_y,
width,
height,
texture});
// bottom left
m_copy_data.append((float) dest_x);
m_copy_data.append((float) (dest_y + height));
m_copy_data.append(0.0f);
m_copy_data.append(0.0f);
// top left
m_copy_data.append((float) dest_x);
m_copy_data.append((float) dest_y);
m_copy_data.append(0.0f);
m_copy_data.append(1.0f);
// bottom right
m_copy_data.append((float) (dest_x + width));
m_copy_data.append((float) (dest_y + height));
m_copy_data.append(1.0f);
m_copy_data.append(0.0f);
// top right
m_copy_data.append((float) (dest_x + width));
m_copy_data.append((float) dest_y);
m_copy_data.append(1.0f);
m_copy_data.append(1.0f);
m_copy_count++;
}
void Uploader::gotFillRect(const int x, const int y, const int width, const int height, const float red, const float green, const float blue)
......@@ -59,11 +118,13 @@ void Uploader::gotFillRect(const int x, const int y, const int width, const int
m_fill_data.append(red);
m_fill_data.append(green);
m_fill_data.append(blue);
m_fill_count++;
}
void Uploader::gotBitmap(const QImage &image, const int x, const int y, const int width, const int height)
{
m_draw_textures.append(new QOpenGLTexture(image, QOpenGLTexture::DontGenerateMipMaps));
m_draw_textures->append(new QOpenGLTexture(image, QOpenGLTexture::DontGenerateMipMaps));
// bottom left
m_draw_data.append((float) x);
......@@ -85,35 +146,77 @@ void Uploader::gotBitmap(const QImage &image, const int x, const int y, const in
m_draw_data.append((float) y);
m_draw_data.append(1.0f);
m_draw_data.append(1.0f);
m_draw_count++;
}
void Uploader::finishedUpdate()
{
QOpenGLFunctions *fun = QOpenGLContext::currentContext()->functions();
if(m_copy_count > 0) {
m_copy_buffer->bind();
m_copy_buffer->allocate(m_copy_data.constData(), m_copy_data.size() * sizeof(float));
m_copy_buffer->release();
}
// Upload fill
int fill_size = m_fill_data.size() * sizeof(float);
m_fill_buffer.bind();
m_fill_buffer.allocate(fill_size);
m_fill_buffer.write(0, m_fill_data.constData(), fill_size);
m_fill_buffer.release();
m_fill_data.clear();
if(m_fill_count > 0) {
m_fill_buffer->bind();
m_fill_buffer->allocate(m_fill_data.constData(), m_fill_data.size() * sizeof(float));
m_fill_buffer->release();
}
// Upload draw
int draw_size = m_draw_data.size() * sizeof(float);
m_draw_buffer.bind();
m_draw_buffer.allocate(draw_size);
m_fill_buffer.write(0, m_fill_data.constData(), fill_size);
m_fill_buffer.release();
m_fill_data.clear();
if(m_draw_count > 0) {
m_draw_buffer->bind();
m_draw_buffer->allocate(m_draw_data.data(), m_draw_data.size() * sizeof(float));
m_draw_buffer->release();
}
}
void Uploader::setFramebufferHeight(int framebufferHeight)
{
m_framebufferHeight = framebufferHeight;
}
QOpenGLBuffer Uploader::draw_buffer() const
unsigned int Uploader::fill_count() const
{
return m_draw_buffer;
return m_fill_count;
}
unsigned int Uploader::copy_count() const
{
return m_copy_count;
}
unsigned int Uploader::draw_count() const
{
return m_draw_count;
}
QSharedPointer<QVector<copy>> Uploader::copy_source()
{
return m_copy_source;
}
QSharedPointer<QOpenGLBuffer> Uploader::copy_buffer()
{
return m_copy_buffer;
}
QOpenGLBuffer Uploader::fill_buffer() const
QSharedPointer<QOpenGLBuffer> Uploader::fill_buffer()
{
return m_fill_buffer;
}
QSharedPointer<QOpenGLBuffer> Uploader::draw_buffer()
{
return m_draw_buffer;
}
QSharedPointer<QVector<QOpenGLTexture *>> Uploader::draw_textures()
{
return m_draw_textures;
}
QOpenGLContext *Uploader::uploader_context() const
{
return m_uploader_context;
}
#ifndef UPLOADER_H
#define UPLOADER_H
#include <QQuickWindow>
#include <QDebug>
#include <QVector>
#include <QOffscreenSurface>
#include <QOpenGLContext>
......@@ -9,29 +11,59 @@
#include <QOpenGLTexture>
#include <QThreadPool>
#include <QtAlgorithms>
#include <QSharedPointer>
class Uploader : public QObject
typedef struct {
int src_x;
int src_y;
int width;
int height;
QOpenGLTexture *texture;
} copy;
class Uploader
{
public:
Uploader();
QOpenGLBuffer fill_buffer() const;
QOpenGLBuffer draw_buffer() const;
void create_context(QOpenGLContext *context);
void startedUpdate();
void gotCopyRect(const int src_x, const int src_y, const int width, const int height, const int dest_x, const int dest_y);
void gotFillRect(const int x, const int y, const int width, const int height, const float red, const float green, const float blue);
void gotBitmap(const QImage &image, const int x, const int y, const int width, const int height);
void finishedUpdate();
void setFramebufferHeight(int framebufferHeight);
unsigned int fill_count() const;
unsigned int copy_count() const;
unsigned int draw_count() const;
QSharedPointer<QVector<copy>> copy_source();
QSharedPointer<QOpenGLBuffer> copy_buffer();
QSharedPointer<QOpenGLBuffer> fill_buffer();
QSharedPointer<QOpenGLBuffer> draw_buffer();
QSharedPointer<QVector<QOpenGLTexture *>> draw_textures();
QOpenGLContext *uploader_context() const;
private:
int m_framebufferHeight;
QOffscreenSurface m_surface;
QOpenGLContext m_uploader_context;
QOpenGLContext *m_uploader_context;
unsigned int m_copy_count;
QVector<float> m_copy_data;
QSharedPointer<QVector<copy>> m_copy_source;
QSharedPointer<QOpenGLBuffer> m_copy_buffer;
unsigned int m_fill_count;
QVector<float> m_fill_data;
QOpenGLBuffer m_fill_buffer;
QSharedPointer<QOpenGLBuffer> m_fill_buffer;
unsigned int m_draw_count;
QVector<float> m_draw_data;
QOpenGLBuffer m_draw_buffer;
QVector<*QOpenGLTexture> m_draw_textures;
QSharedPointer<QOpenGLBuffer> m_draw_buffer;
QSharedPointer<QVector<QOpenGLTexture*>> m_draw_textures;
uchar m_decoders_running;
};
......
#include "vncrenderer.h"
VncRenderer::VncRenderer(QOpenGLBuffer fill_buffer, QOpenGLBuffer draw_buffer, QOpenGLTexture draw_texture) :
m_fill_buffer(fill_buffer), m_draw_buffer(draw_buffer), m_draw_texture(draw_texture)
VncRenderer::VncRenderer(QQuickWindow *window,
QSharedPointer<QOpenGLBuffer> fill_buffer,
QSharedPointer<QVector<copy>> copy_source,
QSharedPointer<QOpenGLBuffer> copy_buffer,
QSharedPointer<QOpenGLBuffer> draw_buffer,
QSharedPointer<QVector<QOpenGLTexture*>> draw_textures,
QObject *parent) :
QObject(parent), m_window(window), m_fill_buffer(fill_buffer), m_copy_source(copy_source),
m_copy_buffer(copy_buffer), m_draw_buffer(draw_buffer), m_draw_textures(draw_textures), m_clear(true)
{
QOpenGLShader fill_vshader(QOpenGLShader::Vertex, &m_fill_program);
m_draw_buffer->create();
/*QOpenGLShader fill_vshader(QOpenGLShader::Vertex, &m_fill_program);
fill_vshader.compileSourceCode("uniform highp mat4 ortho;\n"
"attribute highp vec2 position;\n"
"attribute lowp vec3 color;\n"
......@@ -25,76 +33,95 @@ VncRenderer::VncRenderer(QOpenGLBuffer fill_buffer, QOpenGLBuffer draw_buffer, Q
m_fill_program.addShader(&fill_fshader);
m_fill_program.link();
m_fill_program.enableAttributeArray("position");
m_fill_program.enableAttributeArray("color");
m_fill_program.enableAttributeArray("color");*/
QOpenGLShader draw_vshader(QOpenGLShader::Vertex, &m_fill_program);
draw_vshader.compileSourceCode("uniform highp mat2 ortho;\n"
"uniform highp mat4 atlasortho;\n"
"attribute highp vec2 position;\n"
"attribute lowp vec2 texture;\n"
"varying lowp vec2 vartexture;\n"
"void main(void)\n"
"{\n"
" vartexture = atlasortho * texture;\n"
" gl_Position = ortho * vec4(position, 0.0, 1.0);\n"
"}\n");
QOpenGLShader draw_fshader(QOpenGLShader::Fragment, &m_fill_program);
draw_fshader.compileSourceCode("uniform sampler2D atlas;\n"
"varying lowp vec2 vartexture;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = texture2D(atlas, vartexture);\n"
"}\n");
m_draw_program.addShader(&draw_vshader);
m_draw_program.addShader(&draw_fshader);
m_draw_program.link();
m_draw_program.addShaderFromSourceFile(QOpenGLShader::Vertex, "draw_shader.vsh");
m_draw_program.addShaderFromSourceFile(QOpenGLShader::Fragment, "draw_shader.fsh");
m_draw_program.bind();
m_draw_program.setUniformValue("texture", GL_TEXTURE_2D);
m_draw_program.enableAttributeArray("position");
m_draw_program.enableAttributeArray("texture");
m_draw_program.enableAttributeArray("texcoord");
m_draw_program.release();
}
void VncRenderer::render()
{
QOpenGLFunctions *fun = QOpenGLContext::currentContext()->functions();
// fill rectangles with solid color
m_fill_program.bind();
m_fill_buffer.bind();
for(unsigned int i = 0; i < m_fill_count; i++)
fun->glDrawArrays(GL_TRIANGLES, 0, 4);
m_fill_buffer.release();
m_fill_program.release();
m_draw_program.bind();
m_draw_buffer.bind();
m_draw_texture.bind();
foreach(const Uploader::CopyToAtlas &copy, m_copy_data)
fun->glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA32,);
// draw the vertices of the texture atlas
for(int i = 0; i < m_draw_count; i++)
fun->glDrawArrays(GL_TRIANGLES, 0, 4);
m_draw_texture.release();
m_draw_buffer.release();
m_draw_program.release();
QQuickWindow::resetOpenGLState();
emit rendered();
QOpenGLFunctions *fun = m_window->openglContext()->functions();
if(m_clear) {
fun->glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
fun->glClear(GL_COLOR_BUFFER_BIT);
m_clear = false;
}
/*if(m_fill_count > 0) {
m_fill_program.bind();
m_fill_buffer.bind();
m_fill_program.setAttributeBuffer("position", GL_FLOAT, 0, 2, 3 * sizeof(float));
m_fill_program.setAttributeBuffer("color", GL_FLOAT, 2, 3, 2 * sizeof(float));
for(unsigned int i = 0; i < m_fill_count; i++)
fun->glDrawArrays(GL_TRIANGLES, i * 4, 4);
m_fill_buffer.release();
m_fill_program.release();
}
*/
if(m_copy_count > 0 || m_draw_count > 0)
m_draw_program.bind();
m_draw_program.enableAttributeArray("position");
m_draw_program.enableAttributeArray("texcoord");
/*
if(m_copy_count > 0){
m_copy_buffer.bind();
m_draw_program.setAttributeBuffer("position", GL_FLOAT, 0 * sizeof(float), 2, 4 * sizeof(float));
m_draw_program.setAttributeBuffer("texcoord", GL_FLOAT, 2 * sizeof(float), 2, 4 * sizeof(float));
for(unsigned int i = 0; i < m_copy_count; i++) {
m_copy_source->at(i).texture->bind();
fun->glCopyTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
m_copy_source->at(i).src_x,
m_copy_source->at(i).src_y,
m_copy_source->at(i).width,
m_copy_source->at(i).height,
0);
fun->glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4);
m_copy_source->at(i).texture->release();
}
m_copy_buffer.release();
}*/
if(m_draw_count > 0) {
m_draw_buffer->bind();
m_draw_program.setAttributeBuffer("position", GL_FLOAT, 0 * sizeof(float), 2, 4 * sizeof(float));
m_draw_program.setAttributeBuffer("texcoord", GL_FLOAT, 2 * sizeof(float), 2, 4 * sizeof(float));
for(unsigned int i = 0; i < m_draw_count; i++) {
m_draw_textures->at(i)->bind();
fun->glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4);
m_draw_textures->at(i)->release();
}
m_draw_buffer->release();
}
if(m_copy_count > 0 || m_draw_count > 0)
m_draw_program.release();
m_window->resetOpenGLState();
emit finishedRendering();
}
QOpenGLFramebufferObject *VncRenderer::createFramebufferObject(const QSize &size)
{
// Set the orthogonal transformation matrix
m_fill_program.bind();
QMatrix4x4 ortho;
ortho.ortho(QRect(QPoint(0, 0), size));
m_fill_program.setUniformValue("ortho", mat);
m_fill_program.release();
ortho.ortho(QRect(QPoint(0, size.height()), QSize(size.width(), -1 * size.height())));
//m_fill_program.bind();
//m_fill_program.setUniformValue("ortho", ortho);
m_draw_program.bind();
m_draw_program.setUniformValue("ortho", ortho);
m_draw_program.release();
return new QOpenGLFramebufferObject(size);
}
......@@ -102,4 +129,8 @@ QOpenGLFramebufferObject *VncRenderer::createFramebufferObject(const QSize &size
void VncRenderer::synchronize(QQuickFramebufferObject *object)
{
QVnc *vnc = static_cast<QVnc*>(object);
Dispatcher *dispatcher = vnc->dispatcher();
m_fill_count = dispatcher->fill_count();
m_copy_count = dispatcher->copy_count();
m_draw_count = dispatcher->draw_count();
}
#ifndef VNCRENDERER_H
#define VNCRENDERER_H
#include <QObject>
#include <QQuickWindow>
#include <QQuickFramebufferObject>
#include <QOpenGLFramebufferObject>
......@@ -11,35 +10,46 @@
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QSharedPointer>
#include "qvnc.h"
#include "uploader.h"
class VncRenderer : public QQuickFramebufferObject::Renderer
class VncRenderer : public QObject, public QQuickFramebufferObject::Renderer
{
Q_OBJECT
public:
VncRenderer(QOpenGLBuffer fill_buffer, QOpenGLBuffer draw_buffer, QOpenGLTexture draw_texture);
VncRenderer(QQuickWindow* window,
QSharedPointer<QOpenGLBuffer> fill_buffer,
QSharedPointer<QVector<copy>> copy_source,
QSharedPointer<QOpenGLBuffer> copy_buffer,
QSharedPointer<QOpenGLBuffer> draw_buffer,
QSharedPointer<QVector<QOpenGLTexture*>> draw_textures,
QObject *parent = 0);
protected:
void render() override;
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override;
void synchronize(QQuickFramebufferObject *) override;
private:
// for filling a rectangle with a solid color
QOpenGLShaderProgram m_fill_program;
QOpenGLBuffer m_fill_buffer;
QQuickWindow *m_window;
unsigned int m_fill_count;
// for copying portions of the framebuffer
QVector<Uploader::CopyToAtlas> m_copy_data;
// for drawing from a texture atlas
QOpenGLShaderProgram m_draw_program;
QOpenGLBuffer m_draw_buffer;
QVector<*QOpenGLTexture> m_draw_texture;
QOpenGLShaderProgram m_fill_program;
QSharedPointer<QOpenGLBuffer> m_fill_buffer;
unsigned int m_copy_count;
QSharedPointer<QVector<copy>> m_copy_source;
QSharedPointer<QOpenGLBuffer> m_copy_buffer;
unsigned int m_draw_count;
QOpenGLShaderProgram m_draw_program;
QSharedPointer<QOpenGLBuffer> m_draw_buffer;
QSharedPointer<QVector<QOpenGLTexture*>> m_draw_textures;
QMatrix4x4 m_ortho;
bool m_clear;
signals:
void rendered();
void finishedRendering();
};
#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