Commit 1eb3ee74 by Balázs Ludmány

Commit Arnoldnak!

parent cb68f729
...@@ -18,11 +18,10 @@ QML_IMPORT_PATH = ...@@ -18,11 +18,10 @@ QML_IMPORT_PATH =
# Default rules for deployment. # Default rules for deployment.
include(deployment.pri) include(deployment.pri)
LIBS += -L$$PWD/../libvnc/libvncclient/.libs/ -lvncclient -lEGL -ljpeg -L$$PWD/../build-texload-Desktop_Qt_5_9_0_GCC_64bit-Release -ltexload
unix|win32: LIBS += -L$$PWD/../libvnc/libvncclient/.libs/ -lvncclient -lEGL -ljpeg INCLUDEPATH += $$PWD/../libvnc $$PWD/../texload
DEPENDPATH += $$PWD/../libvnc $$PWD/../texload
INCLUDEPATH += $$PWD/../libvnc
DEPENDPATH += $$PWD/../libvnc
HEADERS += \ HEADERS += \
vncrenderer.h \ vncrenderer.h \
...@@ -33,11 +32,12 @@ HEADERS += \ ...@@ -33,11 +32,12 @@ HEADERS += \
concurrentqueue.h concurrentqueue.h
DISTFILES += \ DISTFILES += \
draw_shader.fsh \
draw_shader.vsh \
copy_shader.vsh \ copy_shader.vsh \
copy_shader.fsh \ copy_shader.fsh \
fill_shader.vsh \ fill_shader.vsh \
fill_shader.fsh \ fill_shader.fsh \
bitmap_shader.vsh \ bitmap_shader.vsh \
bitmap_shader.fsh bitmap_shader.fsh \
ycbcr_shader.fsh
#QMAKE_CXXFLAGS_RELEASE -= -O2
<?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-08-01T17:47:15. --> <!-- Written by QtCreator 4.3.1, 2017-07-03T16:01:35. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>
<value type="QByteArray">{922a144e-00be-428d-a407-33848eeec705}</value> <value type="QByteArray">{221989f1-8db7-4676-b888-f4ceb403e265}</value>
</data> </data>
<data> <data>
<variable>ProjectExplorer.Project.ActiveTarget</variable> <variable>ProjectExplorer.Project.ActiveTarget</variable>
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value> <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value> <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value> <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value> <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value> <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value> <value type="int" key="EditorConfiguration.TabSize">8</value>
...@@ -53,19 +54,21 @@ ...@@ -53,19 +54,21 @@
</data> </data>
<data> <data>
<variable>ProjectExplorer.Project.PluginSettings</variable> <variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/> <valuemap type="QVariantMap">
<valuelist type="QVariantList" key="ClangStaticAnalyzer.SuppressedDiagnostics"/>
</valuemap>
</data> </data>
<data> <data>
<variable>ProjectExplorer.Project.Target.0</variable> <variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap"> <valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.9.0 GCC 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.9.0 GCC 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{9fe100e5-65f5-4993-908d-e24f092a1cff}</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.59.gcc_64_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</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">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/ldmnyblzs/files/Projects/build-ThinClient-Desktop-Debug</value> <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ldmnyblzs/Projects/build-ThinClient-Desktop_Qt_5_9_0_GCC_64bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
...@@ -73,7 +76,6 @@ ...@@ -73,7 +76,6 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value> <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">false</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value> <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value> <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value> <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
...@@ -118,7 +120,9 @@ ...@@ -118,7 +120,9 @@
</valuemap> </valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges">
<value type="QString">QT_QPA_VERBOSE=opengl:1</value>
</valuelist>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
...@@ -126,7 +130,7 @@ ...@@ -126,7 +130,7 @@
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap> </valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/ldmnyblzs/files/Projects/build-ThinClient-Desktop-Release</value> <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ldmnyblzs/Projects/build-ThinClient-Desktop_Qt_5_9_0_GCC_64bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
...@@ -134,7 +138,6 @@ ...@@ -134,7 +138,6 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value> <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value> <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value> <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value> <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
...@@ -186,7 +189,67 @@ ...@@ -186,7 +189,67 @@
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value> <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap> </valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value> <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ldmnyblzs/Projects/build-ThinClient-Desktop_Qt_5_9_0_GCC_64bit-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value> <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
...@@ -202,6 +265,11 @@ ...@@ -202,6 +265,11 @@
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value> <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/> <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/> <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value> <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value> <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
...@@ -237,23 +305,22 @@ ...@@ -237,23 +305,22 @@
<value type="int">14</value> <value type="int">14</value>
</valuelist> </valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value> <value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"> <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString">QML_RENDER_TIMING=1</value>
</valuelist>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">ThinClient</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">ThinClient</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/media/ldmnyblzs/files/Projects/ThinClient/ThinClient.pro</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/ldmnyblzs/Projects/ThinClient/ThinClient.pro</value>
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value> <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">ThinClient.pro</value> <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">ThinClient.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value> <value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value> <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">/home/ldmnyblzs/Projects/build-ThinClient-Desktop_Qt_5_9_0_GCC_64bit-Release</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">true</value> <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">false</value> <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value> <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">false</value> <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap> </valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value> <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap> </valuemap>
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.2.1, 2017-06-03T23:07:15. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{922a144e-00be-428d-a407-33848eeec705}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">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="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/ldmnyblzs/files/Projects/build-ThinClient-Desktop-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/media/ldmnyblzs/files/Projects/build-ThinClient-Desktop-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
<value type="QString">-w</value>
<value type="QString">-r</value>
</valuelist>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">ThinClient</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">ThinClient2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/ldmnyblzs/Projects/ThinClient/ThinClient.pro</value>
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">ThinClient.pro</value>
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">/media/ldmnyblzs/files/Projects/build-ThinClient-Desktop-Release</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">18</value>
</data>
<data>
<variable>Version</variable>
<value type="int">18</value>
</data>
</qtcreator>
uniform sampler2D texture; uniform sampler2D texture;
varying highp vec4 vartexcoord; varying highp vec2 vartexcoord;
void main(void) void main(void)
{ {
gl_FragColor = texture2D(texture, vartexcoord.st); gl_FragColor = vec4(texture2D(texture, vartexcoord).rgb, 1.0);
//gl_FragColor = vec4(vartexcoord.st, 0.0, 1.0);
} }
uniform highp mat4 ortho; uniform highp mat4 ortho; // transforms screen coordinates to [-1, 1]
uniform highp mat4 texortho; uniform highp mat4 texortho; // transforms screen coordinates to [0, 1]
attribute highp vec2 position; attribute highp vec2 position;
attribute highp vec2 texcoord;
varying highp vec4 vartexcoord; varying highp vec2 vartexcoord;
void main(void) void main(void)
{ {
gl_Position = ortho * vec4(position, 0.0, 1.0); gl_Position = ortho * vec4(position, 0.0, 1.0);
vartexcoord = texortho * vec4(texcoord, 0.0, 1.0); vartexcoord = vec4(texortho * vec4(position, 0.0, 1.0)).xy;
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <QSemaphore> #include <QSemaphore>
#include <QMutex> #include <QMutex>
#include <QTime>
template <class T, const unsigned short S> template <class T, const unsigned short S>
class ConcurrentQueue class ConcurrentQueue
...@@ -14,6 +15,7 @@ public: ...@@ -14,6 +15,7 @@ public:
bool isEmpty() const; bool isEmpty() const;
private: private:
T m_buffer[S]; T m_buffer[S];
QTime m_time[S];
unsigned short m_next; unsigned short m_next;
unsigned short m_first; unsigned short m_first;
QSemaphore m_free; QSemaphore m_free;
......
uniform sampler2D texture; uniform sampler2D texture;
varying mediump vec2 vartexcoord; varying highp vec2 vartarget;
void main(void) void main(void)
{ {
gl_FragColor = texture2D(texture, vartexcoord); gl_FragColor = texture2D(texture, vartarget);
} }
uniform mediump mat4 ortho; uniform highp mat4 srcortho;
uniform mediump mat4 texortho; uniform highp mat4 trgortho;
attribute mediump vec2 position; attribute highp vec2 source;
attribute mediump vec2 texcoord; attribute highp vec2 target;
varying mediump vec2 vartexcoord; varying highp vec2 vartarget;
void main(void) void main(void)
{ {
gl_Position = vec4((position.x - 1024.0) / 1024.0, (position.y - 1024.0) / 1024.0, 0.0, 1.0); gl_Position = trgortho * vec4(target, 0.0, 1.0);
vartexcoord = vec2(texcoord.x / 1920.0, texcoord.y / 1080.0); vartarget = vec4(srcortho * vec4(source, 0.0, 1.0)).xy;
} }
#include "dispatcher.h" #include "dispatcher.h"
#include "uploader.h"
Dispatcher::Dispatcher(Uploader *uploader, QObject *parent) : Dispatcher::Dispatcher(Uploader *uploader, QObject *parent) :
QObject(parent), m_client(NULL), m_uploader(uploader) QObject(parent)
{
m_client = rfbGetClient(8, 3, 4);
m_client->canHandleNewFBSize = FALSE;
m_client->MallocFrameBuffer = Dispatcher::MallocFrameBuffer;
m_client->GotCopyRect = Dispatcher::GotCopyRect;
m_client->GotFillRect = Dispatcher::GotFillRect;
m_client->GotBitmap = Dispatcher::GotBitmap;
m_client->GotJpeg = Dispatcher::GotJpeg;
m_client->FinishedFrameBufferUpdate = Dispatcher::FinishedFrameBufferUpdate;
m_client->GetPassword = Dispatcher::GetPassword;
rfbClientSetClientData(m_client, const_cast<char*>("dispatcher"), this);
// the pointer to the Uploader is stored in the rfbClient instead of a member of the class to avoid duplication
rfbClientSetClientData(m_client, const_cast<char*>("uploader"), uploader);
}
Dispatcher::~Dispatcher()
{ {
rfbClientCleanup(m_client);
} }
rfbBool Dispatcher::MallocFrameBuffer(rfbClient *client) rfbBool Dispatcher::MallocFrameBuffer(rfbClient *client)
{ {
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0); auto dispatcher = static_cast<Dispatcher *>(rfbClientGetClientData(client, const_cast<char*>("dispatcher")));
emit dispatcher->resizeFramebuffer(QSize(client->width, client->height)); emit dispatcher->resizeFramebuffer(QSize(client->width, client->height));
return TRUE; return TRUE;
} }
void Dispatcher::GotCopyRect(rfbClient *client, const int src_x, const int src_y, const int w, const int h, const int dest_x, const int dest_y) void Dispatcher::GotCopyRect(rfbClient *client, const int src_x, const int src_y, const int w, const int h, const int dest_x, const int dest_y)
{ {
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0); auto uploader = static_cast<Uploader *>(rfbClientGetClientData(client, const_cast<char*>("uploader")));
dispatcher->uploader()->gotCopy(src_x, src_y, w, h, dest_x, dest_y); uploader->gotCopy(src_x, src_y, w, h, dest_x, dest_y);
} }
void Dispatcher::GotFillRect(rfbClient *client, int x, int y, int w, int h, uint32_t colour) void Dispatcher::GotFillRect(rfbClient *client, int x, int y, int w, int h, uint32_t colour)
{ {
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0); auto uploader = static_cast<Uploader *>(rfbClientGetClientData(client, const_cast<char*>("uploader")));
int red = (colour >> client->format.redShift) & client->format.redMax; int red = (colour >> client->format.redShift) & client->format.redMax;
int green = (colour >> client->format.greenShift) & client->format.greenMax; int green = (colour >> client->format.greenShift) & client->format.greenMax;
int blue = (colour >> client->format.blueShift) & client->format.blueMax; int blue = (colour >> client->format.blueShift) & client->format.blueMax;
dispatcher->uploader()->gotFill(x, y, w, h, red, green, blue); uploader->gotFill(x, y, w, h, red, green, blue);
} }
void Dispatcher::GotBitmap(rfbClient *client, const uint8_t *buffer, int x, int y, int w, int h) void Dispatcher::GotBitmap(rfbClient *client, const uint8_t *buffer, int x, int y, int w, int h)
{ {
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0); auto uploader = static_cast<Uploader *>(rfbClientGetClientData(client, const_cast<char*>("uploader")));
// We have to make a deep copy because libvnc might free the buffer as soon as this function returns uploader->gotBitmap(buffer, 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) rfbBool Dispatcher::GotJpeg(rfbClient *client, const uint8_t *buffer, int length, int x, int y, int w, int h)
{ {
Dispatcher *dispatcher = static_cast<Dispatcher *>(rfbClientGetClientData(client, 0)); auto uploader = static_cast<Uploader *>(rfbClientGetClientData(client, const_cast<char*>("uploader")));
dispatcher->uploader()->gotJpeg(); uploader->gotJpeg(buffer, length, x, y, w, h);
Jpeg *jpeg = new Jpeg({(unsigned char*)buffer, length, x, y, w, h});
dispatcher->queue()->enqueue(jpeg);
return TRUE; return TRUE;
} }
void Dispatcher::FinishedFrameBufferUpdate(rfbClient *client) void Dispatcher::FinishedFrameBufferUpdate(rfbClient *client)
{ {
Dispatcher *dispatcher = (Dispatcher *) rfbClientGetClientData(client, 0); auto uploader = static_cast<Uploader *>(rfbClientGetClientData(client, const_cast<char*>("uploader")));
dispatcher->uploader()->finishedUpdate(); uploader->finishedUpdate();
} }
char *Dispatcher::GetPassword(rfbClient *client) char *Dispatcher::GetPassword(rfbClient *client)
{ {
char* password = new char[9]; char* password = (char*) std::malloc(sizeof(char) * 9);
strcpy(password, "asdfasdf"); strcpy(password, "asdfasdf");
return password; return password;
} }
...@@ -78,39 +96,18 @@ int Dispatcher::bitsPerPixel() ...@@ -78,39 +96,18 @@ int Dispatcher::bitsPerPixel()
return m_client->format.bitsPerPixel; return m_client->format.bitsPerPixel;
} }
ConcurrentQueue<Jpeg *, 256u> *Dispatcher::queue()
{
return &m_queue;
}
Uploader *Dispatcher::uploader() const
{
return m_uploader;
}
void Dispatcher::open(const QString host, const int port, const int width, const int height) void Dispatcher::open(const QString host, const int port, const int width, const int height)
{ {
QByteArray tmp = host.toLocal8Bit(); QByteArray tmp = host.toLocal8Bit();
m_client = rfbGetClient(8, 3, 4);
m_client->canHandleNewFBSize = FALSE;
m_client->serverHost = new char[tmp.size() + 1]; m_client->serverHost = new char[tmp.size() + 1];
strcpy(m_client->serverHost, tmp.constData()); strcpy(m_client->serverHost, tmp.constData());
m_client->serverPort = port; m_client->serverPort = port;
m_client->MallocFrameBuffer = Dispatcher::MallocFrameBuffer; //m_client->appData.useRemoteCursor = TRUE;
m_client->GotCopyRect = Dispatcher::GotCopyRect;
m_client->GotFillRect = Dispatcher::GotFillRect;
m_client->GotBitmap = Dispatcher::GotBitmap;
m_client->GotJpeg = Dispatcher::GotJpeg;
m_client->FinishedFrameBufferUpdate = Dispatcher::FinishedFrameBufferUpdate;
m_client->GetPassword = Dispatcher::GetPassword;
// 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 = 9; //m_client->appData.compressLevel = 0;
m_client->appData.qualityLevel = 0; //m_client->appData.qualityLevel = 9;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
m_client->format.bigEndian = TRUE; m_client->format.bigEndian = TRUE;
#else #else
...@@ -120,30 +117,11 @@ void Dispatcher::open(const QString host, const int port, const int width, const ...@@ -120,30 +117,11 @@ void Dispatcher::open(const QString host, const int port, const int width, const
m_client->format.trueColour = TRUE; m_client->format.trueColour = TRUE;
m_client->format.bitsPerPixel = 32; m_client->format.bitsPerPixel = 32;
rfbClientSetClientData(m_client, 0, this);
if(!rfbInitClient(m_client, NULL, NULL)) { if(!rfbInitClient(m_client, NULL, NULL)) {
emit error(); emit error();
return; return;
} }
// Stick to the format sent by the server if we can render it easily, set a new one otherwise
//
// Formats OpenGL ES 2.0 can (should be able to) handle:
// Internal Format External Format Type Bytes per Pixel
// --------------- --------------- ---- ---------------
// RGBA RGBA UNSIGNED_BYTE 4
// RGB RGB UNSIGNED_BYTE 3
// RGBA RGBA UNSIGNED_SHORT_4_4_4_4 2
// RGBA RGBA UNSIGNED_SHORT_5_5_5_1 2
// RGB RGB UNSIGNED_SHORT_5_6_5 2
// The Raspberry Pi supports BGRA too but only through extensions
//
// JPEG is RGB UNSIGNED_BYTE
// Supported raw formats:
// 32 bit: RGB888
// 16 bit: RGB444, RGB555, RGB565
refresh(); refresh();
decode(); decode();
} }
...@@ -166,10 +144,9 @@ void Dispatcher::refresh() ...@@ -166,10 +144,9 @@ void Dispatcher::refresh()
} }
void Dispatcher::decode() void Dispatcher::decode()
{ {
if(m_client == NULL)
return;
m_uploader->startDecoding(); auto uploader = static_cast<Uploader *>(rfbClientGetClientData(m_client, const_cast<char*>("uploader")));
uploader->startDecoding();
if(!HandleRFBServerMessage(m_client)) { if(!HandleRFBServerMessage(m_client)) {
terminate(); terminate();
......
#ifndef RFBDISPATCH_H #ifndef RFBDISPATCH_H
#define RFBDISPATCH_H #define RFBDISPATCH_H
#include <QOpenGLContext>
#include <QCoreApplication>
#include <QImage>
#include <QThreadPool>
#include <QObject> #include <QObject>
#include <QPoint>
#include <QSize>
#include <QColor>
#include <QMouseEvent>
#include <QVector3D>
#include <QTime>
#include <rfb/rfbclient.h> #include <rfb/rfbclient.h>
#include "uploader.h" class Uploader;
#include "jpegdecoder.h"
extern QTime elapsed;
class Dispatcher : public QObject class Dispatcher : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
Dispatcher(Uploader *uploader, QObject *parent = Q_NULLPTR); explicit Dispatcher(Uploader *uploader, QObject *parent = Q_NULLPTR);
~Dispatcher();
// libvnc hooks // libvnc hooks
static rfbBool MallocFrameBuffer(rfbClient* client); static rfbBool MallocFrameBuffer(rfbClient* client);
...@@ -40,14 +28,8 @@ public: ...@@ -40,14 +28,8 @@ public:
// parameters of the VNC connection // parameters of the VNC connection
int bitsPerPixel(); int bitsPerPixel();
// getters
ConcurrentQueue<Jpeg *, 256u>* queue();
Uploader *uploader() const;
private: private:
rfbClient *m_client; rfbClient *m_client;
Uploader *m_uploader;
ConcurrentQueue<Jpeg*, 256u> m_queue;
signals: signals:
// libvnc events // libvnc events
void gotCopy(const int src_x, const int src_y, const int width, const int height, const int dest_x, const int dest_y); void gotCopy(const int src_x, const int src_y, const int width, const int height, const int dest_x, const int dest_y);
......
uniform sampler2D texture;
varying mediump vec2 vartexcoord;
varying lowp vec4 varcolor;
void main(void)
{
gl_FragColor = vec4(texture2D(texture, vartexcoord).rgb + varcolor.rgb, 1.0);
}
uniform mediump mat4 ortho;
attribute mediump vec2 position;
attribute lowp vec4 color;
attribute mediump vec2 texcoord;
varying lowp vec4 varcolor;
varying mediump vec2 vartexcoord;
void main(void)
{
gl_Position = ortho * vec4(position, 0.0, 1.0);
varcolor = color;
vartexcoord = vec2(texcoord.x / 2048.0, texcoord.y / 2048.0);
}
...@@ -2,5 +2,5 @@ varying highp vec4 varcolor; ...@@ -2,5 +2,5 @@ varying highp vec4 varcolor;
void main(void) void main(void)
{ {
gl_FragColor = varcolor; gl_FragColor = vec4(varcolor.rgb, 1.0);
} }
#include "jpegdecoder.h" #include "jpegdecoder.h"
int Jpeg::y_width = 0;
int Jpeg::cb_width = 0;
int Jpeg::cr_width = 0;
unsigned char *Jpeg::y_pointer = 0;
unsigned char *Jpeg::cb_pointer = 0;
unsigned char *Jpeg::cr_pointer = 0;
struct error_mgr
{
struct jpeg_error_mgr mgr;
jmp_buf setjmp_buffer;
};
typedef struct error_mgr* error_ptr;
METHODDEF(void)
error_exit (j_common_ptr cinfo)
{
error_ptr myerr = (error_ptr) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
JpegDecoder::JpegDecoder(ConcurrentQueue<Jpeg *, 256u> *queue, QObject *parent) : JpegDecoder::JpegDecoder(ConcurrentQueue<Jpeg *, 1024u> *queue, QObject *parent) :
QObject(parent), m_queue(queue) QObject(parent), m_queue(queue)
{ {
} }
void JpegDecoder::operate() void JpegDecoder::operate()
{ {
//QTime time;
//time.start();
struct jpeg_decompress_struct cinfo; struct jpeg_decompress_struct cinfo;
struct error_mgr jerr; struct error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr.mgr); cinfo.err = jpeg_std_error(&jerr.mgr);
jerr.mgr.error_exit = error_exit; jerr.mgr.error_exit = &error_exit;
if (setjmp(jerr.setjmp_buffer)) { if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
} }
jpeg_create_decompress(&cinfo); jpeg_create_decompress(&cinfo);
Jpeg *jpeg;
JSAMPLE *samples;
JSAMPROW *rows;
//int dequeue, decompress;
forever { forever {
//time.restart(); auto jpeg = m_queue->dequeue();
jpeg = m_queue->dequeue();
//dequeue = time.elapsed(); jpeg->output = new JSAMPARRAY[3];
jpeg_mem_src(&cinfo, jpeg->data, jpeg->length);
(void) jpeg_read_header(&cinfo, TRUE); int paddingHeight = (16 - (jpeg->height % 16));
cinfo.dct_method = JDCT_FASTEST; int paddingWidth = jpeg->width + (16 - jpeg->width % 16);
cinfo.do_fancy_upsampling = FALSE;
cinfo.two_pass_quantize = FALSE; jpeg->padding = new JSAMPLE[3 * paddingHeight * paddingWidth];
cinfo.dither_mode = JDITHER_ORDERED;
//cinfo.scale_num = 1; jpeg->rows = new JSAMPROW[3 * (jpeg->height + paddingHeight)];
//cinfo.scale_denom = 8; for (unsigned char component = 0; component < 3; ++component)
cinfo.out_color_space = JCS_EXT_RGBX; jpeg->output[component] = &jpeg->rows[component * (jpeg->height + paddingHeight)];
(void) jpeg_start_decompress(&cinfo);
for (int row = 0; row < jpeg->height; ++row)
samples = new JSAMPLE[cinfo.output_width * cinfo.output_height * cinfo.output_components]; {
rows = new JSAMPROW[cinfo.output_height * cinfo.output_components]; jpeg->output[0][row] = &Jpeg::y_pointer[jpeg->x + (jpeg->y + row) * Jpeg::y_width];
for(size_t i = 0; i < cinfo.output_height; i++) { jpeg->output[1][row] = &Jpeg::cb_pointer[jpeg->x + (jpeg->y + row) * Jpeg::cb_width];
rows[i] = samples + (i * cinfo.output_width * cinfo.output_components); jpeg->output[2][row] = &Jpeg::cr_pointer[jpeg->x + (jpeg->y + row) * Jpeg::cr_width];
}
for (int row = 0; row < paddingHeight; ++row)
{
jpeg->output[0][jpeg->height + row] = &jpeg->padding[row * paddingWidth];
jpeg->output[1][jpeg->height + row] = &jpeg->padding[(paddingHeight + row) * paddingWidth];
jpeg->output[2][jpeg->height + row] = &jpeg->padding[(2 * paddingHeight + row) * paddingWidth];
} }
jpeg_mem_src(&cinfo, jpeg->input, jpeg->length);
jpeg_read_header(&cinfo, TRUE);
cinfo.dct_method = JDCT_FASTEST;
cinfo.raw_data_out = TRUE;
jpeg_start_decompress(&cinfo);
JSAMPARRAY rowzero[3];
for(int component = 0; component < cinfo.output_components; component++)
rowzero[component] = &jpeg->output[component][0];
while (cinfo.output_scanline < cinfo.output_height) { while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, rows + cinfo.output_scanline, 1); for(int component = 0; component < cinfo.output_components; component++)
jpeg->output[component] = &rowzero[component][cinfo.output_scanline / (cinfo.max_v_samp_factor * cinfo.comp_info[component].v_samp_factor)];
jpeg_read_raw_data(&cinfo, jpeg->output, qMax(static_cast<int>(cinfo.output_height - cinfo.output_scanline), cinfo.max_v_samp_factor * DCTSIZE));
} }
(void) jpeg_finish_decompress(&cinfo);
//decompress = time.elapsed(); jpeg_finish_decompress(&cinfo);
//qDebug() << "dequeue" << dequeue << "decompress" << decompress; emit finishedJpeg();
emit finished(samples, jpeg->x, jpeg->y, jpeg->width, jpeg->height);
delete[] jpeg->data;
delete jpeg; delete jpeg;
delete[] rows;
} }
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
} }
...@@ -15,12 +15,39 @@ ...@@ -15,12 +15,39 @@
struct Jpeg struct Jpeg
{ {
uint8_t *data; uint8_t *input;
int length; std::size_t length;
int x; JSAMPIMAGE output;
int y; JSAMPROW *rows;
JSAMPLE *padding;
int width; int width;
int height; int height;
int x;
int y;
static int y_width;
static int cb_width;
static int cr_width;
static unsigned char *y_pointer;
static unsigned char *cb_pointer;
static unsigned char *cr_pointer;
Jpeg(uint8_t *input,
const std::size_t length,
const int width,
const int height,
const int x,
const int y) : input(input), length(length), width(width), height(height), x(x), y(y)
{
}
~Jpeg()
{
std::free(input);
delete[] output;
delete[] rows;
delete[] padding;
}
}; };
/*! /*!
...@@ -32,28 +59,12 @@ class JpegDecoder : public QObject ...@@ -32,28 +59,12 @@ class JpegDecoder : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
JpegDecoder(ConcurrentQueue<Jpeg*, 256u> *queue, QObject *parent = 0); JpegDecoder(ConcurrentQueue<Jpeg*, 1024u> *queue, QObject *parent = 0);
ConcurrentQueue<Jpeg*, 256u> *m_queue; ConcurrentQueue<Jpeg*, 1024u> *m_queue;
signals: signals:
void finished(const unsigned char *image, const quint32 x, const quint32 y, const quint32 width, const quint32 height); void finishedJpeg();
public slots: public slots:
void operate(); void operate();
}; };
struct error_mgr
{
struct jpeg_error_mgr mgr;
jmp_buf setjmp_buffer;
};
typedef struct error_mgr* error_ptr;
METHODDEF(void)
error_exit (j_common_ptr cinfo)
{
error_ptr myerr = (error_ptr) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
#endif // JPEGDECODER_H #endif // JPEGDECODER_H
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
#include <QtQml> #include <QtQml>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
QTime elapsed;
#include "qvnc.h" #include "qvnc.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
...@@ -18,8 +16,8 @@ int main(int argc, char *argv[]) ...@@ -18,8 +16,8 @@ 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::DoubleBuffer); format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
format.setSwapInterval(1); format.setSwapInterval(0);
#ifdef OGL_DEBUG #ifdef OGL_DEBUG
format.setOption(QSurfaceFormat::DebugContext, true); format.setOption(QSurfaceFormat::DebugContext, true);
#endif #endif
...@@ -27,7 +25,7 @@ int main(int argc, char *argv[]) ...@@ -27,7 +25,7 @@ int main(int argc, char *argv[])
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES, true); QGuiApplication::setAttribute(Qt::AA_UseOpenGLES, true);
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
qmlRegisterType<QVnc>("thinclient", 1, 3, "QVnc"); qmlRegisterType<QVnc>("thinclient", 1, 4, "QVnc");
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
......
import QtQuick 2.6 import QtQuick 2.5
import QtQuick.Controls 2.0 import QtQuick.Controls 2.1
import thinclient 1.3 import thinclient 1.4
ApplicationWindow { ApplicationWindow {
visible: true visible: true
...@@ -27,9 +27,9 @@ ApplicationWindow { ...@@ -27,9 +27,9 @@ ApplicationWindow {
QVnc { QVnc {
id: vnc id: vnc
host: "vm.ik.bme.hu" host: "vm.ik.bme.hu"
port: 10495 port: 13070
width: 1920 width: 1920
height: 1080 height: 1080
transform: Scale {xScale: window.width / vnc.width; yScale: (window.height - tab.height) / vnc.height} //transform: Scale {xScale: window.width / vnc.width; yScale: (window.height - tab.height) / vnc.height}
} }
} }
#include "qvnc.h" #include "qvnc.h"
QVnc::QVnc(QQuickItem *parent) : QVnc::QVnc(QQuickItem *parent) :
QQuickFramebufferObject(parent), m_decoders(DECODER_COUNT), m_threads(DECODER_COUNT + 1) QQuickFramebufferObject(parent), m_host(""), m_port(0)
{ {
setAcceptedMouseButtons(Qt::AllButtons); setAcceptedMouseButtons(Qt::AllButtons);
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
// this makes sure the rendering is called only when we explicitly ask for it
setTextureFollowsItemSize(false); setTextureFollowsItemSize(false);
for(int i = 0; i < m_threads.length(); i++)
m_threads[i] = new QThread(this);
connect(this, &QVnc::windowChanged, this, &QVnc::winChanged); connect(this, &QVnc::windowChanged, this, &QVnc::winChanged);
m_uploader = new Uploader; m_uploader = new Uploader;
m_uploader->moveToThread(m_threads[0]); connect(m_uploader, &Uploader::uploadFinished, this, &QVnc::update);
connect(&m_worker, &QThread::finished, m_uploader, &QObject::deleteLater);
connect(m_threads[0], &QThread::finished, m_uploader, &QObject::deleteLater);
m_dispatcher = new Dispatcher(m_uploader); m_dispatcher = new Dispatcher(m_uploader);
m_dispatcher->moveToThread(m_threads[0]); connect(&m_worker, &QThread::finished, m_dispatcher, &QObject::deleteLater);
connect(m_threads[0], &QThread::finished, m_dispatcher, &QObject::deleteLater);
connect(this, &QVnc::open_connection, m_dispatcher, &Dispatcher::open);
connect(this, &QVnc::terminate_connection, m_dispatcher, &Dispatcher::terminate);
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; m_uploader->moveToThread(&m_worker);
foreach(JpegDecoder* d, m_decoders) { m_dispatcher->moveToThread(&m_worker);
d = new JpegDecoder(m_dispatcher->queue());
d->moveToThread(m_threads[i]);
connect(m_threads[i], &QThread::finished, d, &QObject::deleteLater);
connect(d, &JpegDecoder::finished, m_uploader, &Uploader::finishedJpeg);
connect(this, &QVnc::operate, d, &JpegDecoder::operate);
i++;
}
for(int i = 0; i < m_threads.length(); i++) m_worker.start();
m_threads.at(i)->start();
emit operate(); connect(this, &QVnc::open_connection, m_dispatcher, &Dispatcher::open);
connect(this, &QVnc::terminate_connection, m_dispatcher, &Dispatcher::terminate);
connect(m_dispatcher, &Dispatcher::error, this, &QVnc::dispatch_error);
} }
QVnc::~QVnc() QVnc::~QVnc()
{ {
foreach(QThread* t, m_threads) {
t->quit();
t->wait();
}
} }
void QVnc::open() void QVnc::open()
...@@ -88,25 +67,19 @@ void QVnc::dispatch_error() ...@@ -88,25 +67,19 @@ void QVnc::dispatch_error()
void QVnc::winChanged(QQuickWindow *window) 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);
connect(window, &QQuickWindow::frameSwapped, m_uploader, &Uploader::swapBuffers, Qt::BlockingQueuedConnection);
}
} }
QQuickFramebufferObject::Renderer *QVnc::createRenderer() const QQuickFramebufferObject::Renderer *QVnc::createRenderer() const
{ {
return new VncRenderer(window(), auto renderer = new VncRenderer(window(),
m_uploader->fillBuffer(), m_uploader->fillBuffer(),
m_uploader->copyBuffer(), m_uploader->copyBuffer(),
m_uploader->bitmapBuffer(), m_uploader->bitmapBuffer(),
m_uploader->texture(), m_uploader->ycbcrBuffer());
NULL, connect(renderer, &VncRenderer::rendered, m_dispatcher, &Dispatcher::decode);
NULL, return renderer;
NULL,
m_uploader->fillCount(),
m_uploader->copyCount(),
m_uploader->bitmapCount());
} }
QString QVnc::host() const QString QVnc::host() const
...@@ -170,9 +143,9 @@ void QVnc::wheelEvent(QWheelEvent *event) ...@@ -170,9 +143,9 @@ void QVnc::wheelEvent(QWheelEvent *event)
void QVnc::mouseMoveEvent(QMouseEvent *event) void QVnc::mouseMoveEvent(QMouseEvent *event)
{ {
// Filter mouse move events, we don't need 100+ of them in a second // 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(); Qt::MouseButtons buttons = event->buttons();
m_lastMouseEvent = event->timestamp(); // m_lastMouseEvent = event->timestamp();
if(m_dispatcher->mouseEvent(event->x(), if(m_dispatcher->mouseEvent(event->x(),
event->y(), event->y(),
buttons & Qt::LeftButton, buttons & Qt::LeftButton,
...@@ -183,13 +156,13 @@ void QVnc::mouseMoveEvent(QMouseEvent *event) ...@@ -183,13 +156,13 @@ void QVnc::mouseMoveEvent(QMouseEvent *event)
event->accept(); event->accept();
else else
event->ignore(); event->ignore();
} //}
} }
void QVnc::hoverMoveEvent(QHoverEvent *event) void QVnc::hoverMoveEvent(QHoverEvent *event)
{ {
// Qt bug: timestamp is zero for QHoverEvent // Qt bug: timestamp is zero for QHoverEvent
// if((event->timestamp() - m_lastMouseEvent) > 33) { //if((event->timestamp() - m_lastMouseEvent) > 33) {
// m_lastMouseEvent = event->timestamp(); // m_lastMouseEvent = event->timestamp();
QPoint position = event->pos(); QPoint position = event->pos();
if(m_dispatcher->mouseEvent(position.x(), if(m_dispatcher->mouseEvent(position.x(),
...@@ -202,7 +175,7 @@ void QVnc::hoverMoveEvent(QHoverEvent *event) ...@@ -202,7 +175,7 @@ void QVnc::hoverMoveEvent(QHoverEvent *event)
event->accept(); event->accept();
else else
event->ignore(); event->ignore();
// } //}
} }
Uploader *QVnc::uploader() const Uploader *QVnc::uploader() const
......
#ifndef VNC_H #ifndef VNC_H
#define VNC_H #define VNC_H
#define DECODER_COUNT 5 #define TEXTURE_WIDTH 1920
#define TEXTURE_HEIGHT 1080
// #define OGL_DEBUG #define VERTEX_BUFFER 16384
//#define OGL_DEBUG
#include <QQuickWindow> #include <QQuickWindow>
#include <QObject> #include <QObject>
...@@ -32,7 +33,7 @@ public: ...@@ -32,7 +33,7 @@ public:
explicit QVnc(QQuickItem *parent = Q_NULLPTR); explicit QVnc(QQuickItem *parent = Q_NULLPTR);
~QVnc(); ~QVnc();
Renderer *createRenderer() const; Renderer *createRenderer() const override;
QString host() const; QString host() const;
int port() const; int port() const;
Uploader *uploader() const; Uploader *uploader() const;
...@@ -47,9 +48,7 @@ protected: ...@@ -47,9 +48,7 @@ protected:
private: private:
Dispatcher *m_dispatcher; Dispatcher *m_dispatcher;
Uploader *m_uploader; Uploader *m_uploader;
QVector<JpegDecoder*> m_decoders; QThread m_worker;
VncRenderer *m_renderer;
QVector<QThread*> m_threads;
QString m_host; QString m_host;
int m_port; int m_port;
...@@ -64,10 +63,6 @@ signals: ...@@ -64,10 +63,6 @@ signals:
void hostChanged(QString host); void hostChanged(QString host);
void portChanged(int port); void portChanged(int port);
void operate();
void refresh();
public slots: public slots:
void open(); void open();
void terminate(); void terminate();
......
#include "uploader.h" #include "uploader.h"
#include <cstring>
#include <texturefactory.h>
#include "jpegdecoder.h"
#include <QElapsedTimer>
//QElapsedTimer timer;
Uploader::Uploader(QObject *parent) : Uploader::Uploader(QObject *parent) :
QObject(parent), m_context(this), QObject(parent), m_context(this), m_fillIndex(0), m_copyIndex(0), m_bitmapIndex(0), m_ycbcrIndex(0), m_jpegs(0), m_finished(false), m_first(true)
m_uploadFill(new QOpenGLBuffer*), m_renderFill(new QOpenGLBuffer*),
m_uploadCopy(new QOpenGLBuffer*), m_renderCopy(new QOpenGLBuffer*),
m_uploadBitmap(new QOpenGLBuffer*), m_renderBitmap(new QOpenGLBuffer*),
m_uploadTexture(new GLuint*), m_renderTexture(new GLuint*),
m_jpegs(0), m_atlasX(0), m_atlasY(0), m_atlasRowHeight(0), m_atlasLastWidth(0)
{ {
// "applications must ensure that create() is only called on the main (GUI) thread" // "applications must ensure that create() is only called on the main (GUI) thread"
QSurfaceFormat format; QSurfaceFormat format;
...@@ -24,9 +29,17 @@ Uploader::Uploader(QObject *parent) : ...@@ -24,9 +29,17 @@ Uploader::Uploader(QObject *parent) :
m_surface.setFormat(format); m_surface.setFormat(format);
m_surface.create(); m_surface.create();
m_fillCount = new unsigned int(0); for(std::size_t i = 0; i < m_workers.size(); ++i)
m_copyCount = new unsigned int(0); {
m_bitmapCount = new unsigned int(0); m_decoders[i] = new JpegDecoder(&m_queue);
m_decoders[i]->moveToThread(&m_workers[i]);
connect(&m_workers[i], &QThread::finished, m_decoders[i], &QObject::deleteLater);
connect(m_decoders[i], &JpegDecoder::finishedJpeg, this, &Uploader::finishedJpeg);
connect(this, &Uploader::operate, m_decoders[i], &JpegDecoder::operate);
m_workers[i].start();
}
emit operate();
} }
Uploader::~Uploader() Uploader::~Uploader()
...@@ -53,53 +66,37 @@ void Uploader::createContext(QOpenGLContext *context) ...@@ -53,53 +66,37 @@ void Uploader::createContext(QOpenGLContext *context)
m_gl = m_context.functions(); m_gl = m_context.functions();
*m_renderFill = new QOpenGLBuffer; m_fillBuffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
(*m_renderFill)->setUsagePattern(QOpenGLBuffer::DynamicDraw); m_fillBuffer.create();
(*m_renderFill)->create(); m_fillBuffer.bind();
(*m_renderFill)->bind(); m_fillBuffer.allocate(VERTEX_BUFFER * sizeof(Fill));
(*m_renderFill)->allocate(VERTEX_BUFFER * sizeof(Fill));
m_copyBuffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
*m_uploadFill = new QOpenGLBuffer; m_copyBuffer.create();
(*m_uploadFill)->setUsagePattern(QOpenGLBuffer::DynamicDraw); m_copyBuffer.bind();
(*m_uploadFill)->create(); m_copyBuffer.allocate(VERTEX_BUFFER * sizeof(Copy));
(*m_uploadFill)->bind();
(*m_uploadFill)->allocate(VERTEX_BUFFER * sizeof(Fill)); m_bitmapBuffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
m_bitmapBuffer.create();
*m_renderCopy = new QOpenGLBuffer; m_bitmapBuffer.bind();
(*m_renderCopy)->setUsagePattern(QOpenGLBuffer::DynamicDraw); m_bitmapBuffer.allocate(VERTEX_BUFFER * sizeof(Bitmap));
(*m_renderCopy)->create();
(*m_renderCopy)->bind(); m_ycbcrBuffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
(*m_renderCopy)->allocate(VERTEX_BUFFER * sizeof(Bitmap)); m_ycbcrBuffer.create();
m_ycbcrBuffer.bind();
*m_uploadCopy = new QOpenGLBuffer; m_ycbcrBuffer.allocate(VERTEX_BUFFER * sizeof(Bitmap));
(*m_uploadCopy)->setUsagePattern(QOpenGLBuffer::DynamicDraw);
(*m_uploadCopy)->create(); auto textureFactory = TextureFactory::create();
(*m_uploadCopy)->bind(); m_rgbTexture = textureFactory->createTexture(QSize(TEXTURE_WIDTH, TEXTURE_HEIGHT));
(*m_uploadCopy)->allocate(VERTEX_BUFFER * sizeof(Bitmap)); m_yTexture = textureFactory->createTexture(QSize(TEXTURE_WIDTH / 4, TEXTURE_HEIGHT));
m_cbTexture = textureFactory->createTexture(QSize(TEXTURE_WIDTH / 8, TEXTURE_HEIGHT));
*m_renderBitmap = new QOpenGLBuffer; m_crTexture = textureFactory->createTexture(QSize(TEXTURE_WIDTH / 8, TEXTURE_HEIGHT));
(*m_renderBitmap)->setUsagePattern(QOpenGLBuffer::DynamicDraw);
(*m_renderBitmap)->create(); Jpeg::y_width = m_yTexture->allocated.width() * 4;
(*m_renderBitmap)->bind(); Jpeg::cb_width = m_cbTexture->allocated.width() * 4;
(*m_renderBitmap)->allocate(VERTEX_BUFFER * sizeof(Bitmap)); Jpeg::cr_width = m_crTexture->allocated.width() * 4;
*m_uploadBitmap = new QOpenGLBuffer; m_gl->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
(*m_uploadBitmap)->setUsagePattern(QOpenGLBuffer::DynamicDraw);
(*m_uploadBitmap)->create();
(*m_uploadBitmap)->bind();
(*m_uploadBitmap)->allocate(VERTEX_BUFFER * sizeof(Bitmap));
m_gl->glActiveTexture(GL_TEXTURE0);
m_gl->glGenTextures(2, m_texId);
for(size_t i = 0; i < 2; i++) {
m_gl->glBindTexture(GL_TEXTURE_2D, m_texId[i]);
m_gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
*m_renderTexture = &m_texId[0];
*m_uploadTexture = &m_texId[1];
m_gl->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
} }
void Uploader::gotFill(const GLushort x, const GLushort y, void Uploader::gotFill(const GLushort x, const GLushort y,
...@@ -120,23 +117,20 @@ void Uploader::gotCopy(const GLushort src_x, const GLushort src_y, ...@@ -120,23 +117,20 @@ void Uploader::gotCopy(const GLushort src_x, const GLushort src_y,
const GLushort width, const GLushort height, const GLushort width, const GLushort height,
const GLushort dest_x, const GLushort dest_y) const GLushort dest_x, const GLushort dest_y)
{ {
if(!refreshAtlas(width, height))
return;
if(m_copyIndex + 4 < VERTEX_BUFFER) { if(m_copyIndex + 4 < VERTEX_BUFFER) {
m_copyPointer[m_copyIndex++] = Bitmap({m_atlasX, (GLushort) (m_atlasY + height), src_x, (GLushort) (src_y + height)}); m_copyPointer[m_copyIndex++] = Copy({src_x, (GLushort) (src_y + height), dest_x, (GLushort) (dest_y + height)});
m_copyPointer[m_copyIndex++] = Bitmap({m_atlasX, m_atlasY, src_x, src_y}); m_copyPointer[m_copyIndex++] = Copy({src_x, src_y, dest_x, dest_y});
m_copyPointer[m_copyIndex++] = Bitmap({(GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height), (GLushort) (src_x + width), (GLushort) (src_y + height)}); m_copyPointer[m_copyIndex++] = Copy({(GLushort) (src_x + width), (GLushort) (src_y + height), (GLushort) (dest_x + width), (GLushort) (dest_y + height)});
m_copyPointer[m_copyIndex++] = Bitmap({(GLushort) (m_atlasX + width), m_atlasY, (GLushort) (src_x + width), src_y}); m_copyPointer[m_copyIndex++] = Copy({(GLushort) (src_x + width), src_y, (GLushort) (dest_x + width), dest_y});
} else { } else {
qDebug() << "Out of memory"; qDebug() << "Out of memory";
} }
if(m_bitmapIndex + 4 < VERTEX_BUFFER) { if(m_bitmapIndex + 4 < VERTEX_BUFFER) {
m_bitmapPointer[m_bitmapIndex++] = Bitmap({dest_x, (GLushort) (dest_y + height), m_atlasX, (GLushort) (m_atlasY + height)}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({dest_x, (GLushort) (dest_y + height)});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({dest_x, dest_y, m_atlasX, m_atlasY}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({dest_x, dest_y});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (dest_x + width), (GLushort) (dest_y + height), (GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height)}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (dest_x + width), (GLushort) (dest_y + height)});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (dest_x + width), dest_y, (GLushort) (m_atlasX + width), m_atlasY}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (dest_x + width), dest_y});
} else { } else {
qDebug() << "Out of memory"; qDebug() << "Out of memory";
} }
...@@ -146,50 +140,40 @@ void Uploader::gotBitmap(const unsigned char *image, ...@@ -146,50 +140,40 @@ void Uploader::gotBitmap(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)
{ {
if(!refreshAtlas(width, height)) for (std::size_t row = 0; row < height; ++row)
return; std::memcpy(&m_rgbPointer[(x + (y + row) * m_rgbTexture->allocated.width()) * 4], &image[row * width * 4], width * 4);
m_gl->glTexSubImage2D(GL_TEXTURE_2D, 0, m_atlasX, m_atlasY, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
if(m_bitmapIndex + 4 < VERTEX_BUFFER) { if(m_bitmapIndex + 4 < VERTEX_BUFFER) {
m_bitmapPointer[m_bitmapIndex++] = Bitmap({x, (GLushort) (y + height), m_atlasX, (GLushort) (m_atlasY + height)}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({x, (GLushort) (y + height)});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({x, y, m_atlasX, m_atlasY}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({x, y});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (x + width), (GLushort) (y + height), (GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height)}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (x + width), (GLushort) (y + height)});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (x + width), y, (GLushort) (m_atlasX + width), m_atlasY}); m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (x + width), y});
} else { } else {
qDebug() << "Out of memory"; qDebug() << "Out of memory";
} }
} }
void Uploader::gotJpeg() void Uploader::gotJpeg(const uint8_t *buffer, int length, int x, int y, int width, int height)
{ {
m_jpegs++; Jpeg *jpeg = new Jpeg((unsigned char*)buffer, length, width, height, x, y);
} m_queue.enqueue(jpeg);
void Uploader::finishedJpeg(const unsigned char *image, if(m_ycbcrIndex + 4 < VERTEX_BUFFER) {
const GLushort x, const GLushort y, m_ycbcrPointer[m_ycbcrIndex++] = Bitmap({static_cast<GLushort>(x), static_cast<GLushort>(y + height)});
const GLushort width, const GLushort height) m_ycbcrPointer[m_ycbcrIndex++] = Bitmap({static_cast<GLushort>(x), static_cast<GLushort>(y)});
{ m_ycbcrPointer[m_ycbcrIndex++] = Bitmap({static_cast<GLushort>(x + width), static_cast<GLushort>(y + height)});
if(!refreshAtlas(width, height)) m_ycbcrPointer[m_ycbcrIndex++] = Bitmap({static_cast<GLushort>(x + width), static_cast<GLushort>(y)});
return;
m_jpegs--;
m_gl->glTexSubImage2D(GL_TEXTURE_2D, 0, m_atlasX, m_atlasY, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
delete[] image;
if(m_bitmapIndex + 4 < VERTEX_BUFFER) {
m_bitmapPointer[m_bitmapIndex++] = Bitmap({x, (GLushort) (y + height), m_atlasX, (GLushort) (m_atlasY + height)});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({x, y, m_atlasX, m_atlasY});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (x + width), (GLushort) (y + height), (GLushort) (m_atlasX + width), (GLushort) (m_atlasY + height)});
m_bitmapPointer[m_bitmapIndex++] = Bitmap({(GLushort) (x + width), y, (GLushort) (m_atlasX + width), m_atlasY});
} else { } else {
qDebug() << "Out of memory"; qDebug() << "Out of memory";
} }
if(m_jpegs == 0) m_jpegs++;
qDebug() << "jpeg" << elapsed.elapsed(); }
void Uploader::finishedJpeg()
{
//qDebug() << "jpeg" << timer.elapsed();
m_jpegs--;
if(m_jpegs == 0 && m_finished) { if(m_jpegs == 0 && m_finished) {
startRendering(); startRendering();
} }
...@@ -197,129 +181,77 @@ void Uploader::finishedJpeg(const unsigned char *image, ...@@ -197,129 +181,77 @@ void Uploader::finishedJpeg(const unsigned char *image,
void Uploader::finishedUpdate() void Uploader::finishedUpdate()
{ {
//qDebug() << "finished" << timer.elapsed();
m_finished = true; m_finished = true;
if(m_jpegs == 0) if(m_jpegs == 0)
startRendering(); startRendering();
} }
bool Uploader::refreshAtlas(const int width, const int height) void Uploader::startDecoding()
{ {
if(m_atlasX + m_atlasLastWidth + width <= TEXTURE_WIDTH) { //timer.start();
if(m_atlasY + height > TEXTURE_HEIGHT) { if (m_fillIndex > 0 || m_first)
qDebug() << "Atlas out of memory" << m_atlasX << m_atlasY << width << height; {
return false; m_fillBuffer.bind();
m_fillPointer = (Fill*) m_fillBuffer.map(QOpenGLBuffer::WriteOnly);
} }
if (m_copyIndex > 0 || m_first)
m_atlasX += m_atlasLastWidth; {
m_atlasLastWidth = width; m_copyBuffer.bind();
m_copyPointer = (Copy*) m_copyBuffer.map(QOpenGLBuffer::WriteOnly);
if(height > m_atlasRowHeight)
m_atlasRowHeight = height;
} else {
if(m_atlasY + m_atlasRowHeight + height > TEXTURE_HEIGHT) {
qDebug() << "Atlas out of memory" << m_atlasX << m_atlasY << width << height;
return false;
} }
if (m_bitmapIndex > 0 || m_first)
m_atlasX = 0; {
m_atlasY += m_atlasRowHeight; m_bitmapBuffer.bind();
m_atlasRowHeight = height; m_bitmapPointer = (Bitmap*) m_bitmapBuffer.map(QOpenGLBuffer::WriteOnly);
m_atlasLastWidth = width; m_rgbPointer = static_cast<unsigned char*>(m_rgbTexture->map());
}
if (m_ycbcrIndex > 0 || m_first)
{
m_ycbcrBuffer.bind();
m_ycbcrPointer = (Bitmap*) m_ycbcrBuffer.map(QOpenGLBuffer::WriteOnly);
Jpeg::y_pointer = static_cast<unsigned char*>(m_yTexture->map());
Jpeg::cb_pointer = static_cast<unsigned char*>(m_cbTexture->map());
Jpeg::cr_pointer = static_cast<unsigned char*>(m_crTexture->map());
} }
return true;
}
void Uploader::startDecoding()
{
(*m_uploadFill)->bind();
m_fillPointer = (Fill*) (*m_uploadFill)->map(QOpenGLBuffer::WriteOnly);
(*m_uploadCopy)->bind();
m_copyPointer = (Bitmap*) (*m_uploadCopy)->map(QOpenGLBuffer::WriteOnly);
(*m_uploadBitmap)->bind();
m_bitmapPointer = (Bitmap*) (*m_uploadBitmap)->map(QOpenGLBuffer::WriteOnly);
m_gl->glBindTexture(GL_TEXTURE_2D, **m_uploadTexture);
m_fillIndex = 0; m_fillIndex = 0;
m_copyIndex = 0; m_copyIndex = 0;
m_bitmapIndex = 0; m_bitmapIndex = 0;
m_ycbcrIndex = 0;
m_atlasX = 1; m_first = false;
m_atlasY = 1;
m_atlasRowHeight = 0;
m_atlasLastWidth = 0;
elapsed.restart();
}
void Uploader::startRendering()
{
(*m_uploadFill)->bind();
(*m_uploadFill)->unmap();
(*m_uploadCopy)->bind();
(*m_uploadCopy)->unmap();
(*m_uploadBitmap)->bind();
(*m_uploadBitmap)->unmap();
qDebug() << "rendering" << elapsed.elapsed();
m_gl->glFlush();
m_finished = false; m_finished = false;
m_swap = true; m_jpegs = 0;
qDebug() << "flush" << elapsed.elapsed();
emit uploadFinished();
} }
void Uploader::swapBuffers() void Uploader::startRendering()
{ {
if(m_swap) { if (m_fillIndex > 0)
std::swap(*m_uploadFill, *m_renderFill); {
std::swap(*m_uploadCopy, *m_renderCopy); m_fillBuffer.bind();
std::swap(*m_uploadBitmap, *m_renderBitmap); m_fillBuffer.unmap();
std::swap(*m_uploadTexture, *m_renderTexture);
*m_fillCount = m_fillIndex ? (m_fillIndex / 4) * 6 - 2 : 0;
*m_copyCount = m_copyIndex ? (m_copyIndex / 4) * 6 - 2 : 0;
*m_bitmapCount = m_bitmapIndex ? (m_bitmapIndex / 4) * 6 - 2 : 0;
m_swap = false;
qDebug() << "swap" << elapsed.elapsed();
emit buffersSwapped();
} }
} if (m_copyIndex > 0)
{
GLuint **Uploader::texture() const m_copyBuffer.bind();
{ m_copyBuffer.unmap();
return m_renderTexture; }
} if (m_bitmapIndex > 0)
{
QOpenGLBuffer **Uploader::fillBuffer() const m_bitmapBuffer.bind();
{ m_bitmapBuffer.unmap();
return m_renderFill; m_rgbTexture->unmap();
} }
if (m_ycbcrIndex > 0)
QOpenGLBuffer **Uploader::copyBuffer() const {
{ m_ycbcrBuffer.bind();
return m_renderCopy; m_ycbcrBuffer.unmap();
} m_yTexture->unmap();
m_cbTexture->unmap();
QOpenGLBuffer **Uploader::bitmapBuffer() const m_crTexture->unmap();
{ }
return m_renderBitmap; //qDebug() << "uploaded" << timer.elapsed();
}
unsigned int *Uploader::fillCount() const
{
return m_fillCount;
}
unsigned int *Uploader::copyCount() const
{
return m_copyCount;
}
unsigned int *Uploader::bitmapCount() const emit uploadFinished();
{
return m_bitmapCount;
} }
...@@ -16,12 +16,13 @@ ...@@ -16,12 +16,13 @@
#ifndef UPLOADER_H #ifndef UPLOADER_H
#define UPLOADER_H #define UPLOADER_H
#define TEXTURE_WIDTH 4096 #define TEXTURE_WIDTH 1920
#define TEXTURE_HEIGHT 4096 #define TEXTURE_HEIGHT 1080
#define VERTEX_BUFFER 1024 #define VERTEX_BUFFER 16384
// #define OGL_DEBUG //#define OGL_DEBUG
#include <utility> #include <utility>
#include <memory>
#include <QObject> #include <QObject>
#include <QDebug> #include <QDebug>
...@@ -33,15 +34,26 @@ ...@@ -33,15 +34,26 @@
#include <QtMath> #include <QtMath>
#include <QTime> #include <QTime>
#include <QOpenGLDebugLogger> #include <QOpenGLDebugLogger>
#include <QThread>
extern QTime elapsed; #include <texture.h>
#include "concurrentqueue.h"
#define DECODER_COUNT 5
struct Bitmap struct Bitmap
{ {
GLushort x; GLushort x;
GLushort y; GLushort y;
GLushort texX; };
GLushort texY;
struct Copy
{
GLushort src_x;
GLushort src_y;
GLushort dest_x;
GLushort dest_y;
}; };
struct Fill struct Fill
...@@ -54,6 +66,9 @@ struct Fill ...@@ -54,6 +66,9 @@ struct Fill
GLubyte alpha; GLubyte alpha;
}; };
class JpegDecoder;
class Jpeg;
/*! /*!
* \brief The Uploader class * \brief The Uploader class
* *
...@@ -63,17 +78,22 @@ class Uploader : public QObject ...@@ -63,17 +78,22 @@ class Uploader : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
Uploader(QObject *parent = Q_NULLPTR); explicit Uploader(QObject *parent = Q_NULLPTR);
~Uploader(); ~Uploader();
GLuint **texture() const; // might as well make these public, they are shared with the renderer
QOpenGLBuffer **fillBuffer() const; std::shared_ptr<Texture> rgbTexture() const {return m_rgbTexture;}
QOpenGLBuffer **copyBuffer() const; std::shared_ptr<Texture> yTexture() const {return m_yTexture;}
QOpenGLBuffer **bitmapBuffer() const; std::shared_ptr<Texture> cbTexture() const {return m_cbTexture;}
unsigned int *fillCount() const; std::shared_ptr<Texture> crTexture() const {return m_crTexture;}
unsigned int *copyCount() const; QOpenGLBuffer fillBuffer() const {return m_fillBuffer;}
unsigned int *bitmapCount() const; QOpenGLBuffer copyBuffer() const {return m_copyBuffer;}
void swapBuffers(); QOpenGLBuffer bitmapBuffer() const {return m_bitmapBuffer;}
QOpenGLBuffer ycbcrBuffer() const {return m_ycbcrBuffer;}
std::size_t fillCount() const {return m_fillIndex;}
std::size_t copyCount() const {return m_copyIndex;}
std::size_t bitmapCount() const {return m_bitmapIndex;}
std::size_t ycbcrCount() const {return m_ycbcrIndex;}
// VNC events // VNC events
void gotFill(const GLushort x, const GLushort y, void gotFill(const GLushort x, const GLushort y,
...@@ -85,56 +105,55 @@ public: ...@@ -85,56 +105,55 @@ public:
void gotBitmap(const unsigned char *image, void gotBitmap(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 gotJpeg(); void gotJpeg(const uint8_t *buffer, int length, int x, int y, int width, int height);
void finishedUpdate(); void finishedUpdate();
void startDecoding(); void startDecoding();
private: private:
QOffscreenSurface m_surface; QOffscreenSurface m_surface;
QOpenGLContext m_context; QOpenGLContext m_context;
QOpenGLFunctions *m_gl; QOpenGLFunctions *m_gl;
QOpenGLBuffer **m_uploadFill; QOpenGLBuffer m_fillBuffer;
QOpenGLBuffer **m_renderFill;
Fill *m_fillPointer; Fill *m_fillPointer;
size_t m_fillIndex; std::size_t m_fillIndex;
unsigned int *m_fillCount;
QOpenGLBuffer **m_uploadCopy; QOpenGLBuffer m_copyBuffer;
QOpenGLBuffer **m_renderCopy; Copy *m_copyPointer;
Bitmap *m_copyPointer; std::size_t m_copyIndex;
size_t m_copyIndex;
unsigned int *m_copyCount;
QOpenGLBuffer **m_uploadBitmap; QOpenGLBuffer m_bitmapBuffer;
QOpenGLBuffer **m_renderBitmap;
Bitmap *m_bitmapPointer; Bitmap *m_bitmapPointer;
size_t m_bitmapIndex; std::size_t m_bitmapIndex;
unsigned int *m_bitmapCount;
GLuint m_texId[2]; std::shared_ptr<Texture> m_rgbTexture;
GLuint **m_uploadTexture; unsigned char *m_rgbPointer;
GLuint **m_renderTexture;
QOpenGLBuffer m_ycbcrBuffer;
Bitmap *m_ycbcrPointer;
std::size_t m_ycbcrIndex;
std::shared_ptr<Texture> m_yTexture;
std::shared_ptr<Texture> m_cbTexture;
std::shared_ptr<Texture> m_crTexture;
std::array<QThread, DECODER_COUNT> m_workers;
std::array<JpegDecoder*, DECODER_COUNT> m_decoders;
ConcurrentQueue<Jpeg*, 1024u> m_queue;
int m_jpegs; int m_jpegs;
bool m_finished; bool m_finished;
bool m_swap;
unsigned short m_atlasX; bool m_first;
unsigned short m_atlasY;
unsigned short m_atlasRowHeight;
unsigned short m_atlasLastWidth;
bool refreshAtlas(const int width, const int height);
void startRendering(); void startRendering();
signals: signals:
void uploadFinished(); void uploadFinished();
void buffersSwapped(); void buffersSwapped();
void operate();
public slots: public slots:
void createContext(QOpenGLContext *context); void createContext(QOpenGLContext *context);
void finishedJpeg(const unsigned char *image, void finishedJpeg();
const GLushort x, const GLushort y,
const GLushort width, const GLushort height);
private slots: private slots:
void handleDebugMessage(const QOpenGLDebugMessage &debugMessage); void handleDebugMessage(const QOpenGLDebugMessage &debugMessage);
}; };
......
...@@ -3,20 +3,14 @@ ...@@ -3,20 +3,14 @@
#include "uploader.h" #include "uploader.h"
VncRenderer::VncRenderer(QQuickWindow *window, VncRenderer::VncRenderer(QQuickWindow *window,
QOpenGLBuffer **fillBuffer, QOpenGLBuffer fillBuffer,
QOpenGLBuffer **copyBuffer, QOpenGLBuffer copyBuffer,
QOpenGLBuffer **bitmapBuffer, QOpenGLBuffer bitmapBuffer,
GLuint **rgbTexture, QOpenGLBuffer ycbcrBuffer,
GLuint **yTexture, QObject *parent) :
GLuint **cbTexture,
GLuint **crTexture,
unsigned int *fillCount,
unsigned int *copyCount,
unsigned int *bitmapCount, QObject *parent) :
QObject(parent), m_window(window), QObject(parent), m_window(window),
m_fillBuffer(fillBuffer), m_copyBuffer(copyBuffer), m_bitmapBuffer(bitmapBuffer), m_fillBuffer(fillBuffer), m_copyBuffer(copyBuffer), m_bitmapBuffer(bitmapBuffer), m_ycbcrBuffer(ycbcrBuffer),
m_rgbTexture(rgbTexture), m_yTexture(yTexture), m_cbTexture(cbTexture), m_crTexture(crTexture), m_fillCount(0), m_copyCount(0), m_bitmapCount(0), m_ycbcrCount(0),
m_fillCount(fillCount), m_copyCount(copyCount), m_bitmapCount(bitmapCount),
m_indices(QOpenGLBuffer::IndexBuffer) m_indices(QOpenGLBuffer::IndexBuffer)
{ {
#ifdef OGL_DEBUG #ifdef OGL_DEBUG
...@@ -26,33 +20,49 @@ VncRenderer::VncRenderer(QQuickWindow *window, ...@@ -26,33 +20,49 @@ VncRenderer::VncRenderer(QQuickWindow *window,
logger->startLogging(); logger->startLogging();
#endif #endif
m_copyOrtho.ortho(QRect(QPoint(0, TEXTURE_HEIGHT), QSize(TEXTURE_WIDTH, -1 * TEXTURE_HEIGHT))); m_toTexture.ortho(QRect(QPoint(0, TEXTURE_HEIGHT), QSize(TEXTURE_WIDTH, -1 * TEXTURE_HEIGHT)));
m_bitmapTexortho.ortho(QRect(QPoint(-1 * TEXTURE_WIDTH, TEXTURE_HEIGHT), QSize(2 * TEXTURE_WIDTH, -2 * TEXTURE_HEIGHT))); m_fromTexture.ortho(QRect(QPoint(-1 * TEXTURE_WIDTH, TEXTURE_HEIGHT), QSize(2 * TEXTURE_WIDTH, -2 * TEXTURE_HEIGHT)));
m_fillProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "/home/ldmnyblzs/Projects/ThinClient/fill_shader.vsh"); m_fillProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "/home/ldmnyblzs/Projects/ThinClient/fill_shader.vsh");
m_fillProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "/home/ldmnyblzs/Projects/ThinClient/fill_shader.fsh"); m_fillProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "/home/ldmnyblzs/Projects/ThinClient/fill_shader.fsh");
m_fillProgram.link(); m_fillProgram.link();
m_copyProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "/home/ldmnyblzs/Projects/ThinClient/copy_shader.vsh");
m_copyProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "/home/ldmnyblzs/Projects/ThinClient/copy_shader.fsh");
m_copyProgram.bind();
m_copyProgram.setUniformValue("trgortho", m_toTexture);
m_copyProgram.setUniformValue("texture", 0);
m_copyProgram.release();
m_bitmapProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "/home/ldmnyblzs/Projects/ThinClient/bitmap_shader.vsh"); m_bitmapProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "/home/ldmnyblzs/Projects/ThinClient/bitmap_shader.vsh");
m_bitmapProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "/home/ldmnyblzs/Projects/ThinClient/bitmap_shader.fsh"); m_bitmapProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "/home/ldmnyblzs/Projects/ThinClient/bitmap_shader.fsh");
m_bitmapProgram.link();
/*m_ycbcrProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "/home/ldmnyblzs/Projects/ThinClient/bitmap_shader.vsh"); m_bitmapProgram.bind();
m_bitmapProgram.setUniformValue("texture", 1);
m_bitmapProgram.setUniformValue("texortho", m_fromTexture);
m_bitmapProgram.release();
m_ycbcrProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "/home/ldmnyblzs/Projects/ThinClient/bitmap_shader.vsh");
m_ycbcrProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "/home/ldmnyblzs/Projects/ThinClient/ycbcr_shader.fsh"); m_ycbcrProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "/home/ldmnyblzs/Projects/ThinClient/ycbcr_shader.fsh");
m_ycbcrProgram.bind(); m_ycbcrProgram.bind();
m_ycbcrProgram.enableAttributeArray("position");
m_ycbcrProgram.enableAttributeArray("texcoord");
m_ycbcrProgram.setUniformValue("y_texture", 2); m_ycbcrProgram.setUniformValue("y_texture", 2);
m_ycbcrProgram.setUniformValue("cb_texture", 3); m_ycbcrProgram.setUniformValue("cb_texture", 3);
m_ycbcrProgram.setUniformValue("cr_texture", 4);*/ m_ycbcrProgram.setUniformValue("cr_texture", 4);
m_ycbcrProgram.setUniformValue("texortho", m_fromTexture);
m_ycbcrProgram.release();
m_indices.create(); m_indices.create();
m_indices.bind(); m_indices.bind();
m_indices.allocate(ind.i, (VERTEX_BUFFER / 4) * 6 - 2); m_indices.allocate(ind.i, (VERTEX_BUFFER / 4) * 6 - 2);
m_indices.release();
m_gl = QOpenGLContext::currentContext()->functions(); m_gl = QOpenGLContext::currentContext()->functions();
m_gl->glGenFramebuffers(0, &m_textureTarget); m_gl->glGenFramebuffers(1, &m_textureTarget);
m_clear = true;
frameCount = 0;
frameTime.start(); frameTime.start();
} }
...@@ -63,12 +73,25 @@ void VncRenderer::handleDebugMessage(const QOpenGLDebugMessage &debugMessage) ...@@ -63,12 +73,25 @@ void VncRenderer::handleDebugMessage(const QOpenGLDebugMessage &debugMessage)
void VncRenderer::render() void VncRenderer::render()
{ {
frameCount++; if (m_clear)
if(frameTime.elapsed() > 1000) { {
// qDebug() << frameCount; m_gl->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
m_gl->glClear(GL_COLOR_BUFFER_BIT);
m_clear = false;
}
if(m_fillCount > 0 || m_bitmapCount > 0 || m_ycbcrCount > 0)
{
//frameCount++;
}
else
return;
/*if(frameTime.elapsed() > 1000) {
qDebug() << frameCount;
frameCount = 0; frameCount = 0;
frameTime.restart(); frameTime.restart();
} }*/
/* Rendering: /* Rendering:
* 1. Draw filled rectangles * 1. Draw filled rectangles
...@@ -77,136 +100,170 @@ void VncRenderer::render() ...@@ -77,136 +100,170 @@ void VncRenderer::render()
* 4. Draw YCbCr textured rectangles * 4. Draw YCbCr textured rectangles
*/ */
/*m_gl->glActiveTexture(GL_TEXTURE0);
m_gl->glBindTexture(GL_TEXTURE_2D, m_framebufferObject->texture());
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/
m_gl->glActiveTexture(GL_TEXTURE1);
m_gl->glBindTexture(GL_TEXTURE_2D, **m_rgbTexture);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/*m_gl->glActiveTexture(GL_TEXTURE2);
m_gl->glBindTexture(GL_TEXTURE_2D, **m_yTexture);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_gl->glActiveTexture(GL_TEXTURE3);
m_gl->glBindTexture(GL_TEXTURE_2D, **m_crTexture);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_gl->glActiveTexture(GL_TEXTURE4);
m_gl->glBindTexture(GL_TEXTURE_2D, **m_cbTexture);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/
m_indices.bind(); m_indices.bind();
if(*m_fillCount > 0) { if(m_fillCount > 0) {
m_fillProgram.bind(); m_fillProgram.bind();
m_fillBuffer.bind();
m_fillProgram.enableAttributeArray("position"); m_fillProgram.enableAttributeArray("position");
m_fillProgram.enableAttributeArray("color"); m_fillProgram.enableAttributeArray("color");
(*m_fillBuffer)->bind();
m_gl->glVertexAttribPointer(m_fillProgram.attributeLocation("position"), m_gl->glVertexAttribPointer(m_fillProgram.attributeLocation("position"),
2, 2,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
GL_FALSE, GL_FALSE,
sizeof(Fill), sizeof(Fill),
(void*) 0); NULL);
m_gl->glVertexAttribPointer(m_fillProgram.attributeLocation("color"), m_gl->glVertexAttribPointer(m_fillProgram.attributeLocation("color"),
4, 4,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
GL_TRUE, GL_TRUE,
sizeof(Fill), sizeof(Fill),
(void*) (2 * sizeof(GLushort))); reinterpret_cast<void*>(2 * sizeof(GLushort)));
m_fillProgram.setUniformValue("ortho", m_bitmapOrtho);
m_gl->glDrawElements(GL_TRIANGLE_STRIP, *m_fillCount, GL_UNSIGNED_SHORT, (void*) 0); m_gl->glDrawElements(GL_TRIANGLE_STRIP, m_fillCount, GL_UNSIGNED_SHORT, NULL);
}
if(*m_bitmapCount > 0) { m_fillBuffer.release();
m_bitmapProgram.bind(); m_fillProgram.release();
m_bitmapProgram.enableAttributeArray("position");
m_bitmapProgram.enableAttributeArray("texcoord");
} }
if(*m_copyCount > 0) { if(m_copyCount > 0) {
(*m_copyBuffer)->bind(); m_gl->glActiveTexture(GL_TEXTURE0);
m_gl->glVertexAttribPointer(m_bitmapProgram.attributeLocation("position"), m_gl->glBindTexture(GL_TEXTURE_2D, m_framebufferObject->texture());
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_copyProgram.bind();
m_copyBuffer.bind();
m_copyProgram.enableAttributeArray("source");
m_copyProgram.enableAttributeArray("target");
m_gl->glVertexAttribPointer(m_copyProgram.attributeLocation("source"),
2, 2,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
GL_FALSE, GL_FALSE,
sizeof(Bitmap), sizeof(Copy),
(void*) 0); NULL);
m_gl->glVertexAttribPointer(m_bitmapProgram.attributeLocation("texcoord"), m_gl->glVertexAttribPointer(m_copyProgram.attributeLocation("target"),
2, 2,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
GL_FALSE, GL_FALSE,
sizeof(Bitmap), sizeof(Copy),
(void*) (2 * sizeof(GLushort))); reinterpret_cast<void*>(2 * sizeof(GLushort)));
// copy to the texture
m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_textureTarget); m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_textureTarget);
m_gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, **m_rgbTexture, 0); m_gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *m_rgbTexture, 0);
m_gl->glViewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT); m_gl->glViewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
m_bitmapProgram.setUniformValue("texture", 0);
m_bitmapProgram.setUniformValue("ortho", m_copyOrtho); m_gl->glDrawElements(GL_TRIANGLE_STRIP, m_copyCount, GL_UNSIGNED_SHORT, NULL);
m_bitmapProgram.setUniformValue("texortho", m_copyTexortho);
m_gl->glDrawElements(GL_TRIANGLE_STRIP, *m_copyCount, GL_UNSIGNED_SHORT, (void*) 0);
m_framebufferObject->bind(); m_framebufferObject->bind();
m_gl->glViewport(0, 0, 1920, 1080); m_gl->glViewport(0, 0, 1920, 1080);
m_copyBuffer.release();
m_copyProgram.release();
} }
if(*m_bitmapCount > 0) { if(m_bitmapCount > 0) {
// rgb m_rgbTexture->bind(GL_TEXTURE1);
(*m_bitmapBuffer)->bind(); m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_bitmapProgram.bind();
m_bitmapBuffer.bind();
m_bitmapProgram.enableAttributeArray("position");
m_gl->glVertexAttribPointer(m_bitmapProgram.attributeLocation("position"), m_gl->glVertexAttribPointer(m_bitmapProgram.attributeLocation("position"),
2, 2,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
GL_FALSE, GL_FALSE,
sizeof(Bitmap), 0,
(void*) 0); NULL);
m_gl->glVertexAttribPointer(m_bitmapProgram.attributeLocation("texcoord"), m_gl->glDrawElements(GL_TRIANGLE_STRIP, m_bitmapCount, GL_UNSIGNED_SHORT, NULL);
m_bitmapBuffer.release();
m_bitmapProgram.release();
}
if(m_ycbcrCount > 0) {
m_yTexture->bind(GL_TEXTURE2);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_crTexture->bind(GL_TEXTURE3);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_cbTexture->bind(GL_TEXTURE4);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_ycbcrProgram.bind();
m_ycbcrBuffer.bind();
m_ycbcrProgram.enableAttributeArray("position");
m_gl->glVertexAttribPointer(m_ycbcrProgram.attributeLocation("position"),
2, 2,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
GL_FALSE, GL_FALSE,
sizeof(Bitmap), 0,
(void*) (2 * sizeof(GLushort))); NULL);
m_gl->glDrawElements(GL_TRIANGLE_STRIP, m_ycbcrCount, GL_UNSIGNED_SHORT, NULL);
m_ycbcrBuffer.release();
m_ycbcrProgram.release();
}
m_bitmapProgram.setUniformValue("texture", 1); m_indices.release();
m_bitmapProgram.setUniformValue("ortho", m_bitmapOrtho);
m_bitmapProgram.setUniformValue("texortho", m_bitmapTexortho);
m_gl->glDrawElements(GL_TRIANGLE_STRIP, *m_bitmapCount, GL_UNSIGNED_SHORT, (void*) 0); m_window->resetOpenGLState();
}
*m_fillCount = 0; emit rendered();
*m_copyCount = 0; }
*m_bitmapCount = 0;
update(); void VncRenderer::synchronize(QQuickFramebufferObject *fbo)
{
auto qvnc = static_cast<QVnc*>(fbo);
auto uploader = qvnc->uploader();
m_fillCount = std::max(uploader->fillCount() / 4 * 6, 2uL) - 2;
m_copyCount = std::max(uploader->copyCount() / 4 * 6, 2uL) - 2;
m_bitmapCount = std::max(uploader->bitmapCount() / 4 * 6, 2uL) - 2;
m_ycbcrCount = std::max(uploader->ycbcrCount() / 4 * 6, 2uL) - 2;
m_window->resetOpenGLState(); // query until it is finally set
if (m_rgbTexture.get() == nullptr)
{
m_rgbTexture = uploader->rgbTexture();
m_yTexture = uploader->yTexture();
m_cbTexture = uploader->cbTexture();
m_crTexture = uploader->crTexture();
}
} }
QOpenGLFramebufferObject *VncRenderer::createFramebufferObject(const QSize &size) QOpenGLFramebufferObject *VncRenderer::createFramebufferObject(const QSize &size)
{ {
m_copyTexortho.ortho(QRect(QPoint(-1 * size.width(), size.height()), QSize(2 * size.width(), -2 * size.height()))); m_toFramebuffer.ortho(QRect(QPoint(0, size.height()), QSize(size.width(), -1 * size.height())));
m_bitmapOrtho.ortho(QRect(QPoint(0, size.height()), QSize(size.width(), -1 * size.height()))); m_fromFramebuffer.ortho(QRect(QPoint(-1 * size.width(), size.height()), QSize(2 * size.width(), -2 * size.height())));
m_fillProgram.bind();
m_fillProgram.setUniformValue("ortho", m_toFramebuffer);
m_fillProgram.release();
m_copyProgram.bind();
m_copyProgram.setUniformValue("srcortho", m_fromFramebuffer);
m_copyProgram.release();
m_bitmapProgram.bind();
m_bitmapProgram.setUniformValue("ortho", m_toFramebuffer);
m_bitmapProgram.release();
m_ycbcrProgram.bind();
m_ycbcrProgram.setUniformValue("ortho", m_toFramebuffer);
m_ycbcrProgram.release();
m_framebufferObject = new QOpenGLFramebufferObject(size); return (m_framebufferObject = new QOpenGLFramebufferObject(size));
return m_framebufferObject;
} }
#ifndef VNCRENDERER_H #ifndef VNCRENDERER_H
#define VNCRENDERER_H #define VNCRENDERER_H
#include <memory>
#include <QQuickWindow> #include <QQuickWindow>
#include <QQuickFramebufferObject> #include <QQuickFramebufferObject>
#include <QOpenGLFramebufferObject> #include <QOpenGLFramebufferObject>
...@@ -11,6 +12,8 @@ ...@@ -11,6 +12,8 @@
#include <QOpenGLBuffer> #include <QOpenGLBuffer>
#include <QTime> #include <QTime>
#include <texture.h>
#include "qvnc.h" #include "qvnc.h"
struct Indices struct Indices
...@@ -35,54 +38,56 @@ class VncRenderer : public QObject, public QQuickFramebufferObject::Renderer ...@@ -35,54 +38,56 @@ class VncRenderer : public QObject, public QQuickFramebufferObject::Renderer
Q_OBJECT Q_OBJECT
public: public:
VncRenderer(QQuickWindow *window, VncRenderer(QQuickWindow *window,
QOpenGLBuffer **fillBuffer, QOpenGLBuffer fillBuffer,
QOpenGLBuffer **copyBuffer, QOpenGLBuffer copyBuffer,
QOpenGLBuffer **bitmapBuffer, QOpenGLBuffer bitmapBuffer,
GLuint **rgbTexture, QOpenGLBuffer ycbcrBuffer,
GLuint **yTexture,
GLuint **cbTexture,
GLuint **crTexture,
unsigned int *fillCount,
unsigned int *copyCount,
unsigned int *bitmapCount,
QObject *parent = nullptr); QObject *parent = nullptr);
protected: protected:
void render() override; void render() override;
void synchronize(QQuickFramebufferObject *fbo) override;
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override; QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override;
private: private:
QQuickWindow *m_window; QQuickWindow *m_window;
QMatrix4x4 m_copyOrtho; QMatrix4x4 m_fromTexture;
QMatrix4x4 m_copyTexortho; QMatrix4x4 m_toFramebuffer;
QMatrix4x4 m_bitmapOrtho; QMatrix4x4 m_fromFramebuffer;
QMatrix4x4 m_bitmapTexortho; QMatrix4x4 m_toTexture;
QOpenGLBuffer **m_fillBuffer; QOpenGLBuffer m_fillBuffer;
QOpenGLBuffer **m_copyBuffer; QOpenGLBuffer m_copyBuffer;
QOpenGLBuffer **m_bitmapBuffer; QOpenGLBuffer m_bitmapBuffer;
QOpenGLBuffer m_ycbcrBuffer;
GLuint **m_rgbTexture; std::shared_ptr<Texture> m_rgbTexture;
GLuint **m_yTexture; std::shared_ptr<Texture> m_yTexture;
GLuint **m_cbTexture; std::shared_ptr<Texture> m_cbTexture;
GLuint **m_crTexture; std::shared_ptr<Texture> m_crTexture;
unsigned int *m_fillCount; unsigned int m_fillCount;
unsigned int *m_copyCount; unsigned int m_copyCount;
unsigned int *m_bitmapCount; unsigned int m_bitmapCount;
unsigned int m_ycbcrCount;
QOpenGLBuffer m_indices; QOpenGLBuffer m_indices;
QOpenGLShaderProgram m_fillProgram; QOpenGLShaderProgram m_fillProgram;
QOpenGLShaderProgram m_bitmapProgram; QOpenGLShaderProgram m_bitmapProgram;
QOpenGLShaderProgram m_ycbcrProgram; QOpenGLShaderProgram m_ycbcrProgram;
QOpenGLShaderProgram m_copyProgram;
GLuint m_textureTarget; GLuint m_textureTarget;
QOpenGLFunctions *m_gl; QOpenGLFunctions *m_gl;
QOpenGLFramebufferObject *m_framebufferObject; QOpenGLFramebufferObject *m_framebufferObject;
bool m_clear;
int frameCount; int frameCount;
QTime frameTime; QTime frameTime;
private slots: private slots:
void handleDebugMessage(const QOpenGLDebugMessage &debugMessage); void handleDebugMessage(const QOpenGLDebugMessage &debugMessage);
signals:
void rendered();
}; };
#endif // VNCRENDERER_H #endif // VNCRENDERER_H
uniform sampler2D y_texture;
uniform sampler2D cb_texture;
uniform sampler2D cr_texture;
varying highp vec2 vartexcoord;
varying highp float vartexindex;
void main(void)
{
highp float Y;
highp float Cb;
highp float Cr;
highp float pos = mod((gl_FragCoord.x - 0.5), 4.0);
if(pos < 1.0) {
Y = texture2D(y_texture, vartexcoord).r;
Cb = texture2D(cb_texture, vartexcoord).r;
Cr = texture2D(cr_texture, vartexcoord).r;
} else if(pos < 2.0) {
Y = texture2D(y_texture, vartexcoord).g;
Cb = texture2D(cb_texture, vartexcoord).g;
Cr = texture2D(cr_texture, vartexcoord).g;
} else if(pos < 3.0) {
Y = texture2D(y_texture, vartexcoord).b;
Cb = texture2D(cb_texture, vartexcoord).b;
Cr = texture2D(cr_texture, vartexcoord).b;
} else {
Y = texture2D(y_texture, vartexcoord).a;
Cb = texture2D(cb_texture, vartexcoord).a;
Cr = texture2D(cr_texture, vartexcoord).a;
}
highp float R = Y + 1.402 * (Cr - 0.5);
highp float G = Y - 0.34414 * (Cb - 0.5) - 0.71414 * (Cr - 0.5);
highp float B = Y + 1.772 * (Cb - 0.5);
gl_FragColor = vec4(B, G, R, 1.0);
}
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