Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(462)

Side by Side Diff: remoting/host/differ.cc

Issue 2714007: Initial code for screen differ that divides screen into blocks and calculate... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/differ.h ('k') | remoting/host/differ_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "remoting/host/differ.h"
6
7 #include "base/logging.h"
8
9 namespace remoting {
10
11 Differ::Differ(int width, int height, int bpp) {
12 // Dimensions of screen.
13 width_ = width;
14 height_ = height;
15 bytes_per_pixel_ = bpp;
16 bytes_per_row_ = width_ * bytes_per_pixel_;
17
18 // Calc number of blocks (full and partial) required to cover entire image.
19 // One additional row/column is added as a boundary on the right & bottom.
20 diff_info_width_ = (width_ + kBlockSize - 1) / kBlockSize + 1;
21 diff_info_height_ = (height_ + kBlockSize - 1) / kBlockSize + 1;
22 diff_info_size_ = diff_info_width_ * diff_info_height_ * sizeof(DiffInfo);
23 diff_info_.reset(new uint8[diff_info_size_]);
24 }
25
26 void Differ::CalcDirtyRects(const void* prev_buffer, const void* curr_buffer,
27 DirtyRects* rects) {
28 if (!rects) {
29 return;
30 }
31 rects->clear();
32
33 if (!prev_buffer || !curr_buffer) {
34 return;
35 }
36
37 // Identify all the blocks that contain changed pixels.
38 MarkDirtyBlocks(prev_buffer, curr_buffer);
39
40 // Now that we've identified the blocks that have changed, merge adjacent
41 // blocks to minimize the number of rects that we return.
42 MergeBlocks(rects);
43 }
44
45 void Differ::MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer) {
46 memset(diff_info_.get(), 0, diff_info_size_);
47
48 // Calc number of full blocks.
49 int x_full_blocks = width_ / kBlockSize;
50 int y_full_blocks = height_ / kBlockSize;
51
52 // Calc size of partial blocks which may be present on right and bottom edge.
53 int partial_column_width = width_ - (x_full_blocks * kBlockSize);
54 int partial_row_height = height_ - (y_full_blocks * kBlockSize);
55
56 // Offset from the start of one block-column to the next.
57 int block_x_offset = bytes_per_pixel_ * kBlockSize;
58 // Offset from the start of one block-row to the next.
59 int block_y_stride = (width_ * bytes_per_pixel_) * kBlockSize;
60 // Offset from the start of one diff_info row to the next.
61 int diff_info_stride = diff_info_width_ * sizeof(DiffInfo);
62
63 const uint8* prev_block_row_start = static_cast<const uint8*>(prev_buffer);
64 const uint8* curr_block_row_start = static_cast<const uint8*>(curr_buffer);
65 uint8* diff_info_row_start = static_cast<uint8*>(diff_info_.get());
66
67 for (int y = 0; y < y_full_blocks; y++) {
68 const uint8* prev_block = prev_block_row_start;
69 const uint8* curr_block = curr_block_row_start;
70 uint8* diff_info = diff_info_row_start;
71
72 for (int x = 0; x < x_full_blocks; x++) {
73 DiffInfo diff = DiffBlock(prev_block, curr_block, bytes_per_row_);
74 if (diff != 0) {
75 // Mark this block as being modified so that it gets incorporated into
76 // a dirty rect.
77 *diff_info = diff;
78 }
79 prev_block += block_x_offset;
80 curr_block += block_x_offset;
81 diff_info += sizeof(DiffInfo);
82 }
83
84 // If there is a partial column at the end, handle it.
85 if (partial_column_width != 0) {
86 // TODO(garykac): Handle last partial column.
87 }
88
89 // Update pointers for next row.
90 prev_block_row_start += block_y_stride;
91 curr_block_row_start += block_y_stride;
92 diff_info_row_start += diff_info_stride;
93 }
94 if (partial_row_height != 0) {
95 // TODO(garykac): Handle last partial row.
96 }
97 }
98
99 DiffInfo Differ::DiffBlock(const uint8* prev_buffer, const uint8* curr_buffer,
100 int stride) {
101 const uint8* prev_row_start = prev_buffer;
102 const uint8* curr_row_start = curr_buffer;
103
104 // Number of uint64s in each row of the block.
105 // This must be an integral number.
106 int int64s_per_row = (kBlockSize * bytes_per_pixel_) / sizeof(uint64);
107 DCHECK(((kBlockSize * bytes_per_pixel_) % sizeof(uint64)) == 0);
108
109 for (int y = 0; y < kBlockSize; y++) {
110 const uint64* prev = reinterpret_cast<const uint64*>(prev_row_start);
111 const uint64* curr = reinterpret_cast<const uint64*>(curr_row_start);
112
113 // Check each row in uint64-sized chunks.
114 // Note that this check may straddle multiple pixels. This is OK because
115 // we're interested in identifying whether or not there was change - we
116 // don't care what the actual change is.
117 for (int x = 0; x < int64s_per_row; x++) {
118 if (*prev++ != *curr++) {
119 return 1;
120 }
121 }
122 prev_row_start += stride;
123 curr_row_start += stride;
124 }
125 return 0;
126 }
127
128 DiffInfo Differ::DiffPartialBlock(const uint8* prev_buffer,
129 const uint8* curr_buffer,
130 int stride, int width, int height) {
131 const uint8* prev_row_start = prev_buffer;
132 const uint8* curr_row_start = curr_buffer;
133
134 for (int y = 0; y < height; y++) {
135 const uint8* prev = prev_row_start;
136 const uint8* curr = curr_row_start;
137 for (int x = 0; x < width; x++) {
138 for (int b = 0; b < bytes_per_pixel_; b++) {
139 if (*prev++ != *curr++) {
140 return 1;
141 }
142 }
143 }
144 prev_row_start += bytes_per_row_;
145 curr_row_start += bytes_per_row_;
146 }
147 return 0;
148 }
149
150 void Differ::MergeBlocks(DirtyRects* rects) {
151 DCHECK(rects);
152 rects->clear();
153
154 uint8* diff_info_row_start = static_cast<uint8*>(diff_info_.get());
155 int diff_info_stride = diff_info_width_ * sizeof(DiffInfo);
156
157 for (int y = 0; y < diff_info_height_; y++) {
158 uint8* diff_info = diff_info_row_start;
159 for (int x = 0; x < diff_info_width_; x++) {
160 if (*diff_info != 0) {
161 // We've found a modified block. Look at blocks to the right and below
162 // to group this block with as many others as we can.
163 int left = x * kBlockSize;
164 int top = y * kBlockSize;
165 int width = 1;
166 int height = 1;
167 *diff_info = 0;
168
169 // Group with blocks to the right.
170 // We can keep looking until we find an unchanged block because we
171 // have a boundary block which is never marked as having diffs.
172 uint8* right = diff_info + 1;
173 while (*right) {
174 *right++ = 0;
175 width++;
176 }
177
178 // Group with blocks below.
179 // The entire width of blocks that we matched above much match for
180 // each row that we add.
181 uint8* bottom = diff_info;
182 bool found_new_row;
183 do {
184 found_new_row = true;
185 bottom += diff_info_stride;
186 right = bottom;
187 for (int x2 = 0; x2 < width; x2++) {
188 if (*right++ == 0) {
189 found_new_row = false;
190 }
191 }
192
193 if (found_new_row) {
194 height++;
195
196 // We need to go back and erase the diff markers so that we don't
197 // try to add these blocks a second time.
198 right = bottom;
199 for (int x2 = 0; x2 < width; x2++) {
200 *right++ = 0;
201 }
202 }
203 } while (found_new_row);
204
205 // Add rect to list of dirty rects.
206 width *= kBlockSize;
207 if (left + width > width_) {
208 width = width_ - left;
209 }
210 height *= kBlockSize;
211 if (top + height > height_) {
212 height = height_ - top;
213 }
214 rects->push_back(gfx::Rect(left, top, width, height));
215 }
216
217 // Increment to next block in this row.
218 diff_info++;
219 }
220
221 // Go to start of next row.
222 diff_info_row_start += diff_info_stride;
223 }
224 }
225
226 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/differ.h ('k') | remoting/host/differ_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698