OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "base/memory/scoped_ptr.h" | |
6 #include "media/video/capture/screen/differ.h" | |
7 #include "media/video/capture/screen/differ_block.h" | |
8 #include "testing/gmock/include/gmock/gmock.h" | |
9 | |
10 namespace media { | |
11 | |
12 // 96x96 screen gives a 4x4 grid of blocks. | |
13 const int kScreenWidth= 96; | |
14 const int kScreenHeight = 96; | |
15 | |
16 // To test partial blocks, we need a width and height that are not multiples | |
17 // of 16 (or 32, depending on current block size). | |
18 const int kPartialScreenWidth = 70; | |
19 const int kPartialScreenHeight = 70; | |
20 | |
21 class DifferTest : public testing::Test { | |
22 public: | |
23 DifferTest() { | |
24 } | |
25 | |
26 protected: | |
27 void InitDiffer(int width, int height) { | |
28 width_ = width; | |
29 height_ = height; | |
30 bytes_per_pixel_ = kBytesPerPixel; | |
31 stride_ = (kBytesPerPixel * width); | |
32 buffer_size_ = width_ * height_ * bytes_per_pixel_; | |
33 | |
34 differ_.reset(new Differ(width_, height_, bytes_per_pixel_, stride_)); | |
35 | |
36 prev_.reset(new uint8[buffer_size_]); | |
37 memset(prev_.get(), 0, buffer_size_); | |
38 | |
39 curr_.reset(new uint8[buffer_size_]); | |
40 memset(curr_.get(), 0, buffer_size_); | |
41 } | |
42 | |
43 void ClearBuffer(uint8* buffer) { | |
44 memset(buffer, 0, buffer_size_); | |
45 } | |
46 | |
47 // Here in DifferTest so that tests can access private methods of Differ. | |
48 void MarkDirtyBlocks(const void* prev_buffer, const void* curr_buffer) { | |
49 differ_->MarkDirtyBlocks(prev_buffer, curr_buffer); | |
50 } | |
51 | |
52 void MergeBlocks(webrtc::DesktopRegion* dirty) { | |
53 differ_->MergeBlocks(dirty); | |
54 } | |
55 | |
56 // Convenience method to count rectangles in a region. | |
57 int RegionRectCount(const webrtc::DesktopRegion& region) { | |
58 int count = 0; | |
59 for (webrtc::DesktopRegion::Iterator iter(region); | |
60 !iter.IsAtEnd(); iter.Advance()) { | |
61 ++count; | |
62 } | |
63 return count; | |
64 } | |
65 | |
66 // Convenience wrapper for Differ's DiffBlock that calculates the appropriate | |
67 // offset to the start of the desired block. | |
68 DiffInfo DiffBlock(int block_x, int block_y) { | |
69 // Offset from upper-left of buffer to upper-left of requested block. | |
70 int block_offset = ((block_y * stride_) + (block_x * bytes_per_pixel_)) | |
71 * kBlockSize; | |
72 return BlockDifference(prev_.get() + block_offset, | |
73 curr_.get() + block_offset, | |
74 stride_); | |
75 } | |
76 | |
77 // Write the pixel |value| into the specified block in the |buffer|. | |
78 // This is a convenience wrapper around WritePixel(). | |
79 void WriteBlockPixel(uint8* buffer, int block_x, int block_y, | |
80 int pixel_x, int pixel_y, uint32 value) { | |
81 WritePixel(buffer, (block_x * kBlockSize) + pixel_x, | |
82 (block_y * kBlockSize) + pixel_y, value); | |
83 } | |
84 | |
85 // Write the test pixel |value| into the |buffer| at the specified |x|,|y| | |
86 // location. | |
87 // Only the low-order bytes from |value| are written (assuming little-endian). | |
88 // So, for |value| = 0xaabbccdd: | |
89 // If bytes_per_pixel = 4, then ddccbbaa will be written as the pixel value. | |
90 // If = 3, ddccbb | |
91 // If = 2, ddcc | |
92 // If = 1, dd | |
93 void WritePixel(uint8* buffer, int x, int y, uint32 value) { | |
94 uint8* pixel = reinterpret_cast<uint8*>(&value); | |
95 buffer += (y * stride_) + (x * bytes_per_pixel_); | |
96 for (int b = bytes_per_pixel_ - 1; b >= 0; b--) { | |
97 *buffer++ = pixel[b]; | |
98 } | |
99 } | |
100 | |
101 // DiffInfo utility routines. | |
102 // These are here so that we don't have to make each DifferText_Xxx_Test | |
103 // class a friend class to Differ. | |
104 | |
105 // Clear out the entire |diff_info_| buffer. | |
106 void ClearDiffInfo() { | |
107 memset(differ_->diff_info_.get(), 0, differ_->diff_info_size_); | |
108 } | |
109 | |
110 // Get the value in the |diff_info_| array at (x,y). | |
111 DiffInfo GetDiffInfo(int x, int y) { | |
112 DiffInfo* diff_info = differ_->diff_info_.get(); | |
113 return diff_info[(y * GetDiffInfoWidth()) + x]; | |
114 } | |
115 | |
116 // Width of |diff_info_| array. | |
117 int GetDiffInfoWidth() { | |
118 return differ_->diff_info_width_; | |
119 } | |
120 | |
121 // Height of |diff_info_| array. | |
122 int GetDiffInfoHeight() { | |
123 return differ_->diff_info_height_; | |
124 } | |
125 | |
126 // Size of |diff_info_| array. | |
127 int GetDiffInfoSize() { | |
128 return differ_->diff_info_size_; | |
129 } | |
130 | |
131 void SetDiffInfo(int x, int y, const DiffInfo& value) { | |
132 DiffInfo* diff_info = differ_->diff_info_.get(); | |
133 diff_info[(y * GetDiffInfoWidth()) + x] = value; | |
134 } | |
135 | |
136 // Mark the range of blocks specified. | |
137 void MarkBlocks(int x_origin, int y_origin, int width, int height) { | |
138 for (int y = 0; y < height; y++) { | |
139 for (int x = 0; x < width; x++) { | |
140 SetDiffInfo(x_origin + x, y_origin + y, 1); | |
141 } | |
142 } | |
143 } | |
144 | |
145 // Verify that |region| contains a rectangle defined by |x|, |y|, |width| and | |
146 // |height|. | |
147 // |x|, |y|, |width| and |height| are specified in block (not pixel) units. | |
148 bool CheckDirtyRegionContainsRect(const webrtc::DesktopRegion& region, | |
149 int x, int y, | |
150 int width, int height) { | |
151 webrtc::DesktopRect r = | |
152 webrtc::DesktopRect::MakeXYWH(x * kBlockSize, y * kBlockSize, | |
153 width * kBlockSize, height * kBlockSize); | |
154 for (webrtc::DesktopRegion::Iterator i(region); !i.IsAtEnd(); i.Advance()) { | |
155 if (i.rect().equals(r)) | |
156 return true; | |
157 } | |
158 return false; | |
159 } | |
160 | |
161 // Mark the range of blocks specified and then verify that they are | |
162 // merged correctly. | |
163 // Only one rectangular region of blocks can be checked with this routine. | |
164 bool MarkBlocksAndCheckMerge(int x_origin, int y_origin, | |
165 int width, int height) { | |
166 ClearDiffInfo(); | |
167 MarkBlocks(x_origin, y_origin, width, height); | |
168 | |
169 webrtc::DesktopRegion dirty; | |
170 MergeBlocks(&dirty); | |
171 | |
172 | |
173 webrtc::DesktopRect expected_rect = webrtc::DesktopRect::MakeXYWH( | |
174 x_origin * kBlockSize, y_origin * kBlockSize, | |
175 width * kBlockSize, height * kBlockSize); | |
176 | |
177 // Verify that the region contains expected_rect and it's the only | |
178 // rectangle. | |
179 webrtc::DesktopRegion::Iterator it(dirty); | |
180 return !it.IsAtEnd() && expected_rect.equals(it.rect()) && | |
181 (it.Advance(), it.IsAtEnd()); | |
182 } | |
183 | |
184 // The differ class we're testing. | |
185 scoped_ptr<Differ> differ_; | |
186 | |
187 // Screen/buffer info. | |
188 int width_; | |
189 int height_; | |
190 int bytes_per_pixel_; | |
191 int stride_; | |
192 | |
193 // Size of each screen buffer. | |
194 int buffer_size_; | |
195 | |
196 // Previous and current screen buffers. | |
197 scoped_ptr<uint8[]> prev_; | |
198 scoped_ptr<uint8[]> curr_; | |
199 | |
200 private: | |
201 DISALLOW_COPY_AND_ASSIGN(DifferTest); | |
202 }; | |
203 | |
204 TEST_F(DifferTest, Setup) { | |
205 InitDiffer(kScreenWidth, kScreenHeight); | |
206 // 96x96 pixels results in 3x3 array. Add 1 to each dimension as boundary. | |
207 // +---+---+---+---+ | |
208 // | o | o | o | _ | | |
209 // +---+---+---+---+ o = blocks mapped to screen pixels | |
210 // | o | o | o | _ | | |
211 // +---+---+---+---+ _ = boundary blocks | |
212 // | o | o | o | _ | | |
213 // +---+---+---+---+ | |
214 // | _ | _ | _ | _ | | |
215 // +---+---+---+---+ | |
216 EXPECT_EQ(4, GetDiffInfoWidth()); | |
217 EXPECT_EQ(4, GetDiffInfoHeight()); | |
218 EXPECT_EQ(16, GetDiffInfoSize()); | |
219 } | |
220 | |
221 TEST_F(DifferTest, MarkDirtyBlocks_All) { | |
222 InitDiffer(kScreenWidth, kScreenHeight); | |
223 ClearDiffInfo(); | |
224 | |
225 // Update a pixel in each block. | |
226 for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { | |
227 for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { | |
228 WriteBlockPixel(curr_.get(), x, y, 10, 10, 0xff00ff); | |
229 } | |
230 } | |
231 | |
232 MarkDirtyBlocks(prev_.get(), curr_.get()); | |
233 | |
234 // Make sure each block is marked as dirty. | |
235 for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { | |
236 for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { | |
237 EXPECT_EQ(1, GetDiffInfo(x, y)) | |
238 << "when x = " << x << ", and y = " << y; | |
239 } | |
240 } | |
241 } | |
242 | |
243 TEST_F(DifferTest, MarkDirtyBlocks_Sampling) { | |
244 InitDiffer(kScreenWidth, kScreenHeight); | |
245 ClearDiffInfo(); | |
246 | |
247 // Update some pixels in image. | |
248 WriteBlockPixel(curr_.get(), 1, 0, 10, 10, 0xff00ff); | |
249 WriteBlockPixel(curr_.get(), 2, 1, 10, 10, 0xff00ff); | |
250 WriteBlockPixel(curr_.get(), 0, 2, 10, 10, 0xff00ff); | |
251 | |
252 MarkDirtyBlocks(prev_.get(), curr_.get()); | |
253 | |
254 // Make sure corresponding blocks are updated. | |
255 EXPECT_EQ(0, GetDiffInfo(0, 0)); | |
256 EXPECT_EQ(0, GetDiffInfo(0, 1)); | |
257 EXPECT_EQ(1, GetDiffInfo(0, 2)); | |
258 EXPECT_EQ(1, GetDiffInfo(1, 0)); | |
259 EXPECT_EQ(0, GetDiffInfo(1, 1)); | |
260 EXPECT_EQ(0, GetDiffInfo(1, 2)); | |
261 EXPECT_EQ(0, GetDiffInfo(2, 0)); | |
262 EXPECT_EQ(1, GetDiffInfo(2, 1)); | |
263 EXPECT_EQ(0, GetDiffInfo(2, 2)); | |
264 } | |
265 | |
266 TEST_F(DifferTest, DiffBlock) { | |
267 InitDiffer(kScreenWidth, kScreenHeight); | |
268 | |
269 // Verify no differences at start. | |
270 EXPECT_EQ(0, DiffBlock(0, 0)); | |
271 EXPECT_EQ(0, DiffBlock(1, 1)); | |
272 | |
273 // Write new data into the 4 corners of the middle block and verify that | |
274 // neighboring blocks are not affected. | |
275 int max = kBlockSize - 1; | |
276 WriteBlockPixel(curr_.get(), 1, 1, 0, 0, 0xffffff); | |
277 WriteBlockPixel(curr_.get(), 1, 1, 0, max, 0xffffff); | |
278 WriteBlockPixel(curr_.get(), 1, 1, max, 0, 0xffffff); | |
279 WriteBlockPixel(curr_.get(), 1, 1, max, max, 0xffffff); | |
280 EXPECT_EQ(0, DiffBlock(0, 0)); | |
281 EXPECT_EQ(0, DiffBlock(0, 1)); | |
282 EXPECT_EQ(0, DiffBlock(0, 2)); | |
283 EXPECT_EQ(0, DiffBlock(1, 0)); | |
284 EXPECT_EQ(1, DiffBlock(1, 1)); // Only this block should change. | |
285 EXPECT_EQ(0, DiffBlock(1, 2)); | |
286 EXPECT_EQ(0, DiffBlock(2, 0)); | |
287 EXPECT_EQ(0, DiffBlock(2, 1)); | |
288 EXPECT_EQ(0, DiffBlock(2, 2)); | |
289 } | |
290 | |
291 TEST_F(DifferTest, Partial_Setup) { | |
292 InitDiffer(kPartialScreenWidth, kPartialScreenHeight); | |
293 // 70x70 pixels results in 3x3 array: 2x2 full blocks + partials around | |
294 // the edge. One more is added to each dimension as a boundary. | |
295 // +---+---+---+---+ | |
296 // | o | o | + | _ | | |
297 // +---+---+---+---+ o = blocks mapped to screen pixels | |
298 // | o | o | + | _ | | |
299 // +---+---+---+---+ + = partial blocks (top/left mapped to screen pixels) | |
300 // | + | + | + | _ | | |
301 // +---+---+---+---+ _ = boundary blocks | |
302 // | _ | _ | _ | _ | | |
303 // +---+---+---+---+ | |
304 EXPECT_EQ(4, GetDiffInfoWidth()); | |
305 EXPECT_EQ(4, GetDiffInfoHeight()); | |
306 EXPECT_EQ(16, GetDiffInfoSize()); | |
307 } | |
308 | |
309 TEST_F(DifferTest, Partial_FirstPixel) { | |
310 InitDiffer(kPartialScreenWidth, kPartialScreenHeight); | |
311 ClearDiffInfo(); | |
312 | |
313 // Update the first pixel in each block. | |
314 for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { | |
315 for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { | |
316 WriteBlockPixel(curr_.get(), x, y, 0, 0, 0xff00ff); | |
317 } | |
318 } | |
319 | |
320 MarkDirtyBlocks(prev_.get(), curr_.get()); | |
321 | |
322 // Make sure each block is marked as dirty. | |
323 for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { | |
324 for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { | |
325 EXPECT_EQ(1, GetDiffInfo(x, y)) | |
326 << "when x = " << x << ", and y = " << y; | |
327 } | |
328 } | |
329 } | |
330 | |
331 TEST_F(DifferTest, Partial_BorderPixel) { | |
332 InitDiffer(kPartialScreenWidth, kPartialScreenHeight); | |
333 ClearDiffInfo(); | |
334 | |
335 // Update the right/bottom border pixels. | |
336 for (int y = 0; y < height_; y++) { | |
337 WritePixel(curr_.get(), width_ - 1, y, 0xff00ff); | |
338 } | |
339 for (int x = 0; x < width_; x++) { | |
340 WritePixel(curr_.get(), x, height_ - 1, 0xff00ff); | |
341 } | |
342 | |
343 MarkDirtyBlocks(prev_.get(), curr_.get()); | |
344 | |
345 // Make sure last (partial) block in each row/column is marked as dirty. | |
346 int x_last = GetDiffInfoWidth() - 2; | |
347 for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { | |
348 EXPECT_EQ(1, GetDiffInfo(x_last, y)) | |
349 << "when x = " << x_last << ", and y = " << y; | |
350 } | |
351 int y_last = GetDiffInfoHeight() - 2; | |
352 for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { | |
353 EXPECT_EQ(1, GetDiffInfo(x, y_last)) | |
354 << "when x = " << x << ", and y = " << y_last; | |
355 } | |
356 // All other blocks are clean. | |
357 for (int y = 0; y < GetDiffInfoHeight() - 2; y++) { | |
358 for (int x = 0; x < GetDiffInfoWidth() - 2; x++) { | |
359 EXPECT_EQ(0, GetDiffInfo(x, y)) << "when x = " << x << ", and y = " << y; | |
360 } | |
361 } | |
362 } | |
363 | |
364 TEST_F(DifferTest, MergeBlocks_Empty) { | |
365 InitDiffer(kScreenWidth, kScreenHeight); | |
366 | |
367 // No blocks marked: | |
368 // +---+---+---+---+ | |
369 // | | | | _ | | |
370 // +---+---+---+---+ | |
371 // | | | | _ | | |
372 // +---+---+---+---+ | |
373 // | | | | _ | | |
374 // +---+---+---+---+ | |
375 // | _ | _ | _ | _ | | |
376 // +---+---+---+---+ | |
377 ClearDiffInfo(); | |
378 | |
379 webrtc::DesktopRegion dirty; | |
380 MergeBlocks(&dirty); | |
381 | |
382 EXPECT_TRUE(dirty.is_empty()); | |
383 } | |
384 | |
385 TEST_F(DifferTest, MergeBlocks_SingleBlock) { | |
386 InitDiffer(kScreenWidth, kScreenHeight); | |
387 // Mark a single block and make sure that there is a single merged | |
388 // rect with the correct bounds. | |
389 for (int y = 0; y < GetDiffInfoHeight() - 1; y++) { | |
390 for (int x = 0; x < GetDiffInfoWidth() - 1; x++) { | |
391 ASSERT_TRUE(MarkBlocksAndCheckMerge(x, y, 1, 1)) << "x: " << x | |
392 << "y: " << y; | |
393 } | |
394 } | |
395 } | |
396 | |
397 TEST_F(DifferTest, MergeBlocks_BlockRow) { | |
398 InitDiffer(kScreenWidth, kScreenHeight); | |
399 | |
400 // +---+---+---+---+ | |
401 // | X | X | | _ | | |
402 // +---+---+---+---+ | |
403 // | | | | _ | | |
404 // +---+---+---+---+ | |
405 // | | | | _ | | |
406 // +---+---+---+---+ | |
407 // | _ | _ | _ | _ | | |
408 // +---+---+---+---+ | |
409 ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 2, 1)); | |
410 | |
411 // +---+---+---+---+ | |
412 // | | | | _ | | |
413 // +---+---+---+---+ | |
414 // | X | X | X | _ | | |
415 // +---+---+---+---+ | |
416 // | | | | _ | | |
417 // +---+---+---+---+ | |
418 // | _ | _ | _ | _ | | |
419 // +---+---+---+---+ | |
420 ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 1, 3, 1)); | |
421 | |
422 // +---+---+---+---+ | |
423 // | | | | _ | | |
424 // +---+---+---+---+ | |
425 // | | | | _ | | |
426 // +---+---+---+---+ | |
427 // | | X | X | _ | | |
428 // +---+---+---+---+ | |
429 // | _ | _ | _ | _ | | |
430 // +---+---+---+---+ | |
431 ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 2, 2, 1)); | |
432 } | |
433 | |
434 TEST_F(DifferTest, MergeBlocks_BlockColumn) { | |
435 InitDiffer(kScreenWidth, kScreenHeight); | |
436 | |
437 // +---+---+---+---+ | |
438 // | X | | | _ | | |
439 // +---+---+---+---+ | |
440 // | X | | | _ | | |
441 // +---+---+---+---+ | |
442 // | | | | _ | | |
443 // +---+---+---+---+ | |
444 // | _ | _ | _ | _ | | |
445 // +---+---+---+---+ | |
446 ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 1, 2)); | |
447 | |
448 // +---+---+---+---+ | |
449 // | | | | _ | | |
450 // +---+---+---+---+ | |
451 // | | X | | _ | | |
452 // +---+---+---+---+ | |
453 // | | X | | _ | | |
454 // +---+---+---+---+ | |
455 // | _ | _ | _ | _ | | |
456 // +---+---+---+---+ | |
457 ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 1, 1, 2)); | |
458 | |
459 // +---+---+---+---+ | |
460 // | | | X | _ | | |
461 // +---+---+---+---+ | |
462 // | | | X | _ | | |
463 // +---+---+---+---+ | |
464 // | | | X | _ | | |
465 // +---+---+---+---+ | |
466 // | _ | _ | _ | _ | | |
467 // +---+---+---+---+ | |
468 ASSERT_TRUE(MarkBlocksAndCheckMerge(2, 0, 1, 3)); | |
469 } | |
470 | |
471 TEST_F(DifferTest, MergeBlocks_BlockRect) { | |
472 InitDiffer(kScreenWidth, kScreenHeight); | |
473 | |
474 // +---+---+---+---+ | |
475 // | X | X | | _ | | |
476 // +---+---+---+---+ | |
477 // | X | X | | _ | | |
478 // +---+---+---+---+ | |
479 // | | | | _ | | |
480 // +---+---+---+---+ | |
481 // | _ | _ | _ | _ | | |
482 // +---+---+---+---+ | |
483 ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 2, 2)); | |
484 | |
485 // +---+---+---+---+ | |
486 // | | | | _ | | |
487 // +---+---+---+---+ | |
488 // | | X | X | _ | | |
489 // +---+---+---+---+ | |
490 // | | X | X | _ | | |
491 // +---+---+---+---+ | |
492 // | _ | _ | _ | _ | | |
493 // +---+---+---+---+ | |
494 ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 1, 2, 2)); | |
495 | |
496 // +---+---+---+---+ | |
497 // | | X | X | _ | | |
498 // +---+---+---+---+ | |
499 // | | X | X | _ | | |
500 // +---+---+---+---+ | |
501 // | | X | X | _ | | |
502 // +---+---+---+---+ | |
503 // | _ | _ | _ | _ | | |
504 // +---+---+---+---+ | |
505 ASSERT_TRUE(MarkBlocksAndCheckMerge(1, 0, 2, 3)); | |
506 | |
507 // +---+---+---+---+ | |
508 // | | | | _ | | |
509 // +---+---+---+---+ | |
510 // | X | X | X | _ | | |
511 // +---+---+---+---+ | |
512 // | X | X | X | _ | | |
513 // +---+---+---+---+ | |
514 // | _ | _ | _ | _ | | |
515 // +---+---+---+---+ | |
516 ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 1, 3, 2)); | |
517 | |
518 // +---+---+---+---+ | |
519 // | X | X | X | _ | | |
520 // +---+---+---+---+ | |
521 // | X | X | X | _ | | |
522 // +---+---+---+---+ | |
523 // | X | X | X | _ | | |
524 // +---+---+---+---+ | |
525 // | _ | _ | _ | _ | | |
526 // +---+---+---+---+ | |
527 ASSERT_TRUE(MarkBlocksAndCheckMerge(0, 0, 3, 3)); | |
528 } | |
529 | |
530 // This tests marked regions that require more than 1 single dirty rect. | |
531 // The exact rects returned depend on the current implementation, so these | |
532 // may need to be updated if we modify how we merge blocks. | |
533 TEST_F(DifferTest, MergeBlocks_MultiRect) { | |
534 InitDiffer(kScreenWidth, kScreenHeight); | |
535 webrtc::DesktopRegion dirty; | |
536 | |
537 // +---+---+---+---+ +---+---+---+ | |
538 // | | X | | _ | | | 0 | | | |
539 // +---+---+---+---+ +---+---+---+ | |
540 // | X | | | _ | | 1 | | | | |
541 // +---+---+---+---+ => +---+---+---+ | |
542 // | | | X | _ | | | | 2 | | |
543 // +---+---+---+---+ +---+---+---+ | |
544 // | _ | _ | _ | _ | | |
545 // +---+---+---+---+ | |
546 ClearDiffInfo(); | |
547 MarkBlocks(1, 0, 1, 1); | |
548 MarkBlocks(0, 1, 1, 1); | |
549 MarkBlocks(2, 2, 1, 1); | |
550 | |
551 dirty.Clear(); | |
552 MergeBlocks(&dirty); | |
553 | |
554 ASSERT_EQ(3, RegionRectCount(dirty)); | |
555 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 0, 1, 1)); | |
556 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); | |
557 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 2, 1, 1)); | |
558 | |
559 // +---+---+---+---+ +---+---+---+ | |
560 // | | | X | _ | | | | 0 | | |
561 // +---+---+---+---+ +---+---+---+ | |
562 // | X | X | X | _ | | 1 1 1 | | |
563 // +---+---+---+---+ => + + | |
564 // | X | X | X | _ | | 1 1 1 | | |
565 // +---+---+---+---+ +---+---+---+ | |
566 // | _ | _ | _ | _ | | |
567 // +---+---+---+---+ | |
568 ClearDiffInfo(); | |
569 MarkBlocks(2, 0, 1, 1); | |
570 MarkBlocks(0, 1, 3, 2); | |
571 | |
572 dirty.Clear(); | |
573 MergeBlocks(&dirty); | |
574 | |
575 ASSERT_EQ(2, RegionRectCount(dirty)); | |
576 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 0, 1, 1)); | |
577 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 3, 2)); | |
578 | |
579 // +---+---+---+---+ +---+---+---+ | |
580 // | | | | _ | | | | | | |
581 // +---+---+---+---+ +---+---+---+ | |
582 // | X | | X | _ | | 0 | | 1 | | |
583 // +---+---+---+---+ => +---+---+---+ | |
584 // | X | X | X | _ | | 2 2 2 | | |
585 // +---+---+---+---+ +---+---+---+ | |
586 // | _ | _ | _ | _ | | |
587 // +---+---+---+---+ | |
588 ClearDiffInfo(); | |
589 MarkBlocks(0, 1, 1, 1); | |
590 MarkBlocks(2, 1, 1, 1); | |
591 MarkBlocks(0, 2, 3, 1); | |
592 | |
593 dirty.Clear(); | |
594 MergeBlocks(&dirty); | |
595 | |
596 ASSERT_EQ(3, RegionRectCount(dirty)); | |
597 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); | |
598 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 1)); | |
599 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 2, 3, 1)); | |
600 | |
601 // +---+---+---+---+ +---+---+---+ | |
602 // | X | X | X | _ | | 0 0 0 | | |
603 // +---+---+---+---+ +---+---+---+ | |
604 // | X | | X | _ | | 1 | | 2 | | |
605 // +---+---+---+---+ => +---+---+---+ | |
606 // | X | X | X | _ | | 3 3 3 | | |
607 // +---+---+---+---+ +---+---+---+ | |
608 // | _ | _ | _ | _ | | |
609 // +---+---+---+---+ | |
610 ClearDiffInfo(); | |
611 MarkBlocks(0, 0, 3, 1); | |
612 MarkBlocks(0, 1, 1, 1); | |
613 MarkBlocks(2, 1, 1, 1); | |
614 MarkBlocks(0, 2, 3, 1); | |
615 | |
616 dirty.Clear(); | |
617 MergeBlocks(&dirty); | |
618 | |
619 ASSERT_EQ(4, RegionRectCount(dirty)); | |
620 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 3, 1)); | |
621 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 1, 1, 1)); | |
622 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 2, 1, 1, 1)); | |
623 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 2, 3, 1)); | |
624 | |
625 // +---+---+---+---+ +---+---+---+ | |
626 // | X | X | | _ | | 0 0 | | | |
627 // +---+---+---+---+ + +---+ | |
628 // | X | X | | _ | | 0 0 | | | |
629 // +---+---+---+---+ => +---+---+---+ | |
630 // | | X | | _ | | | 1 | | | |
631 // +---+---+---+---+ +---+---+---+ | |
632 // | _ | _ | _ | _ | | |
633 // +---+---+---+---+ | |
634 ClearDiffInfo(); | |
635 MarkBlocks(0, 0, 2, 2); | |
636 MarkBlocks(1, 2, 1, 1); | |
637 | |
638 dirty.Clear(); | |
639 MergeBlocks(&dirty); | |
640 | |
641 ASSERT_EQ(2, RegionRectCount(dirty)); | |
642 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 0, 0, 2, 2)); | |
643 ASSERT_TRUE(CheckDirtyRegionContainsRect(dirty, 1, 2, 1, 1)); | |
644 } | |
645 | |
646 } // namespace media | |
OLD | NEW |