Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Ludmány Balázs
/
thin-client
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
d4f375e9
authored
Jul 06, 2016
by
Ludmány Balázs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First somewhat working version
parent
f37580d7
Pipeline
#124
skipped in 0 seconds
Changes
16
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
428 additions
and
155 deletions
+428
-155
ThinClient.pro
+2
-1
ThinClient.pro.user
+1
-1
dispatcher.cpp
+64
-17
dispatcher.h
+12
-2
draw_shader.fsh
+3
-3
draw_shader.vsh
+10
-0
jpegdecoder.cpp
+3
-3
jpegdecoder.h
+8
-5
main.cpp
+0
-3
main.qml
+4
-4
qvnc.cpp
+26
-3
qvnc.h
+7
-1
uploader.cpp
+131
-28
uploader.h
+40
-8
vncrenderer.cpp
+93
-62
vncrenderer.h
+24
-14
No files found.
ThinClient.pro
View file @
d4f375e9
...
...
@@ -32,4 +32,5 @@ HEADERS += \
dispatcher
.
h
DISTFILES
+=
\
draw_shader
.
fsh
draw_shader
.
fsh
\
draw_shader
.
vsh
ThinClient.pro.user
View file @
d4f375e9
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.5.1, 2016-07-0
1T15:26:59
. -->
<!-- Written by QtCreator 3.5.1, 2016-07-0
6T14:51:57
. -->
<qtcreator>
<data>
<variable>
EnvironmentId
</variable>
...
...
dispatcher.cpp
View file @
d4f375e9
#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
(
d
ispatcher
->
d
ecoderCount
()
==
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
();
...
...
dispatcher.h
View file @
d4f375e9
#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
draw_shader.fsh
View file @
d4f375e9
uniform sampler2D
qt_Texture0
;
varying highp vec
4 qt_TexCoord0
;
uniform sampler2D
texture
;
varying highp vec
2 vartexcoord
;
void main(void)
{
gl_FragColor = texture2D(
qt_Texture0, qt_TexCoord0.st
);
gl_FragColor = texture2D(
texture, vartexcoord
);
}
draw_shader.vsh
0 → 100644
View file @
d4f375e9
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;
}
jpegdecoder.cpp
View file @
d4f375e9
#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
);
}
jpegdecoder.h
View file @
d4f375e9
...
...
@@ -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
Q
Object
,
public
Q
Runnable
{
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
main.cpp
View file @
d4f375e9
...
...
@@ -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"
);
...
...
main.qml
View file @
d4f375e9
...
...
@@ -4,8 +4,8 @@ import thinclient 1.1
ApplicationWindow
{
visible
:
true
width
:
64
0
height
:
480
width
:
128
0
height
:
1024
header
:
TabBar
{
width
:
parent
.
width
...
...
@@ -26,7 +26,7 @@ ApplicationWindow {
id
:
vnc
host
:
"vm.ik.bme.hu"
port
:
10495
width
:
1
024
height
:
768
width
:
1
280
height
:
1024
}
}
qvnc.cpp
View file @
d4f375e9
...
...
@@ -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
;
}
...
...
qvnc.h
View file @
d4f375e9
#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
uploader.cpp
View file @
d4f375e9
#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.0
f
);
m_copy_data
.
append
(
0.0
f
);
// top left
m_copy_data
.
append
((
float
)
dest_x
);
m_copy_data
.
append
((
float
)
dest_y
);
m_copy_data
.
append
(
0.0
f
);
m_copy_data
.
append
(
1.0
f
);
// bottom right
m_copy_data
.
append
((
float
)
(
dest_x
+
width
));
m_copy_data
.
append
((
float
)
(
dest_y
+
height
));
m_copy_data
.
append
(
1.0
f
);
m_copy_data
.
append
(
0.0
f
);
// top right
m_copy_data
.
append
((
float
)
(
dest_x
+
width
));
m_copy_data
.
append
((
float
)
dest_y
);
m_copy_data
.
append
(
1.0
f
);
m_copy_data
.
append
(
1.0
f
);
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.0
f
);
m_draw_data
.
append
(
1.0
f
);
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
;
}
uploader.h
View file @
d4f375e9
#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
;
Q
OpenGLBuffer
m_fill_buffer
;
Q
SharedPointer
<
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
;
};
...
...
vncrenderer.cpp
View file @
d4f375e9
#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.0
f
,
0.0
f
,
0.0
f
,
1.0
f
);
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
();
}
vncrenderer.h
View file @
d4f375e9
#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
Q
Object
,
public
Q
QuickFramebufferObject
::
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment