blob: 50c116e054e46ed8a4e5b764771181001301ebd8 [file] [log] [blame]
Constantin Kaplinskyaf1891c2005-09-29 06:18:28 +00001/* Copyright (C) 2004-2005 Constantin Kaplinsky. All Rights Reserved.
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// PollingManager.cxx
20//
21
22#include <stdio.h>
23#include <string.h>
24#include <sys/time.h>
25#include <X11/Xlib.h>
26#include <rfb/VNCServer.h>
27
28#include <x0vncserver/Image.h>
29#include <x0vncserver/PollingManager.h>
30
31const int PollingManager::m_pollingOrder[32] = {
32 0, 16, 8, 24, 4, 20, 12, 28,
33 10, 26, 18, 2, 22, 6, 30, 14,
34 1, 17, 9, 25, 7, 23, 15, 31,
35 19, 3, 27, 11, 29, 13, 5, 21
36};
37
38//
39// Constructor. Note that dpy and image should remain valid during
40// object lifetime, while factory is used only in the constructor
41// itself.
42//
43
44PollingManager::PollingManager(Display *dpy, Image *image,
45 ImageFactory *factory)
46 : m_dpy(dpy), m_server(0), m_image(image), m_pollingStep(0)
47{
48 // Create two additional images used in the polling algorithm.
49 // FIXME: verify that these images use the same pixel format as in m_image.
50 m_rowImage = factory->newImage(m_dpy, m_image->xim->width, 1);
51 m_tileImage = factory->newImage(m_dpy, 32, 32);
52}
53
54void PollingManager::setVNCServer(VNCServer* s)
55{
56 m_server = s;
57}
58
59//
60// DEBUG: a version of poll() measuring time spent in the function.
61//
62
63void PollingManager::pollDebug()
64{
65 struct timeval timeSaved, timeNow;
66 struct timezone tz;
67 timeSaved.tv_sec = 0;
68 timeSaved.tv_usec = 0;
69 gettimeofday(&timeSaved, &tz);
70
71 poll();
72
73 gettimeofday(&timeNow, &tz);
74 int diff = (int)((timeNow.tv_usec - timeSaved.tv_usec + 500) / 1000 +
75 (timeNow.tv_sec - timeSaved.tv_sec) * 1000);
76 if (diff != 0)
77 fprintf(stderr, "DEBUG: poll(): %4d ms\n", diff);
78}
79
80//
81// Search for changed rectangles on the screen.
82//
83
84void PollingManager::poll()
85{
86 if (!m_server)
87 return;
88
89 int nTilesChanged = 0;
90 int scanLine = m_pollingOrder[m_pollingStep++ % 32];
91 int bytesPerPixel = m_image->xim->bits_per_pixel / 8;
92 int bytesPerLine = m_image->xim->bytes_per_line;
93 int w = m_image->xim->width, h = m_image->xim->height;
94 Rect rect;
95
96 for (int y = 0; y * 32 < h; y++) {
97 int tile_h = (h - y * 32 >= 32) ? 32 : h - y * 32;
98 if (scanLine >= tile_h)
99 continue;
100 int scan_y = y * 32 + scanLine;
101 m_rowImage->get(DefaultRootWindow(m_dpy), 0, scan_y);
102 char *ptr_old = m_image->xim->data + scan_y * bytesPerLine;
103 char *ptr_new = m_rowImage->xim->data;
104 for (int x = 0; x * 32 < w; x++) {
105 int tile_w = (w - x * 32 >= 32) ? 32 : w - x * 32;
106 int nBytes = tile_w * bytesPerPixel;
107 if (memcmp(ptr_old, ptr_new, nBytes)) {
108 if (tile_w == 32 && tile_h == 32) {
109 m_tileImage->get(DefaultRootWindow(m_dpy), x * 32, y * 32);
110 } else {
111 m_tileImage->get(DefaultRootWindow(m_dpy), x * 32, y * 32,
112 tile_w, tile_h);
113 }
114 m_image->updateRect(m_tileImage, x * 32, y * 32);
115 rect.setXYWH(x * 32, y * 32, tile_w, tile_h);
116 m_server->add_changed(rect);
117 nTilesChanged++;
118 }
119 ptr_old += nBytes;
120 ptr_new += nBytes;
121 }
122 }
123
124 if (nTilesChanged)
125 m_server->tryUpdate();
126}
127