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

Side by Side Diff: ui/gfx/compositor/layer_unittest.cc

Issue 10365007: ui: Move compositor/ directory out of gfx/, up to ui/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix DEPS Created 8 years, 7 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 | « ui/gfx/compositor/layer_type.h ('k') | ui/gfx/compositor/run_all_unittests.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/basictypes.h"
6 #include "base/compiler_specific.h"
7 #include "base/file_path.h"
8 #include "base/file_util.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "base/string_util.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/gfx/canvas.h"
14 #include "ui/gfx/codec/png_codec.h"
15 #include "ui/gfx/compositor/compositor_observer.h"
16 #include "ui/gfx/compositor/layer.h"
17 #include "ui/gfx/compositor/layer_animation_sequence.h"
18 #include "ui/gfx/compositor/test/test_compositor_host.h"
19 #include "ui/gfx/gfx_paths.h"
20 #include "ui/gfx/skia_util.h"
21
22 #include "ui/gfx/compositor/compositor_setup.h"
23
24 namespace ui {
25
26 namespace {
27
28 // Encodes a bitmap into a PNG and write to disk. Returns true on success. The
29 // parent directory does not have to exist.
30 bool WritePNGFile(const SkBitmap& bitmap, const FilePath& file_path) {
31 std::vector<unsigned char> png_data;
32 if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &png_data) &&
33 file_util::CreateDirectory(file_path.DirName())) {
34 char* data = reinterpret_cast<char*>(&png_data[0]);
35 int size = static_cast<int>(png_data.size());
36 return file_util::WriteFile(file_path, data, size) == size;
37 }
38 return false;
39 }
40
41 // Reads and decodes a PNG image to a bitmap. Returns true on success. The PNG
42 // should have been encoded using |gfx::PNGCodec::Encode|.
43 bool ReadPNGFile(const FilePath& file_path, SkBitmap* bitmap) {
44 DCHECK(bitmap);
45 std::string png_data;
46 return file_util::ReadFileToString(file_path, &png_data) &&
47 gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&png_data[0]),
48 png_data.length(),
49 bitmap);
50 }
51
52 // Compares with a PNG file on disk, and returns true if it is the same as
53 // the given image. |ref_img_path| is absolute.
54 bool IsSameAsPNGFile(const SkBitmap& gen_bmp, FilePath ref_img_path) {
55 SkBitmap ref_bmp;
56 if (!ReadPNGFile(ref_img_path, &ref_bmp)) {
57 LOG(ERROR) << "Cannot read reference image: " << ref_img_path.value();
58 return false;
59 }
60
61 if (ref_bmp.width() != gen_bmp.width() ||
62 ref_bmp.height() != gen_bmp.height()) {
63 LOG(ERROR)
64 << "Dimensions do not match (Expected) vs (Actual):"
65 << "(" << ref_bmp.width() << "x" << ref_bmp.height()
66 << ") vs. "
67 << "(" << gen_bmp.width() << "x" << gen_bmp.height() << ")";
68 return false;
69 }
70
71 // Compare pixels and create a simple diff image.
72 int diff_pixels_count = 0;
73 SkAutoLockPixels lock_bmp(gen_bmp);
74 SkAutoLockPixels lock_ref_bmp(ref_bmp);
75 // The reference images were saved with no alpha channel. Use the mask to
76 // set alpha to 0.
77 uint32_t kAlphaMask = 0x00FFFFFF;
78 for (int x = 0; x < gen_bmp.width(); ++x) {
79 for (int y = 0; y < gen_bmp.height(); ++y) {
80 if ((*gen_bmp.getAddr32(x, y) & kAlphaMask) !=
81 (*ref_bmp.getAddr32(x, y) & kAlphaMask)) {
82 ++diff_pixels_count;
83 }
84 }
85 }
86
87 if (diff_pixels_count != 0) {
88 LOG(ERROR) << "Images differ by pixel count: " << diff_pixels_count;
89 return false;
90 }
91
92 return true;
93 }
94
95 // Returns a comma-separated list of the names of |layer|'s children in
96 // bottom-to-top stacking order.
97 std::string GetLayerChildrenNames(const Layer& layer) {
98 std::string names;
99 for (std::vector<Layer*>::const_iterator it = layer.children().begin();
100 it != layer.children().end(); ++it) {
101 if (!names.empty())
102 names += ",";
103 names += (*it)->name();
104 }
105 return names;
106 }
107
108
109 // There are three test classes in here that configure the Compositor and
110 // Layer's slightly differently:
111 // - LayerWithNullDelegateTest uses NullLayerDelegate as the LayerDelegate. This
112 // is typically the base class you want to use.
113 // - LayerWithDelegateTest uses LayerDelegate on the delegates.
114 // - LayerWithRealCompositorTest when a real compositor is required for testing.
115 // - Slow because they bring up a window and run the real compositor. This
116 // is typically not what you want.
117
118 class ColoredLayer : public Layer, public LayerDelegate {
119 public:
120 explicit ColoredLayer(SkColor color)
121 : Layer(LAYER_TEXTURED),
122 color_(color) {
123 set_delegate(this);
124 }
125
126 virtual ~ColoredLayer() { }
127
128 // Overridden from LayerDelegate:
129 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
130 canvas->DrawColor(color_);
131 }
132
133 private:
134 SkColor color_;
135 };
136
137 class LayerWithRealCompositorTest : public testing::Test {
138 public:
139 LayerWithRealCompositorTest() {
140 if (PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_)) {
141 test_data_directory_ = test_data_directory_.AppendASCII("compositor");
142 } else {
143 LOG(ERROR) << "Could not open test data directory.";
144 }
145 }
146 virtual ~LayerWithRealCompositorTest() {}
147
148 // Overridden from testing::Test:
149 virtual void SetUp() OVERRIDE {
150 DisableTestCompositor();
151 const gfx::Rect host_bounds(10, 10, 500, 500);
152 window_.reset(TestCompositorHost::Create(host_bounds));
153 window_->Show();
154 }
155
156 virtual void TearDown() OVERRIDE {
157 }
158
159 Compositor* GetCompositor() {
160 return window_->GetCompositor();
161 }
162
163 Layer* CreateLayer(LayerType type) {
164 return new Layer(type);
165 }
166
167 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
168 Layer* layer = new ColoredLayer(color);
169 layer->SetBounds(bounds);
170 return layer;
171 }
172
173 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
174 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
175 layer->SetBounds(bounds);
176 return layer;
177 }
178
179 void DrawTree(Layer* root) {
180 GetCompositor()->SetRootLayer(root);
181 GetCompositor()->Draw(false);
182 }
183
184 bool ReadPixels(SkBitmap* bitmap) {
185 return GetCompositor()->ReadPixels(bitmap,
186 gfx::Rect(GetCompositor()->size()));
187 }
188
189 void RunPendingMessages() {
190 MessageLoopForUI::current()->RunAllPending();
191 }
192
193 // Invalidates the entire contents of the layer.
194 void SchedulePaintForLayer(Layer* layer) {
195 layer->SchedulePaint(
196 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
197 }
198
199 const FilePath& test_data_directory() const { return test_data_directory_; }
200
201 private:
202 scoped_ptr<TestCompositorHost> window_;
203
204 // The root directory for test files.
205 FilePath test_data_directory_;
206
207 DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
208 };
209
210 // LayerDelegate that paints colors to the layer.
211 class TestLayerDelegate : public LayerDelegate {
212 public:
213 explicit TestLayerDelegate() : color_index_(0) {}
214 virtual ~TestLayerDelegate() {}
215
216 void AddColor(SkColor color) {
217 colors_.push_back(color);
218 }
219
220 const gfx::Size& paint_size() const { return paint_size_; }
221 int color_index() const { return color_index_; }
222
223 // Overridden from LayerDelegate:
224 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
225 SkBitmap contents = canvas->ExtractBitmap();
226 paint_size_ = gfx::Size(contents.width(), contents.height());
227 canvas->FillRect(gfx::Rect(paint_size_), colors_[color_index_]);
228 color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size());
229 }
230
231 private:
232 std::vector<SkColor> colors_;
233 int color_index_;
234 gfx::Size paint_size_;
235
236 DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate);
237 };
238
239 // LayerDelegate that verifies that a layer was asked to update its canvas.
240 class DrawTreeLayerDelegate : public LayerDelegate {
241 public:
242 DrawTreeLayerDelegate() : painted_(false) {}
243 virtual ~DrawTreeLayerDelegate() {}
244
245 void Reset() {
246 painted_ = false;
247 }
248
249 bool painted() const { return painted_; }
250
251 private:
252 // Overridden from LayerDelegate:
253 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
254 painted_ = true;
255 }
256
257 bool painted_;
258
259 DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate);
260 };
261
262 // The simplest possible layer delegate. Does nothing.
263 class NullLayerDelegate : public LayerDelegate {
264 public:
265 NullLayerDelegate() {}
266 virtual ~NullLayerDelegate() {}
267
268 private:
269 // Overridden from LayerDelegate:
270 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
271 }
272
273 DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate);
274 };
275
276 // Remembers if it has been notified.
277 class TestCompositorObserver : public CompositorObserver {
278 public:
279 TestCompositorObserver() : started_(false), ended_(false) {}
280
281 bool notified() const { return started_ && ended_; }
282
283 void Reset() {
284 started_ = false;
285 ended_ = false;
286 }
287
288 private:
289 virtual void OnCompositingStarted(Compositor* compositor) OVERRIDE {
290 started_ = true;
291 }
292
293 virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE {
294 ended_ = true;
295 }
296
297 bool started_;
298 bool ended_;
299
300 DISALLOW_COPY_AND_ASSIGN(TestCompositorObserver);
301 };
302
303 } // namespace
304
305 #if defined(OS_WIN)
306 // These are disabled on windows as they don't run correctly on the buildbot.
307 // Reenable once we move to the real compositor.
308 #define MAYBE_Delegate DISABLED_Delegate
309 #define MAYBE_Draw DISABLED_Draw
310 #define MAYBE_DrawTree DISABLED_DrawTree
311 #define MAYBE_Hierarchy DISABLED_Hierarchy
312 #define MAYBE_HierarchyNoTexture DISABLED_HierarchyNoTexture
313 #define MAYBE_DrawPixels DISABLED_DrawPixels
314 #define MAYBE_SetRootLayer DISABLED_SetRootLayer
315 #define MAYBE_CompositorObservers DISABLED_CompositorObservers
316 #define MAYBE_ModifyHierarchy DISABLED_ModifyHierarchy
317 #define MAYBE_Opacity DISABLED_Opacity
318 #else
319 #define MAYBE_Delegate DISABLED_Delegate
320 #define MAYBE_Draw Draw
321 #define MAYBE_DrawTree DISABLED_DrawTree
322 #define MAYBE_Hierarchy Hierarchy
323 #define MAYBE_HierarchyNoTexture DISABLED_HierarchyNoTexture
324 #define MAYBE_DrawPixels DrawPixels
325 #define MAYBE_SetRootLayer SetRootLayer
326 #define MAYBE_CompositorObservers DISABLED_CompositorObservers
327 #define MAYBE_ModifyHierarchy ModifyHierarchy
328 #define MAYBE_Opacity Opacity
329 #endif
330
331 TEST_F(LayerWithRealCompositorTest, MAYBE_Draw) {
332 scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED,
333 gfx::Rect(20, 20, 50, 50)));
334 DrawTree(layer.get());
335 }
336
337 // Create this hierarchy:
338 // L1 - red
339 // +-- L2 - blue
340 // | +-- L3 - yellow
341 // +-- L4 - magenta
342 //
343 TEST_F(LayerWithRealCompositorTest, MAYBE_Hierarchy) {
344 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
345 gfx::Rect(20, 20, 400, 400)));
346 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
347 gfx::Rect(10, 10, 350, 350)));
348 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
349 gfx::Rect(5, 5, 25, 25)));
350 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
351 gfx::Rect(300, 300, 100, 100)));
352
353 l1->Add(l2.get());
354 l1->Add(l4.get());
355 l2->Add(l3.get());
356
357 DrawTree(l1.get());
358 }
359
360 class LayerWithDelegateTest : public testing::Test, public CompositorDelegate {
361 public:
362 LayerWithDelegateTest() : schedule_draw_invoked_(false) {}
363 virtual ~LayerWithDelegateTest() {}
364
365 // Overridden from testing::Test:
366 virtual void SetUp() OVERRIDE {
367 ui::SetupTestCompositor();
368 compositor_.reset(new Compositor(
369 this, gfx::kNullAcceleratedWidget, gfx::Size(1000, 1000)));
370 }
371
372 virtual void TearDown() OVERRIDE {
373 }
374
375 Compositor* compositor() { return compositor_.get(); }
376
377 virtual Layer* CreateLayer(LayerType type) {
378 return new Layer(type);
379 }
380
381 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
382 Layer* layer = new ColoredLayer(color);
383 layer->SetBounds(bounds);
384 return layer;
385 }
386
387 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
388 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
389 layer->SetBounds(bounds);
390 return layer;
391 }
392
393 void DrawTree(Layer* root) {
394 compositor()->SetRootLayer(root);
395 compositor()->Draw(false);
396 }
397
398 // Invalidates the entire contents of the layer.
399 void SchedulePaintForLayer(Layer* layer) {
400 layer->SchedulePaint(
401 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
402 }
403
404 // Invokes DrawTree on the compositor.
405 void Draw() {
406 compositor_->Draw(false);
407 }
408
409 // CompositorDelegate overrides.
410 virtual void ScheduleDraw() OVERRIDE {
411 schedule_draw_invoked_ = true;
412 }
413
414 protected:
415 // Set to true when ScheduleDraw (CompositorDelegate override) is invoked.
416 bool schedule_draw_invoked_;
417
418 private:
419 scoped_ptr<Compositor> compositor_;
420
421 DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
422 };
423
424 // L1
425 // +-- L2
426 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
427 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
428 gfx::Rect(20, 20, 400, 400)));
429 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
430 gfx::Rect(10, 10, 350, 350)));
431 l1->Add(l2.get());
432 DrawTree(l1.get());
433
434 gfx::Point point1_in_l2_coords(5, 5);
435 Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords);
436 gfx::Point point1_in_l1_coords(15, 15);
437 EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords);
438
439 gfx::Point point2_in_l1_coords(5, 5);
440 Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords);
441 gfx::Point point2_in_l2_coords(-5, -5);
442 EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords);
443 }
444
445 // L1
446 // +-- L2
447 // +-- L3
448 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
449 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
450 gfx::Rect(20, 20, 400, 400)));
451 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
452 gfx::Rect(10, 10, 350, 350)));
453 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
454 gfx::Rect(10, 10, 100, 100)));
455 l1->Add(l2.get());
456 l2->Add(l3.get());
457 DrawTree(l1.get());
458
459 gfx::Point point1_in_l3_coords(5, 5);
460 Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords);
461 gfx::Point point1_in_l1_coords(25, 25);
462 EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords);
463
464 gfx::Point point2_in_l1_coords(5, 5);
465 Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords);
466 gfx::Point point2_in_l3_coords(-15, -15);
467 EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords);
468 }
469
470 TEST_F(LayerWithRealCompositorTest, MAYBE_Delegate) {
471 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorBLACK,
472 gfx::Rect(20, 20, 400, 400)));
473 GetCompositor()->SetRootLayer(l1.get());
474 RunPendingMessages();
475
476 TestLayerDelegate delegate;
477 l1->set_delegate(&delegate);
478 delegate.AddColor(SK_ColorWHITE);
479 delegate.AddColor(SK_ColorYELLOW);
480 delegate.AddColor(SK_ColorGREEN);
481
482 l1->SchedulePaint(gfx::Rect(0, 0, 400, 400));
483 RunPendingMessages();
484 EXPECT_EQ(delegate.color_index(), 1);
485 EXPECT_EQ(delegate.paint_size(), l1->bounds().size());
486
487 l1->SchedulePaint(gfx::Rect(10, 10, 200, 200));
488 RunPendingMessages();
489 EXPECT_EQ(delegate.color_index(), 2);
490 EXPECT_EQ(delegate.paint_size(), gfx::Size(200, 200));
491
492 l1->SchedulePaint(gfx::Rect(5, 5, 50, 50));
493 RunPendingMessages();
494 EXPECT_EQ(delegate.color_index(), 0);
495 EXPECT_EQ(delegate.paint_size(), gfx::Size(50, 50));
496 }
497
498 TEST_F(LayerWithRealCompositorTest, MAYBE_DrawTree) {
499 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
500 gfx::Rect(20, 20, 400, 400)));
501 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
502 gfx::Rect(10, 10, 350, 350)));
503 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
504 gfx::Rect(10, 10, 100, 100)));
505 l1->Add(l2.get());
506 l2->Add(l3.get());
507
508 GetCompositor()->SetRootLayer(l1.get());
509 RunPendingMessages();
510
511 DrawTreeLayerDelegate d1;
512 l1->set_delegate(&d1);
513 DrawTreeLayerDelegate d2;
514 l2->set_delegate(&d2);
515 DrawTreeLayerDelegate d3;
516 l3->set_delegate(&d3);
517
518 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
519 RunPendingMessages();
520 EXPECT_FALSE(d1.painted());
521 EXPECT_TRUE(d2.painted());
522 EXPECT_FALSE(d3.painted());
523 }
524
525 // Tests no-texture Layers.
526 // Create this hierarchy:
527 // L1 - red
528 // +-- L2 - NO TEXTURE
529 // | +-- L3 - yellow
530 // +-- L4 - magenta
531 //
532 TEST_F(LayerWithRealCompositorTest, MAYBE_HierarchyNoTexture) {
533 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
534 gfx::Rect(20, 20, 400, 400)));
535 scoped_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350)));
536 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
537 gfx::Rect(5, 5, 25, 25)));
538 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
539 gfx::Rect(300, 300, 100, 100)));
540
541 l1->Add(l2.get());
542 l1->Add(l4.get());
543 l2->Add(l3.get());
544
545 GetCompositor()->SetRootLayer(l1.get());
546 RunPendingMessages();
547
548 DrawTreeLayerDelegate d2;
549 l2->set_delegate(&d2);
550 DrawTreeLayerDelegate d3;
551 l3->set_delegate(&d3);
552
553 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
554 l3->SchedulePaint(gfx::Rect(5, 5, 5, 5));
555 RunPendingMessages();
556
557 // |d2| should not have received a paint notification since it has no texture.
558 EXPECT_FALSE(d2.painted());
559 // |d3| should have received a paint notification.
560 EXPECT_TRUE(d3.painted());
561 }
562
563 class LayerWithNullDelegateTest : public LayerWithDelegateTest {
564 public:
565 LayerWithNullDelegateTest() {}
566 virtual ~LayerWithNullDelegateTest() {}
567
568 // Overridden from testing::Test:
569 virtual void SetUp() OVERRIDE {
570 LayerWithDelegateTest::SetUp();
571 default_layer_delegate_.reset(new NullLayerDelegate());
572 }
573
574 virtual void TearDown() OVERRIDE {
575 }
576
577 Layer* CreateLayer(LayerType type) OVERRIDE {
578 Layer* layer = new Layer(type);
579 layer->set_delegate(default_layer_delegate_.get());
580 return layer;
581 }
582
583 Layer* CreateTextureRootLayer(const gfx::Rect& bounds) {
584 Layer* layer = CreateTextureLayer(bounds);
585 compositor()->SetRootLayer(layer);
586 return layer;
587 }
588
589 Layer* CreateTextureLayer(const gfx::Rect& bounds) {
590 Layer* layer = CreateLayer(LAYER_TEXTURED);
591 layer->SetBounds(bounds);
592 return layer;
593 }
594
595 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) OVERRIDE {
596 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
597 layer->SetBounds(bounds);
598 return layer;
599 }
600
601 void RunPendingMessages() {
602 MessageLoopForUI::current()->RunAllPending();
603 }
604
605 private:
606 scoped_ptr<NullLayerDelegate> default_layer_delegate_;
607
608 DISALLOW_COPY_AND_ASSIGN(LayerWithNullDelegateTest);
609 };
610
611 // Various visibile/drawn assertions.
612 TEST_F(LayerWithNullDelegateTest, Visibility) {
613 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
614 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
615 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
616 l1->Add(l2.get());
617 l2->Add(l3.get());
618
619 NullLayerDelegate delegate;
620 l1->set_delegate(&delegate);
621 l2->set_delegate(&delegate);
622 l3->set_delegate(&delegate);
623
624 // Layers should initially be drawn.
625 EXPECT_TRUE(l1->IsDrawn());
626 EXPECT_TRUE(l2->IsDrawn());
627 EXPECT_TRUE(l3->IsDrawn());
628 EXPECT_EQ(1.f, l1->web_layer().opacity());
629 EXPECT_EQ(1.f, l2->web_layer().opacity());
630 EXPECT_EQ(1.f, l3->web_layer().opacity());
631
632 compositor()->SetRootLayer(l1.get());
633
634 Draw();
635
636 l1->SetVisible(false);
637 EXPECT_FALSE(l1->IsDrawn());
638 EXPECT_FALSE(l2->IsDrawn());
639 EXPECT_FALSE(l3->IsDrawn());
640 EXPECT_EQ(0.f, l1->web_layer().opacity());
641
642 l3->SetVisible(false);
643 EXPECT_FALSE(l1->IsDrawn());
644 EXPECT_FALSE(l2->IsDrawn());
645 EXPECT_FALSE(l3->IsDrawn());
646 EXPECT_EQ(0.f, l3->web_layer().opacity());
647
648 l1->SetVisible(true);
649 EXPECT_TRUE(l1->IsDrawn());
650 EXPECT_TRUE(l2->IsDrawn());
651 EXPECT_FALSE(l3->IsDrawn());
652 EXPECT_EQ(1.f, l1->web_layer().opacity());
653 }
654
655 // Checks that stacking-related methods behave as advertised.
656 TEST_F(LayerWithNullDelegateTest, Stacking) {
657 scoped_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
658 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
659 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
660 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
661 l1->set_name("1");
662 l2->set_name("2");
663 l3->set_name("3");
664 root->Add(l3.get());
665 root->Add(l2.get());
666 root->Add(l1.get());
667
668 // Layers' children are stored in bottom-to-top order.
669 EXPECT_EQ("3,2,1", GetLayerChildrenNames(*root.get()));
670
671 root->StackAtTop(l3.get());
672 EXPECT_EQ("2,1,3", GetLayerChildrenNames(*root.get()));
673
674 root->StackAtTop(l1.get());
675 EXPECT_EQ("2,3,1", GetLayerChildrenNames(*root.get()));
676
677 root->StackAtTop(l1.get());
678 EXPECT_EQ("2,3,1", GetLayerChildrenNames(*root.get()));
679
680 root->StackAbove(l2.get(), l3.get());
681 EXPECT_EQ("3,2,1", GetLayerChildrenNames(*root.get()));
682
683 root->StackAbove(l1.get(), l3.get());
684 EXPECT_EQ("3,1,2", GetLayerChildrenNames(*root.get()));
685
686 root->StackAbove(l2.get(), l1.get());
687 EXPECT_EQ("3,1,2", GetLayerChildrenNames(*root.get()));
688
689 root->StackAtBottom(l2.get());
690 EXPECT_EQ("2,3,1", GetLayerChildrenNames(*root.get()));
691
692 root->StackAtBottom(l3.get());
693 EXPECT_EQ("3,2,1", GetLayerChildrenNames(*root.get()));
694
695 root->StackAtBottom(l3.get());
696 EXPECT_EQ("3,2,1", GetLayerChildrenNames(*root.get()));
697
698 root->StackBelow(l2.get(), l3.get());
699 EXPECT_EQ("2,3,1", GetLayerChildrenNames(*root.get()));
700
701 root->StackBelow(l1.get(), l3.get());
702 EXPECT_EQ("2,1,3", GetLayerChildrenNames(*root.get()));
703
704 root->StackBelow(l3.get(), l2.get());
705 EXPECT_EQ("3,2,1", GetLayerChildrenNames(*root.get()));
706
707 root->StackBelow(l3.get(), l2.get());
708 EXPECT_EQ("3,2,1", GetLayerChildrenNames(*root.get()));
709
710 root->StackBelow(l3.get(), l1.get());
711 EXPECT_EQ("2,3,1", GetLayerChildrenNames(*root.get()));
712 }
713
714 // Verifies SetBounds triggers the appropriate painting/drawing.
715 TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
716 scoped_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
717 compositor()->SetRootLayer(l1.get());
718
719 Draw();
720
721 schedule_draw_invoked_ = false;
722 l1->SetBounds(gfx::Rect(5, 5, 200, 200));
723
724 // The CompositorDelegate (us) should have been told to draw for a move.
725 EXPECT_TRUE(schedule_draw_invoked_);
726
727 schedule_draw_invoked_ = false;
728 l1->SetBounds(gfx::Rect(5, 5, 100, 100));
729
730 // The CompositorDelegate (us) should have been told to draw for a resize.
731 EXPECT_TRUE(schedule_draw_invoked_);
732 }
733
734 // Checks that pixels are actually drawn to the screen with a read back.
735 TEST_F(LayerWithRealCompositorTest, MAYBE_DrawPixels) {
736 scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED,
737 gfx::Rect(0, 0, 500, 500)));
738 scoped_ptr<Layer> layer2(CreateColorLayer(SK_ColorBLUE,
739 gfx::Rect(0, 0, 500, 10)));
740
741 layer->Add(layer2.get());
742
743 DrawTree(layer.get());
744
745 SkBitmap bitmap;
746 gfx::Size size = GetCompositor()->size();
747 ASSERT_TRUE(GetCompositor()->ReadPixels(&bitmap,
748 gfx::Rect(0, 10,
749 size.width(), size.height() - 10)));
750 ASSERT_FALSE(bitmap.empty());
751
752 SkAutoLockPixels lock(bitmap);
753 bool is_all_red = true;
754 for (int x = 0; is_all_red && x < 500; x++)
755 for (int y = 0; is_all_red && y < 490; y++)
756 is_all_red = is_all_red && (bitmap.getColor(x, y) == SK_ColorRED);
757
758 EXPECT_TRUE(is_all_red);
759 }
760
761 // Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
762 TEST_F(LayerWithRealCompositorTest, MAYBE_SetRootLayer) {
763 Compositor* compositor = GetCompositor();
764 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
765 gfx::Rect(20, 20, 400, 400)));
766 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
767 gfx::Rect(10, 10, 350, 350)));
768
769 EXPECT_EQ(NULL, l1->GetCompositor());
770 EXPECT_EQ(NULL, l2->GetCompositor());
771
772 compositor->SetRootLayer(l1.get());
773 EXPECT_EQ(compositor, l1->GetCompositor());
774
775 l1->Add(l2.get());
776 EXPECT_EQ(compositor, l2->GetCompositor());
777
778 l1->Remove(l2.get());
779 EXPECT_EQ(NULL, l2->GetCompositor());
780
781 l1->Add(l2.get());
782 EXPECT_EQ(compositor, l2->GetCompositor());
783
784 compositor->SetRootLayer(NULL);
785 EXPECT_EQ(NULL, l1->GetCompositor());
786 EXPECT_EQ(NULL, l2->GetCompositor());
787 }
788
789 // Checks that compositor observers are notified when:
790 // - DrawTree is called,
791 // - After ScheduleDraw is called, or
792 // - Whenever SetBounds, SetOpacity or SetTransform are called.
793 // TODO(vollick): could be reorganized into compositor_unittest.cc
794 TEST_F(LayerWithRealCompositorTest, MAYBE_CompositorObservers) {
795 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
796 gfx::Rect(20, 20, 400, 400)));
797 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
798 gfx::Rect(10, 10, 350, 350)));
799 l1->Add(l2.get());
800 TestCompositorObserver observer;
801 GetCompositor()->AddObserver(&observer);
802
803 // Explicitly called DrawTree should cause the observers to be notified.
804 // NOTE: this call to DrawTree sets l1 to be the compositor's root layer.
805 DrawTree(l1.get());
806 RunPendingMessages();
807 EXPECT_TRUE(observer.notified());
808
809 // As should scheduling a draw and waiting.
810 observer.Reset();
811 l1->ScheduleDraw();
812 RunPendingMessages();
813 EXPECT_TRUE(observer.notified());
814
815 // Moving, but not resizing, a layer should alert the observers.
816 observer.Reset();
817 l2->SetBounds(gfx::Rect(0, 0, 350, 350));
818 RunPendingMessages();
819 EXPECT_TRUE(observer.notified());
820
821 // So should resizing a layer.
822 observer.Reset();
823 l2->SetBounds(gfx::Rect(0, 0, 400, 400));
824 RunPendingMessages();
825 EXPECT_TRUE(observer.notified());
826
827 // Opacity changes should alert the observers.
828 observer.Reset();
829 l2->SetOpacity(0.5f);
830 RunPendingMessages();
831 EXPECT_TRUE(observer.notified());
832
833 // So should setting the opacity back.
834 observer.Reset();
835 l2->SetOpacity(1.0f);
836 RunPendingMessages();
837 EXPECT_TRUE(observer.notified());
838
839 // Setting the transform of a layer should alert the observers.
840 observer.Reset();
841 Transform transform;
842 transform.ConcatTranslate(-200, -200);
843 transform.ConcatRotate(90.0f);
844 transform.ConcatTranslate(200, 200);
845 l2->SetTransform(transform);
846 RunPendingMessages();
847 EXPECT_TRUE(observer.notified());
848
849 GetCompositor()->RemoveObserver(&observer);
850
851 // Opacity changes should no longer alert the removed observer.
852 observer.Reset();
853 l2->SetOpacity(0.5f);
854 RunPendingMessages();
855 EXPECT_FALSE(observer.notified());
856 }
857
858 // Checks that modifying the hierarchy correctly affects final composite.
859 TEST_F(LayerWithRealCompositorTest, MAYBE_ModifyHierarchy) {
860 GetCompositor()->WidgetSizeChanged(gfx::Size(50, 50));
861
862 // l0
863 // +-l11
864 // | +-l21
865 // +-l12
866 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
867 gfx::Rect(0, 0, 50, 50)));
868 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
869 gfx::Rect(0, 0, 25, 25)));
870 scoped_ptr<Layer> l21(CreateColorLayer(SK_ColorMAGENTA,
871 gfx::Rect(0, 0, 15, 15)));
872 scoped_ptr<Layer> l12(CreateColorLayer(SK_ColorBLUE,
873 gfx::Rect(10, 10, 25, 25)));
874
875 FilePath ref_img1 = test_data_directory().AppendASCII("ModifyHierarchy1.png");
876 FilePath ref_img2 = test_data_directory().AppendASCII("ModifyHierarchy2.png");
877 SkBitmap bitmap;
878
879 l0->Add(l11.get());
880 l11->Add(l21.get());
881 l0->Add(l12.get());
882 DrawTree(l0.get());
883 ASSERT_TRUE(ReadPixels(&bitmap));
884 ASSERT_FALSE(bitmap.empty());
885 // WritePNGFile(bitmap, ref_img1);
886 EXPECT_TRUE(IsSameAsPNGFile(bitmap, ref_img1));
887
888 l0->StackAtTop(l11.get());
889 DrawTree(l0.get());
890 ASSERT_TRUE(ReadPixels(&bitmap));
891 ASSERT_FALSE(bitmap.empty());
892 // WritePNGFile(bitmap, ref_img2);
893 EXPECT_TRUE(IsSameAsPNGFile(bitmap, ref_img2));
894
895 // l11 is already at the front, should have no effect.
896 l0->StackAtTop(l11.get());
897 DrawTree(l0.get());
898 ASSERT_TRUE(ReadPixels(&bitmap));
899 ASSERT_FALSE(bitmap.empty());
900 EXPECT_TRUE(IsSameAsPNGFile(bitmap, ref_img2));
901
902 // l11 is already at the front, should have no effect.
903 l0->StackAbove(l11.get(), l12.get());
904 DrawTree(l0.get());
905 ASSERT_TRUE(ReadPixels(&bitmap));
906 ASSERT_FALSE(bitmap.empty());
907 EXPECT_TRUE(IsSameAsPNGFile(bitmap, ref_img2));
908
909 // should restore to original configuration
910 l0->StackAbove(l12.get(), l11.get());
911 DrawTree(l0.get());
912 ASSERT_TRUE(ReadPixels(&bitmap));
913 ASSERT_FALSE(bitmap.empty());
914 EXPECT_TRUE(IsSameAsPNGFile(bitmap, ref_img1));
915 }
916
917 // Opacity is rendered correctly.
918 // Checks that modifying the hierarchy correctly affects final composite.
919 TEST_F(LayerWithRealCompositorTest, MAYBE_Opacity) {
920 GetCompositor()->WidgetSizeChanged(gfx::Size(50, 50));
921
922 // l0
923 // +-l11
924 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
925 gfx::Rect(0, 0, 50, 50)));
926 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
927 gfx::Rect(0, 0, 25, 25)));
928
929 FilePath ref_img = test_data_directory().AppendASCII("Opacity.png");
930
931 l11->SetOpacity(0.75);
932 l0->Add(l11.get());
933 DrawTree(l0.get());
934 SkBitmap bitmap;
935 ASSERT_TRUE(ReadPixels(&bitmap));
936 ASSERT_FALSE(bitmap.empty());
937 // WritePNGFile(bitmap, ref_img);
938 EXPECT_TRUE(IsSameAsPNGFile(bitmap, ref_img));
939 }
940
941 namespace {
942
943 class SchedulePaintLayerDelegate : public LayerDelegate {
944 public:
945 SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
946
947 virtual ~SchedulePaintLayerDelegate() {}
948
949 void set_layer(Layer* layer) {
950 layer_ = layer;
951 layer_->set_delegate(this);
952 }
953
954 void SetSchedulePaintRect(const gfx::Rect& rect) {
955 schedule_paint_rect_ = rect;
956 }
957
958 int GetPaintCountAndClear() {
959 int value = paint_count_;
960 paint_count_ = 0;
961 return value;
962 }
963
964 const gfx::Rect& last_clip_rect() const { return last_clip_rect_; }
965
966 private:
967 // Overridden from LayerDelegate:
968 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
969 paint_count_++;
970 if (!schedule_paint_rect_.IsEmpty()) {
971 layer_->SchedulePaint(schedule_paint_rect_);
972 schedule_paint_rect_ = gfx::Rect();
973 }
974 SkRect sk_clip_rect;
975 if (canvas->sk_canvas()->getClipBounds(&sk_clip_rect))
976 last_clip_rect_ = gfx::SkRectToRect(sk_clip_rect);
977 }
978
979 int paint_count_;
980 Layer* layer_;
981 gfx::Rect schedule_paint_rect_;
982 gfx::Rect last_clip_rect_;
983
984 DISALLOW_COPY_AND_ASSIGN(SchedulePaintLayerDelegate);
985 };
986
987 } // namespace
988
989 // Verifies that if SchedulePaint is invoked during painting the layer is still
990 // marked dirty.
991 TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
992 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorRED,
993 gfx::Rect(0, 0, 500, 500)));
994 SchedulePaintLayerDelegate child_delegate;
995 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorBLUE,
996 gfx::Rect(0, 0, 200, 200)));
997 child_delegate.set_layer(child.get());
998
999 root->Add(child.get());
1000
1001 SchedulePaintForLayer(root.get());
1002 DrawTree(root.get());
1003 schedule_draw_invoked_ = false;
1004 child->SchedulePaint(gfx::Rect(0, 0, 20, 20));
1005 child_delegate.GetPaintCountAndClear();
1006 EXPECT_TRUE(schedule_draw_invoked_);
1007 schedule_draw_invoked_ = false;
1008 // Set a rect so that when OnPaintLayer() is invoked SchedulePaint is invoked
1009 // again.
1010 child_delegate.SetSchedulePaintRect(gfx::Rect(10, 10, 30, 30));
1011 DrawTree(root.get());
1012 // |child| should have been painted once.
1013 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1014 // ScheduleDraw() should have been invoked.
1015 EXPECT_TRUE(schedule_draw_invoked_);
1016 // Because SchedulePaint() was invoked from OnPaintLayer() |child| should
1017 // still need to be painted.
1018 DrawTree(root.get());
1019 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1020 EXPECT_TRUE(child_delegate.last_clip_rect().Contains(
1021 gfx::Rect(10, 10, 30, 30)));
1022 }
1023
1024 } // namespace ui
OLDNEW
« no previous file with comments | « ui/gfx/compositor/layer_type.h ('k') | ui/gfx/compositor/run_all_unittests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698