Commit b53b0657 by Ludmány Balázs

Reuse buffers

parent 3aeb58bf
TEMPLATE = app
QT += qml quick
CONFIG += c++14
CONFIG += c++11 ofast
SOURCES += main.cpp \
jpegdecoder.cpp \
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.5.1, 2016-07-26T16:47:48. -->
<!-- Written by QtCreator 3.5.1, 2016-07-27T15:57:27. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
......
......@@ -3,6 +3,5 @@ varying mediump vec2 vartexcoord;
void main(void)
{
gl_FragColor = vec4(texture2D(texture, vartexcoord).rgb, 1.0);
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
gl_FragColor = texture2D(texture, vartexcoord);
}
......@@ -7,5 +7,5 @@ varying mediump vec2 vartexcoord;
void main(void)
{
gl_Position = vec4((position.x - 1024.0) / 1024.0, (position.y - 1024.0) / 1024.0, 0.0, 1.0);
vartexcoord = vec2(0.0, 1.0) - vec2(texcoord.x / 1280.0, texcoord.y / 720.0);
vartexcoord = vec2(texcoord.x / 1280.0, texcoord.y / 720.0);
}
......@@ -31,8 +31,7 @@ void Dispatcher::GotBitmap(rfbClient *client, const uint8_t *buffer, int x, int
{
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0);
// We have to make a deep copy because libvnc might free the buffer as soon as this function returns
QImage image(buffer, w, h, QImage::Format_RGBX8888);
dispatcher->uploader()->gotBitmap(image.convertToFormat(QImage::Format_RGB888), x, y, w, h);
dispatcher->uploader()->gotBitmap(buffer, x, y, w, h);
}
rfbBool Dispatcher::GotJpeg(rfbClient *client, const uint8_t *buffer, int length, int x, int y, int w, int h)
......@@ -152,6 +151,12 @@ void Dispatcher::refresh()
int message = 0;
if(!HandleRFBServerMessage(m_client)) {
terminate();
emit error();
return;
}
// Wait until we get something
while(message == 0) {
message = WaitForMessage(m_client, 1000);
......@@ -161,12 +166,6 @@ void Dispatcher::refresh()
return;
}
}
if(!HandleRFBServerMessage(m_client)) {
terminate();
emit error();
return;
}
}
void Dispatcher::terminate()
......
......@@ -4,6 +4,5 @@ varying lowp vec4 varcolor;
void main(void)
{
gl_FragColor = vec4(texture2D(texture, vartexcoord).rgb, 1.0) + varcolor;
// gl_FragColor = vec4(vartexcoord, 0.0, 1.0);
gl_FragColor = vec4(texture2D(texture, vartexcoord).rgb + varcolor.rgb, 1.0);
}
......@@ -10,6 +10,6 @@ varying mediump vec2 vartexcoord;
void main(void)
{
gl_Position = ortho * vec4(position, 0.0, 1.0);
varcolor = color.gggg;
varcolor = color;
vartexcoord = vec2(texcoord.x / 2048.0, texcoord.y / 2048.0);
}
......@@ -9,27 +9,32 @@ JpegDecoder::JpegDecoder(ConcurrentQueue<Jpeg *, 256u> *queue, QObject *parent)
void JpegDecoder::operate()
{
struct jpeg_decompress_struct cinfo;
struct error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr.mgr);
jerr.mgr.error_exit = error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
}
jpeg_create_decompress(&cinfo);
Jpeg *jpeg;
JSAMPLE *samples;
JSAMPROW *rows;
forever {
jpeg = m_queue->dequeue();
struct jpeg_decompress_struct cinfo;
struct error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr.mgr);
jerr.mgr.error_exit = error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
}
jpeg_create_decompress(&cinfo);
cinfo.do_fancy_upsampling = TRUE;
cinfo.dct_method = JDCT_FLOAT;
jpeg_mem_src(&cinfo, jpeg->data, jpeg->length);
(void) jpeg_read_header(&cinfo, TRUE);
cinfo.dct_method = JDCT_FASTEST;
cinfo.do_fancy_upsampling = FALSE;
cinfo.two_pass_quantize = FALSE;
cinfo.dither_mode = JDITHER_ORDERED;
//cinfo.scale_num = 1;
//cinfo.scale_denom = 8;
cinfo.out_color_space = JCS_EXT_RGBX;
(void) jpeg_start_decompress(&cinfo);
JSAMPLE *samples = new JSAMPLE[cinfo.output_width * cinfo.output_height * cinfo.output_components];
JSAMPROW *rows = new JSAMPROW[cinfo.output_height * cinfo.output_components];
samples = new JSAMPLE[cinfo.output_width * cinfo.output_height * cinfo.output_components];
rows = new JSAMPROW[cinfo.output_height * cinfo.output_components];
for(size_t i = 0; i < cinfo.output_height; i++) {
rows[i] = samples + (i * cinfo.output_width * cinfo.output_components);
}
......@@ -41,7 +46,7 @@ void JpegDecoder::operate()
emit finished(samples, jpeg->x, jpeg->y, jpeg->width, jpeg->height);
delete[] jpeg->data;
delete jpeg;
delete rows;
jpeg_destroy_decompress(&cinfo);
delete[] rows;
}
jpeg_destroy_decompress(&cinfo);
}
......@@ -16,7 +16,7 @@ int main(int argc, char *argv[])
format.setMajorVersion(2);
format.setMinorVersion(0);
format.setRenderableType(QSurfaceFormat::OpenGLES);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
format.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(format);
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES, true);
......@@ -28,4 +28,3 @@ int main(int argc, char *argv[])
return app.exec();
}
......@@ -4,8 +4,8 @@ import thinclient 1.3
ApplicationWindow {
visible: true
width: vnc.width
height: tab.height + vnc.height
width: 800
height: 600
id: window
header: TabBar {
......@@ -30,5 +30,6 @@ ApplicationWindow {
port: 10495
width: 1280
height: 720
transform: Scale {xScale: window.width / vnc.width; yScale: (window.height - tab.height) / vnc.height}
}
}
......@@ -164,7 +164,7 @@ void QVnc::wheelEvent(QWheelEvent *event)
void QVnc::mouseMoveEvent(QMouseEvent *event)
{
// Filter mouse move events, we don't need 100+ of them in a second
if((event->timestamp() - m_lastMouseEvent) > 33) {
//if((event->timestamp() - m_lastMouseEvent) > 33) {
Qt::MouseButtons buttons = event->buttons();
m_lastMouseEvent = event->timestamp();
if(m_dispatcher->mouseEvent(event->x(),
......@@ -177,7 +177,7 @@ void QVnc::mouseMoveEvent(QMouseEvent *event)
event->accept();
else
event->ignore();
}
//}
}
void QVnc::hoverMoveEvent(QHoverEvent *event)
......
#ifndef VNC_H
#define VNC_H
#define DECODER_COUNT 8
#define DECODER_COUNT 256
#include <QQuickWindow>
#include <QObject>
......
......@@ -5,7 +5,7 @@ Uploader::Uploader(QObject *parent) :
QObject(parent), m_context(this), m_indices(QOpenGLBuffer::IndexBuffer),
m_uploadVertices(new QOpenGLBuffer*), m_renderVertices(new QOpenGLBuffer*),
m_uploadTexture(new GLuint*), m_renderTexture(new GLuint*), m_program(this), m_jpegs(0),
m_atlasX(0), m_atlasY(0), m_atlasRowHeight(0), m_atlasLastWidth(0), m_copyIndex(0)
m_atlasX(1), m_atlasY(1), m_atlasRowHeight(0), m_atlasLastWidth(0), m_copyIndex(0)
{
// "applications must ensure that create() is only called on the main (GUI) thread"
m_surface.create();
......@@ -29,24 +29,9 @@ void Uploader::createContext(QOpenGLContext *context)
m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, "copy_shader.vsh");
m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, "copy_shader.fsh");
m_program.bind();
m_program.setUniformValue("texture", 0);
QMatrix4x4 ortho;
ortho.ortho(0, TEXTURE_WIDTH, 0, TEXTURE_HEIGHT, -1, 1);
// m_program.setUniformValue("ortho", ortho);
m_program.setUniformValue("texture", 1);
m_program.enableAttributeArray("position");
m_program.enableAttributeArray("texcoord");
m_functions->glVertexAttribPointer(m_program.attributeLocation("position"),
2,
GL_UNSIGNED_SHORT,
GL_FALSE,
sizeof(Copy),
(void*) 0);
m_functions->glVertexAttribPointer(m_program.attributeLocation("texcoord"),
2,
GL_UNSIGNED_SHORT,
GL_FALSE,
sizeof(Copy),
(void*) (2 * sizeof(GLushort)));
m_indices.create();
m_indices.bind();
......@@ -75,21 +60,21 @@ void Uploader::createContext(QOpenGLContext *context)
m_functions->glEnable(GL_TEXTURE_2D);
m_functions->glActiveTexture(GL_TEXTURE0);
m_functions->glGenTextures(2, m_texId);
unsigned char black[] = {0, 0, 0, 0};
for(size_t i = 0; i < 2; i++) {
m_functions->glBindTexture(GL_TEXTURE_2D, m_texId[i]);
m_functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
m_functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
m_functions->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, black);
}
*m_uploadTexture = m_texId;
*m_renderTexture = m_texId + 1;
m_functions->glBindTexture(GL_TEXTURE_2D, **m_uploadTexture);
m_functions->glGenFramebuffers(1, &m_FBOId);
m_functions->glBindFramebuffer(GL_FRAMEBUFFER, m_FBOId);
m_functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, **m_uploadTexture, 0);
m_functions->glBindTexture(GL_TEXTURE_2D, **m_uploadTexture);
m_functions->glViewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
m_functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
......@@ -120,10 +105,10 @@ void Uploader::gotCopy(const GLushort src_x, const GLushort src_y,
// copy from source
if(m_copyIndex + 4 < COPY_BUFFER) {
m_copyPointer[m_copyIndex++] = Copy({m_atlasX, m_atlasY, src_x, (GLushort) (src_y + height)});
m_copyPointer[m_copyIndex++] = Copy({m_atlasX, (GLushort) (m_atlasY + height), src_x, src_y});
m_copyPointer[m_copyIndex++] = Copy({(GLushort) (m_atlasX + width), m_atlasY, (GLushort) (src_x + width), (GLushort) (src_y + height)});
m_copyPointer[m_copyIndex++] = Copy({(GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height), (GLushort) (src_x + width), src_y});
m_copyPointer[m_copyIndex++] = Copy({m_atlasX, (GLushort) (m_atlasY + height), src_x, (GLushort) (src_y + height)});
m_copyPointer[m_copyIndex++] = Copy({m_atlasX, m_atlasY, src_x, src_y});
m_copyPointer[m_copyIndex++] = Copy({(GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height), (GLushort) (src_x + width), (GLushort) (src_y + height)});
m_copyPointer[m_copyIndex++] = Copy({(GLushort) (m_atlasX + width), m_atlasY, (GLushort) (src_x + width), src_y});
} else {
qDebug() << "Out of memory";
}
......@@ -131,26 +116,26 @@ void Uploader::gotCopy(const GLushort src_x, const GLushort src_y,
// copy to destination
if(m_vertexIndex + 4 < VERTEX_BUFFER) {
// bottom left
m_vertexPointer[m_vertexIndex++] = Vertex({dest_x, (GLushort) (dest_y + height), 0, 0, 0, 0, m_atlasX, m_atlasY});
m_vertexPointer[m_vertexIndex++] = Vertex({dest_x, (GLushort) (dest_y + height), 0, 0, 0, 0, m_atlasX, (GLushort) (m_atlasY + height)});
// top left
m_vertexPointer[m_vertexIndex++] = Vertex({dest_x, dest_y, 0, 0, 0, 0, m_atlasX, (GLushort) (m_atlasY + height)});
m_vertexPointer[m_vertexIndex++] = Vertex({dest_x, dest_y, 0, 0, 0, 0, m_atlasX, m_atlasY});
// bottom right
m_vertexPointer[m_vertexIndex++] = Vertex({(GLushort) (dest_x + width), (GLushort) (dest_y + height), 0, 0, 0, 0, (GLushort) (m_atlasX + width), m_atlasY});
m_vertexPointer[m_vertexIndex++] = Vertex({(GLushort) (dest_x + width), (GLushort) (dest_y + height), 0, 0, 0, 0, (GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height)});
// top right
m_vertexPointer[m_vertexIndex++] = Vertex({(GLushort) (dest_x + width), dest_y, 0, 0, 0, 0, (GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height)});
m_vertexPointer[m_vertexIndex++] = Vertex({(GLushort) (dest_x + width), dest_y, 0, 0, 0, 0, (GLushort) (m_atlasX + width), m_atlasY});
} else {
qDebug() << "Out of memory";
}
}
void Uploader::gotBitmap(const QImage &image,
void Uploader::gotBitmap(const unsigned char *image,
const GLushort x, const GLushort y,
const GLushort width, const GLushort height)
{
if(!refreshAtlas(width, height))
return;
m_functions->glTexSubImage2D(GL_TEXTURE_2D, 0, m_atlasX, m_atlasY, width, height, GL_RGB, GL_UNSIGNED_BYTE, image.constBits());
m_functions->glTexSubImage2D(GL_TEXTURE_2D, 0, m_atlasX, m_atlasY, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
if(m_vertexIndex + 4 < VERTEX_BUFFER) {
// bottom left
......@@ -180,7 +165,7 @@ void Uploader::finishedJpeg(const unsigned char *image,
m_jpegs--;
m_functions->glTexSubImage2D(GL_TEXTURE_2D, 0, m_atlasX, m_atlasY, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
m_functions->glTexSubImage2D(GL_TEXTURE_2D, 0, m_atlasX, m_atlasY, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
delete[] image;
if(m_vertexIndex + 4 < VERTEX_BUFFER) {
......@@ -265,40 +250,44 @@ void Uploader::startRendering()
std::swap(*m_uploadTexture, *m_renderTexture);
m_atlasX = 0;
m_atlasY = 0;
m_atlasX = 1;
m_atlasY = 1;
m_atlasRowHeight = 0;
m_atlasLastWidth = 0;
m_swapped = false;
m_finished = false;
m_functions->glBindTexture(GL_TEXTURE_2D, **m_uploadTexture);
m_functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, **m_uploadTexture, 0);
m_functions->glBindTexture(GL_TEXTURE_2D, **m_uploadTexture);
emit uploadFinished();
}
void Uploader::copyRectangles()
{
if(m_copyIndex > 0) {
// m_functions->glActiveTexture(GL_TEXTURE1);
m_functions->glBindTexture(GL_TEXTURE_2D, m_FBOTexture);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_functions->glActiveTexture(GL_TEXTURE1);
m_copyBuffer.bind();
m_copyBuffer.unmap();
m_functions->glVertexAttribPointer(m_program.attributeLocation("position"),
2,
GL_UNSIGNED_SHORT,
GL_FALSE,
sizeof(Copy),
(void*) 0);
m_functions->glVertexAttribPointer(m_program.attributeLocation("texcoord"),
2,
GL_UNSIGNED_SHORT,
GL_FALSE,
sizeof(Copy),
(void*) (2 * sizeof(GLushort)));
m_indices.bind();
m_functions->glDrawElements(GL_TRIANGLE_STRIP, (m_copyIndex / 4) * 6 - 2, GL_UNSIGNED_SHORT, (GLvoid*) 0);
m_functions->glFinish();
m_copyPointer = (Copy*) m_copyBuffer.map(QOpenGLBuffer::WriteOnly);
(*m_uploadVertices)->bind();
m_functions->glBindTexture(GL_TEXTURE_2D, **m_uploadTexture);
// m_functions->glActiveTexture(GL_TEXTURE0);
m_functions->glActiveTexture(GL_TEXTURE0);
m_copyIndex = 0;
}
}
......@@ -325,14 +314,15 @@ unsigned int *Uploader::drawCount() const
void Uploader::changeFBOTexture(const unsigned int FBOTexture, const QMatrix4x4 &ortho)
{
/*m_functions->glActiveTexture(GL_TEXTURE1);
m_FBOTexture = FBOTexture;
m_functions->glActiveTexture(GL_TEXTURE1);
m_functions->glBindTexture(GL_TEXTURE_2D, m_FBOTexture);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_functions->glActiveTexture(GL_TEXTURE0);*/
m_functions->glActiveTexture(GL_TEXTURE0);
m_FBOTexture = FBOTexture;
m_program.setUniformValue("texortho", ortho);
}
......@@ -40,7 +40,7 @@ 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];
constexpr Indices() : i()
Indices() : i()
{
i[0] = 0;
auto index = 1;
......@@ -51,7 +51,7 @@ struct Indices
}
}
};
constexpr Indices ind;
const struct Indices ind;
struct Vertex
{
......@@ -97,7 +97,7 @@ public:
void gotCopy(const GLushort src_x, const GLushort src_y,
const GLushort width, const GLushort height,
const GLushort dest_x, const GLushort dest_y);
void gotBitmap(const QImage &image,
void gotBitmap(const unsigned char *image,
const GLushort x, const GLushort y,
const GLushort width, const GLushort height);
void gotJpeg();
......
......@@ -25,9 +25,9 @@ VncRenderer::VncRenderer(QQuickWindow *window,
void VncRenderer::render()
{
/*static QTime frameTime;
static QTime frameTime;
qDebug() << qRound(1000.0 / frameTime.elapsed()) << *m_drawCount;
frameTime.restart();*/
frameTime.restart();
if(*m_drawCount > 0) {
m_program.bind();
......
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