blob: a200e5b4ce2762edf5855ba6f29cec9f44185d64 [file] [log] [blame]
Pierre Ossmane1f25452015-02-04 14:12:04 +01001/* Copyright 2015 Pierre Ossman <ossman@cendio.se> for Cendio AB
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19/*
20 * This program reads files produced by TightVNC's/TurboVNC's
21 * compare-encodings. It is basically a dump of the RFB protocol
22 * from the server side from the ServerInit message and forward.
23 * It is assumed that the client is using a bgr888 (LE) pixel
24 * format.
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <math.h>
30
31#include <rdr/Exception.h>
32#include <rdr/FileInStream.h>
33
34#include <rfb/CConnection.h>
35#include <rfb/CMsgReader.h>
Pierre Ossmane1f25452015-02-04 14:12:04 +010036#include <rfb/PixelBuffer.h>
37#include <rfb/PixelFormat.h>
38
39#include "util.h"
40
41// FIXME: Files are always in this format
42static const rfb::PixelFormat filePF(32, 24, false, true, 255, 255, 255, 0, 8, 16);
43
44class CConn : public rfb::CConnection {
45public:
46 CConn(const char *filename);
47 ~CConn();
48
49 virtual void setDesktopSize(int w, int h);
50 virtual void setPixelFormat(const rfb::PixelFormat& pf);
51 virtual void setCursor(int, int, const rfb::Point&, void*, void*);
Pierre Ossman9f273e92015-11-09 16:34:54 +010052 virtual void framebufferUpdateStart();
53 virtual void framebufferUpdateEnd();
Pierre Ossmane1f25452015-02-04 14:12:04 +010054 virtual void setColourMapEntries(int, int, rdr::U16*);
55 virtual void bell();
56 virtual void serverCutText(const char*, rdr::U32);
57
58public:
59 double cpuTime;
60
61protected:
62 rdr::FileInStream *in;
Pierre Ossmane1f25452015-02-04 14:12:04 +010063};
64
65CConn::CConn(const char *filename)
66{
Pierre Ossmane1f25452015-02-04 14:12:04 +010067 cpuTime = 0.0;
68
69 in = new rdr::FileInStream(filename);
70 setStreams(in, NULL);
71
Pierre Ossmane1f25452015-02-04 14:12:04 +010072 // Need to skip the initial handshake
73 setState(RFBSTATE_INITIALISATION);
74 // That also means that the reader and writer weren't setup
75 setReader(new rfb::CMsgReader(this, in));
76}
77
78CConn::~CConn()
79{
Pierre Ossmane1f25452015-02-04 14:12:04 +010080 delete in;
Pierre Ossmane1f25452015-02-04 14:12:04 +010081}
82
83void CConn::setDesktopSize(int w, int h)
84{
85 CConnection::setDesktopSize(w, h);
86
Pierre Ossman9f273e92015-11-09 16:34:54 +010087 setFramebuffer(new rfb::ManagedPixelBuffer(filePF, cp.width, cp.height));
Pierre Ossmane1f25452015-02-04 14:12:04 +010088}
89
90void CConn::setPixelFormat(const rfb::PixelFormat& pf)
91{
92 // Override format
93 CConnection::setPixelFormat(filePF);
Pierre Ossmane1f25452015-02-04 14:12:04 +010094}
95
96void CConn::setCursor(int, int, const rfb::Point&, void*, void*)
97{
98}
99
Pierre Ossman9f273e92015-11-09 16:34:54 +0100100void CConn::framebufferUpdateStart()
Pierre Ossmane1f25452015-02-04 14:12:04 +0100101{
Pierre Ossman3da238d2015-11-12 12:20:05 +0100102 CConnection::framebufferUpdateStart();
103
Pierre Ossmane1f25452015-02-04 14:12:04 +0100104 startCpuCounter();
Pierre Ossman9f273e92015-11-09 16:34:54 +0100105}
106
107void CConn::framebufferUpdateEnd()
108{
Pierre Ossman3da238d2015-11-12 12:20:05 +0100109 CConnection::framebufferUpdateEnd();
110
Pierre Ossmane1f25452015-02-04 14:12:04 +0100111 endCpuCounter();
112
113 cpuTime += getCpuCounter();
114}
115
116void CConn::setColourMapEntries(int, int, rdr::U16*)
117{
118}
119
120void CConn::bell()
121{
122}
123
124void CConn::serverCutText(const char*, rdr::U32)
125{
126}
127
128static double runTest(const char *fn)
129{
130 CConn *cc;
131 double time;
132
Pierre Ossmane1f25452015-02-04 14:12:04 +0100133 try {
DRC13cfb512015-02-26 12:24:03 -0600134 cc = new CConn(fn);
Pierre Ossman86475a62015-03-03 16:42:15 +0100135 } catch (rdr::Exception e) {
136 fprintf(stderr, "Failed to open rfb file: %s\n", e.str());
137 exit(1);
138 }
DRC13cfb512015-02-26 12:24:03 -0600139
Pierre Ossman86475a62015-03-03 16:42:15 +0100140 try {
Pierre Ossmane1f25452015-02-04 14:12:04 +0100141 while (true)
142 cc->processMsg();
143 } catch (rdr::EndOfStream e) {
144 } catch (rdr::Exception e) {
145 fprintf(stderr, "Failed to run rfb file: %s\n", e.str());
146 exit(1);
147 }
148
149 time = cc->cpuTime;
150
151 delete cc;
152
153 return time;
154}
155
156static void sort(double *array, int count)
157{
158 bool sorted;
159 int i;
160 do {
161 sorted = true;
162 for (i = 1;i < count;i++) {
163 if (array[i-1] > array[i]) {
164 double d;
165 d = array[i];
166 array[i] = array[i-1];
167 array[i-1] = d;
168 sorted = false;
169 }
170 }
171 } while (!sorted);
172}
173
174static const int runCount = 9;
175
176int main(int argc, char **argv)
177{
178 int i;
179 double times[runCount], dev[runCount];
180 double median, meddev;
181
182 if (argc != 2) {
183 printf("Syntax: %s <rfb file>\n", argv[0]);
184 return 1;
185 }
186
187 // Warmup
188 runTest(argv[1]);
189
190 // Multiple runs to get a good average
191 for (i = 0;i < runCount;i++)
192 times[i] = runTest(argv[1]);
193
194 // Calculate median and median deviation
195 sort(times, runCount);
196 median = times[runCount/2];
197
198 for (i = 0;i < runCount;i++)
199 dev[i] = fabs((times[i] - median) / median) * 100;
200
201 sort(dev, runCount);
202 meddev = dev[runCount/2];
203
Pierre Ossmanfb450fb2015-03-03 16:34:56 +0100204 printf("CPU time: %g s (+/- %g %%)\n", median, meddev);
Pierre Ossmane1f25452015-02-04 14:12:04 +0100205
206 return 0;
207}