blob: b53b85097ce40675b5a48ced4ded62e32907614a [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. 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// -=- rfbUpdateTracker.cpp
20//
21// Tracks updated regions and a region-copy event, too
22//
23
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000024#include <rfb/UpdateTracker.h>
25#include <rfb/LogWriter.h>
26
27using namespace rfb;
28
29static LogWriter vlog("UpdateTracker");
30
31
32// -=- ClippingUpdateTracker
33
34void ClippingUpdateTracker::add_changed(const Region &region) {
35 ut->add_changed(region.intersect(clipRect));
36}
37
38void ClippingUpdateTracker::add_copied(const Region &dest, const Point &delta) {
39 // Clip the destination to the display area
40 Region clipdest = dest.intersect(clipRect);
41 if (clipdest.is_empty()) return;
42
43 // Clip the source to the screen
44 Region tmp = clipdest;
45 tmp.translate(delta.negate());
46 tmp.assign_intersect(clipRect);
47 if (!tmp.is_empty()) {
48 // Translate the source back to a destination region
49 tmp.translate(delta);
50
51 // Pass the copy region to the child tracker
52 ut->add_copied(tmp, delta);
53 }
54
55 // And add any bits that we had to remove to the changed region
56 tmp = clipdest.subtract(tmp);
57 if (!tmp.is_empty())
58 ut->add_changed(tmp);
59}
60
61// SimpleUpdateTracker
62
63SimpleUpdateTracker::SimpleUpdateTracker(bool use_copyrect) {
64 copy_enabled = use_copyrect;
65}
66
67SimpleUpdateTracker::~SimpleUpdateTracker() {
68}
69
70void SimpleUpdateTracker::enable_copyrect(bool enable) {
71 if (!enable && copy_enabled) {
72 add_changed(copied);
73 copied.clear();
74 }
75 copy_enabled=enable;
76}
77
78void SimpleUpdateTracker::add_changed(const Region &region) {
79 changed.assign_union(region);
80}
81
82void SimpleUpdateTracker::add_copied(const Region &dest, const Point &delta) {
83 // Do we support copyrect?
84 if (!copy_enabled) {
85 add_changed(dest);
86 return;
87 }
88
89 // Is there anything to do?
90 if (dest.is_empty()) return;
91
92 // Calculate whether any of this copy can be treated as a continuation
93 // of an earlier one
94 Region src = dest;
95 src.translate(delta.negate());
96 Region overlap = src.intersect(copied);
97
98 if (overlap.is_empty()) {
99 // There is no overlap
100
101 Rect newbr = dest.get_bounding_rect();
102 Rect oldbr = copied.get_bounding_rect();
103 if (oldbr.area() > newbr.area()) {
104 // Old copyrect is (probably) bigger - use it
105 changed.assign_union(dest);
106 } else {
107 // New copyrect is probably bigger
108 // Use the new one
109 // But be careful not to copy stuff that still needs
110 // to be updated.
111 Region invalid_src = src.intersect(changed);
112 invalid_src.translate(delta);
113 changed.assign_union(invalid_src);
114 changed.assign_union(copied);
115 copied = dest;
116 copy_delta = delta;
117 }
118 return;
119 }
120
121 Region invalid_src = overlap.intersect(changed);
122 invalid_src.translate(delta);
123 changed.assign_union(invalid_src);
124
125 overlap.translate(delta);
126
127 Region nonoverlapped_copied = dest.union_(copied).subtract(overlap);
128 changed.assign_union(nonoverlapped_copied);
129
130 copied = overlap;
131 copy_delta = copy_delta.translate(delta);
132
133 return;
134}
135
136void SimpleUpdateTracker::subtract(const Region& region) {
137 copied.assign_subtract(region);
138 changed.assign_subtract(region);
139}
140
141void SimpleUpdateTracker::getUpdateInfo(UpdateInfo* info, const Region& clip)
142{
Pierre Ossman02e43d72009-03-05 11:57:11 +0000143 copied.assign_subtract(changed);
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000144 info->changed = changed.intersect(clip);
145 info->copied = copied.intersect(clip);
146 info->copy_delta = copy_delta;
147}
148
149void SimpleUpdateTracker::copyTo(UpdateTracker* to) const {
150 if (!copied.is_empty())
151 to->add_copied(copied, copy_delta);
152 if (!changed.is_empty())
153 to->add_changed(changed);
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000154}